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