Add locale module
This commit is contained in:
parent
d1e521ba97
commit
218e6253e7
61
locale/locale.ha
Normal file
61
locale/locale.ha
Normal file
@ -0,0 +1,61 @@
|
||||
use errors;
|
||||
use fmt;
|
||||
use strings;
|
||||
|
||||
// A parsed locale name.
|
||||
export type locale = struct {
|
||||
language: str,
|
||||
country: str,
|
||||
encoding: str,
|
||||
modifier: str,
|
||||
};
|
||||
|
||||
// Parses a [[locale]] name of the form:
|
||||
//
|
||||
// lang_COUNTRY.ENCODING@MODIFIER
|
||||
//
|
||||
// Where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. The function
|
||||
// returns a [[locale]], or [[errors::invalid]] if the input cannot be parsed.
|
||||
// All memory is borrowed from the input.
|
||||
export fn parse_locale(in: str) (locale | errors::invalid) = {
|
||||
let (in, modifier) = strings::rcut(in, "@");
|
||||
if (strings::compare(in, "") == 0) return void: errors::invalid;
|
||||
let (in, encoding) = strings::rcut(in, ".");
|
||||
if (strings::compare(in, "") == 0) return void: errors::invalid;
|
||||
let (in, country) = strings::rcut(in, "_");
|
||||
if (strings::compare(in, "") == 0) return void: errors::invalid;
|
||||
return locale {
|
||||
language = in,
|
||||
country = country,
|
||||
encoding = encoding,
|
||||
modifier = modifier,
|
||||
};
|
||||
};
|
||||
|
||||
// Formats a [[locale]]. The caller must free the return value.
|
||||
export fn format_locale(local: locale) str = {
|
||||
let output = strings::dup(local.language);
|
||||
if (strings::compare(local.country, "") != 0) {
|
||||
let new_output = strings::join("_", output, local.country);
|
||||
free(output);
|
||||
output = new_output;
|
||||
};
|
||||
if (strings::compare(local.encoding, "") != 0) {
|
||||
let new_output = strings::join(".", output, local.encoding);
|
||||
free(output);
|
||||
output = new_output;
|
||||
};
|
||||
if (strings::compare(local.modifier, "") != 0) {
|
||||
let new_output = strings::join("@", output, local.modifier);
|
||||
free(output);
|
||||
output = new_output;
|
||||
};
|
||||
return output;
|
||||
};
|
||||
|
||||
// Checks if two [[locale]]s are equal.
|
||||
export fn locale_equal(a: locale, b: locale) bool =
|
||||
strings::compare(a.language, b.language) == 0 &&
|
||||
strings::compare(a.country, b.country ) == 0 &&
|
||||
strings::compare(a.encoding, b.encoding) == 0 &&
|
||||
strings::compare(a.modifier, b.modifier) == 0;
|
143
locale/locale_test.ha
Normal file
143
locale/locale_test.ha
Normal file
@ -0,0 +1,143 @@
|
||||
use fmt;
|
||||
use errors;
|
||||
use strings;
|
||||
|
||||
@test fn parse_locale_full() void = {
|
||||
let local = match(parse_locale("lang_COUNTRY.ENCODING@MODIFIER")) {
|
||||
case let local: locale => yield local;
|
||||
case => abort("error");
|
||||
};
|
||||
fmt::printf("[{}]\n", local.language)!;
|
||||
assert(strings::compare(local.language, "lang") == 0);
|
||||
fmt::printf("[{}]\n", local.country)!;
|
||||
assert(strings::compare(local.country, "COUNTRY") == 0);
|
||||
fmt::printf("[{}]\n", local.encoding)!;
|
||||
assert(strings::compare(local.encoding, "ENCODING") == 0);
|
||||
fmt::printf("[{}]\n", local.modifier)!;
|
||||
assert(strings::compare(local.modifier, "MODIFIER") == 0);
|
||||
};
|
||||
|
||||
@test fn parse_locale_sparse_a() void = {
|
||||
let local = match(parse_locale("lang.ENCODING@MODIFIER")) {
|
||||
case let local: locale => yield local;
|
||||
case => abort("error");
|
||||
};
|
||||
fmt::printf("[{}]\n", local.language)!;
|
||||
assert(strings::compare(local.language, "lang") == 0);
|
||||
fmt::printf("[{}]\n", local.country)!;
|
||||
assert(strings::compare(local.country, "") == 0);
|
||||
fmt::printf("[{}]\n", local.encoding)!;
|
||||
assert(strings::compare(local.encoding, "ENCODING") == 0);
|
||||
fmt::printf("[{}]\n", local.modifier)!;
|
||||
assert(strings::compare(local.modifier, "MODIFIER") == 0);
|
||||
};
|
||||
|
||||
@test fn parse_locale_sparse_b() void = {
|
||||
let local = match(parse_locale("lang.ENCODING")) {
|
||||
case let local: locale => yield local;
|
||||
case => abort("error");
|
||||
};
|
||||
fmt::printf("[{}]\n", local.language)!;
|
||||
assert(strings::compare(local.language, "lang") == 0);
|
||||
fmt::printf("[{}]\n", local.country)!;
|
||||
assert(strings::compare(local.country, "") == 0);
|
||||
fmt::printf("[{}]\n", local.encoding)!;
|
||||
assert(strings::compare(local.encoding, "ENCODING") == 0);
|
||||
fmt::printf("[{}]\n", local.modifier)!;
|
||||
assert(strings::compare(local.modifier, "") == 0);
|
||||
};
|
||||
|
||||
@test fn parse_locale_sparse_c() void = {
|
||||
let local = match(parse_locale("lang")) {
|
||||
case let local: locale => yield local;
|
||||
case => abort("error");
|
||||
};
|
||||
fmt::printf("[{}]\n", local.language)!;
|
||||
assert(strings::compare(local.language, "lang") == 0);
|
||||
fmt::printf("[{}]\n", local.country)!;
|
||||
assert(strings::compare(local.country, "") == 0);
|
||||
fmt::printf("[{}]\n", local.encoding)!;
|
||||
assert(strings::compare(local.encoding, "") == 0);
|
||||
fmt::printf("[{}]\n", local.modifier)!;
|
||||
assert(strings::compare(local.modifier, "") == 0);
|
||||
};
|
||||
|
||||
@test fn parse_locale_error() void = {
|
||||
let local = match(parse_locale("_COUNTRY.ENCODING@MODIFIER")) {
|
||||
case errors::invalid => void;
|
||||
case => abort("error");
|
||||
};
|
||||
};
|
||||
|
||||
@test fn format_locale_a() void = {
|
||||
let string = format_locale(locale {
|
||||
language = "lang",
|
||||
country = "COUNTRY",
|
||||
encoding = "ENCODING",
|
||||
modifier = "MODIFIER",
|
||||
});
|
||||
defer free(string);
|
||||
fmt::printf("[{}]\n", string)!;
|
||||
assert(strings::compare(string, "lang_COUNTRY.ENCODING@MODIFIER") == 0);
|
||||
};
|
||||
|
||||
@test fn format_locale_b() void = {
|
||||
let string = format_locale(locale {
|
||||
language = "lang",
|
||||
country = "COUNTRY",
|
||||
modifier = "MODIFIER",
|
||||
...
|
||||
});
|
||||
defer free(string);
|
||||
fmt::printf("[{}]\n", string)!;
|
||||
assert(strings::compare(string, "lang_COUNTRY@MODIFIER") == 0);
|
||||
};
|
||||
|
||||
@test fn format_locale_c() void = {
|
||||
let string = format_locale(locale {
|
||||
language = "lang",
|
||||
...
|
||||
});
|
||||
defer free(string);
|
||||
fmt::printf("[{}]\n", string)!;
|
||||
assert(strings::compare(string, "lang") == 0);
|
||||
};
|
||||
|
||||
@test fn locale_equal() void = {
|
||||
assert(locale_equal(locale {
|
||||
language = "lang",
|
||||
country = "COUNTRY",
|
||||
encoding = "ENCODING",
|
||||
modifier = "MODIFIER",
|
||||
},
|
||||
locale {
|
||||
language = "lang",
|
||||
country = "COUNTRY",
|
||||
encoding = "ENCODING",
|
||||
modifier = "MODIFIER",
|
||||
}));
|
||||
assert(!locale_equal(locale {
|
||||
language = "lang",
|
||||
country = "COUNTRY",
|
||||
encoding = "ENCODING",
|
||||
modifier = "MODIFIER",
|
||||
},
|
||||
locale {
|
||||
language = "foo",
|
||||
country = "COUNTRY",
|
||||
encoding = "ENCODING",
|
||||
modifier = "MODIFIER",
|
||||
}));
|
||||
assert(!locale_equal(locale {
|
||||
language = "lang",
|
||||
encoding = "ENCODING",
|
||||
modifier = "MODIFIER",
|
||||
...
|
||||
},
|
||||
locale {
|
||||
language = "lang",
|
||||
country = "COUNTRY",
|
||||
encoding = "ENCODING",
|
||||
...
|
||||
}));
|
||||
};
|
Loading…
Reference in New Issue
Block a user