• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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