From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Fri, 19 Apr 2024 02:47:55 +0200
Subject: Adding upstream version 124.0.1.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 intl/components/src/PluralRules.cpp | 180 ++++++++++++++++++++++++++++++++++++
 1 file changed, 180 insertions(+)
 create mode 100644 intl/components/src/PluralRules.cpp

(limited to 'intl/components/src/PluralRules.cpp')

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
-- 
cgit v1.2.3