Apply 3 upstream CLs beyond 59.1
http://www.icu-project.org/trac/ticket/12333
http://www.icu-project.org/trac/ticket/13189
http://www.icu-project.org/trac/ticket/12635
- patches/ucase_utf8.patch
- patches/ucurr_locale.patch
- patches/collator_range.patch
Bug=chromium:722124
TEST=See the test
TBR=inferno@chromium.org
Change-Id: I3e754734a1c1121c8059a386ca1b5d0f004adb79
Reviewed-on: https://chromium-review.googlesource.com/506592
Reviewed-by: Abhishek Arya <inferno@chromium.org>
Reviewed-by: Jungshik Shin <jshin@chromium.org>
diff --git a/README.chromium b/README.chromium
index 6b1850e..1dce619 100644
--- a/README.chromium
+++ b/README.chromium
@@ -286,4 +286,12 @@
- patches/string_literal_charptr.patch
-
+8. Apply post-59 upstream fixes
+
+ http://www.icu-project.org/trac/ticket/12333
+ http://www.icu-project.org/trac/ticket/13189
+ http://www.icu-project.org/trac/ticket/12635
+
+ - patches/ucase_utf8.patch
+ - patches/ucurr_locale.patch
+ - patches/collator_range.patch
diff --git a/patches/collator_range.patch b/patches/collator_range.patch
new file mode 100644
index 0000000..4d3e383
--- /dev/null
+++ b/patches/collator_range.patch
@@ -0,0 +1,13 @@
+diff --git a/source/i18n/collationweights.cpp b/source/i18n/collationweights.cpp
+index c60da2d8..05458962 100644
+--- a/source/i18n/collationweights.cpp
++++ b/source/i18n/collationweights.cpp
+@@ -527,7 +527,7 @@ CollationWeights::allocWeights(uint32_t lowerLimit, uint32_t upperLimit, int32_t
+ #ifdef UCOL_DEBUG
+ printf("lengthen the short ranges from %ld bytes to %ld and iterate\n", minLength, minLength+1);
+ #endif
+- for(int32_t i=0; ranges[i].length==minLength; ++i) {
++ for(int32_t i=0; i<rangeCount && ranges[i].length==minLength; ++i) {
+ lengthenRange(ranges[i]);
+ }
+ }
diff --git a/patches/ucase_utf8.patch b/patches/ucase_utf8.patch
new file mode 100644
index 0000000..0780ece
--- /dev/null
+++ b/patches/ucase_utf8.patch
@@ -0,0 +1,58 @@
+diff --git a/source/common/ucase.cpp b/source/common/ucase.cpp
+index 706d7289..6b22f9e3 100644
+--- a/source/common/ucase.cpp
++++ b/source/common/ucase.cpp
+@@ -961,6 +961,7 @@ ucase_toFullLower(UChar32 c,
+ 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
+ 0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE
+ */
++ *pString=nullptr;
+ return 0; /* remove the dot (continue without output) */
+ } else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) {
+ /*
+@@ -1059,6 +1060,7 @@ toUpperOrTitle(UChar32 c,
+
+ 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
+ */
++ *pString=nullptr;
+ return 0; /* remove the dot (continue without output) */
+ } else {
+ /* no known conditional special case mapping, use a normal mapping */
+diff --git a/source/common/ucasemap.cpp b/source/common/ucasemap.cpp
+index 391140d6..1523cb6d 100644
+--- a/source/common/ucasemap.cpp
++++ b/source/common/ucasemap.cpp
+@@ -177,18 +177,22 @@ appendResult(uint8_t *dest, int32_t destIndex, int32_t destCapacity,
+ } else {
+ if(result<=UCASE_MAX_STRING_LENGTH) {
+ // string: "result" is the UTF-16 length
+- errorCode=U_ZERO_ERROR;
+- if(destIndex<destCapacity) {
+- u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
+- s, result, &errorCode);
++ if(result==0) {
++ length=0;
+ } else {
+- u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
+- }
+- if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
+- return -1;
+- }
+- if(length>(INT32_MAX-destIndex)) {
+- return -1; // integer overflow
++ errorCode=U_ZERO_ERROR;
++ if(destIndex<destCapacity) {
++ u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
++ s, result, &errorCode);
++ } else {
++ u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
++ }
++ if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
++ return -1;
++ }
++ if(length>(INT32_MAX-destIndex)) {
++ return -1; // integer overflow
++ }
+ }
+ if(edits!=NULL) {
+ edits->addReplace(cpLength, length);
diff --git a/patches/ucurr_locale.patch b/patches/ucurr_locale.patch
new file mode 100644
index 0000000..062afad
--- /dev/null
+++ b/patches/ucurr_locale.patch
@@ -0,0 +1,212 @@
+diff --git a/source/common/ucurr.cpp b/source/common/ucurr.cpp
+index 885ca3a9..f2cae13c 100644
+--- a/source/common/ucurr.cpp
++++ b/source/common/ucurr.cpp
+@@ -25,6 +25,7 @@
+ #include "uenumimp.h"
+ #include "uhash.h"
+ #include "hash.h"
++#include "uinvchar.h"
+ #include "uresimp.h"
+ #include "ulist.h"
+ #include "ureslocs.h"
+@@ -545,93 +546,97 @@ U_CAPI int32_t U_EXPORT2
+ ucurr_forLocale(const char* locale,
+ UChar* buff,
+ int32_t buffCapacity,
+- UErrorCode* ec)
+-{
+- int32_t resLen = 0;
+- const UChar* s = NULL;
+- if (ec != NULL && U_SUCCESS(*ec)) {
+- if ((buff && buffCapacity) || !buffCapacity) {
+- UErrorCode localStatus = U_ZERO_ERROR;
+- char id[ULOC_FULLNAME_CAPACITY];
+- if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
+- // there is a currency keyword. Try to see if it's valid
+- if(buffCapacity > resLen) {
+- /* Normalize the currency keyword value to upper case. */
+- T_CString_toUpperCase(id);
+- u_charsToUChars(id, buff, resLen);
+- }
+- } else {
+- // get country or country_variant in `id'
+- uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
++ UErrorCode* ec) {
++ if (U_FAILURE(*ec)) { return 0; }
++ if (buffCapacity < 0 || (buff == nullptr && buffCapacity > 0)) {
++ *ec = U_ILLEGAL_ARGUMENT_ERROR;
++ return 0;
++ }
+
+- if (U_FAILURE(*ec)) {
+- return 0;
+- }
++ char currency[4]; // ISO currency codes are alpha3 codes.
++ UErrorCode localStatus = U_ZERO_ERROR;
++ int32_t resLen = uloc_getKeywordValue(locale, "currency",
++ currency, UPRV_LENGTHOF(currency), &localStatus);
++ if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency, resLen)) {
++ if (resLen < buffCapacity) {
++ T_CString_toUpperCase(currency);
++ u_charsToUChars(currency, buff, resLen);
++ }
++ return u_terminateUChars(buff, buffCapacity, resLen, ec);
++ }
++
++ // get country or country_variant in `id'
++ char id[ULOC_FULLNAME_CAPACITY];
++ uint32_t variantType = idForLocale(locale, id, UPRV_LENGTHOF(id), ec);
++ if (U_FAILURE(*ec)) {
++ return 0;
++ }
+
+ #if !UCONFIG_NO_SERVICE
+- const UChar* result = CReg::get(id);
+- if (result) {
+- if(buffCapacity > u_strlen(result)) {
+- u_strcpy(buff, result);
+- }
+- return u_strlen(result);
+- }
++ const UChar* result = CReg::get(id);
++ if (result) {
++ if(buffCapacity > u_strlen(result)) {
++ u_strcpy(buff, result);
++ }
++ resLen = u_strlen(result);
++ return u_terminateUChars(buff, buffCapacity, resLen, ec);
++ }
+ #endif
+- // Remove variants, which is only needed for registration.
+- char *idDelim = strchr(id, VAR_DELIM);
+- if (idDelim) {
+- idDelim[0] = 0;
+- }
++ // Remove variants, which is only needed for registration.
++ char *idDelim = uprv_strchr(id, VAR_DELIM);
++ if (idDelim) {
++ idDelim[0] = 0;
++ }
+
+- // Look up the CurrencyMap element in the root bundle.
+- 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 *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
++ const UChar* s; // Currency code from data file.
++ if (id[0] == 0) {
++ // No point looking in the data for an empty string.
++ // This is what we would get.
++ localStatus = U_MISSING_RESOURCE_ERROR;
++ } else {
++ // Look up the CurrencyMap element in the root bundle.
++ 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 *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
++ s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
++
++ // Get the second item when PREEURO is requested, and this is a known Euro country.
++ // If the requested variant is PREEURO, and this isn't a Euro country,
++ // assume that the country changed over to the Euro in the future.
++ // This is probably an old version of ICU that hasn't been updated yet.
++ // The latest currency is probably correct.
++ if (U_SUCCESS(localStatus)) {
++ if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
++ currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
+ s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
+-
+- /*
+- Get the second item when PREEURO is requested, and this is a known Euro country.
+- If the requested variant is PREEURO, and this isn't a Euro country, assume
+- that the country changed over to the Euro in the future. This is probably
+- an old version of ICU that hasn't been updated yet. The latest currency is
+- probably correct.
+- */
+- if (U_SUCCESS(localStatus)) {
+- if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
+- currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
+- s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
+- }
+- else if ((variantType & VARIANT_IS_EURO)) {
+- s = EUR_STR;
+- }
+- }
+- ures_close(countryArray);
+- ures_close(currencyReq);
+-
+- if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
+- {
+- // We don't know about it. Check to see if we support the variant.
+- uloc_getParent(locale, id, sizeof(id), ec);
+- *ec = U_USING_FALLBACK_WARNING;
+- return ucurr_forLocale(id, buff, buffCapacity, ec);
+- }
+- else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
+- // There is nothing to fallback to. Report the failure/warning if possible.
+- *ec = localStatus;
+- }
+- if (U_SUCCESS(*ec)) {
+- if(buffCapacity > resLen) {
+- u_strcpy(buff, s);
+- }
+- }
++ } else if ((variantType & VARIANT_IS_EURO)) {
++ s = EUR_STR;
+ }
+- return u_terminateUChars(buff, buffCapacity, resLen, ec);
+- } else {
+- *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ }
++ ures_close(currencyReq);
++ ures_close(countryArray);
+ }
+- return resLen;
++
++ if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) {
++ // We don't know about it. Check to see if we support the variant.
++ uloc_getParent(locale, id, UPRV_LENGTHOF(id), ec);
++ *ec = U_USING_FALLBACK_WARNING;
++ // TODO: Loop over the shortened id rather than recursing and
++ // looking again for a currency keyword.
++ return ucurr_forLocale(id, buff, buffCapacity, ec);
++ }
++ if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
++ // There is nothing to fallback to. Report the failure/warning if possible.
++ *ec = localStatus;
++ }
++ if (U_SUCCESS(*ec)) {
++ if(buffCapacity > resLen) {
++ u_strcpy(buff, s);
++ }
++ }
++ return u_terminateUChars(buff, buffCapacity, resLen, ec);
+ }
+
+ // end registration
+diff --git a/source/i18n/dcfmtsym.cpp b/source/i18n/dcfmtsym.cpp
+index 08a85b54..43eea49e 100644
+--- a/source/i18n/dcfmtsym.cpp
++++ b/source/i18n/dcfmtsym.cpp
+@@ -433,12 +433,13 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool us
+ UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
+ UChar curriso[4];
+ UnicodeString tempStr;
+- ucurr_forLocale(locStr, curriso, 4, &internalStatus);
+-
+- uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
+- if (U_SUCCESS(internalStatus)) {
+- fSymbols[kIntlCurrencySymbol].setTo(curriso, -1);
+- fSymbols[kCurrencySymbol] = tempStr;
++ int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus);
++ if (U_SUCCESS(internalStatus) && currisoLength == 3) {
++ uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
++ if (U_SUCCESS(internalStatus)) {
++ fSymbols[kIntlCurrencySymbol].setTo(curriso, currisoLength);
++ fSymbols[kCurrencySymbol] = tempStr;
++ }
+ }
+ /* else use the default values. */
+
diff --git a/source/common/ucase.cpp b/source/common/ucase.cpp
index 706d728..6b22f9e 100644
--- a/source/common/ucase.cpp
+++ b/source/common/ucase.cpp
@@ -961,6 +961,7 @@
0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE
*/
+ *pString=nullptr;
return 0; /* remove the dot (continue without output) */
} else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) {
/*
@@ -1059,6 +1060,7 @@
0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
*/
+ *pString=nullptr;
return 0; /* remove the dot (continue without output) */
} else {
/* no known conditional special case mapping, use a normal mapping */
diff --git a/source/common/ucasemap.cpp b/source/common/ucasemap.cpp
index 391140d..1523cb6 100644
--- a/source/common/ucasemap.cpp
+++ b/source/common/ucasemap.cpp
@@ -177,18 +177,22 @@
} else {
if(result<=UCASE_MAX_STRING_LENGTH) {
// string: "result" is the UTF-16 length
- errorCode=U_ZERO_ERROR;
- if(destIndex<destCapacity) {
- u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
- s, result, &errorCode);
+ if(result==0) {
+ length=0;
} else {
- u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
- }
- if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
- return -1;
- }
- if(length>(INT32_MAX-destIndex)) {
- return -1; // integer overflow
+ errorCode=U_ZERO_ERROR;
+ if(destIndex<destCapacity) {
+ u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
+ s, result, &errorCode);
+ } else {
+ u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
+ }
+ if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
+ return -1;
+ }
+ if(length>(INT32_MAX-destIndex)) {
+ return -1; // integer overflow
+ }
}
if(edits!=NULL) {
edits->addReplace(cpLength, length);
diff --git a/source/common/ucurr.cpp b/source/common/ucurr.cpp
index 885ca3a..f2cae13 100644
--- a/source/common/ucurr.cpp
+++ b/source/common/ucurr.cpp
@@ -25,6 +25,7 @@
#include "uenumimp.h"
#include "uhash.h"
#include "hash.h"
+#include "uinvchar.h"
#include "uresimp.h"
#include "ulist.h"
#include "ureslocs.h"
@@ -545,93 +546,97 @@
ucurr_forLocale(const char* locale,
UChar* buff,
int32_t buffCapacity,
- UErrorCode* ec)
-{
- int32_t resLen = 0;
- const UChar* s = NULL;
- if (ec != NULL && U_SUCCESS(*ec)) {
- if ((buff && buffCapacity) || !buffCapacity) {
- UErrorCode localStatus = U_ZERO_ERROR;
- char id[ULOC_FULLNAME_CAPACITY];
- if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
- // there is a currency keyword. Try to see if it's valid
- if(buffCapacity > resLen) {
- /* Normalize the currency keyword value to upper case. */
- T_CString_toUpperCase(id);
- u_charsToUChars(id, buff, resLen);
- }
- } else {
- // get country or country_variant in `id'
- uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
+ UErrorCode* ec) {
+ if (U_FAILURE(*ec)) { return 0; }
+ if (buffCapacity < 0 || (buff == nullptr && buffCapacity > 0)) {
+ *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
- if (U_FAILURE(*ec)) {
- return 0;
- }
+ char currency[4]; // ISO currency codes are alpha3 codes.
+ UErrorCode localStatus = U_ZERO_ERROR;
+ int32_t resLen = uloc_getKeywordValue(locale, "currency",
+ currency, UPRV_LENGTHOF(currency), &localStatus);
+ if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency, resLen)) {
+ if (resLen < buffCapacity) {
+ T_CString_toUpperCase(currency);
+ u_charsToUChars(currency, buff, resLen);
+ }
+ return u_terminateUChars(buff, buffCapacity, resLen, ec);
+ }
+
+ // get country or country_variant in `id'
+ char id[ULOC_FULLNAME_CAPACITY];
+ uint32_t variantType = idForLocale(locale, id, UPRV_LENGTHOF(id), ec);
+ if (U_FAILURE(*ec)) {
+ return 0;
+ }
#if !UCONFIG_NO_SERVICE
- const UChar* result = CReg::get(id);
- if (result) {
- if(buffCapacity > u_strlen(result)) {
- u_strcpy(buff, result);
- }
- return u_strlen(result);
- }
+ const UChar* result = CReg::get(id);
+ if (result) {
+ if(buffCapacity > u_strlen(result)) {
+ u_strcpy(buff, result);
+ }
+ resLen = u_strlen(result);
+ return u_terminateUChars(buff, buffCapacity, resLen, ec);
+ }
#endif
- // Remove variants, which is only needed for registration.
- char *idDelim = strchr(id, VAR_DELIM);
- if (idDelim) {
- idDelim[0] = 0;
- }
+ // Remove variants, which is only needed for registration.
+ char *idDelim = uprv_strchr(id, VAR_DELIM);
+ if (idDelim) {
+ idDelim[0] = 0;
+ }
- // Look up the CurrencyMap element in the root bundle.
- 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 *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
+ const UChar* s; // Currency code from data file.
+ if (id[0] == 0) {
+ // No point looking in the data for an empty string.
+ // This is what we would get.
+ localStatus = U_MISSING_RESOURCE_ERROR;
+ } else {
+ // Look up the CurrencyMap element in the root bundle.
+ 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 *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
+ s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
+
+ // Get the second item when PREEURO is requested, and this is a known Euro country.
+ // If the requested variant is PREEURO, and this isn't a Euro country,
+ // assume that the country changed over to the Euro in the future.
+ // This is probably an old version of ICU that hasn't been updated yet.
+ // The latest currency is probably correct.
+ if (U_SUCCESS(localStatus)) {
+ if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
+ currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
-
- /*
- Get the second item when PREEURO is requested, and this is a known Euro country.
- If the requested variant is PREEURO, and this isn't a Euro country, assume
- that the country changed over to the Euro in the future. This is probably
- an old version of ICU that hasn't been updated yet. The latest currency is
- probably correct.
- */
- if (U_SUCCESS(localStatus)) {
- if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
- currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
- s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
- }
- else if ((variantType & VARIANT_IS_EURO)) {
- s = EUR_STR;
- }
- }
- ures_close(countryArray);
- ures_close(currencyReq);
-
- if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
- {
- // We don't know about it. Check to see if we support the variant.
- uloc_getParent(locale, id, sizeof(id), ec);
- *ec = U_USING_FALLBACK_WARNING;
- return ucurr_forLocale(id, buff, buffCapacity, ec);
- }
- else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
- // There is nothing to fallback to. Report the failure/warning if possible.
- *ec = localStatus;
- }
- if (U_SUCCESS(*ec)) {
- if(buffCapacity > resLen) {
- u_strcpy(buff, s);
- }
- }
+ } else if ((variantType & VARIANT_IS_EURO)) {
+ s = EUR_STR;
}
- return u_terminateUChars(buff, buffCapacity, resLen, ec);
- } else {
- *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ }
+ ures_close(currencyReq);
+ ures_close(countryArray);
+ }
+
+ if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) {
+ // We don't know about it. Check to see if we support the variant.
+ uloc_getParent(locale, id, UPRV_LENGTHOF(id), ec);
+ *ec = U_USING_FALLBACK_WARNING;
+ // TODO: Loop over the shortened id rather than recursing and
+ // looking again for a currency keyword.
+ return ucurr_forLocale(id, buff, buffCapacity, ec);
+ }
+ if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
+ // There is nothing to fallback to. Report the failure/warning if possible.
+ *ec = localStatus;
+ }
+ if (U_SUCCESS(*ec)) {
+ if(buffCapacity > resLen) {
+ u_strcpy(buff, s);
}
}
- return resLen;
+ return u_terminateUChars(buff, buffCapacity, resLen, ec);
}
// end registration
diff --git a/source/i18n/collationweights.cpp b/source/i18n/collationweights.cpp
index c60da2d..0545896 100644
--- a/source/i18n/collationweights.cpp
+++ b/source/i18n/collationweights.cpp
@@ -527,7 +527,7 @@
#ifdef UCOL_DEBUG
printf("lengthen the short ranges from %ld bytes to %ld and iterate\n", minLength, minLength+1);
#endif
- for(int32_t i=0; ranges[i].length==minLength; ++i) {
+ for(int32_t i=0; i<rangeCount && ranges[i].length==minLength; ++i) {
lengthenRange(ranges[i]);
}
}
diff --git a/source/i18n/dcfmtsym.cpp b/source/i18n/dcfmtsym.cpp
index 08a85b5..43eea49 100644
--- a/source/i18n/dcfmtsym.cpp
+++ b/source/i18n/dcfmtsym.cpp
@@ -433,12 +433,13 @@
UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
UChar curriso[4];
UnicodeString tempStr;
- ucurr_forLocale(locStr, curriso, 4, &internalStatus);
-
- uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
- if (U_SUCCESS(internalStatus)) {
- fSymbols[kIntlCurrencySymbol].setTo(curriso, -1);
- fSymbols[kCurrencySymbol] = tempStr;
+ int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus);
+ if (U_SUCCESS(internalStatus) && currisoLength == 3) {
+ uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
+ if (U_SUCCESS(internalStatus)) {
+ fSymbols[kIntlCurrencySymbol].setTo(curriso, currisoLength);
+ fSymbols[kCurrencySymbol] = tempStr;
+ }
}
/* else use the default values. */