diff --git a/icu4c/source/common/localebuilder.cpp b/icu4c/source/common/localebuilder.cpp index ddb5ea3b0a73..e6871b2a8c09 100644 --- a/icu4c/source/common/localebuilder.cpp +++ b/icu4c/source/common/localebuilder.cpp @@ -203,6 +203,7 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords, void _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode) { + if (U_FAILURE(errorCode)) { return; } // Clear Unicode attributes locale.setKeywordValue(kAttributeKey, "", errorCode); @@ -218,6 +219,7 @@ _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode) void _setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode) { + if (U_FAILURE(errorCode)) { return; } // Add the unicode extensions to extensions_ CharString locale_str("und-u-", errorCode); locale_str.append(value, errorCode); diff --git a/icu4c/source/common/localematcher.cpp b/icu4c/source/common/localematcher.cpp index aa5ba0778c5c..6eaa31ac0327 100644 --- a/icu4c/source/common/localematcher.cpp +++ b/icu4c/source/common/localematcher.cpp @@ -4,6 +4,8 @@ // localematcher.cpp // created: 2019may08 Markus W. Scherer +#include + #include "unicode/utypes.h" #include "unicode/localebuilder.h" #include "unicode/localematcher.h" @@ -605,10 +607,11 @@ class LocaleLsrIterator { const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const { if (U_FAILURE(errorCode)) { return nullptr; } - int32_t suppIndex = getBestSuppIndex( + std::optional suppIndex = getBestSuppIndex( getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), nullptr, errorCode); - return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; + return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[suppIndex.value()] + : defaultLocale; } const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales, @@ -618,12 +621,14 @@ const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales, return defaultLocale; } LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); - int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); - return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; + std::optional suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); + return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[suppIndex.value()] + : defaultLocale; } const Locale *LocaleMatcher::getBestMatchForListString( StringPiece desiredLocaleList, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } LocalePriorityList list(desiredLocaleList, errorCode); LocalePriorityList::Iterator iter = list.iterator(); return getBestMatch(iter, errorCode); @@ -634,13 +639,13 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult( if (U_FAILURE(errorCode)) { return Result(nullptr, defaultLocale, -1, -1, false); } - int32_t suppIndex = getBestSuppIndex( + std::optional suppIndex = getBestSuppIndex( getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), nullptr, errorCode); - if (U_FAILURE(errorCode) || suppIndex < 0) { + if (U_FAILURE(errorCode) || !suppIndex.has_value()) { return Result(nullptr, defaultLocale, -1, -1, false); } else { - return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, false); + return Result(&desiredLocale, supportedLocales[suppIndex.value()], 0, suppIndex.value(), false); } } @@ -650,18 +655,19 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult( return Result(nullptr, defaultLocale, -1, -1, false); } LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); - int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); - if (U_FAILURE(errorCode) || suppIndex < 0) { + std::optional suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); + if (U_FAILURE(errorCode) || !suppIndex.has_value()) { return Result(nullptr, defaultLocale, -1, -1, false); } else { - return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex], - lsrIter.getBestDesiredIndex(), suppIndex, true); + return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex.value()], + lsrIter.getBestDesiredIndex(), suppIndex.value(), true); } } -int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, - UErrorCode &errorCode) const { - if (U_FAILURE(errorCode)) { return -1; } +std::optional LocaleMatcher::getBestSuppIndex(LSR desiredLSR, + LocaleLsrIterator *remainingIter, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return std::nullopt; } int32_t desiredIndex = 0; int32_t bestSupportedLsrIndex = -1; for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) { @@ -684,7 +690,7 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance); if (remainingIter != nullptr) { remainingIter->rememberCurrent(desiredIndex, errorCode); - if (U_FAILURE(errorCode)) { return -1; } + if (U_FAILURE(errorCode)) { return std::nullopt; } } bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance); } @@ -695,20 +701,21 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai break; } desiredLSR = remainingIter->next(errorCode); - if (U_FAILURE(errorCode)) { return -1; } + if (U_FAILURE(errorCode)) { return std::nullopt; } ++desiredIndex; } if (bestSupportedLsrIndex < 0) { // no good match - return -1; + return std::nullopt; } return supportedIndexes[bestSupportedLsrIndex]; } UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return false; } LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); - if (U_FAILURE(errorCode)) { return 0; } + if (U_FAILURE(errorCode)) { return false; } const LSR *pSuppLSR = &suppLSR; int32_t indexAndDistance = localeDistance.getBestIndexAndDistance( getMaximalLsrOrUnd(likelySubtags, desired, errorCode), @@ -718,9 +725,10 @@ UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported, } double LocaleMatcher::internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return 0.; } // Returns the inverse of the distance: That is, 1-distance(desired, supported). LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); - if (U_FAILURE(errorCode)) { return 0; } + if (U_FAILURE(errorCode)) { return 0.; } const LSR *pSuppLSR = &suppLSR; int32_t indexAndDistance = localeDistance.getBestIndexAndDistance( getMaximalLsrOrUnd(likelySubtags, desired, errorCode), diff --git a/icu4c/source/common/locavailable.cpp b/icu4c/source/common/locavailable.cpp index af07bf5fbab7..4a2600e88c59 100644 --- a/icu4c/source/common/locavailable.cpp +++ b/icu4c/source/common/locavailable.cpp @@ -101,10 +101,9 @@ icu::UInitOnce ginstalledLocalesInitOnce {}; class AvailableLocalesSink : public ResourceSink { public: void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) override { + if (U_FAILURE(status)) { return; } ResourceTable resIndexTable = value.getTable(status); - if (U_FAILURE(status)) { - return; - } + if (U_FAILURE(status)) { return; } for (int32_t i = 0; resIndexTable.getKeyAndValue(i, key, value); ++i) { ULocAvailableType type; if (uprv_strcmp(key, "InstalledLocales") == 0) { @@ -138,7 +137,8 @@ class AvailableLocalesStringEnumeration : public StringEnumeration { AvailableLocalesStringEnumeration(ULocAvailableType type) : fType(type) { } - const char* next(int32_t *resultLength, UErrorCode&) override { + const char* next(int32_t *resultLength, UErrorCode &status) override { + if (U_FAILURE(status)) { return nullptr; } ULocAvailableType actualType = fType; int32_t actualIndex = fIndex++; @@ -170,11 +170,13 @@ class AvailableLocalesStringEnumeration : public StringEnumeration { return result; } - void reset(UErrorCode&) override { + void reset(UErrorCode &status) override { + if (U_FAILURE(status)) { return; } fIndex = 0; } - int32_t count(UErrorCode&) const override { + int32_t count(UErrorCode &status) const override { + if (U_FAILURE(status)) { return 0; } if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) { return gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT] + gAvailableLocaleCounts[ULOC_AVAILABLE_ONLY_LEGACY_ALIASES]; diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp index f1f0b065342c..a8316174b7ce 100644 --- a/icu4c/source/common/locdispnames.cpp +++ b/icu4c/source/common/locdispnames.cpp @@ -306,6 +306,7 @@ _getStringOrCopyKey(const char *path, const char *locale, const char *substitute, char16_t *dest, int32_t destCapacity, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return 0; } const char16_t *s = nullptr; int32_t length = 0; @@ -368,14 +369,10 @@ _getDisplayNameForComponent(const char *locale, UDisplayNameGetter *getter, const char *tag, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return 0; } UErrorCode localStatus; const char* root = nullptr; - /* argument checking */ - if (U_FAILURE(errorCode)) { - return 0; - } - if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; return 0; @@ -422,6 +419,7 @@ uloc_getDisplayScript(const char* locale, char16_t *dest, int32_t destCapacity, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { return 0; } UErrorCode err = U_ZERO_ERROR; int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, ulocimp_getScript, _kScriptsStandAlone, err); diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index f382041997c4..3a39e62f1c61 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -916,6 +916,8 @@ AliasData::loadData(UErrorCode &status) */ AliasData* AliasDataBuilder::build(UErrorCode &status) { + if (U_FAILURE(status)) { return nullptr; } + LocalUResourceBundlePointer metadata( ures_openDirect(nullptr, "metadata", &status)); LocalUResourceBundlePointer metadataAlias( @@ -1061,7 +1063,7 @@ AliasDataBuilder::build(UErrorCode &status) { */ class AliasReplacer { public: - AliasReplacer(UErrorCode status) : + AliasReplacer(UErrorCode& status) : language(nullptr), script(nullptr), region(nullptr), extensions(nullptr), // store value in variants only once @@ -1126,12 +1128,12 @@ class AliasReplacer { } // Gather fields and generate locale ID into out. - CharString& outputToString(CharString& out, UErrorCode status); + CharString& outputToString(CharString& out, UErrorCode& status); // Generate the lookup key. CharString& generateKey(const char* language, const char* region, const char* variant, CharString& out, - UErrorCode status); + UErrorCode& status); void parseLanguageReplacement(const char* replacement, const char*& replaceLanguage, @@ -1168,8 +1170,9 @@ class AliasReplacer { CharString& AliasReplacer::generateKey( const char* language, const char* region, const char* variant, - CharString& out, UErrorCode status) + CharString& out, UErrorCode& status) { + if (U_FAILURE(status)) { return out; } out.append(language, status); if (notEmpty(region)) { out.append(SEP_CHAR, status) @@ -1587,8 +1590,9 @@ AliasReplacer::replaceTransformedExtensions( CharString& AliasReplacer::outputToString( - CharString& out, UErrorCode status) + CharString& out, UErrorCode& status) { + if (U_FAILURE(status)) { return out; } out.append(language, status); if (notEmpty(script)) { out.append(SEP_CHAR, status) @@ -1778,6 +1782,7 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status bool canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status) { + if (U_FAILURE(status)) { return false; } AliasReplacer replacer(status); return replacer.replace(locale, out, status); } @@ -1787,6 +1792,8 @@ canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status) bool isKnownCanonicalizedLocale(const char* locale, UErrorCode& status) { + if (U_FAILURE(status)) { return false; } + if ( uprv_strcmp(locale, "c") == 0 || uprv_strcmp(locale, "en") == 0 || uprv_strcmp(locale, "en_US") == 0) { @@ -2453,7 +2460,8 @@ class KeywordEnumeration : public StringEnumeration { (int32_t)(current - keywords.data()), status); } - virtual int32_t count(UErrorCode &/*status*/) const override { + virtual int32_t count(UErrorCode& status) const override { + if (U_FAILURE(status)) { return 0; } const char *kw = keywords.data(); int32_t result = 0; while(*kw) { @@ -2483,12 +2491,14 @@ class KeywordEnumeration : public StringEnumeration { } virtual const UnicodeString* snext(UErrorCode& status) override { + if (U_FAILURE(status)) { return nullptr; } int32_t resultLength = 0; const char *s = next(&resultLength, status); return setChars(s, resultLength, status); } - virtual void reset(UErrorCode& /*status*/) override { + virtual void reset(UErrorCode& status) override { + if (U_FAILURE(status)) { return; } current = keywords.data(); } }; @@ -2521,7 +2531,8 @@ class UnicodeKeywordEnumeration : public KeywordEnumeration { if (resultLength != nullptr) *resultLength = 0; return nullptr; } - virtual int32_t count(UErrorCode &/*status*/) const override { + virtual int32_t count(UErrorCode& status) const override { + if (U_FAILURE(status)) { return 0; } const char *kw = keywords.data(); int32_t result = 0; while(*kw) { @@ -2625,6 +2636,10 @@ void Locale::getUnicodeKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + // TODO: Remove the need for a const char* to a NUL terminated buffer. const CharString keywordName_nul(keywordName, status); if (U_FAILURE(status)) { @@ -2632,7 +2647,6 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, } const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); - if (legacy_key == nullptr) { status = U_ILLEGAL_ARGUMENT_ERROR; return; @@ -2705,6 +2719,7 @@ void Locale::setKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status) { + if (U_FAILURE(status)) { return; } // TODO: Remove the need for a const char* to a NUL terminated buffer. const CharString keywordName_nul(keywordName, status); const CharString keywordValue_nul(keywordValue, status); @@ -2715,16 +2730,18 @@ void Locale::setUnicodeKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + // TODO: Remove the need for a const char* to a NUL terminated buffer. const CharString keywordName_nul(keywordName, status); const CharString keywordValue_nul(keywordValue, status); - if (U_FAILURE(status)) { return; } const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); - if (legacy_key == nullptr) { status = U_ILLEGAL_ARGUMENT_ERROR; return; diff --git a/icu4c/source/common/loclikely.cpp b/icu4c/source/common/loclikely.cpp index afbceaaa9950..9e0f058b34a5 100644 --- a/icu4c/source/common/loclikely.cpp +++ b/icu4c/source/common/loclikely.cpp @@ -130,17 +130,17 @@ bool CHECK_TRAILING_VARIANT_SIZE(const char* variant, int32_t variantLength) { return true; } -bool +void _uloc_addLikelySubtags(const char* localeID, icu::ByteSink& sink, UErrorCode& err) { if (U_FAILURE(err)) { - return false; + return; } if (localeID == nullptr) { err = U_ILLEGAL_ARGUMENT_ERROR; - return false; + return; } icu::CharString lang; @@ -150,12 +150,12 @@ _uloc_addLikelySubtags(const char* localeID, const char* trailing = nullptr; ulocimp_getSubtags(localeID, &lang, &script, ®ion, &variant, &trailing, err); if (U_FAILURE(err)) { - return false; + return; } if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) { err = U_ILLEGAL_ARGUMENT_ERROR; - return false; + return; } if (lang.length() > 3) { @@ -164,7 +164,7 @@ _uloc_addLikelySubtags(const char* localeID, lang.clear(); } else { err = U_ILLEGAL_ARGUMENT_ERROR; - return false; + return; } } @@ -172,18 +172,18 @@ _uloc_addLikelySubtags(const char* localeID, const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err); if (U_FAILURE(err)) { - return false; + return; } // We need to keep l on the stack because lsr may point into internal // memory of l. icu::Locale l = icu::Locale::createFromName(localeID); if (l.isBogus()) { err = U_ILLEGAL_ARGUMENT_ERROR; - return false; + return; } icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, err); if (U_FAILURE(err)) { - return false; + return; } const char* language = lsr.language; if (uprv_strcmp(language, "und") == 0) { @@ -202,16 +202,8 @@ _uloc_addLikelySubtags(const char* localeID, trailingLength, sink, err); - - return U_SUCCESS(err); } -// Add likely subtags to the sink -// return true if the value in the sink is produced by a match during the lookup -// return false if the value in the sink is the same as input because there are -// no match after the lookup. -bool _ulocimp_addLikelySubtags(const char*, icu::ByteSink&, UErrorCode&); - void _uloc_minimizeSubtags(const char* localeID, icu::ByteSink& sink, @@ -290,12 +282,12 @@ uloc_addLikelySubtags(const char* localeID, maximizedLocaleID, maximizedLocaleIDCapacity); ulocimp_addLikelySubtags(localeID, sink, *status); - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*status)) { - return sink.Overflowed() ? reslen : -1; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *status = U_BUFFER_OVERFLOW_ERROR; } else { @@ -306,29 +298,17 @@ uloc_addLikelySubtags(const char* localeID, return reslen; } -namespace { -bool -_ulocimp_addLikelySubtags(const char* localeID, - icu::ByteSink& sink, - UErrorCode& status) { +U_EXPORT void +ulocimp_addLikelySubtags(const char* localeID, + icu::ByteSink& sink, + UErrorCode& status) { + if (U_FAILURE(status)) { return; } icu::CharString localeBuffer; { icu::CharStringByteSink localeSink(&localeBuffer); ulocimp_canonicalize(localeID, localeSink, status); } - if (U_SUCCESS(status)) { - return _uloc_addLikelySubtags(localeBuffer.data(), sink, status); - } else { - return false; - } -} -} // namespace - -U_EXPORT void -ulocimp_addLikelySubtags(const char* localeID, - icu::ByteSink& sink, - UErrorCode& status) { - _ulocimp_addLikelySubtags(localeID, sink, status); + _uloc_addLikelySubtags(localeBuffer.data(), sink, status); } U_CAPI int32_t U_EXPORT2 @@ -344,12 +324,12 @@ uloc_minimizeSubtags(const char* localeID, minimizedLocaleID, minimizedLocaleIDCapacity); ulocimp_minimizeSubtags(localeID, sink, false, *status); - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*status)) { - return sink.Overflowed() ? reslen : -1; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *status = U_BUFFER_OVERFLOW_ERROR; } else { @@ -365,6 +345,7 @@ ulocimp_minimizeSubtags(const char* localeID, icu::ByteSink& sink, bool favorScript, UErrorCode& status) { + if (U_FAILURE(status)) { return; } icu::CharString localeBuffer; { icu::CharStringByteSink localeSink(&localeBuffer); diff --git a/icu4c/source/common/loclikelysubtags.cpp b/icu4c/source/common/loclikelysubtags.cpp index 28adec4a7a49..c182191057f4 100644 --- a/icu4c/source/common/loclikelysubtags.cpp +++ b/icu4c/source/common/loclikelysubtags.cpp @@ -70,6 +70,7 @@ struct LikelySubtagsData { } void load(UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode); if (U_FAILURE(errorCode)) { return; } StackUResourceBundle stackTempBundle; @@ -230,6 +231,7 @@ struct LikelySubtagsData { private: bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value, LocalMemory &indexes, int32_t &length, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return false; } if (table.findValue(key, value)) { ResourceArray stringArray = value.getArray(errorCode); if (U_FAILURE(errorCode)) { return false; } @@ -296,7 +298,7 @@ struct LikelySubtagsData { } UnicodeString toRegion(const ResourceArray& m49Array, ResourceValue &value, int encoded, UErrorCode &errorCode) { - if (encoded == 0 || encoded == 1) { + if (U_FAILURE(errorCode) || encoded == 0 || encoded == 1) { return UNICODE_STRING_SIMPLE(""); } encoded &= 0x00ffffff; @@ -314,6 +316,7 @@ struct LikelySubtagsData { bool readLSREncodedStrings(const ResourceTable &table, const char* key, ResourceValue &value, const ResourceArray& m49Array, LocalMemory &indexes, int32_t &length, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return false; } if (table.findValue(key, value)) { const int32_t* vectors = value.getIntVector(length, errorCode); if (U_FAILURE(errorCode)) { return false; } @@ -380,6 +383,7 @@ constexpr const char16_t* MACROREGION_HARDCODE[] = { constexpr char16_t RANGE_MARKER = 0x7E; /* '~' */ void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroRegions, UErrorCode& status) { + if (U_FAILURE(status)) { return; } int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); char16_t buf[6]; regionName.extract(buf,6,status); @@ -399,6 +403,7 @@ void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroR #if U_DEBUG UVector* loadMacroregions(UErrorCode &status) { + if (U_FAILURE(status)) { return nullptr; } LocalPointer newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); LocalUResourceBundlePointer supplementalData(ures_openDirect(nullptr,"supplementalData",&status)); @@ -423,6 +428,7 @@ UVector* loadMacroregions(UErrorCode &status) { #endif // U_DEBUG UVector* getStaticMacroregions(UErrorCode &status) { + if (U_FAILURE(status)) { return nullptr; } LocalPointer newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); if (U_FAILURE(status)) { @@ -515,9 +521,10 @@ LikelySubtags::~LikelySubtags() { LSR LikelySubtags::makeMaximizedLsrFrom(const Locale &locale, bool returnInputIfUnmatch, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return {}; } if (locale.isBogus()) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; - return LSR("", "", "", LSR::EXPLICIT_LSR); + return {}; } const char *name = locale.getName(); if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") @@ -553,6 +560,7 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co const char *variant, bool returnInputIfUnmatch, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return {}; } // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. // They should match only themselves, // not other locales with what looks like the same language and script subtags. @@ -607,6 +615,7 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co LSR LikelySubtags::maximize(const char *language, const char *script, const char *region, bool returnInputIfUnmatch, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return {}; } return maximize({language, (int32_t)uprv_strlen(language)}, {script, (int32_t)uprv_strlen(script)}, {region, (int32_t)uprv_strlen(region)}, @@ -615,10 +624,10 @@ LSR LikelySubtags::maximize(const char *language, const char *script, const char } bool LikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) const { + if (U_FAILURE(errorCode)) { return false; } // In Java, we use Region class. In C++, since Region is under i18n, // we read the same data used by Region into gMacroregions avoid dependency // from common to i18n/region.cpp - if (U_FAILURE(errorCode)) { return false; } umtx_initOnce(gInitOnce, &LikelySubtags::initLikelySubtags, errorCode); if (U_FAILURE(errorCode)) { return false; } UnicodeString str(UnicodeString::fromUTF8(region)); @@ -628,9 +637,7 @@ bool LikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) co LSR LikelySubtags::maximize(StringPiece language, StringPiece script, StringPiece region, bool returnInputIfUnmatch, UErrorCode &errorCode) const { - if (U_FAILURE(errorCode)) { - return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); - } + if (U_FAILURE(errorCode)) { return {}; } if (language.compare("und") == 0) { language = ""; } @@ -920,10 +927,9 @@ LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script, StringPiece region, bool favorScript, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return {}; } LSR max = maximize(language, script, region, true, errorCode); - if (U_FAILURE(errorCode)) { - return max; - } + if (U_FAILURE(errorCode)) { return {}; } // If no match, return it. if (uprv_strlen(max.language) == 0 && uprv_strlen(max.script) == 0 && @@ -936,9 +942,7 @@ LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script, } // try language LSR test = maximize(max.language, "", "", true, errorCode); - if (U_FAILURE(errorCode)) { - return max; - } + if (U_FAILURE(errorCode)) { return {}; } if (test.isEquivalentTo(max)) { return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode); } @@ -947,27 +951,21 @@ LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script, // favor Region // try language and region test = maximize(max.language, "", max.region, true, errorCode); - if (U_FAILURE(errorCode)) { - return max; - } + if (U_FAILURE(errorCode)) { return {}; } if (test.isEquivalentTo(max)) { return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); } } // try language and script test = maximize(max.language, max.script, "", true, errorCode); - if (U_FAILURE(errorCode)) { - return max; - } + if (U_FAILURE(errorCode)) { return {}; } if (test.isEquivalentTo(max)) { return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode); } if (favorScript) { // try language and region test = maximize(max.language, "", max.region, true, errorCode); - if (U_FAILURE(errorCode)) { - return max; - } + if (U_FAILURE(errorCode)) { return {}; } if (test.isEquivalentTo(max)) { return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); } diff --git a/icu4c/source/common/locmap.cpp b/icu4c/source/common/locmap.cpp index a59c7ab4e3ff..d21a11148fa8 100644 --- a/icu4c/source/common/locmap.cpp +++ b/icu4c/source/common/locmap.cpp @@ -977,6 +977,7 @@ idCmp(const char* id1, const char* id2) uint32_t getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status) { + if (U_FAILURE(status)) { return locmap_root->hostID; } int32_t bestIdx = 0; int32_t bestIdxDiff = 0; int32_t posixIDlen = (int32_t)uprv_strlen(posixID); @@ -1004,7 +1005,7 @@ getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status) /*no match found */ status = U_ILLEGAL_ARGUMENT_ERROR; - return this_0->regionMaps->hostID; + return locmap_root->hostID; } const char* @@ -1151,7 +1152,7 @@ uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UEr /* no match found */ *status = U_ILLEGAL_ARGUMENT_ERROR; - return -1; + return 0; } /* @@ -1257,6 +1258,14 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status) U_CAPI uint32_t uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status) { + if (U_FAILURE(*status) || + langID == nullptr || + posixID == nullptr || + uprv_strlen(langID) < 2 || + uprv_strlen(posixID) < 2) { + return locmap_root->hostID; + } + // This function does the table lookup when native platform name->lcid conversion isn't available, // or for locales that don't follow patterns the platform expects. uint32_t low = 0; @@ -1270,11 +1279,6 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status) UErrorCode myStatus; uint32_t idx; - /* Check for incomplete id. */ - if (!langID || !posixID || uprv_strlen(langID) < 2 || uprv_strlen(posixID) < 2) { - return 0; - } - /*Binary search for the map entry for normal cases */ while (high > low) /*binary search*/{ @@ -1319,5 +1323,5 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status) /* no match found */ *status = U_ILLEGAL_ARGUMENT_ERROR; - return 0; /* return international (root) */ + return locmap_root->hostID; /* return international (root) */ } diff --git a/icu4c/source/common/locresdata.cpp b/icu4c/source/common/locresdata.cpp index 05cd24c6ff94..56b27fe5a5b1 100644 --- a/icu4c/source/common/locresdata.cpp +++ b/icu4c/source/common/locresdata.cpp @@ -50,6 +50,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale, int32_t *pLength, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { return nullptr; } /* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/ const char16_t *item=nullptr; UErrorCode errorCode; @@ -159,45 +160,47 @@ _uloc_getOrientationHelper(const char* localeId, { ULayoutType result = ULOC_LAYOUT_UNKNOWN; - if (!U_FAILURE(status)) { - icu::CharString localeBuffer; - { - icu::CharStringByteSink sink(&localeBuffer); - ulocimp_canonicalize(localeId, sink, status); - } + if (U_FAILURE(status)) { return result; } - if (!U_FAILURE(status)) { - int32_t length = 0; - const char16_t* const value = - uloc_getTableStringWithFallback( - nullptr, - localeBuffer.data(), - "layout", - nullptr, - key, - &length, - &status); - - if (!U_FAILURE(status) && length != 0) { - switch(value[0]) - { - case 0x0062: /* 'b' */ - result = ULOC_LAYOUT_BTT; - break; - case 0x006C: /* 'l' */ - result = ULOC_LAYOUT_LTR; - break; - case 0x0072: /* 'r' */ - result = ULOC_LAYOUT_RTL; - break; - case 0x0074: /* 't' */ - result = ULOC_LAYOUT_TTB; - break; - default: - status = U_INTERNAL_PROGRAM_ERROR; - break; - } - } + icu::CharString localeBuffer; + { + icu::CharStringByteSink sink(&localeBuffer); + ulocimp_canonicalize(localeId, sink, status); + } + + if (U_FAILURE(status)) { return result; } + + int32_t length = 0; + const char16_t* const value = + uloc_getTableStringWithFallback( + nullptr, + localeBuffer.data(), + "layout", + nullptr, + key, + &length, + &status); + + if (U_FAILURE(status)) { return result; } + + if (length != 0) { + switch(value[0]) + { + case 0x0062: /* 'b' */ + result = ULOC_LAYOUT_BTT; + break; + case 0x006C: /* 'l' */ + result = ULOC_LAYOUT_LTR; + break; + case 0x0072: /* 'r' */ + result = ULOC_LAYOUT_RTL; + break; + case 0x0074: /* 't' */ + result = ULOC_LAYOUT_TTB; + break; + default: + status = U_INTERNAL_PROGRAM_ERROR; + break; } } diff --git a/icu4c/source/common/uloc.cpp b/icu4c/source/common/uloc.cpp index f5f2219540e8..c17b590bfcf4 100644 --- a/icu4c/source/common/uloc.cpp +++ b/icu4c/source/common/uloc.cpp @@ -553,17 +553,19 @@ namespace { */ CharString locale_canonKeywordName(const char* keywordName, UErrorCode& status) { + if (U_FAILURE(status)) { return {}; } CharString result; for (; *keywordName != 0; keywordName++) { if (!UPRV_ISALPHANUM(*keywordName)) { status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */ - return result; + return {}; } result.append(uprv_tolower(*keywordName), status); } if (result.isEmpty()) { status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name */ + return {}; } return result; @@ -592,6 +594,8 @@ ulocimp_getKeywords(const char* localeID, bool valuesToo, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + KeywordStruct keywordList[ULOC_MAX_NO_KEYWORDS]; int32_t maxKeywords = ULOC_MAX_NO_KEYWORDS; @@ -718,13 +722,12 @@ uloc_getKeywordValue(const char* localeID, CheckedArrayByteSink sink(buffer, bufferCapacity); ulocimp_getKeywordValue(localeID, keywordName, sink, *status); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*status)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *status = U_BUFFER_OVERFLOW_ERROR; } else { @@ -740,102 +743,102 @@ ulocimp_getKeywordValue(const char* localeID, icu::ByteSink& sink, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + + if (localeID == nullptr || keywordName == nullptr || keywordName[0] == 0) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + const char* startSearchHere = nullptr; const char* nextSeparator = nullptr; - if (localeID != nullptr && U_SUCCESS(status)) { - CharString tempBuffer; - const char* tmpLocaleID; + CharString tempBuffer; + const char* tmpLocaleID; - if (keywordName == nullptr || keywordName[0] == 0) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } + CharString canonKeywordName = locale_canonKeywordName(keywordName, status); + if (U_FAILURE(status)) { + return; + } + + if (_hasBCP47Extension(localeID)) { + CharStringByteSink sink(&tempBuffer); + ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status); + tmpLocaleID = U_SUCCESS(status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID; + } else { + tmpLocaleID=localeID; + } - CharString canonKeywordName = locale_canonKeywordName(keywordName, status); - if (U_FAILURE(status)) { + startSearchHere = locale_getKeywordsStart(tmpLocaleID); + if(startSearchHere == nullptr) { + /* no keywords, return at once */ return; - } + } - if (_hasBCP47Extension(localeID)) { - CharStringByteSink sink(&tempBuffer); - ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status); - tmpLocaleID = U_SUCCESS(status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID; - } else { - tmpLocaleID=localeID; - } - - startSearchHere = locale_getKeywordsStart(tmpLocaleID); - if(startSearchHere == nullptr) { - /* no keywords, return at once */ - return; - } - - /* find the first keyword */ - while(startSearchHere) { - const char* keyValueTail; - - startSearchHere++; /* skip @ or ; */ - nextSeparator = uprv_strchr(startSearchHere, '='); - if(!nextSeparator) { - status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */ - return; - } - /* strip leading & trailing spaces (TC decided to tolerate these) */ - while(*startSearchHere == ' ') { - startSearchHere++; + /* find the first keyword */ + while(startSearchHere) { + const char* keyValueTail; + + startSearchHere++; /* skip @ or ; */ + nextSeparator = uprv_strchr(startSearchHere, '='); + if(!nextSeparator) { + status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */ + return; + } + /* strip leading & trailing spaces (TC decided to tolerate these) */ + while(*startSearchHere == ' ') { + startSearchHere++; + } + keyValueTail = nextSeparator; + while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') { + keyValueTail--; + } + /* now keyValueTail points to first char after the keyName */ + /* copy & normalize keyName from locale */ + if (startSearchHere == keyValueTail) { + status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */ + return; + } + CharString localeKeywordName; + while (startSearchHere < keyValueTail) { + if (!UPRV_ISALPHANUM(*startSearchHere)) { + status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */ + return; } - keyValueTail = nextSeparator; - while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') { + localeKeywordName.append(uprv_tolower(*startSearchHere++), status); + } + if (U_FAILURE(status)) { + return; + } + + startSearchHere = uprv_strchr(nextSeparator, ';'); + + if (canonKeywordName == localeKeywordName) { + /* current entry matches the keyword. */ + nextSeparator++; /* skip '=' */ + /* First strip leading & trailing spaces (TC decided to tolerate these) */ + while(*nextSeparator == ' ') { + nextSeparator++; + } + keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator); + while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') { keyValueTail--; - } - /* now keyValueTail points to first char after the keyName */ - /* copy & normalize keyName from locale */ - if (startSearchHere == keyValueTail) { - status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */ - return; - } - CharString localeKeywordName; - while (startSearchHere < keyValueTail) { - if (!UPRV_ISALPHANUM(*startSearchHere)) { - status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */ - return; } - localeKeywordName.append(uprv_tolower(*startSearchHere++), status); - } - if (U_FAILURE(status)) { + /* Now copy the value, but check well-formedness */ + if (nextSeparator == keyValueTail) { + status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */ return; - } - - startSearchHere = uprv_strchr(nextSeparator, ';'); - - if (canonKeywordName == localeKeywordName) { - /* current entry matches the keyword. */ - nextSeparator++; /* skip '=' */ - /* First strip leading & trailing spaces (TC decided to tolerate these) */ - while(*nextSeparator == ' ') { - nextSeparator++; - } - keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator); - while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') { - keyValueTail--; - } - /* Now copy the value, but check well-formedness */ - if (nextSeparator == keyValueTail) { - status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */ + } + while (nextSeparator < keyValueTail) { + if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) { + status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */ return; } - while (nextSeparator < keyValueTail) { - if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) { - status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */ - return; - } - /* Should we lowercase value to return here? Tests expect as-is. */ - sink.Append(nextSeparator++, 1); - } - return; - } - } + /* Should we lowercase value to return here? Tests expect as-is. */ + sink.Append(nextSeparator++, 1); + } + return; + } } } @@ -845,9 +848,7 @@ uloc_setKeywordValue(const char* keywordName, char* buffer, int32_t bufferCapacity, UErrorCode* status) { - if (U_FAILURE(*status)) { - return -1; - } + if (U_FAILURE(*status)) { return 0; } if (bufferCapacity <= 1) { *status = U_ILLEGAL_ARGUMENT_ERROR; @@ -870,8 +871,7 @@ uloc_setKeywordValue(const char* keywordName, keywords, keywordName, keywordValue, sink, *status); if (U_FAILURE(*status)) { - // A positive return value is a length, otherwise it's an error code. - return reslen > 0 ? reslen + baseLen : reslen; + return *status == U_BUFFER_OVERFLOW_ERROR ? reslen + baseLen : 0; } // See the documentation for this function, it's guaranteed to never @@ -904,6 +904,8 @@ ulocimp_setKeywordValue(const char* keywords, ByteSink& sink, UErrorCode& status) { + if (U_FAILURE(status)) { return 0; } + /* TODO: sorting. removal. */ int32_t needLen = 0; int32_t rc; @@ -914,9 +916,6 @@ ulocimp_setKeywordValue(const char* keywords, bool handledInputKeyAndValue = false; char keyValuePrefix = '@'; - if (U_FAILURE(status)) { - return -1; - } if (status == U_STRING_NOT_TERMINATED_WARNING) { status = U_ZERO_ERROR; } @@ -1132,7 +1131,7 @@ inline bool _isBCP47Extension(const char* p) { * The 'list' param should be LANGUAGES, LANGUAGES_3, COUNTRIES, or * COUNTRIES_3. */ -int16_t _findIndex(const char* const* list, const char* key) +std::optional _findIndex(const char* const* list, const char* key) { const char* const* anchor = list; int32_t pass = 0; @@ -1147,26 +1146,20 @@ int16_t _findIndex(const char* const* list, const char* key) } ++list; /* skip final nullptr *CWB*/ } - return -1; + return std::nullopt; } } // namespace U_CFUNC const char* uloc_getCurrentCountryID(const char* oldID){ - int32_t offset = _findIndex(DEPRECATED_COUNTRIES, oldID); - if (offset >= 0) { - return REPLACEMENT_COUNTRIES[offset]; - } - return oldID; + std::optional offset = _findIndex(DEPRECATED_COUNTRIES, oldID); + return offset.has_value() ? REPLACEMENT_COUNTRIES[offset.value()] : oldID; } U_CFUNC const char* uloc_getCurrentLanguageID(const char* oldID){ - int32_t offset = _findIndex(DEPRECATED_LANGUAGES, oldID); - if (offset >= 0) { - return REPLACEMENT_LANGUAGES[offset]; - } - return oldID; + std::optional offset = _findIndex(DEPRECATED_LANGUAGES, oldID); + return offset.has_value() ? REPLACEMENT_LANGUAGES[offset.value()] : oldID; } namespace { @@ -1230,9 +1223,9 @@ _getLanguage(const char* localeID, /* convert 3 character code to 2 character code if possible *CWB*/ U_ASSERT(capacity >= 4); buffer[3] = '\0'; - int32_t offset = _findIndex(LANGUAGES_3, buffer); - if(offset>=0) { - const char* const alias = LANGUAGES[offset]; + std::optional offset = _findIndex(LANGUAGES_3, buffer); + if (offset.has_value()) { + const char* const alias = LANGUAGES[offset.value()]; sink->Append(alias, (int32_t)uprv_strlen(alias)); return; } @@ -1311,9 +1304,9 @@ _getRegion(const char* localeID, /* convert 3 character code to 2 character code if possible *CWB*/ U_ASSERT(capacity >= 4); buffer[3] = '\0'; - int32_t offset = _findIndex(COUNTRIES_3, buffer); - if(offset>=0) { - const char* const alias = COUNTRIES[offset]; + std::optional offset = _findIndex(COUNTRIES_3, buffer); + if (offset.has_value()) { + const char* const alias = COUNTRIES[offset.value()]; sink->Append(alias, (int32_t)uprv_strlen(alias)); return; } @@ -1387,6 +1380,7 @@ _getVariant(const char* localeID, U_EXPORT CharString ulocimp_getLanguage(const char* localeID, UErrorCode& status) { + if (U_FAILURE(status)) { return {}; } CharString language; CharStringByteSink sink(&language); ulocimp_getSubtags( @@ -1402,6 +1396,7 @@ ulocimp_getLanguage(const char* localeID, UErrorCode& status) { U_EXPORT CharString ulocimp_getScript(const char* localeID, UErrorCode& status) { + if (U_FAILURE(status)) { return {}; } CharString script; CharStringByteSink sink(&script); ulocimp_getSubtags( @@ -1417,6 +1412,7 @@ ulocimp_getScript(const char* localeID, UErrorCode& status) { U_EXPORT CharString ulocimp_getRegion(const char* localeID, UErrorCode& status) { + if (U_FAILURE(status)) { return {}; } CharString region; CharStringByteSink sink(®ion); ulocimp_getSubtags( @@ -1432,6 +1428,7 @@ ulocimp_getRegion(const char* localeID, UErrorCode& status) { U_EXPORT CharString ulocimp_getVariant(const char* localeID, UErrorCode& status) { + if (U_FAILURE(status)) { return {}; } CharString variant; CharStringByteSink sink(&variant); ulocimp_getSubtags( @@ -1454,6 +1451,8 @@ ulocimp_getSubtags( CharString* variant, const char** pEnd, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + std::optional languageSink; std::optional scriptSink; std::optional regionSink; @@ -1619,12 +1618,11 @@ static const UEnumeration gKeywordsEnum = { U_CAPI UEnumeration* U_EXPORT2 uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status) { + if (U_FAILURE(*status)) { return nullptr; } + LocalMemory myContext; LocalMemory result; - if (U_FAILURE(*status)) { - return nullptr; - } myContext.adoptInstead(static_cast(uprv_malloc(sizeof(UKeywordsContext)))); result.adoptInstead(static_cast(uprv_malloc(sizeof(UEnumeration)))); if (myContext.isNull() || result.isNull()) { @@ -1648,13 +1646,13 @@ U_CAPI UEnumeration* U_EXPORT2 uloc_openKeywords(const char* localeID, UErrorCode* status) { - CharString tempBuffer; - const char* tmpLocaleID; - if(status==nullptr || U_FAILURE(*status)) { return 0; } + CharString tempBuffer; + const char* tmpLocaleID; + if (_hasBCP47Extension(localeID)) { CharStringByteSink sink(&tempBuffer); ulocimp_forLanguageTag(localeID, -1, sink, nullptr, *status); @@ -1889,13 +1887,12 @@ uloc_getParent(const char* localeID, CheckedArrayByteSink sink(parent, parentCapacity); ulocimp_getParent(localeID, sink, *err); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; } else { @@ -1910,12 +1907,11 @@ ulocimp_getParent(const char* localeID, icu::ByteSink& sink, UErrorCode& err) { + if (U_FAILURE(err)) { return; } + const char *lastUnderscore; int32_t i; - if (U_FAILURE(err)) - return; - if (localeID == nullptr) localeID = uloc_getDefault(); @@ -1956,13 +1952,12 @@ uloc_getLanguage(const char* localeID, nullptr, nullptr, *err); - - int32_t length = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return length; + return 0; } + int32_t length = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; return length; @@ -1990,13 +1985,12 @@ uloc_getScript(const char* localeID, nullptr, nullptr, *err); - - int32_t length = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return length; + return 0; } + int32_t length = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; return length; @@ -2024,13 +2018,12 @@ uloc_getCountry(const char* localeID, nullptr, nullptr, *err); - - int32_t length = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return length; + return 0; } + int32_t length = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; return length; @@ -2058,13 +2051,12 @@ uloc_getVariant(const char* localeID, &sink, nullptr, *err); - - int32_t length = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return length; + return 0; } + int32_t length = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; return length; @@ -2085,13 +2077,12 @@ uloc_getName(const char* localeID, CheckedArrayByteSink sink(name, nameCapacity); ulocimp_getName(localeID, sink, *err); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; } else { @@ -2121,13 +2112,12 @@ uloc_getBaseName(const char* localeID, CheckedArrayByteSink sink(name, nameCapacity); ulocimp_getBaseName(localeID, sink, *err); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; } else { @@ -2157,13 +2147,12 @@ uloc_canonicalize(const char* localeID, CheckedArrayByteSink sink(name, nameCapacity); ulocimp_canonicalize(localeID, sink, *err); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; } else { @@ -2184,7 +2173,6 @@ ulocimp_canonicalize(const char* localeID, U_CAPI const char* U_EXPORT2 uloc_getISO3Language(const char* localeID) { - int16_t offset; UErrorCode err = U_ZERO_ERROR; if (localeID == nullptr) @@ -2194,16 +2182,13 @@ uloc_getISO3Language(const char* localeID) CharString lang = ulocimp_getLanguage(localeID, err); if (U_FAILURE(err)) return ""; - offset = _findIndex(LANGUAGES, lang.data()); - if (offset < 0) - return ""; - return LANGUAGES_3[offset]; + std::optional offset = _findIndex(LANGUAGES, lang.data()); + return offset.has_value() ? LANGUAGES_3[offset.value()] : ""; } U_CAPI const char* U_EXPORT2 uloc_getISO3Country(const char* localeID) { - int16_t offset; UErrorCode err = U_ZERO_ERROR; if (localeID == nullptr) @@ -2213,11 +2198,8 @@ uloc_getISO3Country(const char* localeID) CharString cntry = ulocimp_getRegion(localeID, err); if (U_FAILURE(err)) return ""; - offset = _findIndex(COUNTRIES, cntry.data()); - if (offset < 0) - return ""; - - return COUNTRIES_3[offset]; + std::optional offset = _findIndex(COUNTRIES, cntry.data()); + return offset.has_value() ? COUNTRIES_3[offset.value()] : ""; } U_CAPI uint32_t U_EXPORT2 diff --git a/icu4c/source/common/uloc_tag.cpp b/icu4c/source/common/uloc_tag.cpp index b89867f771ac..878a34b6fd48 100644 --- a/icu4c/source/common/uloc_tag.cpp +++ b/icu4c/source/common/uloc_tag.cpp @@ -1169,12 +1169,9 @@ void _sortVariants(VariantListEntry* first) { void _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool& hadPosix, UErrorCode& status) { - UErrorCode tmpStatus = U_ZERO_ERROR; - - if (U_FAILURE(status)) { - return; - } + if (U_FAILURE(status)) { return; } + UErrorCode tmpStatus = U_ZERO_ERROR; icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus); if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { if (strict) { @@ -1280,6 +1277,8 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str void _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool hadPosix, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + icu::MemoryPool attrPool; icu::MemoryPool extPool; icu::MemoryPool strPool; @@ -1522,6 +1521,8 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str */ void _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendTo, icu::MemoryPool& extPool, icu::MemoryPool& kwdBuf, bool& posixVariant, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + const char *pTag; /* beginning of current subtag */ const char *pKwds; /* beginning of key-type pairs */ bool variantExists = posixVariant; @@ -1782,6 +1783,8 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT void _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + int32_t i, n; int32_t len; ExtensionListEntry *kwdFirst = nullptr; @@ -1791,10 +1794,6 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) icu::MemoryPool kwdBuf; bool posixVariant = false; - if (U_FAILURE(status)) { - return; - } - n = ultag_getExtensionsSize(langtag); /* resolve locale keywords and reordering keys */ @@ -1877,14 +1876,10 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) } void -_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool hadPosix, UErrorCode& status) { - (void)hadPosix; - UErrorCode tmpStatus = U_ZERO_ERROR; - - if (U_FAILURE(status)) { - return; - } +_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool /*hadPosix*/, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + UErrorCode tmpStatus = U_ZERO_ERROR; icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus); if (U_FAILURE(tmpStatus)) { if (strict) { @@ -1986,6 +1981,8 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool s ULanguageTag* ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& status) { + if (U_FAILURE(status)) { return nullptr; } + char *tagBuf; int16_t next; char *pSubtag, *pNext, *pLastGoodPosition; @@ -2001,10 +1998,6 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta *parsedLen = 0; } - if (U_FAILURE(status)) { - return nullptr; - } - if (tagLen < 0) { tagLen = (int32_t)uprv_strlen(tag); } @@ -2583,13 +2576,12 @@ uloc_toLanguageTag(const char* localeID, icu::CheckedArrayByteSink sink(langtag, langtagCapacity); ulocimp_toLanguageTag(localeID, sink, strict, *status); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*status)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *status = U_BUFFER_OVERFLOW_ERROR; } else { @@ -2605,6 +2597,8 @@ ulocimp_toLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + icu::CharString canonical; UErrorCode tmpStatus = U_ZERO_ERROR; bool hadPosix = false; @@ -2684,13 +2678,12 @@ uloc_forLanguageTag(const char* langtag, icu::CheckedArrayByteSink sink(localeID, localeIDCapacity); ulocimp_forLanguageTag(langtag, -1, sink, parsedLength, *status); - - int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*status)) { - return reslen; + return 0; } + int32_t reslen = sink.NumberOfBytesAppended(); + if (sink.Overflowed()) { *status = U_BUFFER_OVERFLOW_ERROR; } else { @@ -2707,6 +2700,8 @@ ulocimp_forLanguageTag(const char* langtag, icu::ByteSink& sink, int32_t* parsedLength, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + bool isEmpty = true; const char *subtag, *p; int32_t len; diff --git a/icu4c/source/common/ulocale.cpp b/icu4c/source/common/ulocale.cpp index 471ef0ce79a6..fada0afe3eb7 100644 --- a/icu4c/source/common/ulocale.cpp +++ b/icu4c/source/common/ulocale.cpp @@ -19,15 +19,17 @@ U_NAMESPACE_USE ULocale* ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) { + if (U_FAILURE(*err)) { return nullptr; } CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err); - if (U_FAILURE(*err)) return nullptr; + if (U_FAILURE(*err)) { return nullptr; } return EXTERNAL(icu::Locale::createFromName(str.data()).clone()); } ULocale* ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err) { + if (U_FAILURE(*err)) { return nullptr; } Locale l = icu::Locale::forLanguageTag(length < 0 ? StringPiece(tag) : StringPiece(tag, length), *err); - if (U_FAILURE(*err)) return nullptr; + if (U_FAILURE(*err)) { return nullptr; } return EXTERNAL(l.clone()); } @@ -57,10 +59,10 @@ int32_t ulocale_get ##N ( \ CONST_INTERNAL(locale)->get ## N( \ keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \ sink, *err); \ - int32_t reslen = sink.NumberOfBytesAppended(); \ if (U_FAILURE(*err)) { \ - return reslen; \ + return 0; \ } \ + int32_t reslen = sink.NumberOfBytesAppended(); \ if (sink.Overflowed()) { \ *err = U_BUFFER_OVERFLOW_ERROR; \ } else { \ diff --git a/icu4c/source/common/ulocbuilder.cpp b/icu4c/source/common/ulocbuilder.cpp index a5af73bef490..a3e14fad6437 100644 --- a/icu4c/source/common/ulocbuilder.cpp +++ b/icu4c/source/common/ulocbuilder.cpp @@ -112,12 +112,13 @@ ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) { int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder, char* buffer, int32_t bufferCapacity, UErrorCode* err) { + if (U_FAILURE(*err)) { return 0; } if (builder == nullptr) { *err = U_ILLEGAL_ARGUMENT_ERROR; return 0; } icu::Locale l = INTERNAL(builder)->build(*err); - if (U_FAILURE(*err)) return 0; + if (U_FAILURE(*err)) { return 0; } int32_t length = (int32_t)(uprv_strlen(l.getName())); if (0 < length && length <= bufferCapacity) { uprv_memcpy(buffer, l.getName(), length); @@ -127,18 +128,17 @@ int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder, int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder, char* buffer, int32_t bufferCapacity, UErrorCode* err) { + if (U_FAILURE(*err)) { return 0; } if (builder == nullptr) { *err = U_ILLEGAL_ARGUMENT_ERROR; return 0; } icu::Locale l = INTERNAL(builder)->build(*err); - if (U_FAILURE(*err)) return 0; + if (U_FAILURE(*err)) { return 0; } CheckedArrayByteSink sink(buffer, bufferCapacity); l.toLanguageTag(sink, *err); + if (U_FAILURE(*err)) { return 0; } int32_t reslen = sink.NumberOfBytesAppended(); - if (U_FAILURE(*err)) { - return reslen; - } if (sink.Overflowed()) { *err = U_BUFFER_OVERFLOW_ERROR; } else { diff --git a/icu4c/source/common/unicode/localematcher.h b/icu4c/source/common/unicode/localematcher.h index 3e62c67c7e16..e16f1a31ca50 100644 --- a/icu4c/source/common/unicode/localematcher.h +++ b/icu4c/source/common/unicode/localematcher.h @@ -11,6 +11,8 @@ #if U_SHOW_CPLUSPLUS_API +#include + #include "unicode/locid.h" #include "unicode/stringpiece.h" #include "unicode/uobject.h" @@ -678,7 +680,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode); - int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; + std::optional getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; const LikelySubtags &likelySubtags; const LocaleDistance &localeDistance; diff --git a/icu4c/source/common/unicode/locid.h b/icu4c/source/common/unicode/locid.h index 9acc67341ab1..8ec8d3e3aece 100644 --- a/icu4c/source/common/unicode/locid.h +++ b/icu4c/source/common/unicode/locid.h @@ -1183,6 +1183,7 @@ Locale::operator!=(const Locale& other) const template inline StringClass Locale::toLanguageTag(UErrorCode& status) const { + if (U_FAILURE(status)) { return {}; } StringClass result; StringByteSink sink(&result); toLanguageTag(sink, status); @@ -1222,6 +1223,7 @@ Locale::getName() const template inline void Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const { + if (U_FAILURE(status)) { return; } LocalPointer keys(createKeywords(status)); if (U_FAILURE(status) || keys.isNull()) { return; @@ -1239,6 +1241,7 @@ Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const template inline void Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const { + if (U_FAILURE(status)) { return; } LocalPointer keys(createUnicodeKeywords(status)); if (U_FAILURE(status) || keys.isNull()) { return; @@ -1256,6 +1259,7 @@ Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const template inline StringClass Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const { + if (U_FAILURE(status)) { return {}; } StringClass result; StringByteSink sink(&result); getKeywordValue(keywordName, sink, status); @@ -1265,6 +1269,7 @@ Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const template inline StringClass Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const { + if (U_FAILURE(status)) { return {}; } StringClass result; StringByteSink sink(&result); getUnicodeKeywordValue(keywordName, sink, status); diff --git a/icu4c/source/i18n/ulocdata.cpp b/icu4c/source/i18n/ulocdata.cpp index a6854a527aa8..a1b2daa4436a 100644 --- a/icu4c/source/i18n/ulocdata.cpp +++ b/icu4c/source/i18n/ulocdata.cpp @@ -201,6 +201,8 @@ ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type, namespace { UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){ + if (U_FAILURE(*status)) { return nullptr; } + UResourceBundle *rb; UResourceBundle *measTypeBundle = nullptr; @@ -279,6 +281,7 @@ ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UEr U_CAPI void U_EXPORT2 ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) { + if (U_FAILURE(*status)) { return; } UResourceBundle *rb = nullptr; rb = ures_openDirect(nullptr, "supplementalData", status); ures_getVersionByKey(rb, "cldrVersion", versionArray, status); diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c index 1f0a84b866c9..2935450be2ee 100644 --- a/icu4c/source/test/cintltst/cloctst.c +++ b/icu4c/source/test/cintltst/cloctst.c @@ -5946,19 +5946,19 @@ const errorData maximizeErrors[] = { "enfueiujhytdf", NULL, U_ILLEGAL_ARGUMENT_ERROR, - -1 + 0 }, { "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", NULL, U_ILLEGAL_ARGUMENT_ERROR, - -1 + 0 }, { "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", NULL, U_ILLEGAL_ARGUMENT_ERROR, - -1 + 0 }, { "en_Latn_US_POSIX@currency=EURO", @@ -5979,13 +5979,13 @@ const errorData minimizeErrors[] = { "enfueiujhytdf", NULL, U_ILLEGAL_ARGUMENT_ERROR, - -1 + 0 }, { "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG", NULL, U_ILLEGAL_ARGUMENT_ERROR, - -1 + 0 }, { "en_Latn_US_POSIX@currency=EURO", @@ -6010,7 +6010,7 @@ static int32_t getExpectedReturnValue(const errorData* data) } else { - return -1; + return 0; } }