2024-10-03 17:52:06 -06:00
|
|
|
use errors;
|
|
|
|
use fmt;
|
|
|
|
use strings;
|
|
|
|
|
|
|
|
// A parsed locale name.
|
|
|
|
export type locale = struct {
|
2024-10-04 11:26:37 -06:00
|
|
|
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
|
2024-10-12 21:51:52 -06:00
|
|
|
// returns a [[locale]], or [[invalid]] if the input cannot be parsed. All
|
|
|
|
// memory is borrowed from the input, so [[finish]] should not be used to free
|
|
|
|
// it.
|
|
|
|
export fn parse(in: str) (locale | invalid) = {
|
2024-10-03 17:52:06 -06:00
|
|
|
let (in, modifier) = strings::rcut(in, "@");
|
2024-10-12 21:51:52 -06:00
|
|
|
if (strings::compare(in, "") == 0) return void: invalid;
|
2024-10-03 17:52:06 -06:00
|
|
|
let (in, encoding) = strings::rcut(in, ".");
|
2024-10-12 21:51:52 -06:00
|
|
|
if (strings::compare(in, "") == 0) return void: invalid;
|
2024-10-03 17:52:06 -06:00
|
|
|
let (in, country) = strings::rcut(in, "_");
|
2024-10-12 21:51:52 -06:00
|
|
|
if (strings::compare(in, "") == 0) return void: invalid;
|
2024-10-03 17:52:06 -06:00
|
|
|
return locale {
|
2024-10-04 11:26:37 -06:00
|
|
|
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.
|
2024-10-04 21:17:45 -06:00
|
|
|
export fn format(local: locale) str = {
|
2024-10-04 11:26:37 -06:00
|
|
|
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.
|
2024-10-04 21:17:45 -06:00
|
|
|
export fn 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;
|
|
|
|
|
2024-10-04 21:17:45 -06:00
|
|
|
// Duplicates a [[locale]] structure. Use [[finish]] to get rid of it.
|
|
|
|
export fn dup(local: locale) locale = locale {
|
2024-10-04 21:12:58 -06:00
|
|
|
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.
|
2024-10-04 21:17:45 -06:00
|
|
|
export fn finish(local: locale) void = {
|
2024-10-04 21:12:58 -06:00
|
|
|
free(local.lang);
|
|
|
|
free(local.country);
|
|
|
|
free(local.encoding);
|
|
|
|
free(local.modifier);
|
|
|
|
};
|