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