Desktop entry module almost compiles
This commit is contained in:
parent
3e72688127
commit
e8af5d01d7
@ -31,22 +31,22 @@ export type comment = str;
|
|||||||
// Specification: §3.3
|
// Specification: §3.3
|
||||||
export type entry = struct {
|
export type entry = struct {
|
||||||
key: str,
|
key: str,
|
||||||
value: value,
|
value: str,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A localized key/value pair.
|
// A localized key/value pair.
|
||||||
// Specification: §5
|
// Specification: §5
|
||||||
export type localized_entry = struct {
|
export type localized_entry = struct {
|
||||||
key: str,
|
key: str,
|
||||||
value: value,
|
value: str,
|
||||||
locale: locale::locale,
|
locale: locale::locale,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Gets a non-localized [[value]] from a [[file]]. If the group does not exist,
|
// Gets a non-localized [[value]] from a [[file]]. If the group does not exist,
|
||||||
// or the group exists but the key isn't in it, it returns void.
|
// or the group exists but the key isn't in it, it returns void.
|
||||||
export fn file_get(fil: *file, group_name: str, key: str) (value | void) = {
|
export fn file_get(fil: *file, group_name: str, key: str) (str | void) = {
|
||||||
let grou = match (file_find_group(fil, group_name)) {
|
let grou = match (file_find_group(fil, group_name)) {
|
||||||
case let index: size => yield &fil.groups[index];
|
case let index: size => yield fil.groups[index];
|
||||||
case void => return void;
|
case void => return void;
|
||||||
};
|
};
|
||||||
let lin = match (group_find_entry(grou, key)) {
|
let lin = match (group_find_entry(grou, key)) {
|
||||||
@ -70,9 +70,9 @@ export fn file_get_localized(
|
|||||||
group_name: str,
|
group_name: str,
|
||||||
key: str,
|
key: str,
|
||||||
local: locale::locale,
|
local: locale::locale,
|
||||||
) (value | void) = {
|
) (str | void) = {
|
||||||
let grou = match (file_find_group(fil, group_name)) {
|
let grou = match (file_find_group(fil, group_name)) {
|
||||||
case let index: size => yield &fil.groups[index];
|
case let index: size => yield fil.groups[index];
|
||||||
case void => return void;
|
case void => return void;
|
||||||
};
|
};
|
||||||
let lin = match (group_find_localized_entry(grou, key, local)) {
|
let lin = match (group_find_localized_entry(grou, key, local)) {
|
||||||
@ -103,15 +103,37 @@ export fn file_get_localized(
|
|||||||
//export fn file_encode
|
//export fn file_encode
|
||||||
|
|
||||||
// Frees memory associated with a [[file]].
|
// Frees memory associated with a [[file]].
|
||||||
export fn file_finish(fil *file) void = {
|
export fn file_finish(fil: *file) void = {
|
||||||
for (let lin .. file.lines) {
|
for (let lin .. fil.preceeding_lines) {
|
||||||
line_finish(lin);
|
line_finish(lin);
|
||||||
};
|
};
|
||||||
free(file.lines);
|
free(fil.preceeding_lines);
|
||||||
for (let grou .. file.groups) {
|
for (let grou .. fil.groups) {
|
||||||
group_finish(grou);
|
group_finish(grou);
|
||||||
};
|
};
|
||||||
free(file.groups);
|
free(fil.groups);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frees memory associated with a [[line]].
|
||||||
|
export fn line_finish(lin: line) void = match (lin) {
|
||||||
|
case let lin: comment =>
|
||||||
|
free(lin);
|
||||||
|
case let lin: entry =>
|
||||||
|
free(lin.key);
|
||||||
|
free(lin.value);
|
||||||
|
case let lin: localized_entry =>
|
||||||
|
free(lin.key);
|
||||||
|
free(lin.value);
|
||||||
|
locale::finish(lin.locale);
|
||||||
|
case => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frees memory associated with a [[group]].
|
||||||
|
export fn group_finish(grou: group) void = {
|
||||||
|
for (let lin .. grou.lines) {
|
||||||
|
line_finish(lin);
|
||||||
|
};
|
||||||
|
free(grou.lines);
|
||||||
};
|
};
|
||||||
|
|
||||||
fn file_find_group(fil: *file, group_name: str) (size | void) = {
|
fn file_find_group(fil: *file, group_name: str) (size | void) = {
|
||||||
@ -124,7 +146,7 @@ fn file_find_group(fil: *file, group_name: str) (size | void) = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fn group_find_entry(grou: *group, key: str) (size | void) = {
|
fn group_find_entry(grou: group, key: str) (size | void) = {
|
||||||
let index = 0z;
|
let index = 0z;
|
||||||
for (let lin .. grou.lines) {
|
for (let lin .. grou.lines) {
|
||||||
match (lin) {
|
match (lin) {
|
||||||
@ -138,7 +160,7 @@ fn group_find_entry(grou: *group, key: str) (size | void) = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fn group_find_localized_entry(grou: *group, key: str, local: locale::locale) (size | void) = {
|
fn group_find_localized_entry(grou: group, key: str, local: locale::locale) (size | void) = {
|
||||||
// The matching is done as follows. If LC_MESSAGES is of the form
|
// The matching is done as follows. If LC_MESSAGES is of the form
|
||||||
// lang_COUNTRY.ENCODING@MODIFIER, then it will match a key of the form
|
// lang_COUNTRY.ENCODING@MODIFIER, then it will match a key of the form
|
||||||
// lang_COUNTRY@MODIFIER. If such a key does not exist, it will attempt
|
// lang_COUNTRY@MODIFIER. If such a key does not exist, it will attempt
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
use encoding;
|
|
||||||
use bufio;
|
use bufio;
|
||||||
|
use encoding::utf8;
|
||||||
use io;
|
use io;
|
||||||
|
use locale;
|
||||||
use memio;
|
use memio;
|
||||||
|
use strings;
|
||||||
|
|
||||||
// Parses a [[file]]. The result must be freed using [[file_finish]].
|
// Parses a [[file]]. The result must be freed using [[file_finish]].
|
||||||
export fn file_parse(in: io::stream) (file | error | io::error | utf8::invalid) = {
|
export fn file_parse(in: io::stream) !(file | error | io::error | utf8::invalid) = {
|
||||||
let scanner = bufio::newscanner(in);
|
let scanner = bufio::newscanner(&in);
|
||||||
defer bufio::finish(scanner);
|
defer bufio::finish(&scanner);
|
||||||
|
|
||||||
let fil: file = { ... };
|
let fil = file { ... };
|
||||||
|
|
||||||
for (true) {
|
for (true) {
|
||||||
let text = match (bufio::scan_line(&scanner)) {
|
let text = match (bufio::scan_line(&scanner)) {
|
||||||
@ -17,35 +19,35 @@ export fn file_parse(in: io::stream) (file | error | io::error | utf8::invalid)
|
|||||||
case let err: io::EOF =>
|
case let err: io::EOF =>
|
||||||
break;
|
break;
|
||||||
case let err: (io::error | utf8::invalid) =>
|
case let err: (io::error | utf8::invalid) =>
|
||||||
file_finish(fil);
|
file_finish(&fil);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (text == "") {
|
if (text == "") {
|
||||||
// blank line
|
// blank line
|
||||||
file_append_line(fil, blank);
|
file_append_line(&fil, blank);
|
||||||
|
|
||||||
} else if (strings::has_prefix(text, '#')) {
|
} else if (strings::hasprefix(text, '#')) {
|
||||||
// comment
|
// comment
|
||||||
let text = strings::dup(strings::ltrim(text, '#'));
|
let text = strings::dup(strings::ltrim(text, '#'));
|
||||||
file_append_line(fil, text: comment);
|
file_append_line(&fil, text: comment);
|
||||||
|
|
||||||
} else if (strings::has_prefix(text, '[')) {
|
} else if (strings::hasprefix(text, '[')) {
|
||||||
// group header
|
// group header
|
||||||
let name = strings::dup(parse_group_header(text)?);
|
let name = strings::dup(parse_group_header(text)?);
|
||||||
file_append_group(fil, name);
|
file_append_group(&fil, name);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// key/value pair
|
// key/value pair
|
||||||
let (key, valu, local) = match (parse_entry()) {
|
let (key, valu, local) = match (parse_entry(text)) {
|
||||||
case let result: (str, value, (locale::locale | void)) =>
|
case let result: (str, str, (locale::locale | void)) =>
|
||||||
yield result;
|
yield result;
|
||||||
case let err: error =>
|
case let err: error =>
|
||||||
file_finish(fil);
|
file_finish(&fil);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
file_append_line(fil, match (local) {
|
file_append_line(&fil, match (local) {
|
||||||
case let local: locale::locale =>
|
case let local: locale::locale =>
|
||||||
yield localized_entry {
|
yield localized_entry {
|
||||||
key = key,
|
key = key,
|
||||||
@ -63,9 +65,9 @@ export fn file_parse(in: io::stream) (file | error | io::error | utf8::invalid)
|
|||||||
return fil;
|
return fil;
|
||||||
};
|
};
|
||||||
|
|
||||||
fn file_append_line(fil: *file, lin: line) = {
|
fn file_append_line(fil: *file, lin: line) void = {
|
||||||
if (len(fil.groups) > 0) {
|
if (len(fil.groups) > 0) {
|
||||||
append(fil.groups[len(fil.groups - 1)].lines, lin);
|
append(fil.groups[len(fil.groups) - 1].lines, lin);
|
||||||
} else {
|
} else {
|
||||||
append(fil.preceeding_lines, lin);
|
append(fil.preceeding_lines, lin);
|
||||||
};
|
};
|
||||||
@ -73,37 +75,37 @@ fn file_append_line(fil: *file, lin: line) = {
|
|||||||
|
|
||||||
// memory is borrowed from the input
|
// memory is borrowed from the input
|
||||||
fn parse_group_header(text: str) (str | error) = {
|
fn parse_group_header(text: str) (str | error) = {
|
||||||
if !strings::has_prefix(text, '[') || !strings::has_suffix(text, ']') {
|
if (!strings::hasprefix(text, '[') || !strings::hassuffix(text, ']')) {
|
||||||
return error::INVALID_GROUP_HEADER;
|
return invalid_group_header;
|
||||||
};
|
};
|
||||||
|
|
||||||
text = strings::rtrim(strings::ltrim(text, '['), ']');
|
text = strings::rtrim(strings::ltrim(text, '['), ']');
|
||||||
if strings::contains(text, '[', ']') {
|
if (strings::contains(text, '[', ']')) {
|
||||||
return error::INVALID_GROUP_HEADER;
|
return invalid_group_header;
|
||||||
};
|
};
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
// memory must be freed by the caller
|
// memory must be freed by the caller
|
||||||
fn parse_entry(line: str) ((str, str, (locale::locale | void)) | error) = {
|
fn parse_entry(line: str) ((str, str, (locale::locale | void)) | error) = {
|
||||||
if !strings::contains(line, '=') return error::INVALID_ENTRY;
|
if (!strings::contains(line, '=')) return invalid_entry;
|
||||||
let key, valu_string = strings::cut(line, '=');
|
let (key, valu) = strings::cut(line, "=");
|
||||||
key = strings::ltrim(strings::rtrim(key));
|
key = strings::ltrim(strings::rtrim(key));
|
||||||
if !validate_entry_key(key) return error::INVALID_ENTRY;
|
if (!validate_entry_key(key)) return invalid_entry;
|
||||||
|
|
||||||
let local = (locale::locale | void) = void;
|
let local: (locale::locale | void) = void;
|
||||||
let (key, local_string) = strings::cut(key, '[');
|
let (key, local_string) = strings::cut(key, "[");
|
||||||
if (local_string != "") {
|
if (local_string != "") {
|
||||||
local_string = locale(strings::rtrim(local, ']'));
|
local_string = locale(strings::rtrim(local, "]"));
|
||||||
if (!validate_entry_locale(local_string)) return error::INVALID_ENTRY;
|
if (!validate_entry_locale(local_string)) return invalid_entry;
|
||||||
|
|
||||||
local = match(local_string) {
|
local = match(local_string) {
|
||||||
case let local = locale::locale => yield local;
|
case let local: locale::locale => yield local;
|
||||||
case errors::invalid => return error::INVALID_ENTRY;
|
case errors::invalid => return invalid_entry;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return strings::dup(key), strings::dup(valu), local;
|
return (strings::dup(key), strings::dup(valu), local);
|
||||||
};
|
};
|
||||||
|
|
||||||
fn validate_entry_key(key: str) bool = {
|
fn validate_entry_key(key: str) bool = {
|
||||||
|
Loading…
Reference in New Issue
Block a user