]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | ******************************************************************************* | |
3 | * Copyright (C) 1997-2004, International Business Machines Corporation and * | |
4 | * others. All Rights Reserved. * | |
5 | ******************************************************************************* | |
6 | * | |
7 | * File DCFMTSYM.CPP | |
8 | * | |
9 | * Modification History: | |
10 | * | |
11 | * Date Name Description | |
12 | * 02/19/97 aliu Converted from java. | |
13 | * 03/18/97 clhuang Implemented with C++ APIs. | |
14 | * 03/27/97 helena Updated to pass the simple test after code review. | |
15 | * 08/26/97 aliu Added currency/intl currency symbol support. | |
16 | * 07/20/98 stephen Slightly modified initialization of monetarySeparator | |
17 | ******************************************************************************** | |
18 | */ | |
19 | ||
20 | #include "unicode/utypes.h" | |
21 | ||
22 | #if !UCONFIG_NO_FORMATTING | |
23 | ||
24 | #include "unicode/dcfmtsym.h" | |
25 | #include "unicode/ures.h" | |
26 | #include "unicode/decimfmt.h" | |
27 | #include "unicode/ucurr.h" | |
28 | #include "unicode/choicfmt.h" | |
29 | #include "ucurrimp.h" | |
30 | #include "cstring.h" | |
31 | #include "locbased.h" | |
32 | ||
33 | // ***************************************************************************** | |
34 | // class DecimalFormatSymbols | |
35 | // ***************************************************************************** | |
36 | ||
37 | U_NAMESPACE_BEGIN | |
38 | ||
39 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols) | |
40 | ||
41 | static const char gNumberElements[] = "NumberElements"; | |
42 | ||
43 | static const UChar INTL_CURRENCY_SYMBOL_STR[] = {0xa4, 0xa4, 0}; | |
44 | ||
45 | // ------------------------------------- | |
46 | // Initializes this with the decimal format symbols in the default locale. | |
47 | ||
48 | DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status) | |
49 | : UObject(), | |
50 | locale() | |
51 | { | |
52 | initialize(locale, status, TRUE); | |
53 | } | |
54 | ||
55 | // ------------------------------------- | |
56 | // Initializes this with the decimal format symbols in the desired locale. | |
57 | ||
58 | DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status) | |
59 | : UObject(), | |
60 | locale(loc) | |
61 | { | |
62 | initialize(locale, status); | |
63 | } | |
64 | ||
65 | // ------------------------------------- | |
66 | ||
67 | DecimalFormatSymbols::~DecimalFormatSymbols() | |
68 | { | |
69 | } | |
70 | ||
71 | // ------------------------------------- | |
72 | // copy constructor | |
73 | ||
74 | DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols &source) | |
75 | : UObject(source) | |
76 | { | |
77 | *this = source; | |
78 | } | |
79 | ||
80 | // ------------------------------------- | |
81 | // assignment operator | |
82 | ||
83 | DecimalFormatSymbols& | |
84 | DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs) | |
85 | { | |
86 | if (this != &rhs) { | |
87 | for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) { | |
88 | // fastCopyFrom is safe, see docs on fSymbols | |
89 | fSymbols[(ENumberFormatSymbol)i].fastCopyFrom(rhs.fSymbols[(ENumberFormatSymbol)i]); | |
90 | } | |
91 | locale = rhs.locale; | |
92 | uprv_strcpy(validLocale, rhs.validLocale); | |
93 | uprv_strcpy(actualLocale, rhs.actualLocale); | |
94 | } | |
95 | return *this; | |
96 | } | |
97 | ||
98 | // ------------------------------------- | |
99 | ||
100 | UBool | |
101 | DecimalFormatSymbols::operator==(const DecimalFormatSymbols& that) const | |
102 | { | |
103 | if (this == &that) { | |
104 | return TRUE; | |
105 | } | |
106 | for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) { | |
107 | if(fSymbols[(ENumberFormatSymbol)i] != that.fSymbols[(ENumberFormatSymbol)i]) { | |
108 | return FALSE; | |
109 | } | |
110 | } | |
111 | return locale == that.locale && | |
112 | uprv_strcmp(validLocale, that.validLocale) == 0 && | |
113 | uprv_strcmp(actualLocale, that.actualLocale) == 0; | |
114 | } | |
115 | ||
116 | // ------------------------------------- | |
117 | ||
118 | void | |
119 | DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, | |
120 | UBool useLastResortData) | |
121 | { | |
122 | *validLocale = *actualLocale = 0; | |
123 | ||
124 | if (U_FAILURE(status)) | |
125 | return; | |
126 | ||
127 | const char* locStr = loc.getName(); | |
128 | UResourceBundle *resource = ures_open((char *)0, locStr, &status); | |
129 | UResourceBundle *numberElementsRes = ures_getByKey(resource, gNumberElements, resource, &status); | |
130 | if (U_FAILURE(status)) | |
131 | { | |
132 | // Initializes with last resort data if necessary. | |
133 | if (useLastResortData) | |
134 | { | |
135 | status = U_USING_FALLBACK_WARNING; | |
136 | initialize(); | |
137 | } | |
138 | } | |
139 | else { | |
140 | // Gets the number element array. | |
141 | int32_t numberElementsLength = ures_getSize(numberElementsRes); | |
142 | ||
143 | if (numberElementsLength > (int32_t)kFormatSymbolCount) { | |
144 | /* Warning: Invalid format. Array too large. */ | |
145 | numberElementsLength = (int32_t)kFormatSymbolCount; | |
146 | } | |
147 | // If the array size is too small, something is wrong with the resource | |
148 | // bundle, returns the failure error code. | |
149 | if (numberElementsLength != 12 || U_FAILURE(status)) { | |
150 | status = U_INVALID_FORMAT_ERROR; | |
151 | } | |
152 | else { | |
153 | const UChar *numberElements[kFormatSymbolCount]; | |
154 | int32_t numberElementsStrLen[kFormatSymbolCount]; | |
155 | int32_t i = 0; | |
156 | for(i = 0; i<numberElementsLength; i++) { | |
157 | numberElements[i] = ures_getStringByIndex(numberElementsRes, i, &numberElementsStrLen[i], &status); | |
158 | } | |
159 | ||
160 | if (U_SUCCESS(status)) { | |
161 | initialize(numberElements, numberElementsStrLen, numberElementsLength); | |
162 | ||
163 | // Obtain currency data from the currency API. This is strictly | |
164 | // for backward compatibility; we don't use DecimalFormatSymbols | |
165 | // for currency data anymore. | |
166 | UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out | |
167 | UChar curriso[4]; | |
168 | UnicodeString tempStr; | |
169 | ucurr_forLocale(locStr, curriso, 4, &internalStatus); | |
170 | ||
171 | // Reuse numberElements[0] as a temporary buffer | |
172 | uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); | |
173 | if (U_SUCCESS(internalStatus)) { | |
174 | fSymbols[kIntlCurrencySymbol] = curriso; | |
175 | fSymbols[kCurrencySymbol] = tempStr; | |
176 | } | |
177 | /* else use the default values. */ | |
178 | } | |
179 | ||
180 | U_LOCALE_BASED(locBased, *this); | |
181 | locBased.setLocaleIDs(ures_getLocaleByType(numberElementsRes, | |
182 | ULOC_VALID_LOCALE, &status), | |
183 | ures_getLocaleByType(numberElementsRes, | |
184 | ULOC_ACTUAL_LOCALE, &status)); | |
185 | } | |
186 | } | |
187 | ures_close(numberElementsRes); | |
188 | } | |
189 | ||
190 | // Initializes the DecimalFormatSymbol instance with the data obtained | |
191 | // from ResourceBundle in the desired locale. | |
192 | ||
193 | void | |
194 | DecimalFormatSymbols::initialize(const UChar** numberElements, int32_t *numberElementsStrLen, int32_t numberElementsLength) | |
195 | { | |
196 | static const int32_t TYPE_MAPPING[][2] = { | |
197 | {kDecimalSeparatorSymbol, 0}, | |
198 | {kGroupingSeparatorSymbol, 1}, | |
199 | {kPatternSeparatorSymbol, 2}, | |
200 | {kPercentSymbol, 3}, | |
201 | {kZeroDigitSymbol, 4}, | |
202 | {kDigitSymbol, 5}, | |
203 | {kMinusSignSymbol, 6}, | |
204 | {kExponentialSymbol, 7}, | |
205 | {kPerMillSymbol, 8}, | |
206 | {kInfinitySymbol, 9}, | |
207 | {kNaNSymbol, 10}, | |
208 | {kPlusSignSymbol, 11}, | |
209 | {kMonetarySeparatorSymbol, 0} | |
210 | }; | |
211 | int32_t idx; | |
212 | ||
213 | for (idx = 0; idx < (int32_t)(sizeof(TYPE_MAPPING)/sizeof(TYPE_MAPPING[0])); idx++) { | |
214 | if (TYPE_MAPPING[idx][1] < numberElementsLength) { | |
215 | fSymbols[TYPE_MAPPING[idx][0]].setTo(TRUE, numberElements[TYPE_MAPPING[idx][1]], numberElementsStrLen[TYPE_MAPPING[idx][1]]); | |
216 | } | |
217 | } | |
218 | ||
219 | // Default values until it's set later on. | |
220 | fSymbols[kCurrencySymbol] = (UChar)0xa4; // 'OX' currency symbol | |
221 | fSymbols[kIntlCurrencySymbol] = INTL_CURRENCY_SYMBOL_STR; | |
222 | // TODO: read from locale data, if this makes it into CLDR | |
223 | fSymbols[kSignificantDigitSymbol] = (UChar)0x0040; // '@' significant digit | |
224 | fSymbols[kPadEscapeSymbol] = (UChar)0x002a; // TODO: '*' Hard coded for now; get from resource later | |
225 | } | |
226 | ||
227 | // initialize with default values | |
228 | void | |
229 | DecimalFormatSymbols::initialize() { | |
230 | /* | |
231 | * These strings used to be in static arrays, but the HP/UX aCC compiler | |
232 | * cannot initialize a static array with class constructors. | |
233 | * markus 2000may25 | |
234 | */ | |
235 | fSymbols[kDecimalSeparatorSymbol] = (UChar)0x2e; // '.' decimal separator | |
236 | fSymbols[kGroupingSeparatorSymbol].remove(); // group (thousands) separator | |
237 | fSymbols[kPatternSeparatorSymbol] = (UChar)0x3b; // ';' pattern separator | |
238 | fSymbols[kPercentSymbol] = (UChar)0x25; // '%' percent sign | |
239 | fSymbols[kZeroDigitSymbol] = (UChar)0x30; // '0' native 0 digit | |
240 | fSymbols[kDigitSymbol] = (UChar)0x23; // '#' pattern digit | |
241 | fSymbols[kPlusSignSymbol] = (UChar)0x002b; // '+' plus sign | |
242 | fSymbols[kMinusSignSymbol] = (UChar)0x2d; // '-' minus sign | |
243 | fSymbols[kCurrencySymbol] = (UChar)0xa4; // 'OX' currency symbol | |
244 | fSymbols[kIntlCurrencySymbol] = INTL_CURRENCY_SYMBOL_STR; | |
245 | fSymbols[kMonetarySeparatorSymbol] = (UChar)0x2e; // '.' monetary decimal separator | |
246 | fSymbols[kExponentialSymbol] = (UChar)0x45; // 'E' exponential | |
247 | fSymbols[kPerMillSymbol] = (UChar)0x2030; // '%o' per mill | |
248 | fSymbols[kPadEscapeSymbol] = (UChar)0x2a; // '*' pad escape symbol | |
249 | fSymbols[kInfinitySymbol] = (UChar)0x221e; // 'oo' infinite | |
250 | fSymbols[kNaNSymbol] = (UChar)0xfffd; // SUB NaN | |
251 | fSymbols[kSignificantDigitSymbol] = (UChar)0x0040; // '@' significant digit | |
252 | } | |
253 | ||
254 | Locale | |
255 | DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { | |
256 | U_LOCALE_BASED(locBased, *this); | |
257 | return locBased.getLocale(type, status); | |
258 | } | |
259 | ||
260 | U_NAMESPACE_END | |
261 | ||
262 | #endif /* #if !UCONFIG_NO_FORMATTING */ | |
263 | ||
264 | //eof |