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
DecimalFormatStaticSets(UErrorCode * status)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
~DecimalFormatStaticSets()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
cleanup(void)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
decimfmt_cleanup(void)176 decimfmt_cleanup(void)
177 {
178 return DecimalFormatStaticSets::cleanup();
179 }
180 U_CDECL_END
181
initSets(UErrorCode * status)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
getSimilarDecimals(UChar32 decimal,UBool strictParse)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