]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/decfmtst.cpp
573dcbf912cd1e3e57a31f6062e2858395dc13b3
[apple/icu.git] / icuSources / i18n / decfmtst.cpp
1 //
2 // decfmtst.h
3 //
4 // Copyright (C) 20098, International Business Machines Corporation and others.
5 // All Rights Reserved.
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 #include "unicode/utypes.h"
13
14 #include "unicode/unistr.h"
15 #include "unicode/uniset.h"
16 #include "unicode/uchar.h"
17 #include "cmemory.h"
18 #include "cstring.h"
19 #include "uassert.h"
20 #include "ucln_in.h"
21 #include "umutex.h"
22
23 #include "decfmtst.h"
24
25 U_NAMESPACE_BEGIN
26
27
28 //------------------------------------------------------------------------------
29 //
30 // Unicode Set pattern strings for all of the required constant sets.
31 // Initialized with hex values for portability to EBCDIC based machines.
32 // Really ugly, but there's no good way to avoid it.
33 //
34 //------------------------------------------------------------------------------
35
36 static const UChar gDotEquivalentsPattern[] = {
37 // [ . \u2024 \u3002 \uFE12 \uFE52 \uFF0E \uFF61 ]
38 0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
39
40 static const UChar gCommaEquivalentsPattern[] = {
41 // [ , \u060C \u066B \u3001 \uFE10 \uFE11 \uFE50 \uFE51 \uFF0C \uFF64 ]
42 0x005B, 0x002C, 0x060C, 0x066B, 0x3001, 0xFE10, 0xFE11, 0xFE50, 0xFE51, 0xFF0C, 0xFF64, 0x005D, 0x0000};
43
44 static const UChar gOtherGroupingSeparatorsPattern[] = {
45 // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ]
46 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
47
48 static const UChar gStrictDotEquivalentsPattern[] = {
49 // [ . \u2024 \uFE52 \uFF0E \uFF61 ]
50 0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
51
52 static const UChar gStrictCommaEquivalentsPattern[] = {
53 // [ , \u066B \uFE10 \uFE50 \uFF0C ]
54 0x005B, 0x002C, 0x066B, 0xFE10, 0xFE50, 0xFF0C, 0x005D, 0x0000};
55
56 static const UChar gStrictOtherGroupingSeparatorsPattern[] = {
57 // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ]
58 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
59
60
61 DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL;
62
63 DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
64 : fDotEquivalents(NULL),
65 fCommaEquivalents(NULL),
66 fOtherGroupingSeparators(NULL),
67 fStrictDotEquivalents(NULL),
68 fStrictCommaEquivalents(NULL),
69 fStrictOtherGroupingSeparators(NULL),
70 fDefaultGroupingSeparators(NULL),
71 fStrictDefaultGroupingSeparators(NULL)
72 {
73 fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), *status);
74 fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), *status);
75 fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), *status);
76 fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), *status);
77 fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), *status);
78 fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status);
79
80
81 fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
82 fDefaultGroupingSeparators->addAll(*fCommaEquivalents);
83 fDefaultGroupingSeparators->addAll(*fOtherGroupingSeparators);
84
85 fStrictDefaultGroupingSeparators = new UnicodeSet(*fStrictDotEquivalents);
86 fStrictDefaultGroupingSeparators->addAll(*fStrictCommaEquivalents);
87 fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators);
88
89 // Check for null pointers
90 if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL ||
91 fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL ||
92 fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL) {
93 goto ExitConstrDeleteAll;
94 }
95
96 // Freeze all the sets
97 fDotEquivalents->freeze();
98 fCommaEquivalents->freeze();
99 fOtherGroupingSeparators->freeze();
100 fStrictDotEquivalents->freeze();
101 fStrictCommaEquivalents->freeze();
102 fStrictOtherGroupingSeparators->freeze();
103 fDefaultGroupingSeparators->freeze();
104 fStrictDefaultGroupingSeparators->freeze();
105
106 return; // If we reached this point, everything is fine so just exit
107
108 ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error
109 delete fDotEquivalents; fDotEquivalents = NULL;
110 delete fCommaEquivalents; fCommaEquivalents = NULL;
111 delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
112 delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
113 delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
114 delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
115 delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
116 delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
117
118 *status = U_MEMORY_ALLOCATION_ERROR;
119 }
120
121
122 DecimalFormatStaticSets::~DecimalFormatStaticSets() {
123 delete fDotEquivalents; fDotEquivalents = NULL;
124 delete fCommaEquivalents; fCommaEquivalents = NULL;
125 delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
126 delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
127 delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
128 delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
129 delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
130 delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
131 }
132
133
134 //------------------------------------------------------------------------------
135 //
136 // decfmt_cleanup Memory cleanup function, free/delete all
137 // cached memory. Called by ICU's u_cleanup() function.
138 //
139 //------------------------------------------------------------------------------
140 UBool
141 DecimalFormatStaticSets::cleanup(void)
142 {
143 delete DecimalFormatStaticSets::gStaticSets;
144 DecimalFormatStaticSets::gStaticSets = NULL;
145
146 return TRUE;
147 }
148
149 U_CDECL_BEGIN
150 static UBool U_CALLCONV
151 decimfmt_cleanup(void)
152 {
153 return DecimalFormatStaticSets::cleanup();
154 }
155 U_CDECL_END
156
157 void DecimalFormatStaticSets::initSets(UErrorCode *status)
158 {
159 DecimalFormatStaticSets *p;
160
161 UMTX_CHECK(NULL, gStaticSets, p);
162 if (p == NULL) {
163 p = new DecimalFormatStaticSets(status);
164
165 if (p == NULL) {
166 *status = U_MEMORY_ALLOCATION_ERROR;
167 return;
168 }
169
170 if (U_FAILURE(*status)) {
171 delete p;
172 return;
173 }
174
175 umtx_lock(NULL);
176 if (gStaticSets == NULL) {
177 gStaticSets = p;
178 p = NULL;
179 }
180
181 umtx_unlock(NULL);
182 if (p != NULL) {
183 delete p;
184 }
185
186 ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
187 }
188 }
189
190 UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse, UnicodeSet *fallback)
191 {
192 UErrorCode status = U_ZERO_ERROR;
193
194 initSets(&status);
195
196 if (U_FAILURE(status)) {
197 fallback->set(decimal, decimal);
198 return fallback;
199 }
200
201 if (gStaticSets->fDotEquivalents->contains(decimal)) {
202 return strictParse ? gStaticSets->fStrictDotEquivalents : gStaticSets->fDotEquivalents;
203 }
204
205 if (gStaticSets->fCommaEquivalents->contains(decimal)) {
206 return strictParse ? gStaticSets->fStrictCommaEquivalents : gStaticSets->fCommaEquivalents;
207 }
208
209 // if there is no match, return the character itself
210 fallback->set(decimal, decimal);
211 return fallback;
212 }
213
214
215 U_NAMESPACE_END