use errors; use fmt; use strings; // A parsed locale name. export type locale = struct { lang: 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 { lang = 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.lang); 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.lang, b.lang ) == 0 && strings::compare(a.country, b.country ) == 0 && strings::compare(a.encoding, b.encoding) == 0 && strings::compare(a.modifier, b.modifier) == 0;