From 3a88e99a2735d1689e9fe05ad8811b09d5559094 Mon Sep 17 00:00:00 2001 From: Fredrik Roubert Date: Tue, 5 Mar 2024 21:15:06 +0100 Subject: [PATCH] ICU-22520 Add a StringByteSink template specialization. This makes it possible to call public functions that take a string class as a template parameter and return an object of that class (implemented through the StringByteSink helper class) also with the CharString class, even though this class doesn't actually provide the public API required by StringByteSink. This makes it possible to use such more modern APIs also internally. --- icu4c/source/common/brkiter.cpp | 7 ++----- icu4c/source/common/bytesinkutil.h | 10 ++++++++++ icu4c/source/common/localebuilder.cpp | 14 ++++---------- icu4c/source/common/locdspnm.cpp | 10 +++------- icu4c/source/common/locid.cpp | 13 +++---------- icu4c/source/i18n/units_data.cpp | 8 ++------ 6 files changed, 24 insertions(+), 38 deletions(-) diff --git a/icu4c/source/common/brkiter.cpp b/icu4c/source/common/brkiter.cpp index b452cf2c050..12679c2f474 100644 --- a/icu4c/source/common/brkiter.cpp +++ b/icu4c/source/common/brkiter.cpp @@ -438,17 +438,14 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE); uprv_strcpy(lb_lw, "line"); UErrorCode kvStatus = U_ZERO_ERROR; - CharString value; - CharStringByteSink valueSink(&value); - loc.getKeywordValue("lb", valueSink, kvStatus); + auto value = loc.getKeywordValue("lb", kvStatus); if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) { uprv_strcat(lb_lw, "_"); uprv_strcat(lb_lw, value.data()); } // lw=phrase is only supported in Japanese and Korean if (uprv_strcmp(loc.getLanguage(), "ja") == 0 || uprv_strcmp(loc.getLanguage(), "ko") == 0) { - value.clear(); - loc.getKeywordValue("lw", valueSink, kvStatus); + value = loc.getKeywordValue("lw", kvStatus); if (U_SUCCESS(kvStatus) && value == "phrase") { uprv_strcat(lb_lw, "_"); uprv_strcat(lb_lw, value.data()); diff --git a/icu4c/source/common/bytesinkutil.h b/icu4c/source/common/bytesinkutil.h index 3161b0d5cea..b3bd487be1d 100644 --- a/icu4c/source/common/bytesinkutil.h +++ b/icu4c/source/common/bytesinkutil.h @@ -43,6 +43,16 @@ private: CharString& dest_; }; +// CharString doesn't provide the public API that StringByteSink requires a +// string class to have so this template specialization replaces the default +// implementation of StringByteSink with CharStringByteSink. +template<> +class StringByteSink : public CharStringByteSink { + public: + StringByteSink(CharString* dest) : CharStringByteSink(dest) { } + StringByteSink(CharString* dest, int32_t /*initialAppendCapacity*/) : CharStringByteSink(dest) { } +}; + class U_COMMON_API ByteSinkUtil { public: ByteSinkUtil() = delete; // all static diff --git a/icu4c/source/common/localebuilder.cpp b/icu4c/source/common/localebuilder.cpp index e6871b2a8c0..e53065a8a60 100644 --- a/icu4c/source/common/localebuilder.cpp +++ b/icu4c/source/common/localebuilder.cpp @@ -3,7 +3,7 @@ #include -#include "bytesinkutil.h" // CharStringByteSink +#include "bytesinkutil.h" // StringByteSink #include "charstr.h" #include "cstring.h" #include "ulocimp.h" @@ -183,9 +183,7 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords, } const char* key; while ((key = keywords->next(nullptr, errorCode)) != nullptr) { - CharString value; - CharStringByteSink sink(&value); - from.getKeywordValue(key, sink, errorCode); + auto value = from.getKeywordValue(key, errorCode); if (U_FAILURE(errorCode)) { return; } if (uprv_strcmp(key, kAttributeKey) == 0) { transform(value.data(), value.length()); @@ -307,10 +305,8 @@ LocaleBuilder& LocaleBuilder::addUnicodeLocaleAttribute( return *this; } - CharString attributes; - CharStringByteSink sink(&attributes); UErrorCode localErrorCode = U_ZERO_ERROR; - extensions_->getKeywordValue(kAttributeKey, sink, localErrorCode); + auto attributes = extensions_->getKeywordValue(kAttributeKey, localErrorCode); if (U_FAILURE(localErrorCode)) { CharString new_attributes(value_str.data(), status_); // No attributes, set the attribute. @@ -362,9 +358,7 @@ LocaleBuilder& LocaleBuilder::removeUnicodeLocaleAttribute( } if (extensions_ == nullptr) { return *this; } UErrorCode localErrorCode = U_ZERO_ERROR; - CharString attributes; - CharStringByteSink sink(&attributes); - extensions_->getKeywordValue(kAttributeKey, sink, localErrorCode); + auto attributes = extensions_->getKeywordValue(kAttributeKey, localErrorCode); // get failure, just return if (U_FAILURE(localErrorCode)) { return *this; } // Do not have any attributes, just return. diff --git a/icu4c/source/common/locdspnm.cpp b/icu4c/source/common/locdspnm.cpp index c836876658f..b2efddf4b40 100644 --- a/icu4c/source/common/locdspnm.cpp +++ b/icu4c/source/common/locdspnm.cpp @@ -634,13 +634,9 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, UnicodeString temp2; const char* key; while ((key = e->next((int32_t *)0, status)) != nullptr) { - CharString value; - { - CharStringByteSink sink(&value); - loc.getKeywordValue(key, sink, status); - } - if (U_FAILURE(status)) { - return result; + auto value = loc.getKeywordValue(key, status); + if (U_FAILURE(status)) { + return result; } keyDisplayName(key, temp, true); temp.findAndReplace(formatOpenParen, formatReplaceOpenParen); diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index fcf59b660f5..4a84548b070 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -1521,13 +1521,12 @@ AliasReplacer::replaceTransformedExtensions( const char* tkey = ultag_getTKeyStart(str); int32_t tlangLen = (tkey == str) ? 0 : ((tkey == nullptr) ? len : static_cast((tkey - str - 1))); - CharStringByteSink sink(&output); if (tlangLen > 0) { Locale tlang = LocaleBuilder() .setLanguageTag(StringPiece(str, tlangLen)) .build(status); tlang.canonicalize(status); - tlang.toLanguageTag(sink, status); + output = tlang.toLanguageTag(status); if (U_FAILURE(status)) { return false; } @@ -1728,9 +1727,7 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status while ((key = iter->next(nullptr, status)) != nullptr) { if (uprv_strcmp("sd", key) == 0 || uprv_strcmp("rg", key) == 0 || uprv_strcmp("t", key) == 0) { - CharString value; - CharStringByteSink valueSink(&value); - locale.getKeywordValue(key, valueSink, status); + auto value = locale.getKeywordValue(key, status); if (U_FAILURE(status)) { status = U_ZERO_ERROR; continue; @@ -2628,11 +2625,7 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, return; } - CharString legacy_value; - { - CharStringByteSink sink(&legacy_value); - getKeywordValue(legacy_key, sink, status); - } + auto legacy_value = getKeywordValue(legacy_key, status); if (U_FAILURE(status)) { return; diff --git a/icu4c/source/i18n/units_data.cpp b/icu4c/source/i18n/units_data.cpp index 22859270b73..5160113d2b5 100644 --- a/icu4c/source/i18n/units_data.cpp +++ b/icu4c/source/i18n/units_data.cpp @@ -403,12 +403,8 @@ U_I18N_API UnitPreferences::UnitPreferences(UErrorCode &status) { } CharString getKeyWordValue(const Locale &locale, StringPiece kw, UErrorCode &status) { - CharString result; - if (U_FAILURE(status)) { return result; } - { - CharStringByteSink sink(&result); - locale.getKeywordValue(kw, sink, status); - } + if (U_FAILURE(status)) { return {}; } + auto result = locale.getKeywordValue(kw, status); if (U_SUCCESS(status) && result.isEmpty()) { status = U_MISSING_RESOURCE_ERROR; }