diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp index 70470a862912..5f725e09ae89 100644 --- a/icu4c/source/common/locdispnames.cpp +++ b/icu4c/source/common/locdispnames.cpp @@ -835,7 +835,10 @@ uloc_getDisplayKeywordValue( const char* locale, } /* get the keyword value */ - CharString keywordValue = ulocimp_getKeywordValue(locale, keyword, *status); + CharString keywordValue; + if (keyword != nullptr && *keyword != '\0') { + keywordValue = ulocimp_getKeywordValue(locale, keyword, *status); + } /* * if the keyword is equal to currency .. then to get the display name diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index df6211947027..d608ba8a2ed4 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -2597,13 +2597,7 @@ Locale::getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& sta return; } - // TODO: Remove the need for a const char* to a NUL terminated buffer. - const CharString keywordName_nul(keywordName, status); - if (U_FAILURE(status)) { - return; - } - - ulocimp_getKeywordValue(fullName, keywordName_nul.data(), sink, status); + ulocimp_getKeywordValue(fullName, keywordName, sink, status); } void diff --git a/icu4c/source/common/loclikely.cpp b/icu4c/source/common/loclikely.cpp index e7188be3667b..1e6538134a6a 100644 --- a/icu4c/source/common/loclikely.cpp +++ b/icu4c/source/common/loclikely.cpp @@ -19,6 +19,7 @@ * that then do not depend on resource bundle code and likely-subtags data. */ +#include #include #include "unicode/bytestream.h" @@ -388,7 +389,7 @@ U_NAMESPACE_END namespace { icu::CharString -GetRegionFromKey(const char* localeID, const char* key, UErrorCode& status) { +GetRegionFromKey(const char* localeID, std::string_view key, UErrorCode& status) { icu::CharString result; // First check for keyword value diff --git a/icu4c/source/common/uloc.cpp b/icu4c/source/common/uloc.cpp index c2b7bbfd6af0..a8621a8912c2 100644 --- a/icu4c/source/common/uloc.cpp +++ b/icu4c/source/common/uloc.cpp @@ -31,6 +31,7 @@ */ #include +#include #include "unicode/bytestream.h" #include "unicode/errorcode.h" @@ -551,17 +552,17 @@ namespace { * @param status return status (keyword too long) * @return the keyword name */ -CharString locale_canonKeywordName(const char* keywordName, UErrorCode& status) +CharString locale_canonKeywordName(std::string_view keywordName, UErrorCode& status) { if (U_FAILURE(status)) { return {}; } CharString result; - for (; *keywordName != 0; keywordName++) { - if (!UPRV_ISALPHANUM(*keywordName)) { + for (char c : keywordName) { + if (!UPRV_ISALPHANUM(c)) { status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */ return {}; } - result.append(uprv_tolower(*keywordName), status); + result.append(uprv_tolower(c), status); } if (result.isEmpty()) { status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name */ @@ -733,6 +734,11 @@ uloc_getKeywordValue(const char* localeID, char* buffer, int32_t bufferCapacity, UErrorCode* status) { + if (U_FAILURE(*status)) { return 0; } + if (keywordName == nullptr || *keywordName == '\0') { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } return ByteSinkUtil::viaByteSinkToTerminatedChars( buffer, bufferCapacity, [&](ByteSink& sink, UErrorCode& status) { @@ -743,7 +749,7 @@ uloc_getKeywordValue(const char* localeID, U_EXPORT CharString ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, UErrorCode& status) { return ByteSinkUtil::viaByteSinkToCharString( @@ -755,13 +761,13 @@ ulocimp_getKeywordValue(const char* localeID, U_EXPORT void ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, icu::ByteSink& sink, UErrorCode& status) { if (U_FAILURE(status)) { return; } - if (localeID == nullptr || keywordName == nullptr || keywordName[0] == 0) { + if (localeID == nullptr || keywordName.empty()) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } diff --git a/icu4c/source/common/ulocimp.h b/icu4c/source/common/ulocimp.h index ff3910ac8f35..5eab0812cf58 100644 --- a/icu4c/source/common/ulocimp.h +++ b/icu4c/source/common/ulocimp.h @@ -11,6 +11,7 @@ #define ULOCIMP_H #include +#include #include "unicode/bytestream.h" #include "unicode/uloc.h" @@ -95,12 +96,12 @@ ulocimp_canonicalize(const char* localeID, U_EXPORT icu::CharString ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, UErrorCode& status); U_EXPORT void ulocimp_getKeywordValue(const char* localeID, - const char* keywordName, + std::string_view keywordName, icu::ByteSink& sink, UErrorCode& status); diff --git a/icu4c/source/common/uresbund.cpp b/icu4c/source/common/uresbund.cpp index 59b08688319c..cfe2f4a4d20f 100644 --- a/icu4c/source/common/uresbund.cpp +++ b/icu4c/source/common/uresbund.cpp @@ -3074,9 +3074,12 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, UErrorCode subStatus = U_ZERO_ERROR; int32_t length = 0; if(U_FAILURE(*status)) return 0; - CharString kwVal = ulocimp_getKeywordValue(locid, keyword, subStatus); - if(kwVal == DEFAULT_TAG) { - kwVal.clear(); + CharString kwVal; + if (keyword != nullptr && *keyword != '\0') { + kwVal = ulocimp_getKeywordValue(locid, keyword, subStatus); + if (kwVal == DEFAULT_TAG) { + kwVal.clear(); + } } CharString base = ulocimp_getBaseName(locid, subStatus); #if defined(URES_TREE_DEBUG)