mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 01:41:59 -05:00
LibUnicode: Generate unique units
This commit is contained in:
parent
4c2c8b8e33
commit
1e95e7716b
1 changed files with 56 additions and 29 deletions
|
@ -44,6 +44,9 @@ constexpr auto s_numeric_symbol_list_index_type = "u8"sv;
|
|||
using NumberSystemIndexType = u8;
|
||||
constexpr auto s_number_system_index_type = "u8"sv;
|
||||
|
||||
using UnitIndexType = u16;
|
||||
constexpr auto s_unit_index_type = "u16"sv;
|
||||
|
||||
enum class NumberFormatType {
|
||||
Standard,
|
||||
Compact,
|
||||
|
@ -225,15 +228,50 @@ struct AK::Traits<NumberSystem> : public GenericTraits<NumberSystem> {
|
|||
};
|
||||
|
||||
struct Unit {
|
||||
unsigned hash() const
|
||||
{
|
||||
auto hash = int_hash(unit);
|
||||
hash = pair_int_hash(hash, long_formats);
|
||||
hash = pair_int_hash(hash, short_formats);
|
||||
hash = pair_int_hash(hash, narrow_formats);
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool operator==(Unit const& other) const
|
||||
{
|
||||
return (unit == other.unit)
|
||||
&& (long_formats == other.long_formats)
|
||||
&& (short_formats == other.short_formats)
|
||||
&& (narrow_formats == other.narrow_formats);
|
||||
}
|
||||
|
||||
StringIndexType unit { 0 };
|
||||
NumberFormatListIndexType long_formats { 0 };
|
||||
NumberFormatListIndexType short_formats { 0 };
|
||||
NumberFormatListIndexType narrow_formats { 0 };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AK::Formatter<Unit> : Formatter<FormatString> {
|
||||
ErrorOr<void> format(FormatBuilder& builder, Unit const& system)
|
||||
{
|
||||
return Formatter<FormatString>::format(builder,
|
||||
"{{ {}, {}, {}, {} }}",
|
||||
system.unit,
|
||||
system.long_formats,
|
||||
system.short_formats,
|
||||
system.narrow_formats);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AK::Traits<Unit> : public GenericTraits<Unit> {
|
||||
static unsigned hash(Unit const& u) { return u.hash(); }
|
||||
};
|
||||
|
||||
struct Locale {
|
||||
HashMap<String, NumberSystemIndexType> number_systems;
|
||||
HashMap<String, Unit> units {};
|
||||
HashMap<String, UnitIndexType> units {};
|
||||
};
|
||||
|
||||
struct UnicodeLocaleData {
|
||||
|
@ -242,6 +280,7 @@ struct UnicodeLocaleData {
|
|||
UniqueStorage<NumberFormatList, NumberFormatListIndexType> unique_format_lists;
|
||||
UniqueStorage<NumericSymbolList, NumericSymbolListIndexType> unique_symbols;
|
||||
UniqueStorage<NumberSystem, NumberSystemIndexType> unique_systems;
|
||||
UniqueStorage<Unit, UnitIndexType> unique_units;
|
||||
|
||||
HashMap<String, Locale> locales;
|
||||
size_t max_identifier_count { 0 };
|
||||
|
@ -545,17 +584,19 @@ static ErrorOr<void> parse_units(String locale_units_path, UnicodeLocaleData& lo
|
|||
units_path = units_path.append("units.json"sv);
|
||||
|
||||
auto units_file = TRY(Core::File::open(units_path.string(), Core::OpenMode::ReadOnly));
|
||||
auto units = TRY(JsonValue::from_string(units_file->read_all()));
|
||||
auto locale_units = TRY(JsonValue::from_string(units_file->read_all()));
|
||||
|
||||
auto const& main_object = units.as_object().get("main"sv);
|
||||
auto const& main_object = locale_units.as_object().get("main"sv);
|
||||
auto const& locale_object = main_object.as_object().get(units_path.parent().basename());
|
||||
auto const& locale_units_object = locale_object.as_object().get("units"sv);
|
||||
auto const& long_object = locale_units_object.as_object().get("long"sv);
|
||||
auto const& short_object = locale_units_object.as_object().get("short"sv);
|
||||
auto const& narrow_object = locale_units_object.as_object().get("narrow"sv);
|
||||
|
||||
HashMap<String, Unit> units;
|
||||
|
||||
auto ensure_unit = [&](auto const& unit) -> Unit& {
|
||||
return locale.units.ensure(unit, [&]() {
|
||||
return units.ensure(unit, [&]() {
|
||||
auto unit_index = locale_data.unique_strings.ensure(unit);
|
||||
return Unit { .unit = unit_index };
|
||||
});
|
||||
|
@ -636,6 +677,11 @@ static ErrorOr<void> parse_units(String locale_units_path, UnicodeLocaleData& lo
|
|||
parse_units_object(short_object.as_object(), Unicode::Style::Short);
|
||||
parse_units_object(narrow_object.as_object(), Unicode::Style::Narrow);
|
||||
|
||||
for (auto& unit : units) {
|
||||
auto unit_index = locale_data.unique_units.ensure(move(unit.value));
|
||||
locale.units.set(unit.key, unit_index);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -793,6 +839,7 @@ struct Unit {
|
|||
locale_data.unique_format_lists.generate(generator, s_number_format_index_type, "s_number_format_lists"sv);
|
||||
locale_data.unique_symbols.generate(generator, s_string_index_type, "s_numeric_symbol_lists"sv);
|
||||
locale_data.unique_systems.generate(generator, "NumberSystem"sv, "s_number_systems"sv, 10);
|
||||
locale_data.unique_units.generate(generator, "Unit"sv, "s_units"sv, 10);
|
||||
|
||||
auto append_map = [&](String name, auto type, auto const& map) {
|
||||
generator.set("name", name);
|
||||
|
@ -812,30 +859,8 @@ static constexpr Array<@type@, @size@> @name@ { {)~~~");
|
|||
generator.append(" } };");
|
||||
};
|
||||
|
||||
auto append_units = [&](String name, auto const& units) {
|
||||
generator.set("name", name);
|
||||
generator.set("size", String::number(units.size()));
|
||||
|
||||
generator.append(R"~~~(
|
||||
static constexpr Array<Unit, @size@> @name@ { {)~~~");
|
||||
|
||||
bool first = true;
|
||||
for (auto const& unit : units) {
|
||||
generator.set("unit"sv, String::number(unit.value.unit));
|
||||
generator.set("long_formats"sv, String::number(unit.value.long_formats));
|
||||
generator.set("short_formats"sv, String::number(unit.value.short_formats));
|
||||
generator.set("narrow_formats"sv, String::number(unit.value.narrow_formats));
|
||||
|
||||
generator.append(first ? " " : ", ");
|
||||
generator.append("{ @unit@, @long_formats@, @short_formats@, @narrow_formats@ }");
|
||||
first = false;
|
||||
}
|
||||
|
||||
generator.append(" } };");
|
||||
};
|
||||
|
||||
generate_mapping(generator, locale_data.locales, s_number_system_index_type, "s_locale_number_systems"sv, "s_number_systems_{}", [&](auto const& name, auto const& value) { append_map(name, s_number_system_index_type, value.number_systems); });
|
||||
generate_mapping(generator, locale_data.locales, "Unit"sv, "s_units"sv, "s_units_{}", [&](auto const& name, auto const& value) { append_units(name, value.units); });
|
||||
generate_mapping(generator, locale_data.locales, s_unit_index_type, "s_locale_units"sv, "s_units_{}", [&](auto const& name, auto const& value) { append_map(name, s_unit_index_type, value.units); });
|
||||
|
||||
generator.append(R"~~~(
|
||||
static NumberSystem const* find_number_system(StringView locale, StringView system)
|
||||
|
@ -947,9 +972,11 @@ static Unit const* find_units(StringView locale, StringView unit)
|
|||
return nullptr;
|
||||
|
||||
auto locale_index = to_underlying(*locale_value) - 1; // Subtract 1 because 0 == Locale::None.
|
||||
auto const& locale_units = s_units.at(locale_index);
|
||||
auto const& locale_units = s_locale_units.at(locale_index);
|
||||
|
||||
for (auto unit_index : locale_units) {
|
||||
auto const& units = s_units.at(unit_index);
|
||||
|
||||
for (auto const& units : locale_units) {
|
||||
if (unit == s_string_list[units.unit])
|
||||
return &units;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue