hare-xdg/locale/locale.ha

85 lines
2.4 KiB
Hare
Raw Normal View History

2024-10-03 17:52:06 -06:00
use errors;
use fmt;
use strings;
// A parsed locale name.
export type locale = struct {
lang: str,
2024-10-03 17:52:06 -06:00
country: str,
encoding: str,
modifier: str,
};
2024-10-04 21:12:58 -06:00
// The default locale. Stands for computer, the C language, etc.
export def c = locale {
lang = "C",
...
};
2024-10-03 17:52:06 -06:00
// 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.
2024-10-04 21:12:58 -06:00
// All memory is borrowed from the input, so [[locale_finish]] should not be
// used to free it.
2024-10-03 17:52:06 -06:00
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 {
lang = in,
2024-10-03 17:52:06 -06:00
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.lang);
2024-10-03 17:52:06 -06:00
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 =
2024-10-04 21:12:58 -06:00
a.lang == b.lang &&
a.country == b.country &&
a.encoding == b.encoding &&
a.modifier == b.modifier;
// Duplicates a [[locale]] structure. Use [[locale_finish]] to get rid of it.
export fn locale_dup(local: locale) locale = locale {
lang = strings::dup(local.lang),
country = strings::dup(local.country),
encoding = strings::dup(local.encoding),
modifier = strings::dup(local.modifier),
};
// Frees memory associated with a [[locale]] structure.
export fn locale_finish(local: locale) void = {
free(local.lang);
free(local.country);
free(local.encoding);
free(local.modifier);
};