Bug 1719696 - Rework FillUTF8Buffer to FillBuffer; r=platform-i18n-reviewers,dminor
authorGreg Tatum <tatum.creative@gmail.com>
Mon, 13 Sep 2021 20:53:00 +0000
changeset 591808 9a05f50a92ebd6e5b4a021203380664268ab466d
parent 591807 268ea13a74e762a01bd0fe85049b7e2390ec9d43
child 591809 c36bd08f375226e1cf6f23ecee0d62f3c8b3bcb4
push id38787
push usernbeleuzu@mozilla.com
push dateTue, 14 Sep 2021 14:35:56 +0000
treeherdermozilla-central@ae68c3ee95d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersplatform-i18n-reviewers, dminor
bugs1719696
milestone94.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1719696 - Rework FillUTF8Buffer to FillBuffer; r=platform-i18n-reviewers,dminor Differential Revision: https://phabricator.services.mozilla.com/D125252
intl/components/src/DateTimeFormat.h
intl/components/src/ICU4CGlue.h
intl/components/src/NumberFormat.h
intl/components/src/RelativeTimeFormat.h
--- a/intl/components/src/DateTimeFormat.h
+++ b/intl/components/src/DateTimeFormat.h
@@ -332,17 +332,17 @@ class DateTimeFormat final {
                                       UErrorCode* status) {
             return udat_format(mDateFormat, aUnixEpoch, target, length,
                                /* UFieldPosition* */ nullptr, status);
           });
       if (result.isErr()) {
         return result;
       }
 
-      if (!FillUTF8Buffer(u16Vec, aBuffer)) {
+      if (!FillBuffer(u16Vec, aBuffer)) {
         return Err(ICUError::OutOfMemory);
       }
       return Ok{};
     } else {
       static_assert(std::is_same<typename B::CharType, char16_t>::value);
 
       // The output buffer is UTF-16. ICU can output directly into this buffer.
       return FillBufferWithICUCall(
--- a/intl/components/src/ICU4CGlue.h
+++ b/intl/components/src/ICU4CGlue.h
@@ -166,35 +166,49 @@ static ICUResult FillVectorWithICUCall(V
   return FillBufferWithICUCall(buffer, strFn);
 }
 
 /**
  * ICU4C works with UTF-16 strings, but consumers of mozilla::intl may require
  * UTF-8 strings.
  */
 template <typename Buffer>
-[[nodiscard]] bool FillUTF8Buffer(Span<const char16_t> utf16Span,
-                                  Buffer& utf8TargetBuffer) {
-  static_assert(std::is_same<typename Buffer::CharType, char>::value ||
-                std::is_same<typename Buffer::CharType, unsigned char>::value);
+[[nodiscard]] bool FillBuffer(Span<const char16_t> utf16Span,
+                              Buffer& targetBuffer) {
+  static_assert(std::is_same_v<typename Buffer::CharType, char> ||
+                std::is_same_v<typename Buffer::CharType, unsigned char> ||
+                std::is_same_v<typename Buffer::CharType, char16_t>);
 
-  if (utf16Span.Length() & mozilla::tl::MulOverflowMask<3>::value) {
-    // Tripling the size of the buffer overflows the size_t.
-    return false;
-  }
+  if constexpr (std::is_same_v<typename Buffer::CharType, char> ||
+                std::is_same_v<typename Buffer::CharType, unsigned char>) {
+    if (utf16Span.Length() & mozilla::tl::MulOverflowMask<3>::value) {
+      // Tripling the size of the buffer overflows the size_t.
+      return false;
+    }
+
+    if (!targetBuffer.reserve(3 * utf16Span.Length())) {
+      return false;
+    }
 
-  if (!utf8TargetBuffer.reserve(3 * utf16Span.Length())) {
-    return false;
-  }
+    size_t amount = ConvertUtf16toUtf8(
+        utf16Span, Span(reinterpret_cast<char*>(targetBuffer.data()),
+                        targetBuffer.capacity()));
 
-  size_t amount = ConvertUtf16toUtf8(
-      utf16Span, Span(reinterpret_cast<char*>(utf8TargetBuffer.data()),
-                      utf8TargetBuffer.capacity()));
-
-  utf8TargetBuffer.written(amount);
+    targetBuffer.written(amount);
+  }
+  if constexpr (std::is_same_v<typename Buffer::CharType, char16_t>) {
+    size_t amount = utf16Span.Length();
+    if (!targetBuffer.reserve(amount)) {
+      return false;
+    }
+    for (size_t i = 0; i < amount; i++) {
+      targetBuffer.data()[i] = utf16Span[i];
+    }
+    targetBuffer.written(amount);
+  }
 
   return true;
 }
 
 /**
  * It is convenient for callers to be able to pass in UTF-8 strings to the API.
  * This function can be used to convert that to a stack-allocated UTF-16
  * mozilla::Vector that can then be passed into ICU calls.
--- a/intl/components/src/NumberFormat.h
+++ b/intl/components/src/NumberFormat.h
@@ -417,17 +417,17 @@ class NumberFormat final {
   Result<Ok, ICUError> formatResult(B& buffer) const {
     // We only support buffers with char or char16_t.
     static_assert(std::is_same<C, char>::value ||
                   std::is_same<C, char16_t>::value);
 
     return formatResult().andThen(
         [&buffer](std::u16string_view result) -> Result<Ok, ICUError> {
           if constexpr (std::is_same<C, char>::value) {
-            if (!FillUTF8Buffer(Span(result.data(), result.size()), buffer)) {
+            if (!FillBuffer(Span(result.data(), result.size()), buffer)) {
               return Err(ICUError::OutOfMemory);
             }
             return Ok();
           } else {
             // ICU provides APIs which accept a buffer, but they just copy from
             // an internal buffer behind the scenes anyway.
             if (!buffer.reserve(result.size())) {
               return Err(ICUError::OutOfMemory);
--- a/intl/components/src/RelativeTimeFormat.h
+++ b/intl/components/src/RelativeTimeFormat.h
@@ -93,17 +93,17 @@ class RelativeTimeFormat final {
 
       MOZ_TRY(FillVectorWithICUCall(
           u16Vec, [this, aNumber, aUnit, fmt](UChar* target, int32_t length,
                                               UErrorCode* status) {
             return fmt(mFormatter, aNumber, ToURelativeDateTimeUnit(aUnit),
                        target, length, status);
           }));
 
-      if (!FillUTF8Buffer(u16Vec, aBuffer)) {
+      if (!FillBuffer(u16Vec, aBuffer)) {
         return Err(ICUError::OutOfMemory);
       }
       return Ok{};
     } else {
       static_assert(std::is_same_v<typename B::CharType, char16_t>);
 
       return FillBufferWithICUCall(
           aBuffer, [this, aNumber, aUnit, fmt](UChar* target, int32_t length,