Coverage Report

Created: 2025-08-28 06:26

/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
}