Просмотр исходного кода

LibUnicode: Replace NumberFormat::Plurality with Unicode::PluralCategory

To prepare for using plural rules within number & duration format, this
removes the NumberFormat::Plurality enumeration.

This also adds PluralCategory::ExactlyZero & PluralCategory::ExactlyOne.
These are used in locales like French, where PluralCategory::One really
means any value from 0.00 to 1.99. PluralCategory::ExactlyOne means only
the value 1, as the name implies. These exact rules are not known by the
general plural rules, they are explicitly for number / currency format.
Timothy Flynn 3 лет назад
Родитель
Сommit
232df4196b

+ 7 - 24
Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeNumberFormat.cpp

@@ -29,6 +29,7 @@
 #include <LibJS/Runtime/Intl/AbstractOperations.h>
 #include <LibUnicode/Locale.h>
 #include <LibUnicode/NumberFormat.h>
+#include <LibUnicode/PluralRules.h>
 #include <math.h>
 
 using StringIndexType = u16;
@@ -57,29 +58,10 @@ enum class NumberFormatType {
 struct NumberFormat : public Unicode::NumberFormat {
     using Base = Unicode::NumberFormat;
 
-    static Base::Plurality plurality_from_string(StringView plurality)
-    {
-        if (plurality == "other"sv)
-            return Base::Plurality::Other;
-        if (plurality == "1"sv)
-            return Base::Plurality::Single;
-        if (plurality == "zero"sv)
-            return Base::Plurality::Zero;
-        if (plurality == "one"sv)
-            return Base::Plurality::One;
-        if (plurality == "two"sv)
-            return Base::Plurality::Two;
-        if (plurality == "few"sv)
-            return Base::Plurality::Few;
-        if (plurality == "many"sv)
-            return Base::Plurality::Many;
-        VERIFY_NOT_REACHED();
-    }
-
     unsigned hash() const
     {
         auto hash = pair_int_hash(magnitude, exponent);
-        hash = pair_int_hash(hash, static_cast<u8>(plurality));
+        hash = pair_int_hash(hash, to_underlying(plurality));
         hash = pair_int_hash(hash, zero_format_index);
         hash = pair_int_hash(hash, positive_format_index);
         hash = pair_int_hash(hash, negative_format_index);
@@ -118,7 +100,7 @@ struct AK::Formatter<NumberFormat> : Formatter<FormatString> {
             "{{ {}, {}, {}, {}, {}, {}, {{ {} }} }}",
             format.magnitude,
             format.exponent,
-            static_cast<u8>(format.plurality),
+            to_underlying(format.plurality),
             format.zero_format_index,
             format.positive_format_index,
             format.negative_format_index,
@@ -496,7 +478,7 @@ static ErrorOr<void> parse_number_systems(String locale_numbers_path, UnicodeLoc
                 VERIFY(split_key[0] == "unitPattern"sv);
             }
 
-            format.plurality = NumberFormat::plurality_from_string(split_key[2]);
+            format.plurality = Unicode::plural_category_from_string(split_key[2]);
             parse_number_pattern(move(patterns), locale_data, NumberFormatType::Compact, format);
 
             auto format_index = locale_data.unique_formats.ensure(move(format));
@@ -675,7 +657,7 @@ static ErrorOr<void> parse_units(String locale_units_path, UnicodeLocaleData& lo
                 NumberFormat format {};
 
                 auto plurality = unit_key.substring_view(unit_pattern_prefix.length());
-                format.plurality = NumberFormat::plurality_from_string(plurality);
+                format.plurality = Unicode::plural_category_from_string(plurality);
 
                 auto zero_format = pattern_value.as_string().replace("{0}"sv, "{number}"sv, ReplaceMode::FirstOnly);
                 zero_format = parse_identifiers(zero_format, "unitIdentifier"sv, locale_data, format);
@@ -807,6 +789,7 @@ static ErrorOr<void> generate_unicode_locale_implementation(Core::Stream::Buffer
 #include <AK/Vector.h>
 #include <LibUnicode/Locale.h>
 #include <LibUnicode/NumberFormat.h>
+#include <LibUnicode/PluralRules.h>
 #include <LibUnicode/UnicodeLocale.h>
 #include <LibUnicode/UnicodeNumberFormat.h>
 
@@ -822,7 +805,7 @@ struct NumberFormatImpl {
 
         number_format.magnitude = magnitude;
         number_format.exponent = exponent;
-        number_format.plurality = static_cast<NumberFormat::Plurality>(plurality);
+        number_format.plurality = static_cast<PluralCategory>(plurality);
         number_format.zero_format = s_string_list[zero_format];
         number_format.positive_format = s_string_list[positive_format];
         number_format.negative_format = s_string_list[negative_format];

+ 7 - 16
Userland/Libraries/LibUnicode/NumberFormat.h

@@ -11,6 +11,7 @@
 #include <AK/StringView.h>
 #include <AK/Vector.h>
 #include <LibUnicode/Forward.h>
+#include <LibUnicode/PluralRules.h>
 
 namespace Unicode {
 
@@ -36,19 +37,9 @@ enum class CompactNumberFormatType : u8 {
 };
 
 struct NumberFormat {
-    enum class Plurality : u8 {
-        Other,
-        Zero,
-        Single,
-        One,
-        Two,
-        Few,
-        Many,
-    };
-
     u8 magnitude { 0 };
     u8 exponent { 0 };
-    Plurality plurality { Plurality::Other };
+    PluralCategory plurality { PluralCategory::Other };
     StringView zero_format {};
     StringView positive_format {};
     StringView negative_format {};
@@ -94,20 +85,20 @@ Optional<FormatType> select_pattern_with_plurality(Vector<FormatType> const& for
     };
 
     if (number == 0) {
-        if (auto patterns = find_plurality(FormatType::Plurality::Zero); patterns.has_value())
+        if (auto patterns = find_plurality(PluralCategory::Zero); patterns.has_value())
             return patterns;
     } else if (number == 1) {
-        if (auto patterns = find_plurality(FormatType::Plurality::One); patterns.has_value())
+        if (auto patterns = find_plurality(PluralCategory::One); patterns.has_value())
             return patterns;
     } else if (number == 2) {
-        if (auto patterns = find_plurality(FormatType::Plurality::Two); patterns.has_value())
+        if (auto patterns = find_plurality(PluralCategory::Two); patterns.has_value())
             return patterns;
     } else if (number > 2) {
-        if (auto patterns = find_plurality(FormatType::Plurality::Many); patterns.has_value())
+        if (auto patterns = find_plurality(PluralCategory::Many); patterns.has_value())
             return patterns;
     }
 
-    return find_plurality(FormatType::Plurality::Other);
+    return find_plurality(PluralCategory::Other);
 }
 
 }

+ 12 - 0
Userland/Libraries/LibUnicode/PluralRules.h

@@ -25,6 +25,10 @@ enum class PluralCategory : u8 {
     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
@@ -81,6 +85,10 @@ constexpr PluralCategory plural_category_from_string(StringView category)
         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();
 }
 
@@ -100,6 +108,10 @@ constexpr StringView plural_category_to_string(PluralCategory category)
         return "few"sv;
     case PluralCategory::Many:
         return "many"sv;
+    case PluralCategory::ExactlyZero:
+        return "0"sv;
+    case PluralCategory::ExactlyOne:
+        return "1"sv;
     }
 
     VERIFY_NOT_REACHED();