diff options
Diffstat (limited to 'Userland/Libraries/LibLocale/PluralRules.h')
-rw-r--r-- | Userland/Libraries/LibLocale/PluralRules.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/Userland/Libraries/LibLocale/PluralRules.h b/Userland/Libraries/LibLocale/PluralRules.h new file mode 100644 index 0000000000..0f93234b7f --- /dev/null +++ b/Userland/Libraries/LibLocale/PluralRules.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Assertions.h> +#include <AK/StringView.h> +#include <AK/Types.h> +#include <LibLocale/Forward.h> + +namespace Locale { + +enum class PluralForm { + Cardinal, + Ordinal, +}; + +enum class PluralCategory : u8 { + Other, + Zero, + One, + Two, + Few, + Many, + + // https://unicode.org/reports/tr35/tr35-numbers.html#Explicit_0_1_rules + ExactlyZero, + ExactlyOne, +}; + +// https://unicode.org/reports/tr35/tr35-numbers.html#Plural_Operand_Meanings +struct PluralOperands { + static constexpr StringView symbol_to_variable_name(char symbol) + { + if (symbol == 'n') + return "number"sv; + if (symbol == 'i') + return "integer_digits"sv; + if (symbol == 'f') + return "fraction_digits"sv; + if (symbol == 'v') + return "number_of_fraction_digits"sv; + if (symbol == 't') + return "fraction_digits_without_trailing"sv; + if (symbol == 'w') + return "number_of_fraction_digits_without_trailing"sv; + VERIFY_NOT_REACHED(); + } + + static constexpr bool symbol_requires_floating_point_modulus(char symbol) + { + // From TR-35: "The modulus (% or mod) is a remainder operation as defined in Java; for + // example, where n = 4.3 the result of n mod 3 is 1.3." + // + // So, this returns whether the symbol represents a decimal value, and thus requires fmod. + return symbol == 'n'; + } + + double number { 0 }; + u64 integer_digits { 0 }; + u64 fraction_digits { 0 }; + u64 number_of_fraction_digits { 0 }; + u64 fraction_digits_without_trailing { 0 }; + u64 number_of_fraction_digits_without_trailing { 0 }; +}; + +PluralForm plural_form_from_string(StringView plural_form); +StringView plural_form_to_string(PluralForm plural_form); + +// NOTE: This must be defined inline to be callable from the code generators. +constexpr PluralCategory plural_category_from_string(StringView category) +{ + if (category == "other"sv) + return PluralCategory::Other; + if (category == "zero"sv) + return PluralCategory::Zero; + if (category == "one"sv) + return PluralCategory::One; + if (category == "two"sv) + return PluralCategory::Two; + if (category == "few"sv) + return PluralCategory::Few; + if (category == "many"sv) + return PluralCategory::Many; + if (category == "0"sv) + return PluralCategory::ExactlyZero; + if (category == "1"sv) + return PluralCategory::ExactlyOne; + VERIFY_NOT_REACHED(); +} + +// NOTE: This must be defined inline to be callable from the code generators. +constexpr StringView plural_category_to_string(PluralCategory category) +{ + switch (category) { + case PluralCategory::Other: + return "other"sv; + case PluralCategory::Zero: + return "zero"sv; + case PluralCategory::One: + return "one"sv; + case PluralCategory::Two: + return "two"sv; + case PluralCategory::Few: + return "few"sv; + case PluralCategory::Many: + return "many"sv; + case PluralCategory::ExactlyZero: + return "0"sv; + case PluralCategory::ExactlyOne: + return "1"sv; + } + + VERIFY_NOT_REACHED(); +} + +PluralCategory determine_plural_category(StringView locale, PluralForm form, PluralOperands operands); +Span<PluralCategory const> available_plural_categories(StringView locale, PluralForm form); +PluralCategory determine_plural_range(StringView locale, PluralCategory start, PluralCategory end); + +} |