diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /intl/components/src/PluralRules.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'intl/components/src/PluralRules.cpp')
-rw-r--r-- | intl/components/src/PluralRules.cpp | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/intl/components/src/PluralRules.cpp b/intl/components/src/PluralRules.cpp new file mode 100644 index 0000000000..891ca45769 --- /dev/null +++ b/intl/components/src/PluralRules.cpp @@ -0,0 +1,180 @@ +/* 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/. */ + +#include "mozilla/intl/PluralRules.h" + +#include "mozilla/intl/ICU4CGlue.h" +#include "mozilla/intl/NumberFormat.h" +#include "mozilla/intl/NumberRangeFormat.h" +#include "mozilla/Utf8.h" +#include "mozilla/PodOperations.h" +#include "mozilla/Span.h" +#include "ScopedICUObject.h" + +#include "unicode/unum.h" +#include "unicode/upluralrules.h" +#include "unicode/ustring.h" + +namespace mozilla::intl { + +PluralRules::PluralRules(UPluralRules*& aPluralRules, + UniquePtr<NumberFormat>&& aNumberFormat, + UniquePtr<NumberRangeFormat>&& aNumberRangeFormat) + : mPluralRules(aPluralRules), + mNumberFormat(std::move(aNumberFormat)), + mNumberRangeFormat(std::move(aNumberRangeFormat)) { + MOZ_ASSERT(aPluralRules); + aPluralRules = nullptr; +} + +Result<UniquePtr<PluralRules>, ICUError> PluralRules::TryCreate( + const std::string_view aLocale, const PluralRulesOptions& aOptions) { + auto numberFormat = + NumberFormat::TryCreate(aLocale, aOptions.ToNumberFormatOptions()); + + if (numberFormat.isErr()) { + return Err(numberFormat.unwrapErr()); + } + + auto numberRangeFormat = NumberRangeFormat::TryCreate( + aLocale, aOptions.ToNumberRangeFormatOptions()); + + if (numberRangeFormat.isErr()) { + return Err(numberRangeFormat.unwrapErr()); + } + + UErrorCode status = U_ZERO_ERROR; + auto pluralType = aOptions.mPluralType == PluralRules::Type::Cardinal + ? UPLURAL_TYPE_CARDINAL + : UPLURAL_TYPE_ORDINAL; + UPluralRules* pluralRules = uplrules_openForType( + AssertNullTerminatedString(aLocale), pluralType, &status); + + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + + return UniquePtr<PluralRules>(new PluralRules( + pluralRules, numberFormat.unwrap(), numberRangeFormat.unwrap())); +} + +Result<PluralRules::Keyword, ICUError> PluralRules::Select( + const double aNumber) const { + char16_t keyword[MAX_KEYWORD_LENGTH]; + + auto lengthResult = mNumberFormat->selectFormatted( + aNumber, keyword, MAX_KEYWORD_LENGTH, mPluralRules); + + if (lengthResult.isErr()) { + return Err(lengthResult.unwrapErr()); + } + + return KeywordFromUtf16(Span(keyword, lengthResult.unwrap())); +} + +Result<PluralRules::Keyword, ICUError> PluralRules::SelectRange( + double aStart, double aEnd) const { + char16_t keyword[MAX_KEYWORD_LENGTH]; + + auto lengthResult = mNumberRangeFormat->selectForRange( + aStart, aEnd, keyword, MAX_KEYWORD_LENGTH, mPluralRules); + + if (lengthResult.isErr()) { + return Err(lengthResult.unwrapErr()); + } + + return KeywordFromUtf16(Span(keyword, lengthResult.unwrap())); +} + +Result<EnumSet<PluralRules::Keyword>, ICUError> PluralRules::Categories() + const { + UErrorCode status = U_ZERO_ERROR; + UEnumeration* enumeration = uplrules_getKeywords(mPluralRules, &status); + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + + ScopedICUObject<UEnumeration, uenum_close> closeEnum(enumeration); + EnumSet<PluralRules::Keyword> set; + + while (true) { + int32_t keywordLength; + const char* keyword = uenum_next(enumeration, &keywordLength, &status); + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + + if (!keyword) { + break; + } + + set += KeywordFromAscii(Span(keyword, keywordLength)); + } + + return set; +} + +PluralRules::Keyword PluralRules::KeywordFromUtf16( + Span<const char16_t> aKeyword) { + static constexpr auto kZero = MakeStringSpan(u"zero"); + static constexpr auto kOne = MakeStringSpan(u"one"); + static constexpr auto kTwo = MakeStringSpan(u"two"); + static constexpr auto kFew = MakeStringSpan(u"few"); + static constexpr auto kMany = MakeStringSpan(u"many"); + + if (aKeyword == kZero) { + return PluralRules::Keyword::Zero; + } + if (aKeyword == kOne) { + return PluralRules::Keyword::One; + } + if (aKeyword == kTwo) { + return PluralRules::Keyword::Two; + } + if (aKeyword == kFew) { + return PluralRules::Keyword::Few; + } + if (aKeyword == kMany) { + return PluralRules::Keyword::Many; + } + + MOZ_ASSERT(aKeyword == MakeStringSpan(u"other")); + return PluralRules::Keyword::Other; +} + +PluralRules::Keyword PluralRules::KeywordFromAscii(Span<const char> aKeyword) { + static constexpr auto kZero = MakeStringSpan("zero"); + static constexpr auto kOne = MakeStringSpan("one"); + static constexpr auto kTwo = MakeStringSpan("two"); + static constexpr auto kFew = MakeStringSpan("few"); + static constexpr auto kMany = MakeStringSpan("many"); + + if (aKeyword == kZero) { + return PluralRules::Keyword::Zero; + } + if (aKeyword == kOne) { + return PluralRules::Keyword::One; + } + if (aKeyword == kTwo) { + return PluralRules::Keyword::Two; + } + if (aKeyword == kFew) { + return PluralRules::Keyword::Few; + } + if (aKeyword == kMany) { + return PluralRules::Keyword::Many; + } + + MOZ_ASSERT(aKeyword == MakeStringSpan("other")); + return PluralRules::Keyword::Other; +} + +PluralRules::~PluralRules() { + if (mPluralRules) { + uplrules_close(mPluralRules); + mPluralRules = nullptr; + } +} + +} // namespace mozilla::intl |