Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef intl_components_PluralRules_h_
#define intl_components_PluralRules_h_
#include <string_view>
#include <utility>
#include "mozilla/intl/ICUError.h"
#include "mozilla/intl/NumberFormat.h"
#include "mozilla/intl/NumberRangeFormat.h"
#include "mozilla/EnumSet.h"
#include "mozilla/Maybe.h"
#include "mozilla/Result.h"
#include "mozilla/Span.h"
#include "unicode/utypes.h"
namespace mozilla::intl {
class PluralRules final {
public:
/**
* The set of keywords that a PluralRules object uses.
*
*/
enum class Keyword : uint8_t {
Few,
Many,
One,
Other,
Two,
Zero,
};
/**
* The two different types of PluralRules objects that can be created.
*
*/
enum class Type : uint8_t {
Cardinal,
Ordinal,
};
PluralRules(const PluralRules&) = delete;
PluralRules& operator=(const PluralRules&) = delete;
/**
* Attempts to construct a PluralRules with the given locale and options.
*/
// TODO(1709880) use mozilla::Span instead of std::string_view.
static Result<UniquePtr<PluralRules>, ICUError> TryCreate(
std::string_view aLocale, const PluralRulesOptions& aOptions);
/**
* Returns the PluralRules keyword that corresponds to the |aNumber|.
*
*/
Result<PluralRules::Keyword, ICUError> Select(double aNumber) const;
/**
* Returns the PluralRules keyword that corresponds to the range from |aStart|
* to |aEnd|.
*
*/
Result<PluralRules::Keyword, ICUError> SelectRange(double aStart,
double aEnd) const;
/**
* Returns an EnumSet with the plural-rules categories that are supported by
* the locale that the PluralRules instance was created with.
*/
Result<EnumSet<PluralRules::Keyword>, ICUError> Categories() const;
~PluralRules();
private:
// The longest keyword is "other"
static const size_t MAX_KEYWORD_LENGTH = 5;
UPluralRules* mPluralRules = nullptr;
UniquePtr<NumberFormat> mNumberFormat;
UniquePtr<NumberRangeFormat> mNumberRangeFormat;
PluralRules(UPluralRules*&, UniquePtr<NumberFormat>&&,
UniquePtr<NumberRangeFormat>&&);
/**
* Returns the PluralRules::Keyword that matches the UTF-16 string.
* Strings must be [u"few", u"many", u"one", u"other", u"two", u"zero"]
*/
static PluralRules::Keyword KeywordFromUtf16(Span<const char16_t> aKeyword);
/**
* Returns the PluralRules::Keyword that matches the ASCII string.
* Strings must be ["few", "many", "one", "other", "two", "zero"]
*/
static PluralRules::Keyword KeywordFromAscii(Span<const char> aKeyword);
};
/**
* Options required for constructing a PluralRules object.
*/
struct MOZ_STACK_CLASS PluralRulesOptions {
/**
* Creates a NumberFormatOptions from the PluralRulesOptions.
*/
NumberFormatOptions ToNumberFormatOptions() const {
NumberFormatOptions options;
options.mRoundingMode = NumberFormatOptions::RoundingMode::HalfExpand;
if (mFractionDigits.isSome()) {
options.mFractionDigits.emplace(mFractionDigits.ref());
}
if (mMinIntegerDigits.isSome()) {
options.mMinIntegerDigits.emplace(mMinIntegerDigits.ref());
}
if (mSignificantDigits.isSome()) {
options.mSignificantDigits.emplace(mSignificantDigits.ref());
}
options.mStripTrailingZero = mStripTrailingZero;
options.mRoundingIncrement = mRoundingIncrement;
options.mRoundingMode = NumberFormatOptions::RoundingMode(mRoundingMode);
options.mRoundingPriority =
NumberFormatOptions::RoundingPriority(mRoundingPriority);
return options;
}
/**
* Creates a NumberFormatOptions from the PluralRulesOptions.
*/
NumberRangeFormatOptions ToNumberRangeFormatOptions() const {
NumberRangeFormatOptions options;
options.mRoundingMode = NumberRangeFormatOptions::RoundingMode::HalfExpand;
options.mRangeCollapse = NumberRangeFormatOptions::RangeCollapse::None;
options.mRangeIdentityFallback =
NumberRangeFormatOptions::RangeIdentityFallback::Range;
if (mFractionDigits.isSome()) {
options.mFractionDigits.emplace(mFractionDigits.ref());
}
if (mMinIntegerDigits.isSome()) {
options.mMinIntegerDigits.emplace(mMinIntegerDigits.ref());
}
if (mSignificantDigits.isSome()) {
options.mSignificantDigits.emplace(mSignificantDigits.ref());
}
options.mStripTrailingZero = mStripTrailingZero;
options.mRoundingIncrement = mRoundingIncrement;
options.mRoundingMode = NumberFormatOptions::RoundingMode(mRoundingMode);
options.mRoundingPriority =
NumberFormatOptions::RoundingPriority(mRoundingPriority);
return options;
}
/**
* Set the plural type between cardinal and ordinal.
*
*/
PluralRules::Type mPluralType = PluralRules::Type::Cardinal;
/**
* Set the minimum number of integer digits. |min| must be a non-zero
* number.
*
*/
Maybe<uint32_t> mMinIntegerDigits;
/**
* Set the fraction digits settings. |min| can be zero, |max| must be
* larger-or-equal to |min|.
*
*/
Maybe<std::pair<uint32_t, uint32_t>> mFractionDigits;
/**
* Set the significant digits settings. |min| must be a non-zero number, |max|
* must be larger-or-equal to |min|.
*
*/
Maybe<std::pair<uint32_t, uint32_t>> mSignificantDigits;
/**
* Set to true to strip trailing zeros after the decimal point for integer
* values.
*/
bool mStripTrailingZero = false;
/**
* Set the rounding increment, which must be a non-zero number.
*/
uint32_t mRoundingIncrement = 1;
/**
* Set the rounding mode.
*/
using RoundingMode = NumberFormatOptions::RoundingMode;
RoundingMode mRoundingMode = RoundingMode::HalfExpand;
/**
* Set the rounding priority. |mFractionDigits| and |mSignificantDigits| must
* both be set if the rounding priority isn't equal to "auto".
*/
using RoundingPriority = NumberFormatOptions::RoundingPriority;
RoundingPriority mRoundingPriority = RoundingPriority::Auto;
};
} // namespace mozilla::intl
#endif