PluralRules.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Assertions.h>
  8. #include <AK/StringView.h>
  9. #include <AK/Types.h>
  10. #include <LibUnicode/Forward.h>
  11. namespace Unicode {
  12. enum class PluralForm {
  13. Cardinal,
  14. Ordinal,
  15. };
  16. enum class PluralCategory : u8 {
  17. Other,
  18. Zero,
  19. One,
  20. Two,
  21. Few,
  22. Many,
  23. // https://unicode.org/reports/tr35/tr35-numbers.html#Explicit_0_1_rules
  24. ExactlyZero,
  25. ExactlyOne,
  26. };
  27. // https://unicode.org/reports/tr35/tr35-numbers.html#Plural_Operand_Meanings
  28. struct PluralOperands {
  29. static constexpr StringView symbol_to_variable_name(char symbol)
  30. {
  31. if (symbol == 'n')
  32. return "number"sv;
  33. if (symbol == 'i')
  34. return "integer_digits"sv;
  35. if (symbol == 'f')
  36. return "fraction_digits"sv;
  37. if (symbol == 'v')
  38. return "number_of_fraction_digits"sv;
  39. if (symbol == 't')
  40. return "fraction_digits_without_trailing"sv;
  41. if (symbol == 'w')
  42. return "number_of_fraction_digits_without_trailing"sv;
  43. VERIFY_NOT_REACHED();
  44. }
  45. static constexpr bool symbol_requires_floating_point_modulus(char symbol)
  46. {
  47. // From TR-35: "The modulus (% or mod) is a remainder operation as defined in Java; for
  48. // example, where n = 4.3 the result of n mod 3 is 1.3."
  49. //
  50. // So, this returns whether the symbol represents a decimal value, and thus requires fmod.
  51. return symbol == 'n';
  52. }
  53. double number { 0 };
  54. u64 integer_digits { 0 };
  55. u64 fraction_digits { 0 };
  56. u64 number_of_fraction_digits { 0 };
  57. u64 fraction_digits_without_trailing { 0 };
  58. u64 number_of_fraction_digits_without_trailing { 0 };
  59. };
  60. PluralForm plural_form_from_string(StringView plural_form);
  61. StringView plural_form_to_string(PluralForm plural_form);
  62. // NOTE: This must be defined inline to be callable from the code generators.
  63. constexpr PluralCategory plural_category_from_string(StringView category)
  64. {
  65. if (category == "other"sv)
  66. return PluralCategory::Other;
  67. if (category == "zero"sv)
  68. return PluralCategory::Zero;
  69. if (category == "one"sv)
  70. return PluralCategory::One;
  71. if (category == "two"sv)
  72. return PluralCategory::Two;
  73. if (category == "few"sv)
  74. return PluralCategory::Few;
  75. if (category == "many"sv)
  76. return PluralCategory::Many;
  77. if (category == "0"sv)
  78. return PluralCategory::ExactlyZero;
  79. if (category == "1"sv)
  80. return PluralCategory::ExactlyOne;
  81. VERIFY_NOT_REACHED();
  82. }
  83. // NOTE: This must be defined inline to be callable from the code generators.
  84. constexpr StringView plural_category_to_string(PluralCategory category)
  85. {
  86. switch (category) {
  87. case PluralCategory::Other:
  88. return "other"sv;
  89. case PluralCategory::Zero:
  90. return "zero"sv;
  91. case PluralCategory::One:
  92. return "one"sv;
  93. case PluralCategory::Two:
  94. return "two"sv;
  95. case PluralCategory::Few:
  96. return "few"sv;
  97. case PluralCategory::Many:
  98. return "many"sv;
  99. case PluralCategory::ExactlyZero:
  100. return "0"sv;
  101. case PluralCategory::ExactlyOne:
  102. return "1"sv;
  103. }
  104. VERIFY_NOT_REACHED();
  105. }
  106. PluralCategory determine_plural_category(StringView locale, PluralForm form, PluralOperands operands);
  107. Span<PluralCategory const> available_plural_categories(StringView locale, PluralForm form);
  108. PluralCategory determine_plural_range(StringView locale, PluralCategory start, PluralCategory end);
  109. }