summaryrefslogtreecommitdiffstats
path: root/intl/components/src/PluralRules.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /intl/components/src/PluralRules.cpp
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.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.cpp180
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