]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
374ca955 | 3 | * Copyright (C) 1997-2004, International Business Machines Corporation and * |
b75a7d8f A |
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. | |
374ca955 | 16 | * 07/20/98 stephen Slightly modified initialization of monetarySeparator |
b75a7d8f A |
17 | ******************************************************************************** |
18 | */ | |
19 | ||
20 | #include "unicode/utypes.h" | |
21 | ||
22 | #if !UCONFIG_NO_FORMATTING | |
23 | ||
24 | #include "unicode/dcfmtsym.h" | |
374ca955 | 25 | #include "unicode/ures.h" |
b75a7d8f A |
26 | #include "unicode/decimfmt.h" |
27 | #include "unicode/ucurr.h" | |
28 | #include "unicode/choicfmt.h" | |
374ca955 A |
29 | #include "ucurrimp.h" |
30 | #include "cstring.h" | |
31 | #include "locbased.h" | |
b75a7d8f A |
32 | |
33 | // ***************************************************************************** | |
34 | // class DecimalFormatSymbols | |
35 | // ***************************************************************************** | |
36 | ||
37 | U_NAMESPACE_BEGIN | |
38 | ||
374ca955 | 39 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols) |
b75a7d8f | 40 | |
374ca955 | 41 | static const char gNumberElements[] = "NumberElements"; |
b75a7d8f A |
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) | |
374ca955 A |
49 | : UObject(), |
50 | locale() | |
b75a7d8f | 51 | { |
374ca955 | 52 | initialize(locale, status, TRUE); |
b75a7d8f A |
53 | } |
54 | ||
55 | // ------------------------------------- | |
56 | // Initializes this with the decimal format symbols in the desired locale. | |
57 | ||
58 | DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status) | |
374ca955 A |
59 | : UObject(), |
60 | locale(loc) | |
b75a7d8f | 61 | { |
374ca955 | 62 | initialize(locale, status); |
b75a7d8f A |
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 | { | |
374ca955 | 77 | *this = source; |
b75a7d8f A |
78 | } |
79 | ||
80 | // ------------------------------------- | |
81 | // assignment operator | |
82 | ||
83 | DecimalFormatSymbols& | |
84 | DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs) | |
85 | { | |
374ca955 A |
86 | if (this != &rhs) { |
87 | for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) { | |
b75a7d8f A |
88 | // fastCopyFrom is safe, see docs on fSymbols |
89 | fSymbols[(ENumberFormatSymbol)i].fastCopyFrom(rhs.fSymbols[(ENumberFormatSymbol)i]); | |
90 | } | |
374ca955 A |
91 | locale = rhs.locale; |
92 | uprv_strcpy(validLocale, rhs.validLocale); | |
93 | uprv_strcpy(actualLocale, rhs.actualLocale); | |
b75a7d8f A |
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 | } | |
374ca955 | 106 | for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) { |
b75a7d8f A |
107 | if(fSymbols[(ENumberFormatSymbol)i] != that.fSymbols[(ENumberFormatSymbol)i]) { |
108 | return FALSE; | |
109 | } | |
110 | } | |
374ca955 A |
111 | return locale == that.locale && |
112 | uprv_strcmp(validLocale, that.validLocale) == 0 && | |
113 | uprv_strcmp(actualLocale, that.actualLocale) == 0; | |
b75a7d8f A |
114 | } |
115 | ||
116 | // ------------------------------------- | |
117 | ||
118 | void | |
119 | DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, | |
120 | UBool useLastResortData) | |
121 | { | |
374ca955 | 122 | *validLocale = *actualLocale = 0; |
b75a7d8f | 123 | |
374ca955 A |
124 | if (U_FAILURE(status)) |
125 | return; | |
b75a7d8f | 126 | |
374ca955 A |
127 | const char* locStr = loc.getName(); |
128 | UResourceBundle *resource = ures_open((char *)0, locStr, &status); | |
129 | UResourceBundle *numberElementsRes = ures_getByKey(resource, gNumberElements, resource, &status); | |
b75a7d8f A |
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 | } | |
b75a7d8f | 138 | } |
374ca955 A |
139 | else { |
140 | // Gets the number element array. | |
141 | int32_t numberElementsLength = ures_getSize(numberElementsRes); | |
b75a7d8f | 142 | |
374ca955 A |
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 | } | |
b75a7d8f | 159 | |
374ca955 A |
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. */ | |
b75a7d8f | 178 | } |
374ca955 A |
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)); | |
b75a7d8f A |
185 | } |
186 | } | |
374ca955 | 187 | ures_close(numberElementsRes); |
b75a7d8f A |
188 | } |
189 | ||
190 | // Initializes the DecimalFormatSymbol instance with the data obtained | |
191 | // from ResourceBundle in the desired locale. | |
192 | ||
193 | void | |
374ca955 | 194 | DecimalFormatSymbols::initialize(const UChar** numberElements, int32_t *numberElementsStrLen, int32_t numberElementsLength) |
b75a7d8f | 195 | { |
374ca955 A |
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 | } | |
b75a7d8f A |
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; | |
374ca955 A |
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 | |
b75a7d8f A |
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 | |
b75a7d8f | 241 | fSymbols[kPlusSignSymbol] = (UChar)0x002b; // '+' plus sign |
374ca955 | 242 | fSymbols[kMinusSignSymbol] = (UChar)0x2d; // '-' minus sign |
b75a7d8f A |
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 | |
374ca955 A |
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); | |
b75a7d8f A |
258 | } |
259 | ||
260 | U_NAMESPACE_END | |
261 | ||
262 | #endif /* #if !UCONFIG_NO_FORMATTING */ | |
263 | ||
264 | //eof |