tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PluralRules.cpp (5201B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "mozilla/intl/PluralRules.h"
      6 
      7 #include "mozilla/intl/ICU4CGlue.h"
      8 #include "mozilla/intl/NumberFormat.h"
      9 #include "mozilla/intl/NumberRangeFormat.h"
     10 #include "mozilla/Span.h"
     11 #include "ScopedICUObject.h"
     12 
     13 #include "unicode/unum.h"
     14 #include "unicode/upluralrules.h"
     15 #include "unicode/ustring.h"
     16 
     17 namespace mozilla::intl {
     18 
     19 PluralRules::PluralRules(UPluralRules*& aPluralRules,
     20                         UniquePtr<NumberFormat>&& aNumberFormat,
     21                         UniquePtr<NumberRangeFormat>&& aNumberRangeFormat)
     22    : mPluralRules(aPluralRules),
     23      mNumberFormat(std::move(aNumberFormat)),
     24      mNumberRangeFormat(std::move(aNumberRangeFormat)) {
     25  MOZ_ASSERT(aPluralRules);
     26  aPluralRules = nullptr;
     27 }
     28 
     29 Result<UniquePtr<PluralRules>, ICUError> PluralRules::TryCreate(
     30    const std::string_view aLocale, const PluralRulesOptions& aOptions) {
     31  auto numberFormat =
     32      NumberFormat::TryCreate(aLocale, aOptions.ToNumberFormatOptions());
     33 
     34  if (numberFormat.isErr()) {
     35    return Err(numberFormat.unwrapErr());
     36  }
     37 
     38  auto numberRangeFormat = NumberRangeFormat::TryCreate(
     39      aLocale, aOptions.ToNumberRangeFormatOptions());
     40 
     41  if (numberRangeFormat.isErr()) {
     42    return Err(numberRangeFormat.unwrapErr());
     43  }
     44 
     45  UErrorCode status = U_ZERO_ERROR;
     46  auto pluralType = aOptions.mPluralType == PluralRules::Type::Cardinal
     47                        ? UPLURAL_TYPE_CARDINAL
     48                        : UPLURAL_TYPE_ORDINAL;
     49  UPluralRules* pluralRules = uplrules_openForType(
     50      AssertNullTerminatedString(aLocale), pluralType, &status);
     51 
     52  if (U_FAILURE(status)) {
     53    return Err(ToICUError(status));
     54  }
     55 
     56  return UniquePtr<PluralRules>(new PluralRules(
     57      pluralRules, numberFormat.unwrap(), numberRangeFormat.unwrap()));
     58 }
     59 
     60 Result<PluralRules::Keyword, ICUError> PluralRules::Select(
     61    const double aNumber) const {
     62  char16_t keyword[MAX_KEYWORD_LENGTH];
     63 
     64  auto lengthResult = mNumberFormat->selectFormatted(
     65      aNumber, keyword, MAX_KEYWORD_LENGTH, mPluralRules);
     66 
     67  if (lengthResult.isErr()) {
     68    return Err(lengthResult.unwrapErr());
     69  }
     70 
     71  return KeywordFromUtf16(Span(keyword, lengthResult.unwrap()));
     72 }
     73 
     74 Result<PluralRules::Keyword, ICUError> PluralRules::SelectRange(
     75    double aStart, double aEnd) const {
     76  char16_t keyword[MAX_KEYWORD_LENGTH];
     77 
     78  auto lengthResult = mNumberRangeFormat->selectForRange(
     79      aStart, aEnd, keyword, MAX_KEYWORD_LENGTH, mPluralRules);
     80 
     81  if (lengthResult.isErr()) {
     82    return Err(lengthResult.unwrapErr());
     83  }
     84 
     85  return KeywordFromUtf16(Span(keyword, lengthResult.unwrap()));
     86 }
     87 
     88 Result<EnumSet<PluralRules::Keyword>, ICUError> PluralRules::Categories()
     89    const {
     90  UErrorCode status = U_ZERO_ERROR;
     91  UEnumeration* enumeration = uplrules_getKeywords(mPluralRules, &status);
     92  if (U_FAILURE(status)) {
     93    return Err(ToICUError(status));
     94  }
     95 
     96  ScopedICUObject<UEnumeration, uenum_close> closeEnum(enumeration);
     97  EnumSet<PluralRules::Keyword> set;
     98 
     99  while (true) {
    100    int32_t keywordLength;
    101    const char* keyword = uenum_next(enumeration, &keywordLength, &status);
    102    if (U_FAILURE(status)) {
    103      return Err(ToICUError(status));
    104    }
    105 
    106    if (!keyword) {
    107      break;
    108    }
    109 
    110    set += KeywordFromAscii(Span(keyword, keywordLength));
    111  }
    112 
    113  return set;
    114 }
    115 
    116 PluralRules::Keyword PluralRules::KeywordFromUtf16(
    117    Span<const char16_t> aKeyword) {
    118  static constexpr auto kZero = MakeStringSpan(u"zero");
    119  static constexpr auto kOne = MakeStringSpan(u"one");
    120  static constexpr auto kTwo = MakeStringSpan(u"two");
    121  static constexpr auto kFew = MakeStringSpan(u"few");
    122  static constexpr auto kMany = MakeStringSpan(u"many");
    123 
    124  if (aKeyword == kZero) {
    125    return PluralRules::Keyword::Zero;
    126  }
    127  if (aKeyword == kOne) {
    128    return PluralRules::Keyword::One;
    129  }
    130  if (aKeyword == kTwo) {
    131    return PluralRules::Keyword::Two;
    132  }
    133  if (aKeyword == kFew) {
    134    return PluralRules::Keyword::Few;
    135  }
    136  if (aKeyword == kMany) {
    137    return PluralRules::Keyword::Many;
    138  }
    139 
    140  MOZ_ASSERT(aKeyword == MakeStringSpan(u"other"));
    141  return PluralRules::Keyword::Other;
    142 }
    143 
    144 PluralRules::Keyword PluralRules::KeywordFromAscii(Span<const char> aKeyword) {
    145  static constexpr auto kZero = MakeStringSpan("zero");
    146  static constexpr auto kOne = MakeStringSpan("one");
    147  static constexpr auto kTwo = MakeStringSpan("two");
    148  static constexpr auto kFew = MakeStringSpan("few");
    149  static constexpr auto kMany = MakeStringSpan("many");
    150 
    151  if (aKeyword == kZero) {
    152    return PluralRules::Keyword::Zero;
    153  }
    154  if (aKeyword == kOne) {
    155    return PluralRules::Keyword::One;
    156  }
    157  if (aKeyword == kTwo) {
    158    return PluralRules::Keyword::Two;
    159  }
    160  if (aKeyword == kFew) {
    161    return PluralRules::Keyword::Few;
    162  }
    163  if (aKeyword == kMany) {
    164    return PluralRules::Keyword::Many;
    165  }
    166 
    167  MOZ_ASSERT(aKeyword == MakeStringSpan("other"));
    168  return PluralRules::Keyword::Other;
    169 }
    170 
    171 PluralRules::~PluralRules() {
    172  if (mPluralRules) {
    173    uplrules_close(mPluralRules);
    174    mPluralRules = nullptr;
    175  }
    176 }
    177 
    178 }  // namespace mozilla::intl