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
|
||||
export type entry = struct {
|
||||
key: str,
|
||||
value: value,
|
||||
value: str,
|
||||
};
|
||||
|
||||
// A localized key/value pair.
|
||||
// Specification: §5
|
||||
export type localized_entry = struct {
|
||||
key: str,
|
||||
value: value,
|
||||
value: str,
|
||||
locale: locale::locale,
|
||||
};
|
||||
|
||||
// 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.
|
||||
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)) {
|
||||
case let index: size => yield &fil.groups[index];
|
||||
case let index: size => yield fil.groups[index];
|
||||
case void => return void;
|
||||
};
|
||||
let lin = match (group_find_entry(grou, key)) {
|
||||
@ -70,9 +70,9 @@ export fn file_get_localized(
|
||||
group_name: str,
|
||||
key: str,
|
||||
local: locale::locale,
|
||||
) (value | void) = {
|
||||
) (str | void) = {
|
||||
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;
|
||||
};
|
||||
let lin = match (group_find_localized_entry(grou, key, local)) {
|
||||
@ -103,15 +103,37 @@ export fn file_get_localized(
|
||||
//export fn file_encode
|
||||
|
||||
// Frees memory associated with a [[file]].
|
||||
export fn file_finish(fil *file) void = {
|
||||
for (let lin .. file.lines) {
|
||||
export fn file_finish(fil: *file) void = {
|
||||
for (let lin .. fil.preceeding_lines) {
|
||||
line_finish(lin);
|
||||
};
|
||||
free(file.lines);
|
||||
for (let grou .. file.groups) {
|
||||
free(fil.preceeding_lines);
|
||||
for (let grou .. fil.groups) {
|
||||
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) = {
|
||||
@ -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;
|
||||
for (let lin .. grou.lines) {
|
||||
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
|
||||
// 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
|
||||
|
@ -1,14 +1,16 @@
|
||||
use encoding;
|
||||
use bufio;
|
||||
use encoding::utf8;
|
||||
use io;
|
||||
use locale;
|
||||
use memio;
|
||||
use strings;
|
||||
|
||||
// Parses a [[file]]. The result must be freed using [[file_finish]].
|
||||
export fn file_parse(in: io::stream) (file | error | io::error | utf8::invalid) = {
|
||||
let scanner = bufio::newscanner(in);
|
||||
defer bufio::finish(scanner);
|
||||
export fn file_parse(in: io::stream) !(file | error | io::error | utf8::invalid) = {
|
||||
let scanner = bufio::newscanner(&in);
|
||||
defer bufio::finish(&scanner);
|
||||
|
||||
let fil: file = { ... };
|
||||
let fil = file { ... };
|
||||
|
||||
for (true) {
|
||||
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 =>
|
||||
break;
|
||||
case let err: (io::error | utf8::invalid) =>
|
||||
file_finish(fil);
|
||||
file_finish(&fil);
|
||||
return err;
|
||||
};
|
||||
|
||||
if (text == "") {
|
||||
// blank line
|
||||
file_append_line(fil, blank);
|
||||
file_append_line(&fil, blank);
|
||||
|
||||
} else if (strings::has_prefix(text, '#')) {
|
||||
} else if (strings::hasprefix(text, '#')) {
|
||||
// comment
|
||||
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
|
||||
let name = strings::dup(parse_group_header(text)?);
|
||||
file_append_group(fil, name);
|
||||
file_append_group(&fil, name);
|
||||
|
||||
} else {
|
||||
// key/value pair
|
||||
let (key, valu, local) = match (parse_entry()) {
|
||||
case let result: (str, value, (locale::locale | void)) =>
|
||||
let (key, valu, local) = match (parse_entry(text)) {
|
||||
case let result: (str, str, (locale::locale | void)) =>
|
||||
yield result;
|
||||
case let err: error =>
|
||||
file_finish(fil);
|
||||
file_finish(&fil);
|
||||
return err;
|
||||
};
|
||||
|
||||
file_append_line(fil, match (local) {
|
||||
file_append_line(&fil, match (local) {
|
||||
case let local: locale::locale =>
|
||||
yield localized_entry {
|
||||
key = key,
|
||||
@ -63,9 +65,9 @@ export fn file_parse(in: io::stream) (file | error | io::error | utf8::invalid)
|
||||
return fil;
|
||||
};
|
||||
|
||||
fn file_append_line(fil: *file, lin: line) = {
|
||||
fn file_append_line(fil: *file, lin: line) void = {
|
||||
if (len(fil.groups) > 0) {
|
||||
append(fil.groups[len(fil.groups - 1)].lines, lin);
|
||||
append(fil.groups[len(fil.groups) - 1].lines, lin);
|
||||
} else {
|
||||
append(fil.preceeding_lines, lin);
|
||||
};
|
||||
@ -73,37 +75,37 @@ fn file_append_line(fil: *file, lin: line) = {
|
||||
|
||||
// memory is borrowed from the input
|
||||
fn parse_group_header(text: str) (str | error) = {
|
||||
if !strings::has_prefix(text, '[') || !strings::has_suffix(text, ']') {
|
||||
return error::INVALID_GROUP_HEADER;
|
||||
if (!strings::hasprefix(text, '[') || !strings::hassuffix(text, ']')) {
|
||||
return invalid_group_header;
|
||||
};
|
||||
|
||||
text = strings::rtrim(strings::ltrim(text, '['), ']');
|
||||
if strings::contains(text, '[', ']') {
|
||||
return error::INVALID_GROUP_HEADER;
|
||||
if (strings::contains(text, '[', ']')) {
|
||||
return invalid_group_header;
|
||||
};
|
||||
return text;
|
||||
};
|
||||
|
||||
// memory must be freed by the caller
|
||||
fn parse_entry(line: str) ((str, str, (locale::locale | void)) | error) = {
|
||||
if !strings::contains(line, '=') return error::INVALID_ENTRY;
|
||||
let key, valu_string = strings::cut(line, '=');
|
||||
if (!strings::contains(line, '=')) return invalid_entry;
|
||||
let (key, valu) = strings::cut(line, "=");
|
||||
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 (key, local_string) = strings::cut(key, '[');
|
||||
let local: (locale::locale | void) = void;
|
||||
let (key, local_string) = strings::cut(key, "[");
|
||||
if (local_string != "") {
|
||||
local_string = locale(strings::rtrim(local, ']'));
|
||||
if (!validate_entry_locale(local_string)) return error::INVALID_ENTRY;
|
||||
local_string = locale(strings::rtrim(local, "]"));
|
||||
if (!validate_entry_locale(local_string)) return invalid_entry;
|
||||
|
||||
local = match(local_string) {
|
||||
case let local = locale::locale => yield local;
|
||||
case errors::invalid => return error::INVALID_ENTRY;
|
||||
case let local: locale::locale => yield local;
|
||||
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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user