PluralRules.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. };
  24. // https://unicode.org/reports/tr35/tr35-numbers.html#Plural_Operand_Meanings
  25. struct PluralOperands {
  26. static constexpr StringView symbol_to_variable_name(char symbol)
  27. {
  28. if (symbol == 'n')
  29. return "number"sv;
  30. if (symbol == 'i')
  31. return "integer_digits"sv;
  32. if (symbol == 'f')
  33. return "fraction_digits"sv;
  34. if (symbol == 'v')
  35. return "number_of_fraction_digits"sv;
  36. if (symbol == 't')
  37. return "fraction_digits_without_trailing"sv;
  38. if (symbol == 'w')
  39. return "number_of_fraction_digits_without_trailing"sv;
  40. VERIFY_NOT_REACHED();
  41. }
  42. static constexpr bool symbol_requires_floating_point_modulus(char symbol)
  43. {
  44. // From TR-35: "The modulus (% or mod) is a remainder operation as defined in Java; for
  45. // example, where n = 4.3 the result of n mod 3 is 1.3."
  46. //
  47. // So, this returns whether the symbol represents a decimal value, and thus requires fmod.
  48. return symbol == 'n';
  49. }
  50. double number { 0 };
  51. u64 integer_digits { 0 };
  52. u64 fraction_digits { 0 };
  53. u64 number_of_fraction_digits { 0 };
  54. u64 fraction_digits_without_trailing { 0 };
  55. u64 number_of_fraction_digits_without_trailing { 0 };
  56. };
  57. PluralForm plural_form_from_string(StringView plural_form);
  58. StringView plural_form_to_string(PluralForm plural_form);
  59. // NOTE: This must be defined inline to be callable from the code generators.
  60. constexpr PluralCategory plural_category_from_string(StringView category)
  61. {
  62. if (category == "other"sv)
  63. return PluralCategory::Other;
  64. if (category == "zero"sv)
  65. return PluralCategory::Zero;
  66. if (category == "one"sv)
  67. return PluralCategory::One;
  68. if (category == "two"sv)
  69. return PluralCategory::Two;
  70. if (category == "few"sv)
  71. return PluralCategory::Few;
  72. if (category == "many"sv)
  73. return PluralCategory::Many;
  74. VERIFY_NOT_REACHED();
  75. }
  76. // NOTE: This must be defined inline to be callable from the code generators.
  77. constexpr StringView plural_category_to_string(PluralCategory category)
  78. {
  79. switch (category) {
  80. case PluralCategory::Other:
  81. return "other"sv;
  82. case PluralCategory::Zero:
  83. return "zero"sv;
  84. case PluralCategory::One:
  85. return "one"sv;
  86. case PluralCategory::Two:
  87. return "two"sv;
  88. case PluralCategory::Few:
  89. return "few"sv;
  90. case PluralCategory::Many:
  91. return "many"sv;
  92. }
  93. VERIFY_NOT_REACHED();
  94. }
  95. PluralCategory determine_plural_category(StringView locale, PluralForm form, PluralOperands operands);
  96. Span<PluralCategory const> available_plural_categories(StringView locale, PluralForm form);
  97. }