Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2009-2011, International Business Machines Corporation and    *
      4 * others. All Rights Reserved.                                                *
      5 *******************************************************************************
      6 *
      7 * This file contains the class DecimalFormatStaticSets
      8 *
      9 * DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient
     10 * parsing of decimal and group separators.
     11 ********************************************************************************
     12 */
     13 
     14 #include "unicode/utypes.h"
     15 
     16 #if !UCONFIG_NO_FORMATTING
     17 
     18 #include "unicode/unistr.h"
     19 #include "unicode/uniset.h"
     20 #include "unicode/uchar.h"
     21 #include "cmemory.h"
     22 #include "cstring.h"
     23 #include "uassert.h"
     24 #include "ucln_in.h"
     25 #include "umutex.h"
     26 
     27 #include "decfmtst.h"
     28 
     29 U_NAMESPACE_BEGIN
     30 
     31 
     32 //------------------------------------------------------------------------------
     33 //
     34 // Unicode Set pattern strings for all of the required constant sets.
     35 //               Initialized with hex values for portability to EBCDIC based machines.
     36 //                Really ugly, but there's no good way to avoid it.
     37 //
     38 //------------------------------------------------------------------------------
     39 
     40 static const UChar gDotEquivalentsPattern[] = {
     41         // [       .    \u2024  \u3002  \uFE12  \uFE52  \uFF0E  \uFF61     ]
     42         0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
     43 
     44 static const UChar gCommaEquivalentsPattern[] = {
     45         // [       ,    \u060C  \u066B  \u3001  \uFE10  \uFE11  \uFE50  \uFE51  \uFF0C  \uFF64    ]
     46         0x005B, 0x002C, 0x060C, 0x066B, 0x3001, 0xFE10, 0xFE11, 0xFE50, 0xFE51, 0xFF0C, 0xFF64, 0x005D, 0x0000};
     47 
     48 static const UChar gOtherGroupingSeparatorsPattern[] = {
     49         // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
     50         0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
     51 
     52 static const UChar gDashEquivalentsPattern[] = {
     53         // [       \      -     HYPHEN  F_DASH  N_DASH   MINUS     ]
     54         0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000};
     55 
     56 static const UChar gStrictDotEquivalentsPattern[] = {
     57         // [      .     \u2024  \uFE52  \uFF0E  \uFF61    ]
     58         0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
     59 
     60 static const UChar gStrictCommaEquivalentsPattern[] = {
     61         // [       ,    \u066B  \uFE10  \uFE50  \uFF0C     ]
     62         0x005B, 0x002C, 0x066B, 0xFE10, 0xFE50, 0xFF0C, 0x005D, 0x0000};
     63 
     64 static const UChar gStrictOtherGroupingSeparatorsPattern[] = {
     65         // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
     66         0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
     67 
     68 static const UChar gStrictDashEquivalentsPattern[] = {
     69         // [       \      -      MINUS     ]
     70         0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
     71 
     72 
     73 DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL;
     74 
     75 DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
     76 : fDotEquivalents(NULL),
     77   fCommaEquivalents(NULL),
     78   fOtherGroupingSeparators(NULL),
     79   fDashEquivalents(NULL),
     80   fStrictDotEquivalents(NULL),
     81   fStrictCommaEquivalents(NULL),
     82   fStrictOtherGroupingSeparators(NULL),
     83   fStrictDashEquivalents(NULL),
     84   fDefaultGroupingSeparators(NULL),
     85   fStrictDefaultGroupingSeparators(NULL)
     86 {
     87     fDotEquivalents                = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1),                *status);
     88     fCommaEquivalents              = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1),              *status);
     89     fOtherGroupingSeparators       = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1),       *status);
     90     fDashEquivalents               = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1),               *status);
     91 
     92     fStrictDotEquivalents          = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1),          *status);
     93     fStrictCommaEquivalents        = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1),        *status);
     94     fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status);
     95     fStrictDashEquivalents         = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1),         *status);
     96 
     97 
     98     fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
     99     fDefaultGroupingSeparators->addAll(*fCommaEquivalents);
    100     fDefaultGroupingSeparators->addAll(*fOtherGroupingSeparators);
    101 
    102     fStrictDefaultGroupingSeparators = new UnicodeSet(*fStrictDotEquivalents);
    103     fStrictDefaultGroupingSeparators->addAll(*fStrictCommaEquivalents);
    104     fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators);
    105 
    106     // Check for null pointers
    107     if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL ||
    108         fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL ||
    109         fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL) {
    110         goto ExitConstrDeleteAll;
    111     }
    112 
    113     // Freeze all the sets
    114     fDotEquivalents->freeze();
    115     fCommaEquivalents->freeze();
    116     fOtherGroupingSeparators->freeze();
    117     fDashEquivalents->freeze();
    118     fStrictDotEquivalents->freeze();
    119     fStrictCommaEquivalents->freeze();
    120     fStrictOtherGroupingSeparators->freeze();
    121     fStrictDashEquivalents->freeze();
    122     fDefaultGroupingSeparators->freeze();
    123     fStrictDefaultGroupingSeparators->freeze();
    124 
    125     return; // If we reached this point, everything is fine so just exit
    126 
    127 ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error
    128     delete fDotEquivalents; fDotEquivalents = NULL;
    129     delete fCommaEquivalents; fCommaEquivalents = NULL;
    130     delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
    131     delete fDashEquivalents; fDashEquivalents = NULL;
    132     delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
    133     delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
    134     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
    135     delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
    136     delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
    137     delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL;
    138     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
    139 
    140     *status = U_MEMORY_ALLOCATION_ERROR;
    141 }
    142 
    143 
    144 DecimalFormatStaticSets::~DecimalFormatStaticSets() {
    145     delete fDotEquivalents; fDotEquivalents = NULL;
    146     delete fCommaEquivalents; fCommaEquivalents = NULL;
    147     delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
    148     delete fDashEquivalents; fDashEquivalents = NULL;
    149     delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
    150     delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
    151     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
    152     delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
    153     delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
    154     delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL;
    155     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
    156 }
    157 
    158 
    159 //------------------------------------------------------------------------------
    160 //
    161 //   decfmt_cleanup     Memory cleanup function, free/delete all
    162 //                      cached memory.  Called by ICU's u_cleanup() function.
    163 //
    164 //------------------------------------------------------------------------------
    165 UBool
    166 DecimalFormatStaticSets::cleanup(void)
    167 {
    168     delete DecimalFormatStaticSets::gStaticSets;
    169     DecimalFormatStaticSets::gStaticSets = NULL;
    170 
    171     return TRUE;
    172 }
    173 
    174 U_CDECL_BEGIN
    175 static UBool U_CALLCONV
    176 decimfmt_cleanup(void)
    177 {
    178     return DecimalFormatStaticSets::cleanup();
    179 }
    180 U_CDECL_END
    181 
    182 void DecimalFormatStaticSets::initSets(UErrorCode *status)
    183 {
    184     DecimalFormatStaticSets *p;
    185 
    186     UMTX_CHECK(NULL, gStaticSets, p);
    187     if (p == NULL) {
    188         p = new DecimalFormatStaticSets(status);
    189 
    190         if (p == NULL) {
    191             *status = U_MEMORY_ALLOCATION_ERROR;
    192             return;
    193         }
    194 
    195         if (U_FAILURE(*status)) {
    196             delete p;
    197             return;
    198         }
    199 
    200         umtx_lock(NULL);
    201         if (gStaticSets == NULL) {
    202             gStaticSets = p;
    203             p = NULL;
    204         }
    205 
    206         umtx_unlock(NULL);
    207         if (p != NULL) {
    208             delete p;
    209         }
    210 
    211         ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
    212     }
    213 }
    214 
    215 const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse)
    216 {
    217     UErrorCode status = U_ZERO_ERROR;
    218 
    219     initSets(&status);
    220 
    221     if (U_FAILURE(status)) {
    222         return NULL;
    223     }
    224 
    225     if (gStaticSets->fDotEquivalents->contains(decimal)) {
    226         return strictParse ? gStaticSets->fStrictDotEquivalents : gStaticSets->fDotEquivalents;
    227     }
    228 
    229     if (gStaticSets->fCommaEquivalents->contains(decimal)) {
    230         return strictParse ? gStaticSets->fStrictCommaEquivalents : gStaticSets->fCommaEquivalents;
    231     }
    232 
    233     // if there is no match, return NULL
    234     return NULL;
    235 }
    236 
    237 
    238 U_NAMESPACE_END
    239 #endif   // !UCONFIG_NO_FORMATTING
    240