diff --git a/format/desktop_entry/value.ha b/format/desktop_entry/value.ha index ed3434e..64726f6 100644 --- a/format/desktop_entry/value.ha +++ b/format/desktop_entry/value.ha @@ -2,6 +2,8 @@ use ascii; use strconv; use strings; +// TODO icon_theme references an "integer" data type. support that here. + // Parses a string value. It may contain all ASCII characters except for control // characters. The memory must be freed by the caller. // Specification: §4 @@ -38,6 +40,7 @@ export fn parse_iconstring(in: str) (str | error) = parse_localestring(in); // Parses a boolean value. It must either be the string "true" or "false". // Specification: §4 export fn parse_boolean(in: str) (bool | error) = { + if (strings::contains(in, ";")) return expected_single; if (in == "true" ) return true; if (in == "false") return false; return invalid_boolean; @@ -48,7 +51,9 @@ export fn parse_boolean(in: str) (bool | error) = { // Specification: §4 export fn parse_numeric(in: str) (f64 | error) = match (strconv::stof64(in)) { case let float: f64 => yield float; -case => yield invalid_numeric; +case => + if (strings::contains(in, ";")) return expected_single; + yield invalid_numeric; }; // Parses multiple string values. See [[parse_string]] for more information. The diff --git a/format/desktop_entry/value_test.ha b/format/desktop_entry/value_test.ha index 4cec217..0eda815 100644 --- a/format/desktop_entry/value_test.ha +++ b/format/desktop_entry/value_test.ha @@ -1,11 +1,13 @@ use fmt; use math; +use strings; @test fn parse_string() void = { assert(parse_string("hello")! == "hello"); assert(parse_string("hel\\s\\n\\t\\r\\\\\\;lo")! == "hel \n\t\r\\;lo"); assert(parse_string("hello☠") is invalid_ascii); assert(parse_string("hello;world") is expected_single); + assert(parse_string("hello\\d") is invalid_escape); }; @test fn parse_localestring() void = { @@ -13,6 +15,7 @@ use math; assert(parse_localestring("hel\\s\\n\\t\\r\\\\\\;lo")! == "hel \n\t\r\\;lo"); assert(parse_localestring("hello☠")! == "hello☠"); assert(parse_localestring("hello;world") is expected_single); + assert(parse_localestring("hello\\d") is invalid_escape); }; @test fn parse_iconstring() void = { @@ -20,6 +23,7 @@ use math; assert(parse_iconstring("hel\\s\\n\\t\\r\\\\\\;lo")! == "hel \n\t\r\\;lo"); assert(parse_iconstring("hello☠")! == "hello☠"); assert(parse_iconstring("hello;world") is expected_single); + assert(parse_iconstring("hello\\d") is invalid_escape); }; @test fn parse_boolean() void = { @@ -47,7 +51,88 @@ use math; assert(parse_numeric("234;7.4") is expected_single); }; -// TODO +@test fn parse_strings() void = { + let correct: []str = [ + "b\r\tird", + "wa;ter", + "", + "riv\ner", + "nuh uh", + ]; + let got = parse_strings("b\\r\\tird;wa\\;ter;;riv\\ner;nuh uh")!; + defer strings::freeall(got); + for (let index = 0z; index < len(correct); index += 1) { + assert(index < len(got), "ran out"); + assert(compare_strings(correct[index], got[index])); + }; + assert(len(got) == len(correct), "not done"); + assert(parse_strings("hello☠;world") is invalid_ascii); + assert(parse_strings("hello\\d;world") is invalid_escape); +}; + +@test fn parse_localestrings() void = { + let correct: []str = [ + "b\r\tir☠d", + "wa;ter", + "", + "ri☠v\ner", + "nuh uh", + ]; + let got = parse_localestrings("b\\r\\tir☠d;wa\\;ter;;ri☠v\\ner;nuh uh")!; + defer strings::freeall(got); + for (let index = 0z; index < len(correct); index += 1) { + assert(index < len(got), "ran out"); + assert(compare_strings(correct[index], got[index])); + }; + assert(len(got) == len(correct), "not done"); + assert(parse_strings("hello\\d;world") is invalid_escape); +}; + +@test fn parse_booleans() void = { + let correct: []bool = [ + true, + true, + false, + true, + false, + true, + ]; + let got = parse_booleans("true;true;false;true;false;true")!; + defer free(got); + for (let index = 0z; index < len(correct); index += 1) { + assert(index < len(got), "ran out"); + let correct = correct[index]; + let got = got[index]; + fmt::printf("[{}]\t[{}]\n", correct, got)!; + assert(correct == got); + }; + assert(len(got) == len(correct), "not done"); + assert(parse_booleans("hello;world") is invalid_boolean); + assert(parse_booleans("true;;") is invalid_boolean); + assert(parse_booleans(";false;") is invalid_boolean); +}; + +@test fn parse_numerics() void = { + let correct: []f64 = [ + 5.0, + 34.9, + 29.0, + 32498.23784, + ]; + let got = parse_numerics("5;34.9;29;32498.23784;")!; + defer free(got); + for (let index = 0z; index < len(correct); index += 1) { + assert(index < len(got), "ran out"); + let correct = correct[index]; + let got = got[index]; + fmt::printf("[{}]\t[{}]\n", correct, got)!; + assert(correct == got); + }; + assert(len(got) == len(correct), "not done"); + assert(parse_numerics("hello;world") is invalid_numeric); + assert(parse_numerics("5;;") is invalid_numeric); + assert(parse_numerics(";5;") is invalid_numeric); +}; @test fn string_escaper_next_a() void = { let escaper = escape_string("bird;water;;river;"); @@ -59,8 +144,7 @@ use math; ]; for (let correct .. correct) { let got = string_escaper_next(&escaper) as str; - fmt::printf("[{}]\t[{}]\n", correct, got)!; - assert(correct == got); + assert(compare_strings(correct, got)); }; assert(string_escaper_next(&escaper) is done, "not done"); }; @@ -76,8 +160,7 @@ use math; ]; for (let correct .. correct) { let got = string_escaper_next(&escaper) as str; - fmt::printf("[{}]\t[{}]\n", correct, got)!; - assert(correct == got); + assert(compare_strings(correct, got)); }; assert(string_escaper_next(&escaper) is done, "not done"); }; @@ -92,8 +175,7 @@ use math; ]; for (let correct .. correct) { let got = splitter_next(&splitte) as str; - fmt::printf("[{}]\t[{}]\n", correct, got)!; - assert(correct == got); + assert(compare_strings(correct, got)); }; assert(splitter_next(&splitte) is done, "not done"); }; @@ -109,7 +191,12 @@ use math; for (let correct .. correct) { let got = splitter_next(&splitte) as str; fmt::printf("[{}]\t[{}]\n", correct, got)!; - assert(correct == got); + assert(compare_strings(correct, got)); }; assert(splitter_next(&splitte) is done, "not done"); }; + +fn compare_strings(a: str, b: str) bool = { + fmt::printf("[{}]\t[{}]\n", a, b)!; + return a == b; +};