From a6efa924ad04f7e3c7ad325237bf026b39abe4e8 Mon Sep 17 00:00:00 2001 From: Fredrik Roubert Date: Tue, 6 Feb 2024 20:02:50 +0100 Subject: [PATCH] ICU-22520 Let ulocimp_getRegionForSupplementalData() return CharString. --- icu4c/source/common/loclikely.cpp | 8 ++--- icu4c/source/common/ucurr.cpp | 51 ++++++++++++++----------------- icu4c/source/common/ulocimp.h | 15 +++------ icu4c/source/i18n/calendar.cpp | 10 +++--- icu4c/source/i18n/dtptngen.cpp | 7 ++--- icu4c/source/i18n/ucal.cpp | 7 ++--- icu4c/source/i18n/ulocdata.cpp | 10 +++--- icu4c/source/i18n/units_data.cpp | 7 ++--- 8 files changed, 50 insertions(+), 65 deletions(-) diff --git a/icu4c/source/common/loclikely.cpp b/icu4c/source/common/loclikely.cpp index abb7d029da7..b0e61596c40 100644 --- a/icu4c/source/common/loclikely.cpp +++ b/icu4c/source/common/loclikely.cpp @@ -580,11 +580,11 @@ GetRegionFromKey(const char* localeID, const char* key, UErrorCode& status) { } } // namespace -U_CAPI int32_t U_EXPORT2 +U_EXPORT icu::CharString U_EXPORT2 ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, - char *region, int32_t regionCapacity, UErrorCode* status) { + UErrorCode* status) { if (U_FAILURE(*status)) { - return 0; + return {}; } icu::CharString rgBuf = GetRegionFromKey(localeID, "rg", *status); if (U_SUCCESS(*status) && rgBuf.isEmpty()) { @@ -608,5 +608,5 @@ ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, } } - return rgBuf.extract(region, regionCapacity, *status); + return rgBuf; } diff --git a/icu4c/source/common/ucurr.cpp b/icu4c/source/common/ucurr.cpp index 70b1bbf2239..a112df80b63 100644 --- a/icu4c/source/common/ucurr.cpp +++ b/icu4c/source/common/ucurr.cpp @@ -349,10 +349,10 @@ _findMetaData(const char16_t* currency, UErrorCode& ec) { // ------------------------------------- -static void -idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec) +static CharString +idForLocale(const char* locale, UErrorCode* ec) { - ulocimp_getRegionForSupplementalData(locale, false, countryAndVariant, capacity, ec); + return ulocimp_getRegionForSupplementalData(locale, false, ec); } // ------------------------------------------ @@ -464,9 +464,8 @@ U_CAPI UCurrRegistryKey U_EXPORT2 ucurr_register(const char16_t* isoCode, const char* locale, UErrorCode *status) { if (status && U_SUCCESS(*status)) { - char id[ULOC_FULLNAME_CAPACITY]; - idForLocale(locale, id, sizeof(id), status); - return CReg::reg(isoCode, id, status); + CharString id = idForLocale(locale, status); + return CReg::reg(isoCode, id.data(), status); } return nullptr; } @@ -540,14 +539,13 @@ ucurr_forLocale(const char* locale, } // get country or country_variant in `id' - char id[ULOC_FULLNAME_CAPACITY]; - idForLocale(locale, id, UPRV_LENGTHOF(id), ec); + CharString id = idForLocale(locale, ec); if (U_FAILURE(*ec)) { return 0; } #if !UCONFIG_NO_SERVICE - const char16_t* result = CReg::get(id); + const char16_t* result = CReg::get(id.data()); if (result) { if(buffCapacity > u_strlen(result)) { u_strcpy(buff, result); @@ -557,13 +555,13 @@ ucurr_forLocale(const char* locale, } #endif // Remove variants, which is only needed for registration. - char *idDelim = uprv_strchr(id, VAR_DELIM); + char *idDelim = uprv_strchr(id.data(), VAR_DELIM); if (idDelim) { - idDelim[0] = 0; + id.truncate(idDelim - id.data()); } const char16_t* s = nullptr; // Currency code from data file. - if (id[0] == 0) { + if (id.isEmpty()) { // No point looking in the data for an empty string. // This is what we would get. localStatus = U_MISSING_RESOURCE_ERROR; @@ -572,7 +570,7 @@ ucurr_forLocale(const char* locale, localStatus = U_ZERO_ERROR; UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus); UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); - UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); + UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus); // https://unicode-org.atlassian.net/browse/ICU-21997 // Prefer to use currencies that are legal tender. if (U_SUCCESS(localStatus)) { @@ -602,7 +600,7 @@ ucurr_forLocale(const char* locale, ures_close(countryArray); } - if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) { + if ((U_FAILURE(localStatus)) && strchr(id.data(), '_') != 0) { // We don't know about it. Check to see if we support the variant. CharString parent; { @@ -2325,10 +2323,9 @@ ucurr_countCurrencies(const char* locale, { // local variables UErrorCode localStatus = U_ZERO_ERROR; - char id[ULOC_FULLNAME_CAPACITY]; // get country or country_variant in `id' - idForLocale(locale, id, sizeof(id), ec); + CharString id = idForLocale(locale, ec); if (U_FAILURE(*ec)) { @@ -2336,10 +2333,10 @@ ucurr_countCurrencies(const char* locale, } // Remove variants, which is only needed for registration. - char *idDelim = strchr(id, VAR_DELIM); + char *idDelim = strchr(id.data(), VAR_DELIM); if (idDelim) { - idDelim[0] = 0; + id.truncate(idDelim - id.data()); } // Look up the CurrencyMap element in the root bundle. @@ -2347,7 +2344,7 @@ ucurr_countCurrencies(const char* locale, UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); // Using the id derived from the local, get the currency data - UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); + UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus); // process each currency to see which one is valid for the given date if (U_SUCCESS(localStatus)) @@ -2440,20 +2437,19 @@ ucurr_forLocaleAndDate(const char* locale, { // local variables UErrorCode localStatus = U_ZERO_ERROR; - char id[ULOC_FULLNAME_CAPACITY]; // get country or country_variant in `id' - idForLocale(locale, id, sizeof(id), ec); + CharString id = idForLocale(locale, ec); if (U_FAILURE(*ec)) { return 0; } // Remove variants, which is only needed for registration. - char *idDelim = strchr(id, VAR_DELIM); + char *idDelim = strchr(id.data(), VAR_DELIM); if (idDelim) { - idDelim[0] = 0; + id.truncate(idDelim - id.data()); } // Look up the CurrencyMap element in the root bundle. @@ -2461,7 +2457,7 @@ ucurr_forLocaleAndDate(const char* locale, UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); // Using the id derived from the local, get the currency data - UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); + UResourceBundle *countryArray = ures_getByKey(rb, id.data(), cm, &localStatus); // process each currency to see which one is valid for the given date bool matchFound = false; @@ -2587,9 +2583,8 @@ static const UEnumeration defaultKeywordValues = { U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) { // Resolve region - char prefRegion[ULOC_COUNTRY_CAPACITY]; - ulocimp_getRegionForSupplementalData(locale, true, prefRegion, sizeof(prefRegion), status); - + CharString prefRegion = ulocimp_getRegionForSupplementalData(locale, true, status); + // Read value from supplementalData UList *values = ulist_createEmptyList(status); UList *otherValues = ulist_createEmptyList(status); @@ -2621,7 +2616,7 @@ U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, break; } const char *region = ures_getKey(&bundlekey); - UBool isPrefRegion = uprv_strcmp(region, prefRegion) == 0 ? true : false; + UBool isPrefRegion = prefRegion == region; if (!isPrefRegion && commonlyUsed) { // With commonlyUsed=true, we do not put // currencies for other regions in the diff --git a/icu4c/source/common/ulocimp.h b/icu4c/source/common/ulocimp.h index bcfe75d1699..bbc07cb591b 100644 --- a/icu4c/source/common/ulocimp.h +++ b/icu4c/source/common/ulocimp.h @@ -212,28 +212,23 @@ ulocimp_forLanguageTag(const char* langtag, * (2) any unicode_region_tag in the locale ID; if none then * (3) if inferRegion is true, the region suggested by * getLikelySubtags on the localeID. - * If no region is found, returns length 0. - * + * If no region is found, returns an empty string. + * * @param localeID * The complete locale ID (with keywords) from which * to get the region to use for supplemental data. * @param inferRegion * If true, will try to infer region from localeID if * no other region is found. - * @param region - * Buffer in which to put the region ID found; should - * have a capacity at least ULOC_COUNTRY_CAPACITY. - * @param regionCapacity - * The actual capacity of the region buffer. * @param status * Pointer to in/out UErrorCode value for latest status. * @return - * The length of any region code found, or 0 if none. + * The region code found, empty if none found. * @internal ICU 57 */ -U_CAPI int32_t U_EXPORT2 +U_EXPORT icu::CharString U_EXPORT2 ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, - char *region, int32_t regionCapacity, UErrorCode* status); + UErrorCode* status); /** * Add the likely subtags for a provided locale ID, per the algorithm described diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp index 0382704ab56..970d5733933 100644 --- a/icu4c/source/i18n/calendar.cpp +++ b/icu4c/source/i18n/calendar.cpp @@ -283,8 +283,7 @@ static ECalType getCalendarTypeForLocale(const char *locid) { // when calendar keyword is not available or not supported, read supplementalData // to get the default calendar type for the locale's region - char region[ULOC_COUNTRY_CAPACITY]; - (void)ulocimp_getRegionForSupplementalData(canonicalName.data(), true, region, sizeof(region), &status); + CharString region = ulocimp_getRegionForSupplementalData(canonicalName.data(), true, &status); if (U_FAILURE(status)) { return CALTYPE_GREGORIAN; } @@ -292,7 +291,7 @@ static ECalType getCalendarTypeForLocale(const char *locid) { // Read preferred calendar values from supplementalData calendarPreference UResourceBundle *rb = ures_openDirect(nullptr, "supplementalData", &status); ures_getByKey(rb, "calendarPreferenceData", rb, &status); - UResourceBundle *order = ures_getByKey(rb, region, nullptr, &status); + UResourceBundle *order = ures_getByKey(rb, region.data(), nullptr, &status); if (status == U_MISSING_RESOURCE_ERROR && rb != nullptr) { status = U_ZERO_ERROR; order = ures_getByKey(rb, "001", nullptr, &status); @@ -4027,13 +4026,12 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode& return; } - char region[ULOC_COUNTRY_CAPACITY]; - (void)ulocimp_getRegionForSupplementalData(desiredLocale.getName(), true, region, sizeof(region), &status); + CharString region = ulocimp_getRegionForSupplementalData(desiredLocale.getName(), true, &status); // Read week data values from supplementalData week data UResourceBundle *rb = ures_openDirect(nullptr, "supplementalData", &status); ures_getByKey(rb, "weekData", rb, &status); - UResourceBundle *weekData = ures_getByKey(rb, region, nullptr, &status); + UResourceBundle *weekData = ures_getByKey(rb, region.data(), nullptr, &status); if (status == U_MISSING_RESOURCE_ERROR && rb != nullptr) { status = U_ZERO_ERROR; weekData = ures_getByKey(rb, "001", nullptr, &status); diff --git a/icu4c/source/i18n/dtptngen.cpp b/icu4c/source/i18n/dtptngen.cpp index aa23b7cd4a6..31e851de144 100644 --- a/icu4c/source/i18n/dtptngen.cpp +++ b/icu4c/source/i18n/dtptngen.cpp @@ -658,10 +658,9 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro if (U_FAILURE(status)) { return; } const char *language = locale.getLanguage(); - char baseCountry[8]; - ulocimp_getRegionForSupplementalData(locale.getName(), false, baseCountry, 8, &status); - const char* country = baseCountry; - + CharString baseCountry = ulocimp_getRegionForSupplementalData(locale.getName(), false, &status); + const char* country = baseCountry.data(); + Locale maxLocale; // must be here for correct lifetime if (*language == '\0' || *country == '\0') { maxLocale = locale; diff --git a/icu4c/source/i18n/ucal.cpp b/icu4c/source/i18n/ucal.cpp index c8ff4fb133c..8b07bd1afea 100644 --- a/icu4c/source/i18n/ucal.cpp +++ b/icu4c/source/i18n/ucal.cpp @@ -716,13 +716,12 @@ static const char * const CAL_TYPES[] = { U_CAPI UEnumeration* U_EXPORT2 ucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool commonlyUsed, UErrorCode *status) { // Resolve region - char prefRegion[ULOC_COUNTRY_CAPACITY]; - (void)ulocimp_getRegionForSupplementalData(locale, true, prefRegion, sizeof(prefRegion), status); - + CharString prefRegion = ulocimp_getRegionForSupplementalData(locale, true, status); + // Read preferred calendar values from supplementalData calendarPreference UResourceBundle *rb = ures_openDirect(nullptr, "supplementalData", status); ures_getByKey(rb, "calendarPreferenceData", rb, status); - UResourceBundle *order = ures_getByKey(rb, prefRegion, nullptr, status); + UResourceBundle *order = ures_getByKey(rb, prefRegion.data(), nullptr, status); if (*status == U_MISSING_RESOURCE_ERROR && rb != nullptr) { *status = U_ZERO_ERROR; order = ures_getByKey(rb, "001", nullptr, status); diff --git a/icu4c/source/i18n/ulocdata.cpp b/icu4c/source/i18n/ulocdata.cpp index 0aab6295819..7bb6b3b8f5f 100644 --- a/icu4c/source/i18n/ulocdata.cpp +++ b/icu4c/source/i18n/ulocdata.cpp @@ -16,6 +16,7 @@ * created by: Ram Viswanadha,John Emmons */ +#include "charstr.h" #include "cmemory.h" #include "unicode/ustring.h" #include "unicode/ures.h" @@ -198,16 +199,15 @@ ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type, } static UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){ - char region[ULOC_COUNTRY_CAPACITY]; UResourceBundle *rb; UResourceBundle *measTypeBundle = nullptr; - - ulocimp_getRegionForSupplementalData(localeID, true, region, ULOC_COUNTRY_CAPACITY, status); - + + icu::CharString region = ulocimp_getRegionForSupplementalData(localeID, true, status); + rb = ures_openDirect(nullptr, "supplementalData", status); ures_getByKey(rb, "measurementData", rb, status); if (rb != nullptr) { - UResourceBundle *measDataBundle = ures_getByKey(rb, region, nullptr, status); + UResourceBundle *measDataBundle = ures_getByKey(rb, region.data(), nullptr, status); if (U_SUCCESS(*status)) { measTypeBundle = ures_getByKey(measDataBundle, measurementType, nullptr, status); } diff --git a/icu4c/source/i18n/units_data.cpp b/icu4c/source/i18n/units_data.cpp index 7a7525f424e..24bbb190715 100644 --- a/icu4c/source/i18n/units_data.cpp +++ b/icu4c/source/i18n/units_data.cpp @@ -6,6 +6,7 @@ #if !UCONFIG_NO_FORMATTING #include "bytesinkutil.h" +#include "charstr.h" #include "cstring.h" #include "measunit_impl.h" #include "number_decimalquantity.h" @@ -443,10 +444,8 @@ MaybeStackVector } } - char regionBuf[8]; - ulocimp_getRegionForSupplementalData(locale.getName(), false, regionBuf, 8, &status); - CharString region(regionBuf, status); - + CharString region = ulocimp_getRegionForSupplementalData(locale.getName(), false, &status); + // Check the locale system tag, e.g `ms=metric`. UErrorCode internalMeasureTagStatus = U_ZERO_ERROR; CharString localeSystem = getKeyWordValue(locale, "measure", internalMeasureTagStatus);