Line data Source code
1 : // © 2016 and later: Unicode, Inc. and others.
2 : // License & terms of use: http://www.unicode.org/copyright.html
3 : /*
4 : *******************************************************************************
5 : * Copyright (C) 1997-2016, International Business Machines Corporation and
6 : * others. All Rights Reserved.
7 : *******************************************************************************
8 : *
9 : * File DCFMTSYM.CPP
10 : *
11 : * Modification History:
12 : *
13 : * Date Name Description
14 : * 02/19/97 aliu Converted from java.
15 : * 03/18/97 clhuang Implemented with C++ APIs.
16 : * 03/27/97 helena Updated to pass the simple test after code review.
17 : * 08/26/97 aliu Added currency/intl currency symbol support.
18 : * 07/20/98 stephen Slightly modified initialization of monetarySeparator
19 : ********************************************************************************
20 : */
21 :
22 : #include "unicode/utypes.h"
23 :
24 : #if !UCONFIG_NO_FORMATTING
25 :
26 : #include "unicode/dcfmtsym.h"
27 : #include "unicode/ures.h"
28 : #include "unicode/decimfmt.h"
29 : #include "unicode/ucurr.h"
30 : #include "unicode/choicfmt.h"
31 : #include "unicode/unistr.h"
32 : #include "unicode/numsys.h"
33 : #include "unicode/unum.h"
34 : #include "unicode/utf16.h"
35 : #include "ucurrimp.h"
36 : #include "cstring.h"
37 : #include "locbased.h"
38 : #include "uresimp.h"
39 : #include "ureslocs.h"
40 : #include "charstr.h"
41 :
42 : // *****************************************************************************
43 : // class DecimalFormatSymbols
44 : // *****************************************************************************
45 :
46 : U_NAMESPACE_BEGIN
47 :
48 0 : UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols)
49 :
50 : static const char gNumberElements[] = "NumberElements";
51 : static const char gCurrencySpacingTag[] = "currencySpacing";
52 : static const char gBeforeCurrencyTag[] = "beforeCurrency";
53 : static const char gAfterCurrencyTag[] = "afterCurrency";
54 : static const char gCurrencyMatchTag[] = "currencyMatch";
55 : static const char gCurrencySudMatchTag[] = "surroundingMatch";
56 : static const char gCurrencyInsertBtnTag[] = "insertBetween";
57 : static const char gLatn[] = "latn";
58 : static const char gSymbols[] = "symbols";
59 : static const char gNumberElementsLatnSymbols[] = "NumberElements/latn/symbols";
60 :
61 : static const UChar INTL_CURRENCY_SYMBOL_STR[] = {0xa4, 0xa4, 0};
62 :
63 : // List of field names to be loaded from the data files.
64 : // These are parallel with the enum ENumberFormatSymbol in unicode/dcfmtsym.h.
65 : static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount] = {
66 : "decimal",
67 : "group",
68 : "list",
69 : "percentSign",
70 : NULL, /* Native zero digit is deprecated from CLDR - get it from the numbering system */
71 : NULL, /* Pattern digit character is deprecated from CLDR - use # by default always */
72 : "minusSign",
73 : "plusSign",
74 : NULL, /* currency symbol - Wait until we know the currency before loading from CLDR */
75 : NULL, /* intl currency symbol - Wait until we know the currency before loading from CLDR */
76 : "currencyDecimal",
77 : "exponential",
78 : "perMille",
79 : NULL, /* Escape padding character - not in CLDR */
80 : "infinity",
81 : "nan",
82 : NULL, /* Significant digit symbol - not in CLDR */
83 : "currencyGroup",
84 : NULL, /* one digit - get it from the numbering system */
85 : NULL, /* two digit - get it from the numbering system */
86 : NULL, /* three digit - get it from the numbering system */
87 : NULL, /* four digit - get it from the numbering system */
88 : NULL, /* five digit - get it from the numbering system */
89 : NULL, /* six digit - get it from the numbering system */
90 : NULL, /* seven digit - get it from the numbering system */
91 : NULL, /* eight digit - get it from the numbering system */
92 : NULL, /* nine digit - get it from the numbering system */
93 : "superscriptingExponent", /* Multiplication (x) symbol for exponents */
94 : };
95 :
96 : // -------------------------------------
97 : // Initializes this with the decimal format symbols in the default locale.
98 :
99 0 : DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
100 : : UObject(),
101 0 : locale()
102 : {
103 0 : initialize(locale, status, TRUE);
104 0 : }
105 :
106 : // -------------------------------------
107 : // Initializes this with the decimal format symbols in the desired locale.
108 :
109 0 : DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status)
110 : : UObject(),
111 0 : locale(loc)
112 : {
113 0 : initialize(locale, status);
114 0 : }
115 :
116 0 : DecimalFormatSymbols::DecimalFormatSymbols()
117 : : UObject(),
118 : locale(Locale::getRoot()),
119 0 : currPattern(NULL) {
120 0 : *validLocale = *actualLocale = 0;
121 0 : initialize();
122 0 : }
123 :
124 : DecimalFormatSymbols*
125 0 : DecimalFormatSymbols::createWithLastResortData(UErrorCode& status) {
126 0 : if (U_FAILURE(status)) { return NULL; }
127 0 : DecimalFormatSymbols* sym = new DecimalFormatSymbols();
128 0 : if (sym == NULL) {
129 0 : status = U_MEMORY_ALLOCATION_ERROR;
130 : }
131 0 : return sym;
132 : }
133 :
134 : // -------------------------------------
135 :
136 0 : DecimalFormatSymbols::~DecimalFormatSymbols()
137 : {
138 0 : }
139 :
140 : // -------------------------------------
141 : // copy constructor
142 :
143 0 : DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols &source)
144 0 : : UObject(source)
145 : {
146 0 : *this = source;
147 0 : }
148 :
149 : // -------------------------------------
150 : // assignment operator
151 :
152 : DecimalFormatSymbols&
153 0 : DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs)
154 : {
155 0 : if (this != &rhs) {
156 0 : for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) {
157 : // fastCopyFrom is safe, see docs on fSymbols
158 0 : fSymbols[(ENumberFormatSymbol)i].fastCopyFrom(rhs.fSymbols[(ENumberFormatSymbol)i]);
159 : }
160 0 : for(int32_t i = 0; i < (int32_t)UNUM_CURRENCY_SPACING_COUNT; ++i) {
161 0 : currencySpcBeforeSym[i].fastCopyFrom(rhs.currencySpcBeforeSym[i]);
162 0 : currencySpcAfterSym[i].fastCopyFrom(rhs.currencySpcAfterSym[i]);
163 : }
164 0 : locale = rhs.locale;
165 0 : uprv_strcpy(validLocale, rhs.validLocale);
166 0 : uprv_strcpy(actualLocale, rhs.actualLocale);
167 0 : fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol;
168 0 : fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol;
169 : }
170 0 : return *this;
171 : }
172 :
173 : // -------------------------------------
174 :
175 : UBool
176 0 : DecimalFormatSymbols::operator==(const DecimalFormatSymbols& that) const
177 : {
178 0 : if (this == &that) {
179 0 : return TRUE;
180 : }
181 0 : if (fIsCustomCurrencySymbol != that.fIsCustomCurrencySymbol) {
182 0 : return FALSE;
183 : }
184 0 : if (fIsCustomIntlCurrencySymbol != that.fIsCustomIntlCurrencySymbol) {
185 0 : return FALSE;
186 : }
187 0 : for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) {
188 0 : if(fSymbols[(ENumberFormatSymbol)i] != that.fSymbols[(ENumberFormatSymbol)i]) {
189 0 : return FALSE;
190 : }
191 : }
192 0 : for(int32_t i = 0; i < (int32_t)UNUM_CURRENCY_SPACING_COUNT; ++i) {
193 0 : if(currencySpcBeforeSym[i] != that.currencySpcBeforeSym[i]) {
194 0 : return FALSE;
195 : }
196 0 : if(currencySpcAfterSym[i] != that.currencySpcAfterSym[i]) {
197 0 : return FALSE;
198 : }
199 : }
200 0 : return locale == that.locale &&
201 0 : uprv_strcmp(validLocale, that.validLocale) == 0 &&
202 0 : uprv_strcmp(actualLocale, that.actualLocale) == 0;
203 : }
204 :
205 : // -------------------------------------
206 :
207 : namespace {
208 :
209 : /**
210 : * Sink for enumerating all of the decimal format symbols (more specifically, anything
211 : * under the "NumberElements.symbols" tree).
212 : *
213 : * More specific bundles (en_GB) are enumerated before their parents (en_001, en, root):
214 : * Only store a value if it is still missing, that is, it has not been overridden.
215 : */
216 : struct DecFmtSymDataSink : public ResourceSink {
217 :
218 : // Destination for data, modified via setters.
219 : DecimalFormatSymbols& dfs;
220 : // Boolean array of whether or not we have seen a particular symbol yet.
221 : // Can't simpy check fSymbols because it is pre-populated with defaults.
222 : UBool seenSymbol[DecimalFormatSymbols::kFormatSymbolCount];
223 :
224 : // Constructor/Destructor
225 0 : DecFmtSymDataSink(DecimalFormatSymbols& _dfs) : dfs(_dfs) {
226 0 : uprv_memset(seenSymbol, FALSE, sizeof(seenSymbol));
227 0 : }
228 : virtual ~DecFmtSymDataSink();
229 :
230 0 : virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
231 : UErrorCode &errorCode) {
232 0 : ResourceTable symbolsTable = value.getTable(errorCode);
233 0 : if (U_FAILURE(errorCode)) { return; }
234 0 : for (int32_t j = 0; symbolsTable.getKeyAndValue(j, key, value); ++j) {
235 0 : for (int32_t i=0; i<DecimalFormatSymbols::kFormatSymbolCount; i++) {
236 0 : if (gNumberElementKeys[i] != NULL && uprv_strcmp(key, gNumberElementKeys[i]) == 0) {
237 0 : if (!seenSymbol[i]) {
238 0 : seenSymbol[i] = TRUE;
239 0 : dfs.setSymbol(
240 : (DecimalFormatSymbols::ENumberFormatSymbol) i,
241 0 : value.getUnicodeString(errorCode));
242 0 : if (U_FAILURE(errorCode)) { return; }
243 : }
244 0 : break;
245 : }
246 : }
247 : }
248 : }
249 :
250 : // Returns true if all the symbols have been seen.
251 0 : UBool seenAll() {
252 0 : for (int32_t i=0; i<DecimalFormatSymbols::kFormatSymbolCount; i++) {
253 0 : if (!seenSymbol[i]) {
254 0 : return FALSE;
255 : }
256 : }
257 0 : return TRUE;
258 : }
259 :
260 : // If monetary decimal or grouping were not explicitly set, then set them to be the
261 : // same as their non-monetary counterparts.
262 0 : void resolveMissingMonetarySeparators(const UnicodeString* fSymbols) {
263 0 : if (!seenSymbol[DecimalFormatSymbols::kMonetarySeparatorSymbol]) {
264 0 : dfs.setSymbol(
265 : DecimalFormatSymbols::kMonetarySeparatorSymbol,
266 0 : fSymbols[DecimalFormatSymbols::kDecimalSeparatorSymbol]);
267 : }
268 0 : if (!seenSymbol[DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol]) {
269 0 : dfs.setSymbol(
270 : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol,
271 0 : fSymbols[DecimalFormatSymbols::kGroupingSeparatorSymbol]);
272 : }
273 0 : }
274 : };
275 :
276 : struct CurrencySpacingSink : public ResourceSink {
277 : DecimalFormatSymbols& dfs;
278 : UBool hasBeforeCurrency;
279 : UBool hasAfterCurrency;
280 :
281 0 : CurrencySpacingSink(DecimalFormatSymbols& _dfs)
282 0 : : dfs(_dfs), hasBeforeCurrency(FALSE), hasAfterCurrency(FALSE) {}
283 : virtual ~CurrencySpacingSink();
284 :
285 0 : virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
286 : UErrorCode &errorCode) {
287 0 : ResourceTable spacingTypesTable = value.getTable(errorCode);
288 0 : for (int32_t i = 0; spacingTypesTable.getKeyAndValue(i, key, value); ++i) {
289 : UBool beforeCurrency;
290 0 : if (uprv_strcmp(key, gBeforeCurrencyTag) == 0) {
291 0 : beforeCurrency = TRUE;
292 0 : hasBeforeCurrency = TRUE;
293 0 : } else if (uprv_strcmp(key, gAfterCurrencyTag) == 0) {
294 0 : beforeCurrency = FALSE;
295 0 : hasAfterCurrency = TRUE;
296 : } else {
297 0 : continue;
298 : }
299 :
300 0 : ResourceTable patternsTable = value.getTable(errorCode);
301 0 : for (int32_t j = 0; patternsTable.getKeyAndValue(j, key, value); ++j) {
302 : UCurrencySpacing pattern;
303 0 : if (uprv_strcmp(key, gCurrencyMatchTag) == 0) {
304 0 : pattern = UNUM_CURRENCY_MATCH;
305 0 : } else if (uprv_strcmp(key, gCurrencySudMatchTag) == 0) {
306 0 : pattern = UNUM_CURRENCY_SURROUNDING_MATCH;
307 0 : } else if (uprv_strcmp(key, gCurrencyInsertBtnTag) == 0) {
308 0 : pattern = UNUM_CURRENCY_INSERT;
309 : } else {
310 0 : continue;
311 : }
312 :
313 0 : const UnicodeString& current = dfs.getPatternForCurrencySpacing(
314 0 : pattern, beforeCurrency, errorCode);
315 0 : if (current.isEmpty()) {
316 0 : dfs.setPatternForCurrencySpacing(
317 0 : pattern, beforeCurrency, value.getUnicodeString(errorCode));
318 : }
319 : }
320 : }
321 0 : }
322 :
323 0 : void resolveMissing() {
324 : // For consistency with Java, this method overwrites everything with the defaults unless
325 : // both beforeCurrency and afterCurrency were found in CLDR.
326 : static const char* defaults[] = { "[:letter:]", "[:digit:]", " " };
327 0 : if (!hasBeforeCurrency || !hasAfterCurrency) {
328 0 : for (UBool beforeCurrency = 0; beforeCurrency <= TRUE; beforeCurrency++) {
329 0 : for (int32_t pattern = 0; pattern < UNUM_CURRENCY_SPACING_COUNT; pattern++) {
330 0 : dfs.setPatternForCurrencySpacing((UCurrencySpacing)pattern,
331 0 : beforeCurrency, UnicodeString(defaults[pattern], -1, US_INV));
332 : }
333 : }
334 : }
335 0 : }
336 : };
337 :
338 : // Virtual destructors must be defined out of line.
339 0 : DecFmtSymDataSink::~DecFmtSymDataSink() {}
340 0 : CurrencySpacingSink::~CurrencySpacingSink() {}
341 :
342 : } // namespace
343 :
344 : void
345 0 : DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData)
346 : {
347 0 : if (U_FAILURE(status)) { return; }
348 0 : *validLocale = *actualLocale = 0;
349 0 : currPattern = NULL;
350 :
351 : // First initialize all the symbols to the fallbacks for anything we can't find
352 0 : initialize();
353 :
354 : //
355 : // Next get the numbering system for this locale and set zero digit
356 : // and the digit string based on the numbering system for the locale
357 : //
358 0 : LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(loc, status));
359 : const char *nsName;
360 0 : if (U_SUCCESS(status) && ns->getRadix() == 10 && !ns->isAlgorithmic()) {
361 0 : nsName = ns->getName();
362 0 : UnicodeString digitString(ns->getDescription());
363 0 : int32_t digitIndex = 0;
364 0 : UChar32 digit = digitString.char32At(0);
365 0 : fSymbols[kZeroDigitSymbol].setTo(digit);
366 0 : for (int32_t i = kOneDigitSymbol; i <= kNineDigitSymbol; ++i) {
367 0 : digitIndex += U16_LENGTH(digit);
368 0 : digit = digitString.char32At(digitIndex);
369 0 : fSymbols[i].setTo(digit);
370 : }
371 : } else {
372 0 : nsName = gLatn;
373 : }
374 :
375 : // Open resource bundles
376 0 : const char* locStr = loc.getName();
377 0 : LocalUResourceBundlePointer resource(ures_open(NULL, locStr, &status));
378 : LocalUResourceBundlePointer numberElementsRes(
379 0 : ures_getByKeyWithFallback(resource.getAlias(), gNumberElements, NULL, &status));
380 :
381 0 : if (U_FAILURE(status)) {
382 0 : if ( useLastResortData ) {
383 0 : status = U_USING_DEFAULT_WARNING;
384 0 : initialize();
385 : }
386 0 : return;
387 : }
388 :
389 : // Set locale IDs
390 : // TODO: Is there a way to do this without depending on the resource bundle instance?
391 0 : U_LOCALE_BASED(locBased, *this);
392 0 : locBased.setLocaleIDs(
393 : ures_getLocaleByType(
394 0 : numberElementsRes.getAlias(),
395 : ULOC_VALID_LOCALE, &status),
396 : ures_getLocaleByType(
397 0 : numberElementsRes.getAlias(),
398 0 : ULOC_ACTUAL_LOCALE, &status));
399 :
400 : // Now load the rest of the data from the data sink.
401 : // Start with loading this nsName if it is not Latin.
402 0 : DecFmtSymDataSink sink(*this);
403 0 : if (uprv_strcmp(nsName, gLatn) != 0) {
404 0 : CharString path;
405 0 : path.append(gNumberElements, status)
406 0 : .append('/', status)
407 0 : .append(nsName, status)
408 0 : .append('/', status)
409 0 : .append(gSymbols, status);
410 0 : ures_getAllItemsWithFallback(resource.getAlias(), path.data(), sink, status);
411 :
412 : // If no symbols exist for the given nsName and resource bundle, silently ignore
413 : // and fall back to Latin.
414 0 : if (status == U_MISSING_RESOURCE_ERROR) {
415 0 : status = U_ZERO_ERROR;
416 0 : } else if (U_FAILURE(status)) {
417 0 : return;
418 : }
419 : }
420 :
421 : // Continue with Latin if necessary.
422 0 : if (!sink.seenAll()) {
423 0 : ures_getAllItemsWithFallback(resource.getAlias(), gNumberElementsLatnSymbols, sink, status);
424 0 : if (U_FAILURE(status)) { return; }
425 : }
426 :
427 : // Let the monetary number separators equal the default number separators if necessary.
428 0 : sink.resolveMissingMonetarySeparators(fSymbols);
429 :
430 : // Obtain currency data from the currency API. This is strictly
431 : // for backward compatibility; we don't use DecimalFormatSymbols
432 : // for currency data anymore.
433 0 : UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
434 : UChar curriso[4];
435 0 : UnicodeString tempStr;
436 0 : ucurr_forLocale(locStr, curriso, 4, &internalStatus);
437 :
438 0 : uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
439 0 : if (U_SUCCESS(internalStatus)) {
440 0 : fSymbols[kIntlCurrencySymbol].setTo(curriso, -1);
441 0 : fSymbols[kCurrencySymbol] = tempStr;
442 : }
443 : /* else use the default values. */
444 :
445 : //load the currency data
446 0 : UChar ucc[4]={0}; //Currency Codes are always 3 chars long
447 0 : int32_t uccLen = 4;
448 0 : const char* locName = loc.getName();
449 0 : UErrorCode localStatus = U_ZERO_ERROR;
450 0 : uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus);
451 :
452 0 : if(U_SUCCESS(localStatus) && uccLen > 0) {
453 0 : char cc[4]={0};
454 0 : u_UCharsToChars(ucc, cc, uccLen);
455 : /* An explicit currency was requested */
456 0 : LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus));
457 : LocalUResourceBundlePointer currency(
458 0 : ures_getByKeyWithFallback(currencyResource.getAlias(), "Currencies", NULL, &localStatus));
459 0 : ures_getByKeyWithFallback(currency.getAlias(), cc, currency.getAlias(), &localStatus);
460 0 : if(U_SUCCESS(localStatus) && ures_getSize(currency.getAlias())>2) { // the length is 3 if more data is present
461 0 : ures_getByIndex(currency.getAlias(), 2, currency.getAlias(), &localStatus);
462 0 : int32_t currPatternLen = 0;
463 0 : currPattern =
464 0 : ures_getStringByIndex(currency.getAlias(), (int32_t)0, &currPatternLen, &localStatus);
465 : UnicodeString decimalSep =
466 0 : ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)1, &localStatus);
467 : UnicodeString groupingSep =
468 0 : ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)2, &localStatus);
469 0 : if(U_SUCCESS(localStatus)){
470 0 : fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep;
471 0 : fSymbols[kMonetarySeparatorSymbol] = decimalSep;
472 : //pattern.setTo(TRUE, currPattern, currPatternLen);
473 0 : status = localStatus;
474 : }
475 : }
476 : /* else An explicit currency was requested and is unknown or locale data is malformed. */
477 : /* ucurr_* API will get the correct value later on. */
478 : }
479 : // else ignore the error if no currency
480 :
481 : // Currency Spacing.
482 0 : LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &status));
483 0 : CurrencySpacingSink currencySink(*this);
484 0 : ures_getAllItemsWithFallback(currencyResource.getAlias(), gCurrencySpacingTag, currencySink, status);
485 0 : currencySink.resolveMissing();
486 0 : if (U_FAILURE(status)) { return; }
487 : }
488 :
489 : void
490 0 : DecimalFormatSymbols::initialize() {
491 : /*
492 : * These strings used to be in static arrays, but the HP/UX aCC compiler
493 : * cannot initialize a static array with class constructors.
494 : * markus 2000may25
495 : */
496 0 : fSymbols[kDecimalSeparatorSymbol] = (UChar)0x2e; // '.' decimal separator
497 0 : fSymbols[kGroupingSeparatorSymbol].remove(); // group (thousands) separator
498 0 : fSymbols[kPatternSeparatorSymbol] = (UChar)0x3b; // ';' pattern separator
499 0 : fSymbols[kPercentSymbol] = (UChar)0x25; // '%' percent sign
500 0 : fSymbols[kZeroDigitSymbol] = (UChar)0x30; // '0' native 0 digit
501 0 : fSymbols[kOneDigitSymbol] = (UChar)0x31; // '1' native 1 digit
502 0 : fSymbols[kTwoDigitSymbol] = (UChar)0x32; // '2' native 2 digit
503 0 : fSymbols[kThreeDigitSymbol] = (UChar)0x33; // '3' native 3 digit
504 0 : fSymbols[kFourDigitSymbol] = (UChar)0x34; // '4' native 4 digit
505 0 : fSymbols[kFiveDigitSymbol] = (UChar)0x35; // '5' native 5 digit
506 0 : fSymbols[kSixDigitSymbol] = (UChar)0x36; // '6' native 6 digit
507 0 : fSymbols[kSevenDigitSymbol] = (UChar)0x37; // '7' native 7 digit
508 0 : fSymbols[kEightDigitSymbol] = (UChar)0x38; // '8' native 8 digit
509 0 : fSymbols[kNineDigitSymbol] = (UChar)0x39; // '9' native 9 digit
510 0 : fSymbols[kDigitSymbol] = (UChar)0x23; // '#' pattern digit
511 0 : fSymbols[kPlusSignSymbol] = (UChar)0x002b; // '+' plus sign
512 0 : fSymbols[kMinusSignSymbol] = (UChar)0x2d; // '-' minus sign
513 0 : fSymbols[kCurrencySymbol] = (UChar)0xa4; // 'OX' currency symbol
514 0 : fSymbols[kIntlCurrencySymbol].setTo(TRUE, INTL_CURRENCY_SYMBOL_STR, 2);
515 0 : fSymbols[kMonetarySeparatorSymbol] = (UChar)0x2e; // '.' monetary decimal separator
516 0 : fSymbols[kExponentialSymbol] = (UChar)0x45; // 'E' exponential
517 0 : fSymbols[kPerMillSymbol] = (UChar)0x2030; // '%o' per mill
518 0 : fSymbols[kPadEscapeSymbol] = (UChar)0x2a; // '*' pad escape symbol
519 0 : fSymbols[kInfinitySymbol] = (UChar)0x221e; // 'oo' infinite
520 0 : fSymbols[kNaNSymbol] = (UChar)0xfffd; // SUB NaN
521 0 : fSymbols[kSignificantDigitSymbol] = (UChar)0x0040; // '@' significant digit
522 0 : fSymbols[kMonetaryGroupingSeparatorSymbol].remove(); //
523 0 : fSymbols[kExponentMultiplicationSymbol] = (UChar)0xd7; // 'x' multiplication symbol for exponents
524 0 : fIsCustomCurrencySymbol = FALSE;
525 0 : fIsCustomIntlCurrencySymbol = FALSE;
526 :
527 0 : }
528 :
529 : Locale
530 0 : DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
531 0 : U_LOCALE_BASED(locBased, *this);
532 0 : return locBased.getLocale(type, status);
533 : }
534 :
535 : const UnicodeString&
536 0 : DecimalFormatSymbols::getPatternForCurrencySpacing(UCurrencySpacing type,
537 : UBool beforeCurrency,
538 : UErrorCode& status) const {
539 0 : if (U_FAILURE(status)) {
540 0 : return fNoSymbol; // always empty.
541 : }
542 0 : if (beforeCurrency) {
543 0 : return currencySpcBeforeSym[(int32_t)type];
544 : } else {
545 0 : return currencySpcAfterSym[(int32_t)type];
546 : }
547 : }
548 :
549 : void
550 0 : DecimalFormatSymbols::setPatternForCurrencySpacing(UCurrencySpacing type,
551 : UBool beforeCurrency,
552 : const UnicodeString& pattern) {
553 0 : if (beforeCurrency) {
554 0 : currencySpcBeforeSym[(int32_t)type] = pattern;
555 : } else {
556 0 : currencySpcAfterSym[(int32_t)type] = pattern;
557 : }
558 0 : }
559 : U_NAMESPACE_END
560 :
561 : #endif /* #if !UCONFIG_NO_FORMATTING */
562 :
563 : //eof
|