Locale defines its own invalid error

This commit is contained in:
Sasha Koshka 2024-10-12 23:51:52 -04:00
parent 19e6aa5259
commit 8521320a7c
7 changed files with 23 additions and 19 deletions

View File

@ -1,4 +1,4 @@
// Any error which may be returned from a function in this module. // All errors defined in this module.
export type error = !( export type error = !(
invalid_group_header | invalid_group_header |
invalid_entry | invalid_entry |

View File

@ -109,7 +109,7 @@ fn parse_entry(line: str) ((str, str, (locale::locale | void)) | error) = {
local = match(locale::parse(local_string)) { local = match(locale::parse(local_string)) {
case let local: locale::locale => yield local; case let local: locale::locale => yield local;
case errors::invalid => return invalid_entry; case locale::invalid => return invalid_entry;
}; };
}; };

View File

@ -52,29 +52,29 @@ fn get_locale(var: str) locale =
}; };
}; };
fn get_locale_no_fallback(var: str) (locale | errors::invalid) = fn get_locale_no_fallback(var: str) (locale | invalid) =
match (get_env_locale(var)) { match (get_env_locale(var)) {
case let local: locale => yield local; case let local: locale => yield local;
case => yield (get_locale_conf_entry(var)); case => yield (get_locale_conf_entry(var));
}; };
fn get_env_locale(var: str) (locale | errors::invalid) = fn get_env_locale(var: str) (locale | invalid) =
match (os::getenv(var)) { match (os::getenv(var)) {
case let env: str => return parse(env); case let env: str => return parse(env);
case => return errors::invalid; case => return invalid;
}; };
let locale_conf: []str = []; let locale_conf: []str = [];
@fini fn locale_conf() void = strings::freeall(locale_conf); @fini fn locale_conf() void = strings::freeall(locale_conf);
fn get_locale_conf_entry(var: str) (locale | errors::invalid) = { fn get_locale_conf_entry(var: str) (locale | invalid) = {
get_locale_conf(); get_locale_conf();
for (let entry .. locale_conf) { for (let entry .. locale_conf) {
let (key, value) = strings::cut(entry, "="); let (key, value) = strings::cut(entry, "=");
if (key == var) return parse(value); if (key == var) return parse(value);
}; };
return errors::invalid; return invalid;
}; };
fn get_locale_conf() []str = { fn get_locale_conf() []str = {

View File

@ -1,5 +1,3 @@
use errors;
// Returns the locale to use for character classification and case conversion. // Returns the locale to use for character classification and case conversion.
// The memory is statically allocated and must not be free'd. It may be // The memory is statically allocated and must not be free'd. It may be
// overwritten later, so use [[dup]] to extend its lifetime. // overwritten later, so use [[dup]] to extend its lifetime.

7
locale/error.ha Normal file
View File

@ -0,0 +1,7 @@
// All errors defined in this module.
export type error = !invalid;
// Returned when a malformed locale is encountered.
export type invalid = !void;
export fn strerror(err: error) str = "invalid locale";

View File

@ -21,16 +21,16 @@ export def c = locale {
// lang_COUNTRY.ENCODING@MODIFIER // lang_COUNTRY.ENCODING@MODIFIER
// //
// Where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. The function // Where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. The function
// returns a [[locale]], or [[errors::invalid]] if the input cannot be parsed. // returns a [[locale]], or [[invalid]] if the input cannot be parsed. All
// All memory is borrowed from the input, so [[finish]] should not be used to // memory is borrowed from the input, so [[finish]] should not be used to free
// free it. // it.
export fn parse(in: str) (locale | errors::invalid) = { export fn parse(in: str) (locale | invalid) = {
let (in, modifier) = strings::rcut(in, "@"); let (in, modifier) = strings::rcut(in, "@");
if (strings::compare(in, "") == 0) return void: errors::invalid; if (strings::compare(in, "") == 0) return void: invalid;
let (in, encoding) = strings::rcut(in, "."); let (in, encoding) = strings::rcut(in, ".");
if (strings::compare(in, "") == 0) return void: errors::invalid; if (strings::compare(in, "") == 0) return void: invalid;
let (in, country) = strings::rcut(in, "_"); let (in, country) = strings::rcut(in, "_");
if (strings::compare(in, "") == 0) return void: errors::invalid; if (strings::compare(in, "") == 0) return void: invalid;
return locale { return locale {
lang = in, lang = in,
country = country, country = country,

View File

@ -1,5 +1,4 @@
use fmt; use fmt;
use errors;
use strings; use strings;
@test fn parse_full() void = { @test fn parse_full() void = {
@ -64,8 +63,8 @@ use strings;
@test fn parse_error() void = { @test fn parse_error() void = {
let local = match(parse("_COUNTRY.ENCODING@MODIFIER")) { let local = match(parse("_COUNTRY.ENCODING@MODIFIER")) {
case errors::invalid => void; case invalid => void;
case => abort("error"); case => abort("no error");
}; };
}; };