Bug 1719735 - Add a UTF-16 span overload for FillBuffer; r=platform-i18n-reviewers,dminor

Differential Revision: https://phabricator.services.mozilla.com/D130798
This commit is contained in:
Greg Tatum 2021-12-01 17:41:36 +00:00
Родитель 8a56f3b16b
Коммит 2ca88d17d8
1 изменённых файлов: 58 добавлений и 8 удалений

Просмотреть файл

@ -290,8 +290,9 @@ static ICUResult FillBufferWithICUCall(AutoTArray<CharType, N>& array,
#endif
/**
* ICU4C works with UTF-16 strings, but consumers of mozilla::intl may require
* UTF-8 strings.
* Fill a UTF-8 or a UTF-16 buffer with a UTF-16 span. ICU4C mostly uses UTF-16
* internally, but different consumers may have different situations with their
* buffers.
*/
template <typename Buffer>
[[nodiscard]] bool FillBuffer(Span<const char16_t> utf16Span,
@ -331,25 +332,74 @@ template <typename Buffer>
return true;
}
/**
* Fill a UTF-8 or a UTF-16 buffer with a UTF-8 span. ICU4C mostly uses UTF-16
* internally, but different consumers may have different situations with their
* buffers.
*/
template <typename Buffer>
[[nodiscard]] bool FillBuffer(Span<const char> utf8Span, 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 constexpr (std::is_same_v<typename Buffer::CharType, char> ||
std::is_same_v<typename Buffer::CharType, unsigned char>) {
size_t amount = utf8Span.Length();
if (!targetBuffer.reserve(amount)) {
return false;
}
for (size_t i = 0; i < amount; i++) {
targetBuffer.data()[i] =
// Static cast in case of a mismatch between `unsigned char` and
// `char`
static_cast<typename Buffer::CharType>(utf8Span[i]);
}
targetBuffer.written(amount);
}
if constexpr (std::is_same_v<typename Buffer::CharType, char16_t>) {
if (!targetBuffer.reserve(utf8Span.Length() + 1)) {
return false;
}
size_t amount = ConvertUtf8toUtf16(
utf8Span, Span(targetBuffer.data(), targetBuffer.capacity()));
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.
* mozilla::Vector that can then be passed into ICU calls. The string will be
* null terminated.
*/
template <size_t StackSize>
[[nodiscard]] static bool FillUTF16Vector(
Span<const char> utf8Span,
mozilla::Vector<char16_t, StackSize>& utf16TargetVec) {
// Per ConvertUtf8toUtf16: The length of aDest must be at least one greater
// than the length of aSource
// than the length of aSource. This additional length will be used for null
// termination.
if (!utf16TargetVec.reserve(utf8Span.Length() + 1)) {
return false;
}
// ConvertUtf8toUtf16 fills the buffer with the data, but the length of the
// vector is unchanged. The call to resizeUninitialized notifies the vector of
// how much was written.
return utf16TargetVec.resizeUninitialized(ConvertUtf8toUtf16(
utf8Span, Span(utf16TargetVec.begin(), utf16TargetVec.capacity())));
// vector is unchanged.
size_t length = ConvertUtf8toUtf16(
utf8Span, Span(utf16TargetVec.begin(), utf16TargetVec.capacity()));
// Assert that the last element is free for writing a null terminator.
MOZ_ASSERT(length < utf16TargetVec.capacity());
utf16TargetVec.begin()[length] = '\0';
// The call to resizeUninitialized notifies the vector of how much was written
// exclusive of the null terminated character.
return utf16TargetVec.resizeUninitialized(length);
}
/**