|
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 |