Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2009-2013, 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 static UChar32 gMinusSigns[] = {
     73     0x002D,
     74     0x207B,
     75     0x208B,
     76     0x2212,
     77     0x2796,
     78     0xFE63,
     79     0xFF0D};
     80 
     81 static UChar32 gPlusSigns[] = {
     82     0x002B,
     83     0x207A,
     84     0x208A,
     85     0x2795,
     86     0xfB29,
     87     0xFE62,
     88     0xFF0B};
     89 
     90 static void initUnicodeSet(const UChar32 *raw, int32_t len, UnicodeSet *s) {
     91     for (int32_t i = 0; i < len; ++i) {
     92         s->add(raw[i]);
     93     }
     94 }
     95 
     96 DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode &status)
     97 : fDotEquivalents(NULL),
     98   fCommaEquivalents(NULL),
     99   fOtherGroupingSeparators(NULL),
    100   fDashEquivalents(NULL),
    101   fStrictDotEquivalents(NULL),
    102   fStrictCommaEquivalents(NULL),
    103   fStrictOtherGroupingSeparators(NULL),
    104   fStrictDashEquivalents(NULL),
    105   fDefaultGroupingSeparators(NULL),
    106   fStrictDefaultGroupingSeparators(NULL),
    107   fMinusSigns(NULL),
    108   fPlusSigns(NULL)
    109 {
    110     fDotEquivalents                = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1),                status);
    111     fCommaEquivalents              = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1),              status);
    112     fOtherGroupingSeparators       = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1),       status);
    113     fDashEquivalents               = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1),               status);
    114 
    115     fStrictDotEquivalents          = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1),          status);
    116     fStrictCommaEquivalents        = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1),        status);
    117     fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), status);
    118     fStrictDashEquivalents         = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1),         status);
    119 
    120 
    121     fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
    122     fDefaultGroupingSeparators->addAll(*fCommaEquivalents);
    123     fDefaultGroupingSeparators->addAll(*fOtherGroupingSeparators);
    124 
    125     fStrictDefaultGroupingSeparators = new UnicodeSet(*fStrictDotEquivalents);
    126     fStrictDefaultGroupingSeparators->addAll(*fStrictCommaEquivalents);
    127     fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators);
    128 
    129     fMinusSigns = new UnicodeSet();
    130     fPlusSigns = new UnicodeSet();
    131 
    132     // Check for null pointers
    133     if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL ||
    134         fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL ||
    135         fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL ||
    136         fMinusSigns == NULL || fPlusSigns == NULL) {
    137       cleanup();
    138       status = U_MEMORY_ALLOCATION_ERROR;
    139       return;
    140     }
    141 
    142     initUnicodeSet(
    143             gMinusSigns,
    144             sizeof(gMinusSigns) / sizeof(gMinusSigns[0]),
    145             fMinusSigns);
    146     initUnicodeSet(
    147             gPlusSigns,
    148             sizeof(gPlusSigns) / sizeof(gPlusSigns[0]),
    149             fPlusSigns);
    150 
    151     // Freeze all the sets
    152     fDotEquivalents->freeze();
    153     fCommaEquivalents->freeze();
    154     fOtherGroupingSeparators->freeze();
    155     fDashEquivalents->freeze();
    156     fStrictDotEquivalents->freeze();
    157     fStrictCommaEquivalents->freeze();
    158     fStrictOtherGroupingSeparators->freeze();
    159     fStrictDashEquivalents->freeze();
    160     fDefaultGroupingSeparators->freeze();
    161     fStrictDefaultGroupingSeparators->freeze();
    162     fMinusSigns->freeze();
    163     fPlusSigns->freeze();
    164 }
    165 
    166 DecimalFormatStaticSets::~DecimalFormatStaticSets() {
    167   cleanup();
    168 }
    169 
    170 void DecimalFormatStaticSets::cleanup() { // Be sure to clean up newly added fields!
    171     delete fDotEquivalents; fDotEquivalents = NULL;
    172     delete fCommaEquivalents; fCommaEquivalents = NULL;
    173     delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
    174     delete fDashEquivalents; fDashEquivalents = NULL;
    175     delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
    176     delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
    177     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
    178     delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
    179     delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
    180     delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL;
    181     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
    182     delete fMinusSigns; fMinusSigns = NULL;
    183     delete fPlusSigns; fPlusSigns = NULL;
    184 }
    185 
    186 static DecimalFormatStaticSets *gStaticSets;
    187 static icu::UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER;
    188 
    189 
    190 //------------------------------------------------------------------------------
    191 //
    192 //   decfmt_cleanup     Memory cleanup function, free/delete all
    193 //                      cached memory.  Called by ICU's u_cleanup() function.
    194 //
    195 //------------------------------------------------------------------------------
    196 U_CDECL_BEGIN
    197 static UBool U_CALLCONV
    198 decimfmt_cleanup(void)
    199 {
    200     delete gStaticSets;
    201     gStaticSets = NULL;
    202     gStaticSetsInitOnce.reset();
    203     return TRUE;
    204 }
    205 
    206 static void U_CALLCONV initSets(UErrorCode &status) {
    207     U_ASSERT(gStaticSets == NULL);
    208     ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
    209     gStaticSets = new DecimalFormatStaticSets(status);
    210     if (U_FAILURE(status)) {
    211         delete gStaticSets;
    212         gStaticSets = NULL;
    213         return;
    214     }
    215     if (gStaticSets == NULL) {
    216         status = U_MEMORY_ALLOCATION_ERROR;
    217     }
    218 }
    219 U_CDECL_END
    220 
    221 const DecimalFormatStaticSets *DecimalFormatStaticSets::getStaticSets(UErrorCode &status) {
    222     umtx_initOnce(gStaticSetsInitOnce, initSets, status);
    223     return gStaticSets;
    224 }
    225 
    226 
    227 const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse)
    228 {
    229     UErrorCode status = U_ZERO_ERROR;
    230     umtx_initOnce(gStaticSetsInitOnce, initSets, status);
    231     if (U_FAILURE(status)) {
    232         return NULL;
    233     }
    234 
    235     if (gStaticSets->fDotEquivalents->contains(decimal)) {
    236         return strictParse ? gStaticSets->fStrictDotEquivalents : gStaticSets->fDotEquivalents;
    237     }
    238 
    239     if (gStaticSets->fCommaEquivalents->contains(decimal)) {
    240         return strictParse ? gStaticSets->fStrictCommaEquivalents : gStaticSets->fCommaEquivalents;
    241     }
    242 
    243     // if there is no match, return NULL
    244     return NULL;
    245 }
    246 
    247 
    248 U_NAMESPACE_END
    249 #endif   // !UCONFIG_NO_FORMATTING
    250