/* * Copyright (c) 2022, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include 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); ReadonlySpan available_plural_categories(StringView locale, PluralForm form); PluralCategory determine_plural_range(StringView locale, PluralCategory start, PluralCategory end); }