tor-browser

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

PluralRules.h (6868B)


      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 #ifndef intl_components_PluralRules_h_
      6 #define intl_components_PluralRules_h_
      7 
      8 #include <string_view>
      9 #include <utility>
     10 
     11 #include "mozilla/intl/ICUError.h"
     12 #include "mozilla/intl/NumberFormat.h"
     13 #include "mozilla/intl/NumberRangeFormat.h"
     14 #include "mozilla/EnumSet.h"
     15 #include "mozilla/Maybe.h"
     16 #include "mozilla/Result.h"
     17 #include "mozilla/Span.h"
     18 
     19 #include "unicode/utypes.h"
     20 
     21 namespace mozilla::intl {
     22 
     23 class PluralRules final {
     24 public:
     25  /**
     26   * The set of keywords that a PluralRules object uses.
     27   *
     28   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
     29   */
     30  enum class Keyword : uint8_t {
     31    Few,
     32    Many,
     33    One,
     34    Other,
     35    Two,
     36    Zero,
     37  };
     38 
     39  /**
     40   * The two different types of PluralRules objects that can be created.
     41   *
     42   * https://tc39.es/ecma402/#sec-properties-of-intl-pluralrules-instances
     43   */
     44  enum class Type : uint8_t {
     45    Cardinal,
     46    Ordinal,
     47  };
     48 
     49  PluralRules(const PluralRules&) = delete;
     50  PluralRules& operator=(const PluralRules&) = delete;
     51 
     52  /**
     53   * Attempts to construct a PluralRules with the given locale and options.
     54   */
     55  // TODO(1709880) use mozilla::Span instead of std::string_view.
     56  static Result<UniquePtr<PluralRules>, ICUError> TryCreate(
     57      std::string_view aLocale, const PluralRulesOptions& aOptions);
     58 
     59  /**
     60   * Returns the PluralRules keyword that corresponds to the |aNumber|.
     61   *
     62   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.select
     63   */
     64  Result<PluralRules::Keyword, ICUError> Select(double aNumber) const;
     65 
     66  /**
     67   * Returns the PluralRules keyword that corresponds to the range from |aStart|
     68   * to |aEnd|.
     69   *
     70   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.selectrange
     71   */
     72  Result<PluralRules::Keyword, ICUError> SelectRange(double aStart,
     73                                                     double aEnd) const;
     74 
     75  /**
     76   * Returns an EnumSet with the plural-rules categories that are supported by
     77   * the locale that the PluralRules instance was created with.
     78   */
     79  Result<EnumSet<PluralRules::Keyword>, ICUError> Categories() const;
     80 
     81  ~PluralRules();
     82 
     83 private:
     84  // The longest keyword is "other"
     85  static const size_t MAX_KEYWORD_LENGTH = 5;
     86 
     87  UPluralRules* mPluralRules = nullptr;
     88  UniquePtr<NumberFormat> mNumberFormat;
     89  UniquePtr<NumberRangeFormat> mNumberRangeFormat;
     90 
     91  PluralRules(UPluralRules*&, UniquePtr<NumberFormat>&&,
     92              UniquePtr<NumberRangeFormat>&&);
     93 
     94  /**
     95   * Returns the PluralRules::Keyword that matches the UTF-16 string.
     96   * Strings must be [u"few", u"many", u"one", u"other", u"two", u"zero"]
     97   */
     98  static PluralRules::Keyword KeywordFromUtf16(Span<const char16_t> aKeyword);
     99 
    100  /**
    101   * Returns the PluralRules::Keyword that matches the ASCII string.
    102   * Strings must be ["few", "many", "one", "other", "two", "zero"]
    103   */
    104  static PluralRules::Keyword KeywordFromAscii(Span<const char> aKeyword);
    105 };
    106 
    107 /**
    108 * Options required for constructing a PluralRules object.
    109 */
    110 struct MOZ_STACK_CLASS PluralRulesOptions {
    111  /**
    112   * Creates a NumberFormatOptions from the PluralRulesOptions.
    113   */
    114  NumberFormatOptions ToNumberFormatOptions() const {
    115    NumberFormatOptions options;
    116    options.mRoundingMode = NumberFormatOptions::RoundingMode::HalfExpand;
    117 
    118    if (mFractionDigits.isSome()) {
    119      options.mFractionDigits.emplace(mFractionDigits.ref());
    120    }
    121 
    122    if (mMinIntegerDigits.isSome()) {
    123      options.mMinIntegerDigits.emplace(mMinIntegerDigits.ref());
    124    }
    125 
    126    if (mSignificantDigits.isSome()) {
    127      options.mSignificantDigits.emplace(mSignificantDigits.ref());
    128    }
    129 
    130    options.mStripTrailingZero = mStripTrailingZero;
    131 
    132    options.mRoundingIncrement = mRoundingIncrement;
    133 
    134    options.mRoundingMode = NumberFormatOptions::RoundingMode(mRoundingMode);
    135 
    136    options.mRoundingPriority =
    137        NumberFormatOptions::RoundingPriority(mRoundingPriority);
    138 
    139    return options;
    140  }
    141  /**
    142   * Creates a NumberFormatOptions from the PluralRulesOptions.
    143   */
    144  NumberRangeFormatOptions ToNumberRangeFormatOptions() const {
    145    NumberRangeFormatOptions options;
    146    options.mRoundingMode = NumberRangeFormatOptions::RoundingMode::HalfExpand;
    147    options.mRangeCollapse = NumberRangeFormatOptions::RangeCollapse::None;
    148    options.mRangeIdentityFallback =
    149        NumberRangeFormatOptions::RangeIdentityFallback::Range;
    150 
    151    if (mFractionDigits.isSome()) {
    152      options.mFractionDigits.emplace(mFractionDigits.ref());
    153    }
    154 
    155    if (mMinIntegerDigits.isSome()) {
    156      options.mMinIntegerDigits.emplace(mMinIntegerDigits.ref());
    157    }
    158 
    159    if (mSignificantDigits.isSome()) {
    160      options.mSignificantDigits.emplace(mSignificantDigits.ref());
    161    }
    162 
    163    options.mStripTrailingZero = mStripTrailingZero;
    164 
    165    options.mRoundingIncrement = mRoundingIncrement;
    166 
    167    options.mRoundingMode = NumberFormatOptions::RoundingMode(mRoundingMode);
    168 
    169    options.mRoundingPriority =
    170        NumberFormatOptions::RoundingPriority(mRoundingPriority);
    171 
    172    return options;
    173  }
    174 
    175  /**
    176   * Set the plural type between cardinal and ordinal.
    177   *
    178   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
    179   */
    180  PluralRules::Type mPluralType = PluralRules::Type::Cardinal;
    181 
    182  /**
    183   * Set the minimum number of integer digits. |min| must be a non-zero
    184   * number.
    185   *
    186   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
    187   */
    188  Maybe<uint32_t> mMinIntegerDigits;
    189 
    190  /**
    191   * Set the fraction digits settings. |min| can be zero, |max| must be
    192   * larger-or-equal to |min|.
    193   *
    194   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
    195   */
    196  Maybe<std::pair<uint32_t, uint32_t>> mFractionDigits;
    197 
    198  /**
    199   * Set the significant digits settings. |min| must be a non-zero number, |max|
    200   * must be larger-or-equal to |min|.
    201   *
    202   * https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
    203   */
    204  Maybe<std::pair<uint32_t, uint32_t>> mSignificantDigits;
    205 
    206  /**
    207   * Set to true to strip trailing zeros after the decimal point for integer
    208   * values.
    209   */
    210  bool mStripTrailingZero = false;
    211 
    212  /**
    213   * Set the rounding increment, which must be a non-zero number.
    214   */
    215  uint32_t mRoundingIncrement = 1;
    216 
    217  /**
    218   * Set the rounding mode.
    219   */
    220  using RoundingMode = NumberFormatOptions::RoundingMode;
    221  RoundingMode mRoundingMode = RoundingMode::HalfExpand;
    222 
    223  /**
    224   * Set the rounding priority. |mFractionDigits| and |mSignificantDigits| must
    225   * both be set if the rounding priority isn't equal to "auto".
    226   */
    227  using RoundingPriority = NumberFormatOptions::RoundingPriority;
    228  RoundingPriority mRoundingPriority = RoundingPriority::Auto;
    229 };
    230 
    231 }  // namespace mozilla::intl
    232 
    233 #endif