1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 2009-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
9 * This file contains the class DecimalFormatStaticSets
11 * DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient
12 * parsing of decimal and group separators.
13 ********************************************************************************
16 #include "unicode/utypes.h"
18 #if !UCONFIG_NO_FORMATTING
20 #include "unicode/unistr.h"
21 #include "unicode/uniset.h"
22 #include "unicode/uchar.h"
34 //------------------------------------------------------------------------------
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.
40 //------------------------------------------------------------------------------
42 static const UChar gDotEquivalentsPattern
[] = {
43 // [ . \u2024 \u3002 \uFE12 \uFE52 \uFF0E \uFF61 ]
44 0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
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};
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};
54 static const UChar gDashEquivalentsPattern
[] = {
55 // [ \ - HYPHEN F_DASH N_DASH MINUS ]
56 0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000};
58 static const UChar gStrictDotEquivalentsPattern
[] = {
59 // [ . \u2024 \uFE52 \uFF0E \uFF61 ]
60 0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
62 static const UChar gStrictCommaEquivalentsPattern
[] = {
63 // [ , \u066B \uFE10 \uFE50 \uFF0C ]
64 0x005B, 0x002C, 0x066B, 0xFE10, 0xFE50, 0xFF0C, 0x005D, 0x0000};
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};
70 static const UChar gStrictDashEquivalentsPattern
[] = {
72 0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
74 static const UChar32 gMinusSigns
[] = {
83 static const UChar32 gPlusSigns
[] = {
92 static void initUnicodeSet(const UChar32
*raw
, int32_t len
, UnicodeSet
*s
) {
93 for (int32_t i
= 0; i
< len
; ++i
) {
98 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
),
112 fDotEquivalents
= new UnicodeSet(UnicodeString(TRUE
, gDotEquivalentsPattern
, -1), status
);
113 fCommaEquivalents
= new UnicodeSet(UnicodeString(TRUE
, gCommaEquivalentsPattern
, -1), status
);
114 fOtherGroupingSeparators
= new UnicodeSet(UnicodeString(TRUE
, gOtherGroupingSeparatorsPattern
, -1), status
);
115 fDashEquivalents
= new UnicodeSet(UnicodeString(TRUE
, gDashEquivalentsPattern
, -1), status
);
117 fStrictDotEquivalents
= new UnicodeSet(UnicodeString(TRUE
, gStrictDotEquivalentsPattern
, -1), status
);
118 fStrictCommaEquivalents
= new UnicodeSet(UnicodeString(TRUE
, gStrictCommaEquivalentsPattern
, -1), status
);
119 fStrictOtherGroupingSeparators
= new UnicodeSet(UnicodeString(TRUE
, gStrictOtherGroupingSeparatorsPattern
, -1), status
);
120 fStrictDashEquivalents
= new UnicodeSet(UnicodeString(TRUE
, gStrictDashEquivalentsPattern
, -1), status
);
123 fDefaultGroupingSeparators
= new UnicodeSet(*fDotEquivalents
);
124 fDefaultGroupingSeparators
->addAll(*fCommaEquivalents
);
125 fDefaultGroupingSeparators
->addAll(*fOtherGroupingSeparators
);
127 fStrictDefaultGroupingSeparators
= new UnicodeSet(*fStrictDotEquivalents
);
128 fStrictDefaultGroupingSeparators
->addAll(*fStrictCommaEquivalents
);
129 fStrictDefaultGroupingSeparators
->addAll(*fStrictOtherGroupingSeparators
);
131 fMinusSigns
= new UnicodeSet();
132 fPlusSigns
= new UnicodeSet();
134 // Check for null pointers
135 if (fDotEquivalents
== NULL
|| fCommaEquivalents
== NULL
|| fOtherGroupingSeparators
== NULL
|| fDashEquivalents
== NULL
||
136 fStrictDotEquivalents
== NULL
|| fStrictCommaEquivalents
== NULL
|| fStrictOtherGroupingSeparators
== NULL
|| fStrictDashEquivalents
== NULL
||
137 fDefaultGroupingSeparators
== NULL
|| fStrictOtherGroupingSeparators
== NULL
||
138 fMinusSigns
== NULL
|| fPlusSigns
== NULL
) {
140 status
= U_MEMORY_ALLOCATION_ERROR
;
146 UPRV_LENGTHOF(gMinusSigns
),
150 UPRV_LENGTHOF(gPlusSigns
),
153 // Freeze all the sets
154 fDotEquivalents
->freeze();
155 fCommaEquivalents
->freeze();
156 fOtherGroupingSeparators
->freeze();
157 fDashEquivalents
->freeze();
158 fStrictDotEquivalents
->freeze();
159 fStrictCommaEquivalents
->freeze();
160 fStrictOtherGroupingSeparators
->freeze();
161 fStrictDashEquivalents
->freeze();
162 fDefaultGroupingSeparators
->freeze();
163 fStrictDefaultGroupingSeparators
->freeze();
164 fMinusSigns
->freeze();
165 fPlusSigns
->freeze();
168 DecimalFormatStaticSets::~DecimalFormatStaticSets() {
172 void DecimalFormatStaticSets::cleanup() { // Be sure to clean up newly added fields!
173 delete fDotEquivalents
; fDotEquivalents
= NULL
;
174 delete fCommaEquivalents
; fCommaEquivalents
= NULL
;
175 delete fOtherGroupingSeparators
; fOtherGroupingSeparators
= NULL
;
176 delete fDashEquivalents
; fDashEquivalents
= NULL
;
177 delete fStrictDotEquivalents
; fStrictDotEquivalents
= NULL
;
178 delete fStrictCommaEquivalents
; fStrictCommaEquivalents
= NULL
;
179 delete fStrictOtherGroupingSeparators
; fStrictOtherGroupingSeparators
= NULL
;
180 delete fStrictDashEquivalents
; fStrictDashEquivalents
= NULL
;
181 delete fDefaultGroupingSeparators
; fDefaultGroupingSeparators
= NULL
;
182 delete fStrictDefaultGroupingSeparators
; fStrictDefaultGroupingSeparators
= NULL
;
183 delete fStrictOtherGroupingSeparators
; fStrictOtherGroupingSeparators
= NULL
;
184 delete fMinusSigns
; fMinusSigns
= NULL
;
185 delete fPlusSigns
; fPlusSigns
= NULL
;
188 static DecimalFormatStaticSets
*gStaticSets
;
189 static icu::UInitOnce gStaticSetsInitOnce
= U_INITONCE_INITIALIZER
;
192 //------------------------------------------------------------------------------
194 // decfmt_cleanup Memory cleanup function, free/delete all
195 // cached memory. Called by ICU's u_cleanup() function.
197 //------------------------------------------------------------------------------
199 static UBool U_CALLCONV
200 decimfmt_cleanup(void)
204 gStaticSetsInitOnce
.reset();
208 static void U_CALLCONV
initSets(UErrorCode
&status
) {
209 U_ASSERT(gStaticSets
== NULL
);
210 ucln_i18n_registerCleanup(UCLN_I18N_DECFMT
, decimfmt_cleanup
);
211 gStaticSets
= new DecimalFormatStaticSets(status
);
212 if (U_FAILURE(status
)) {
217 if (gStaticSets
== NULL
) {
218 status
= U_MEMORY_ALLOCATION_ERROR
;
223 const DecimalFormatStaticSets
*DecimalFormatStaticSets::getStaticSets(UErrorCode
&status
) {
224 umtx_initOnce(gStaticSetsInitOnce
, initSets
, status
);
229 const UnicodeSet
*DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal
, UBool strictParse
)
231 UErrorCode status
= U_ZERO_ERROR
;
232 umtx_initOnce(gStaticSetsInitOnce
, initSets
, status
);
233 if (U_FAILURE(status
)) {
237 if (gStaticSets
->fDotEquivalents
->contains(decimal
)) {
238 return strictParse
? gStaticSets
->fStrictDotEquivalents
: gStaticSets
->fDotEquivalents
;
241 if (gStaticSets
->fCommaEquivalents
->contains(decimal
)) {
242 return strictParse
? gStaticSets
->fStrictCommaEquivalents
: gStaticSets
->fCommaEquivalents
;
245 // if there is no match, return NULL
251 #endif // !UCONFIG_NO_FORMATTING