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