]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/dcfmtsym.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / dcfmtsym.cpp
index 08a85b545e99d63b41376b35037a8e98b52269a4..e6785ab7a1f0537929f29b12d161b9c5fd2dcfe6 100644 (file)
@@ -38,6 +38,7 @@
 #include "uresimp.h"
 #include "ureslocs.h"
 #include "charstr.h"
+#include "uassert.h"
 
 // *****************************************************************************
 // class DecimalFormatSymbols
@@ -65,7 +66,7 @@ static const UChar INTL_CURRENCY_SYMBOL_STR[] = {0xa4, 0xa4, 0};
 static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount] = {
     "decimal",
     "group",
-    "list",
+    NULL, /* #11897: the <list> symbol is NOT the pattern separator symbol */
     "percentSign",
     NULL, /* Native zero digit is deprecated from CLDR - get it from the numbering system */
     NULL, /* Pattern digit character is deprecated from CLDR - use # by default always */
@@ -97,9 +98,7 @@ static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount]
 // Initializes this with the decimal format symbols in the default locale.
 
 DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
-    : UObject(),
-    locale()
-{
+        : UObject(), locale(), currPattern(NULL) {
     initialize(locale, status, TRUE);
 }
 
@@ -107,16 +106,17 @@ DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
 // Initializes this with the decimal format symbols in the desired locale.
 
 DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status)
-    : UObject(),
-    locale(loc)
-{
+        : UObject(), locale(loc), currPattern(NULL) {
     initialize(locale, status);
 }
 
+DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, const NumberingSystem& ns, UErrorCode& status)
+        : UObject(), locale(loc), currPattern(NULL) {
+    initialize(locale, status, FALSE, &ns);
+}
+
 DecimalFormatSymbols::DecimalFormatSymbols()
-        : UObject(),
-          locale(Locale::getRoot()),
-          currPattern(NULL) {
+        : UObject(), locale(Locale::getRoot()), currPattern(NULL) {
     *validLocale = *actualLocale = 0;
     initialize();
 }
@@ -166,6 +166,7 @@ DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs)
         uprv_strcpy(actualLocale, rhs.actualLocale);
         fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol; 
         fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol; 
+        fCodePointZero = rhs.fCodePointZero;
     }
     return *this;
 }
@@ -197,6 +198,7 @@ DecimalFormatSymbols::operator==(const DecimalFormatSymbols& that) const
             return FALSE;
         }
     }
+    // No need to check fCodePointZero since it is based on fSymbols
     return locale == that.locale &&
         uprv_strcmp(validLocale, that.validLocale) == 0 &&
         uprv_strcmp(actualLocale, that.actualLocale) == 0;
@@ -342,11 +344,11 @@ CurrencySpacingSink::~CurrencySpacingSink() {}
 } // namespace
 
 void
-DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData)
+DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status,
+    UBool useLastResortData, const NumberingSystem* ns)
 {
     if (U_FAILURE(status)) { return; }
     *validLocale = *actualLocale = 0;
-    currPattern = NULL;
 
     // First initialize all the symbols to the fallbacks for anything we can't find
     initialize();
@@ -355,7 +357,13 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool us
     // Next get the numbering system for this locale and set zero digit
     // and the digit string based on the numbering system for the locale
     //
-    LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(loc, status));
+    LocalPointer<NumberingSystem> nsLocal;
+    if (ns == nullptr) {
+        // Use the numbering system according to the locale.
+        // Save it into a LocalPointer so it gets cleaned up.
+        nsLocal.adoptInstead(NumberingSystem::createInstance(loc, status));
+        ns = nsLocal.getAlias();
+    }
     const char *nsName;
     if (U_SUCCESS(status) && ns->getRadix() == 10 && !ns->isAlgorithmic()) {
         nsName = ns->getName();
@@ -427,18 +435,37 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool us
     // Let the monetary number separators equal the default number separators if necessary.
     sink.resolveMissingMonetarySeparators(fSymbols);
 
+    // Resolve codePointZero
+    UChar32 tempCodePointZero;
+    for (int32_t i=0; i<=9; i++) {
+        const UnicodeString& stringDigit = getConstDigitSymbol(i);
+        if (stringDigit.countChar32() != 1) {
+            tempCodePointZero = -1;
+            break;
+        }
+        UChar32 cp = stringDigit.char32At(0);
+        if (i == 0) {
+            tempCodePointZero = cp;
+        } else if (cp != tempCodePointZero + i) {
+            tempCodePointZero = -1;
+            break;
+        }
+    }
+    fCodePointZero = tempCodePointZero;
+
     // Obtain currency data from the currency API.  This is strictly
     // for backward compatibility; we don't use DecimalFormatSymbols
     // for currency data anymore.
     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. */
 
@@ -449,6 +476,7 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool us
     UErrorCode localStatus = U_ZERO_ERROR;
     uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus);
 
+    // TODO: Currency pattern data loading is duplicated in number_formatimpl.cpp
     if(U_SUCCESS(localStatus) && uccLen > 0) {
         char cc[4]={0};
         u_UCharsToChars(ucc, cc, uccLen);
@@ -523,6 +551,8 @@ DecimalFormatSymbols::initialize() {
     fSymbols[kExponentMultiplicationSymbol] = (UChar)0xd7; // 'x' multiplication symbol for exponents
     fIsCustomCurrencySymbol = FALSE; 
     fIsCustomIntlCurrencySymbol = FALSE;
+    fCodePointZero = 0x30;
+    U_ASSERT(fCodePointZero == fSymbols[kZeroDigitSymbol].char32At(0));
 
 }