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