]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/decfmtst.cpp
ICU-531.30.tar.gz
[apple/icu.git] / icuSources / i18n / decfmtst.cpp
index 6452936d355d9cfd9e3b29af64e21fca40029294..d1ea6f4d4c4a1f2850c8ef2b5d883e315a515997 100644 (file)
@@ -1,16 +1,20 @@
-//
-//  decfmtst.h
-//
-//  Copyright (C) 20098, International Business Machines Corporation and others.
-//  All Rights Reserved.
-//
-//  This file contains the class DecimalFormatStaticSets
-//
-//  DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient
-//  parsing of decimal and group separators.
-//
+/*
+*******************************************************************************
+* Copyright (C) 2009-2013, International Business Machines Corporation and    *
+* others. All Rights Reserved.                                                *
+*******************************************************************************
+*
+* This file contains the class DecimalFormatStaticSets
+*
+* DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient
+* parsing of decimal and group separators.
+********************************************************************************
+*/
+
 #include "unicode/utypes.h"
 
+#if !UCONFIG_NO_FORMATTING
+
 #include "unicode/unistr.h"
 #include "unicode/uniset.h"
 #include "unicode/uchar.h"
@@ -34,41 +38,62 @@ U_NAMESPACE_BEGIN
 //------------------------------------------------------------------------------
 
 static const UChar gDotEquivalentsPattern[] = {
-               // [       .    \u2024  \u3002  \uFE12  \uFE52  \uFF0E  \uFF61     ]
-               0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
+        // [       .    \u2024  \u3002  \uFE12  \uFE52  \uFF0E  \uFF61     ]
+        0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
 
 static const UChar gCommaEquivalentsPattern[] = {
-               // [       ,    \u060C  \u066B  \u3001  \uFE10  \uFE11  \uFE50  \uFE51  \uFF0C  \uFF64    ]
+        // [       ,    \u060C  \u066B  \u3001  \uFE10  \uFE11  \uFE50  \uFE51  \uFF0C  \uFF64    ]
         0x005B, 0x002C, 0x060C, 0x066B, 0x3001, 0xFE10, 0xFE11, 0xFE50, 0xFE51, 0xFF0C, 0xFF64, 0x005D, 0x0000};
 
 static const UChar gOtherGroupingSeparatorsPattern[] = {
-               // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
+        // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
         0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
 
 static const UChar gDashEquivalentsPattern[] = {
-    // [       \      -     HYPHEN  F_DASH  N_DASH   MINUS     ]
-    0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000};
+        // [       \      -     HYPHEN  F_DASH  N_DASH   MINUS     ]
+        0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000};
 
 static const UChar gStrictDotEquivalentsPattern[] = {
-               // [      .     \u2024  \uFE52  \uFF0E  \uFF61    ]
+        // [      .     \u2024  \uFE52  \uFF0E  \uFF61    ]
         0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
 
 static const UChar gStrictCommaEquivalentsPattern[] = {
-               // [       ,    \u066B  \uFE10  \uFE50  \uFF0C     ]
+        // [       ,    \u066B  \uFE10  \uFE50  \uFF0C     ]
         0x005B, 0x002C, 0x066B, 0xFE10, 0xFE50, 0xFF0C, 0x005D, 0x0000};
 
 static const UChar gStrictOtherGroupingSeparatorsPattern[] = {
-               // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
+        // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
         0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
 
 static const UChar gStrictDashEquivalentsPattern[] = {
-    // [       \      -      MINUS     ]
-    0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
-
-
-DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL;
+        // [       \      -      MINUS     ]
+        0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
+
+static UChar32 gMinusSigns[] = {
+    0x002D,
+    0x207B,
+    0x208B,
+    0x2212,
+    0x2796,
+    0xFE63,
+    0xFF0D};
+
+static UChar32 gPlusSigns[] = {
+    0x002B,
+    0x207A,
+    0x208A,
+    0x2795,
+    0xfB29,
+    0xFE62,
+    0xFF0B};
+
+static void initUnicodeSet(const UChar32 *raw, int32_t len, UnicodeSet *s) {
+    for (int32_t i = 0; i < len; ++i) {
+        s->add(raw[i]);
+    }
+}
 
-DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
+DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode &status)
 : fDotEquivalents(NULL),
   fCommaEquivalents(NULL),
   fOtherGroupingSeparators(NULL),
@@ -78,17 +103,19 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
   fStrictOtherGroupingSeparators(NULL),
   fStrictDashEquivalents(NULL),
   fDefaultGroupingSeparators(NULL),
-  fStrictDefaultGroupingSeparators(NULL)
+  fStrictDefaultGroupingSeparators(NULL),
+  fMinusSigns(NULL),
+  fPlusSigns(NULL)
 {
-    fDotEquivalents                = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1),                *status);
-    fCommaEquivalents              = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1),              *status);
-    fOtherGroupingSeparators       = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1),       *status);
-    fDashEquivalents               = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1),               *status);
+    fDotEquivalents                = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1),                status);
+    fCommaEquivalents              = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1),              status);
+    fOtherGroupingSeparators       = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1),       status);
+    fDashEquivalents               = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1),               status);
     
-    fStrictDotEquivalents          = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1),          *status);
-    fStrictCommaEquivalents        = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1),        *status);
-    fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status);
-    fStrictDashEquivalents         = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1),         *status);
+    fStrictDotEquivalents          = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1),          status);
+    fStrictCommaEquivalents        = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1),        status);
+    fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), status);
+    fStrictDashEquivalents         = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1),         status);
 
 
     fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
@@ -99,13 +126,28 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
     fStrictDefaultGroupingSeparators->addAll(*fStrictCommaEquivalents);
     fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators);
 
+    fMinusSigns = new UnicodeSet();
+    fPlusSigns = new UnicodeSet();
+
     // Check for null pointers
     if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL ||
-               fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL ||
-               fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL) {
-        goto ExitConstrDeleteAll;
+        fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL ||
+        fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL ||
+        fMinusSigns == NULL || fPlusSigns == NULL) {
+      cleanup();
+      status = U_MEMORY_ALLOCATION_ERROR;
+      return;
     }
 
+    initUnicodeSet(
+            gMinusSigns,
+            sizeof(gMinusSigns) / sizeof(gMinusSigns[0]),
+            fMinusSigns);
+    initUnicodeSet(
+            gPlusSigns,
+            sizeof(gPlusSigns) / sizeof(gPlusSigns[0]),
+            fPlusSigns);
+
     // Freeze all the sets
     fDotEquivalents->freeze();
     fCommaEquivalents->freeze();
@@ -117,26 +159,15 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
     fStrictDashEquivalents->freeze();
     fDefaultGroupingSeparators->freeze();
     fStrictDefaultGroupingSeparators->freeze();
-       
-    return; // If we reached this point, everything is fine so just exit
-
-ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error
-    delete fDotEquivalents; fDotEquivalents = NULL;
-    delete fCommaEquivalents; fCommaEquivalents = NULL;
-    delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
-    delete fDashEquivalents; fDashEquivalents = NULL;
-    delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
-    delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
-    delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
-    delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
-    delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
-    delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
-
-    *status = U_MEMORY_ALLOCATION_ERROR;
+    fMinusSigns->freeze();
+    fPlusSigns->freeze();
 }
 
-
 DecimalFormatStaticSets::~DecimalFormatStaticSets() {
+  cleanup();
+}
+
+void DecimalFormatStaticSets::cleanup() { // Be sure to clean up newly added fields!
     delete fDotEquivalents; fDotEquivalents = NULL;
     delete fCommaEquivalents; fCommaEquivalents = NULL;
     delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
@@ -146,9 +177,15 @@ DecimalFormatStaticSets::~DecimalFormatStaticSets() {
     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
     delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
     delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
+    delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL;
     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
+    delete fMinusSigns; fMinusSigns = NULL;
+    delete fPlusSigns; fPlusSigns = NULL;
 }
 
+static DecimalFormatStaticSets *gStaticSets;
+static icu::UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER;
+
 
 //------------------------------------------------------------------------------
 //
@@ -156,66 +193,44 @@ DecimalFormatStaticSets::~DecimalFormatStaticSets() {
 //                      cached memory.  Called by ICU's u_cleanup() function.
 //
 //------------------------------------------------------------------------------
-UBool
-DecimalFormatStaticSets::cleanup(void)
-{
-    delete DecimalFormatStaticSets::gStaticSets;
-    DecimalFormatStaticSets::gStaticSets = NULL;
-
-    return TRUE;
-}
-
 U_CDECL_BEGIN
 static UBool U_CALLCONV
 decimfmt_cleanup(void)
 {
-    return DecimalFormatStaticSets::cleanup();
+    delete gStaticSets;
+    gStaticSets = NULL;
+    gStaticSetsInitOnce.reset();
+    return TRUE;
 }
-U_CDECL_END
 
-void DecimalFormatStaticSets::initSets(UErrorCode *status)
-{
-       DecimalFormatStaticSets *p;
-
-    UMTX_CHECK(NULL, gStaticSets, p);
-    if (p == NULL) {
-        p = new DecimalFormatStaticSets(status);
-
-        if (p == NULL) {
-               *status = U_MEMORY_ALLOCATION_ERROR;
-               return;
-        }
-
-        if (U_FAILURE(*status)) {
-            delete p;
-            return;
-        }
-
-        umtx_lock(NULL);
-        if (gStaticSets == NULL) {
-            gStaticSets = p;
-            p = NULL;
-        }
-
-        umtx_unlock(NULL);
-        if (p != NULL) {
-            delete p;
-        }
-
-        ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
+static void U_CALLCONV initSets(UErrorCode &status) {
+    U_ASSERT(gStaticSets == NULL);
+    ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
+    gStaticSets = new DecimalFormatStaticSets(status);
+    if (U_FAILURE(status)) {
+        delete gStaticSets;
+        gStaticSets = NULL;
+        return;
+    }
+    if (gStaticSets == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
     }
 }
+U_CDECL_END
 
-UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse, UnicodeSet *fallback)
-{
-       UErrorCode status = U_ZERO_ERROR;
+const DecimalFormatStaticSets *DecimalFormatStaticSets::getStaticSets(UErrorCode &status) {
+    umtx_initOnce(gStaticSetsInitOnce, initSets, status);
+    return gStaticSets;
+}
 
-       initSets(&status);
 
-       if (U_FAILURE(status)) {
-               fallback->set(decimal, decimal);
-               return fallback;
-       }
+const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse)
+{
+    UErrorCode status = U_ZERO_ERROR;
+    umtx_initOnce(gStaticSetsInitOnce, initSets, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
 
     if (gStaticSets->fDotEquivalents->contains(decimal)) {
         return strictParse ? gStaticSets->fStrictDotEquivalents : gStaticSets->fDotEquivalents;
@@ -225,10 +240,10 @@ UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool s
         return strictParse ? gStaticSets->fStrictCommaEquivalents : gStaticSets->fCommaEquivalents;
     }
 
-    // if there is no match, return the character itself
-    fallback->set(decimal, decimal);
-    return fallback;
+    // if there is no match, return NULL
+    return NULL;
 }
 
 
 U_NAMESPACE_END
+#endif   // !UCONFIG_NO_FORMATTING