// Represents a file of the generic key/value format used by desktop entries. // Specification: §3 type file = struct { preceeding_lines: []line; groups: []group; }; // A named group of key/value entries. // Specification: §3.2 type group = struct { name: str; lines: []line; } // A line in the file, which can be a comment (or a blank line), an entry, or // a localized entry. type line = (comment | entry | localized_entry); // A comment. // Specification: §3.1 type comment = str; // A key/value pair. // Specification: §3.3 type entry = struct { key: str; value: value; }; // A localized entry. // Specification: §5 type localized_entry struct { key: str; value: value; locale: locale::locale; }; // An entry value. Values that reference memory (such as [[str]]) are borrowed // from the [[file]]. These may be free'd or overwritten when other functions in // this module are called, so [[value_dup]] is required to extend its lifetime. export type value = (str, bool, f32); // 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) { let grou = match (file_find_group(fil, group_name)) { case index: size => yield &file.groups[index]; case void => return void; }; let lin = match (group_find_entry(grou, key)) { case index: size => yield &grou.lines[index]; case void => return void; }; match (lin) { case entr: entry => return entr.value; case => abort(); }; }; // Gets a localized value from a file. If the group does not exist, or the group // exists but the key isnt in it, it returns void. If the key is in the group // but is not localized to the specified locale, the non-localized value is // returned. export fn file_get_localized( fil: *file, group_name: str, key: str, local: locale, ) (value | void) { let grou = match (file_find_group(fil, group_name)) { case index: size => yield &file.groups[index]; case void => return void; }; let lin = match (group_find_localized_entry(grou, key, local)) { case index: size => yield &grou.lines[index]; case void => return void; }; match (lin) { case entr: localized_entry => return entr.value; case entr: entry => return entr.value; case => abort(); }; }; export fn file_add export fn file_add_localized export fn file_remove export fn file_remove_localized export fn file_encode export fn file_finish fn file_find_group (fil *file, group_name str): (size | void) = { let index = 0; for (let grou .. file.groups) { if (strings::compare(group.name, group_name) == 0) { return index; } index ++; } } fn group_find_entry (grou *group, key str): (size | void) { let index = 0; for (let lin .. grou.lines) { match (lin) { case entr: entry => if (strings::compare(entry.key, entr) == 0) { return index; } case => void ; } index ++; } } // Duplicates a [[value]]. Use [[value_finish]] to get rid of it. export fn value_dup(valu: value): value = match (valu) { case let valu: str => yield strings.dup(valu); case => yield valu; }; // Frees an [[entry]] previously duplicated with [[entry_dup]]. export fn value_finish(valu: value): void = match (valu) { case let valu: str => free(valu); case => void; };