1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
11 * Modification History:
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 ********************************************************************************
22 #include "unicode/utypes.h"
24 #if !UCONFIG_NO_FORMATTING
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"
43 // *****************************************************************************
44 // class DecimalFormatSymbols
45 // *****************************************************************************
49 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols
)
51 static const char gNumberElements
[] = "NumberElements";
52 static const char gCurrencySpacingTag
[] = "currencySpacing";
53 static const char gBeforeCurrencyTag
[] = "beforeCurrency";
54 static const char gAfterCurrencyTag
[] = "afterCurrency";
55 static const char gCurrencyMatchTag
[] = "currencyMatch";
56 static const char gCurrencySudMatchTag
[] = "surroundingMatch";
57 static const char gCurrencyInsertBtnTag
[] = "insertBetween";
58 static const char gLatn
[] = "latn";
59 static const char gSymbols
[] = "symbols";
60 static const char gNumberElementsLatnSymbols
[] = "NumberElements/latn/symbols";
62 static const UChar INTL_CURRENCY_SYMBOL_STR
[] = {0xa4, 0xa4, 0};
64 // List of field names to be loaded from the data files.
65 // These are parallel with the enum ENumberFormatSymbol in unicode/dcfmtsym.h.
66 static const char *gNumberElementKeys
[DecimalFormatSymbols::kFormatSymbolCount
] = {
69 NULL
, /* #11897: the <list> symbol is NOT the pattern separator symbol */
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 */
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 */
80 NULL
, /* Escape padding character - not in CLDR */
83 NULL
, /* Significant digit symbol - not in CLDR */
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 */
97 // -------------------------------------
98 // Initializes this with the decimal format symbols in the default locale.
100 DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode
& status
)
101 : UObject(), locale(), currPattern(NULL
) {
102 initialize(locale
, status
, TRUE
);
105 // -------------------------------------
106 // Initializes this with the decimal format symbols in the desired locale.
108 DecimalFormatSymbols::DecimalFormatSymbols(const Locale
& loc
, UErrorCode
& status
)
109 : UObject(), locale(loc
), currPattern(NULL
) {
110 initialize(locale
, status
);
113 DecimalFormatSymbols::DecimalFormatSymbols(const Locale
& loc
, const NumberingSystem
& ns
, UErrorCode
& status
)
114 : UObject(), locale(loc
), currPattern(NULL
) {
115 initialize(locale
, status
, FALSE
, &ns
);
118 DecimalFormatSymbols::DecimalFormatSymbols()
119 : UObject(), locale(Locale::getRoot()), currPattern(NULL
) {
120 *validLocale
= *actualLocale
= *fNSName
= 0;
124 DecimalFormatSymbols
*
125 DecimalFormatSymbols::createWithLastResortData(UErrorCode
& status
) {
126 if (U_FAILURE(status
)) { return NULL
; }
127 DecimalFormatSymbols
* sym
= new DecimalFormatSymbols();
129 status
= U_MEMORY_ALLOCATION_ERROR
;
134 // -------------------------------------
136 DecimalFormatSymbols::~DecimalFormatSymbols()
140 // -------------------------------------
143 DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols
&source
)
149 // -------------------------------------
150 // assignment operator
152 DecimalFormatSymbols
&
153 DecimalFormatSymbols::operator=(const DecimalFormatSymbols
& rhs
)
156 for(int32_t i
= 0; i
< (int32_t)kFormatSymbolCount
; ++i
) {
157 // fastCopyFrom is safe, see docs on fSymbols
158 fSymbols
[(ENumberFormatSymbol
)i
].fastCopyFrom(rhs
.fSymbols
[(ENumberFormatSymbol
)i
]);
160 for(int32_t i
= 0; i
< (int32_t)UNUM_CURRENCY_SPACING_COUNT
; ++i
) {
161 currencySpcBeforeSym
[i
].fastCopyFrom(rhs
.currencySpcBeforeSym
[i
]);
162 currencySpcAfterSym
[i
].fastCopyFrom(rhs
.currencySpcAfterSym
[i
]);
165 uprv_strcpy(validLocale
, rhs
.validLocale
);
166 uprv_strcpy(actualLocale
, rhs
.actualLocale
);
167 fIsCustomCurrencySymbol
= rhs
.fIsCustomCurrencySymbol
;
168 fIsCustomIntlCurrencySymbol
= rhs
.fIsCustomIntlCurrencySymbol
;
169 fCodePointZero
= rhs
.fCodePointZero
;
170 uprv_strcpy(fNSName
, rhs
.fNSName
);
175 // -------------------------------------
178 DecimalFormatSymbols::operator==(const DecimalFormatSymbols
& that
) const
183 if (fIsCustomCurrencySymbol
!= that
.fIsCustomCurrencySymbol
) {
186 if (fIsCustomIntlCurrencySymbol
!= that
.fIsCustomIntlCurrencySymbol
) {
189 for(int32_t i
= 0; i
< (int32_t)kFormatSymbolCount
; ++i
) {
190 if(fSymbols
[(ENumberFormatSymbol
)i
] != that
.fSymbols
[(ENumberFormatSymbol
)i
]) {
194 for(int32_t i
= 0; i
< (int32_t)UNUM_CURRENCY_SPACING_COUNT
; ++i
) {
195 if(currencySpcBeforeSym
[i
] != that
.currencySpcBeforeSym
[i
]) {
198 if(currencySpcAfterSym
[i
] != that
.currencySpcAfterSym
[i
]) {
202 // No need to check fCodePointZero since it is based on fSymbols
203 return locale
== that
.locale
&&
204 uprv_strcmp(validLocale
, that
.validLocale
) == 0 &&
205 uprv_strcmp(actualLocale
, that
.actualLocale
) == 0 &&
206 uprv_strcmp(fNSName
, that
.fNSName
) == 0;
209 // -------------------------------------
214 * Sink for enumerating all of the decimal format symbols (more specifically, anything
215 * under the "NumberElements.symbols" tree).
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.
220 struct DecFmtSymDataSink
: public ResourceSink
{
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
];
228 // Constructor/Destructor
229 DecFmtSymDataSink(DecimalFormatSymbols
& _dfs
) : dfs(_dfs
) {
230 uprv_memset(seenSymbol
, FALSE
, sizeof(seenSymbol
));
232 virtual ~DecFmtSymDataSink();
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
;
244 (DecimalFormatSymbols::ENumberFormatSymbol
) i
,
245 value
.getUnicodeString(errorCode
));
246 if (U_FAILURE(errorCode
)) { return; }
254 // Returns true if all the symbols have been seen.
256 for (int32_t i
=0; i
<DecimalFormatSymbols::kFormatSymbolCount
; i
++) {
257 if (!seenSymbol
[i
]) {
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
]) {
269 DecimalFormatSymbols::kMonetarySeparatorSymbol
,
270 fSymbols
[DecimalFormatSymbols::kDecimalSeparatorSymbol
]);
272 if (!seenSymbol
[DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
]) {
274 DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
,
275 fSymbols
[DecimalFormatSymbols::kGroupingSeparatorSymbol
]);
280 struct CurrencySpacingSink
: public ResourceSink
{
281 DecimalFormatSymbols
& dfs
;
282 UBool hasBeforeCurrency
;
283 UBool hasAfterCurrency
;
285 CurrencySpacingSink(DecimalFormatSymbols
& _dfs
)
286 : dfs(_dfs
), hasBeforeCurrency(FALSE
), hasAfterCurrency(FALSE
) {}
287 virtual ~CurrencySpacingSink();
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
;
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
;
317 const UnicodeString
& current
= dfs
.getPatternForCurrencySpacing(
318 pattern
, beforeCurrency
, errorCode
);
319 if (current
.isEmpty()) {
320 dfs
.setPatternForCurrencySpacing(
321 pattern
, beforeCurrency
, value
.getUnicodeString(errorCode
));
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
));
342 // Virtual destructors must be defined out of line.
343 DecFmtSymDataSink::~DecFmtSymDataSink() {}
344 CurrencySpacingSink::~CurrencySpacingSink() {}
349 DecimalFormatSymbols::initialize(const Locale
& loc
, UErrorCode
& status
,
350 UBool useLastResortData
, const NumberingSystem
* ns
)
352 if (U_FAILURE(status
)) { return; }
353 *validLocale
= *actualLocale
= *fNSName
= 0;
355 // First initialize all the symbols to the fallbacks for anything we can't find
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
362 LocalPointer
<NumberingSystem
> nsLocal
;
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();
369 const char *nsName
= gLatn
;
370 if (U_SUCCESS(status
) && nsName
!= nullptr) {
371 nsName
= ns
->getName();
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()) {
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
);
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
));
396 if (U_FAILURE(status
)) {
397 if ( useLastResortData
) {
398 status
= U_USING_DEFAULT_WARNING
;
405 // TODO: Is there a way to do this without depending on the resource bundle instance?
406 U_LOCALE_BASED(locBased
, *this);
407 locBased
.setLocaleIDs(
408 ures_getLocaleByType(
409 numberElementsRes
.getAlias(),
410 ULOC_VALID_LOCALE
, &status
),
411 ures_getLocaleByType(
412 numberElementsRes
.getAlias(),
413 ULOC_ACTUAL_LOCALE
, &status
));
415 // Now load the rest of the data from the data sink.
416 // Start with loading this nsName if it is not Latin.
417 DecFmtSymDataSink
sink(*this);
418 if (uprv_strcmp(nsName
, gLatn
) != 0) {
420 path
.append(gNumberElements
, status
)
422 .append(nsName
, status
)
424 .append(gSymbols
, status
);
425 ures_getAllItemsWithFallback(resource
.getAlias(), path
.data(), sink
, status
);
427 // If no symbols exist for the given nsName and resource bundle, silently ignore
428 // and fall back to Latin.
429 if (status
== U_MISSING_RESOURCE_ERROR
) {
430 status
= U_ZERO_ERROR
;
431 } else if (U_FAILURE(status
)) {
436 // Continue with Latin if necessary.
437 if (!sink
.seenAll()) {
438 ures_getAllItemsWithFallback(resource
.getAlias(), gNumberElementsLatnSymbols
, sink
, status
);
439 if (U_FAILURE(status
)) { return; }
442 // Let the monetary number separators equal the default number separators if necessary.
443 sink
.resolveMissingMonetarySeparators(fSymbols
);
445 // Resolve codePointZero
446 UChar32 tempCodePointZero
= -1;
447 for (int32_t i
=0; i
<=9; i
++) {
448 const UnicodeString
& stringDigit
= getConstDigitSymbol(i
);
449 if (stringDigit
.countChar32() != 1) {
450 tempCodePointZero
= -1;
453 UChar32 cp
= stringDigit
.char32At(0);
455 tempCodePointZero
= cp
;
456 } else if (cp
!= tempCodePointZero
+ i
) {
457 tempCodePointZero
= -1;
461 fCodePointZero
= tempCodePointZero
;
463 // Obtain currency data from the currency API. This is strictly
464 // for backward compatibility; we don't use DecimalFormatSymbols
465 // for currency data anymore.
466 UErrorCode internalStatus
= U_ZERO_ERROR
; // don't propagate failures out
468 UnicodeString tempStr
;
469 int32_t currisoLength
= ucurr_forLocale(locStr
, curriso
, UPRV_LENGTHOF(curriso
), &internalStatus
);
470 if (U_SUCCESS(internalStatus
) && currisoLength
== 3) {
471 uprv_getStaticCurrencyName(curriso
, locStr
, tempStr
, internalStatus
);
472 if (U_SUCCESS(internalStatus
)) {
473 fSymbols
[kIntlCurrencySymbol
].setTo(curriso
, currisoLength
);
474 fSymbols
[kCurrencySymbol
] = tempStr
;
477 /* else use the default values. */
479 //load the currency data
480 UChar ucc
[4]={0}; //Currency Codes are always 3 chars long
482 const char* locName
= loc
.getName();
483 UErrorCode localStatus
= U_ZERO_ERROR
;
484 uccLen
= ucurr_forLocale(locName
, ucc
, uccLen
, &localStatus
);
486 // TODO: Currency pattern data loading is duplicated in number_formatimpl.cpp
487 if(U_SUCCESS(localStatus
) && uccLen
> 0) {
489 u_UCharsToChars(ucc
, cc
, uccLen
);
490 /* An explicit currency was requested */
491 LocalUResourceBundlePointer
currencyResource(ures_open(U_ICUDATA_CURR
, locStr
, &localStatus
));
492 LocalUResourceBundlePointer
currency(
493 ures_getByKeyWithFallback(currencyResource
.getAlias(), "Currencies", NULL
, &localStatus
));
494 ures_getByKeyWithFallback(currency
.getAlias(), cc
, currency
.getAlias(), &localStatus
);
495 if(U_SUCCESS(localStatus
) && ures_getSize(currency
.getAlias())>2) { // the length is 3 if more data is present
496 ures_getByIndex(currency
.getAlias(), 2, currency
.getAlias(), &localStatus
);
497 int32_t currPatternLen
= 0;
499 ures_getStringByIndex(currency
.getAlias(), (int32_t)0, &currPatternLen
, &localStatus
);
500 UnicodeString decimalSep
=
501 ures_getUnicodeStringByIndex(currency
.getAlias(), (int32_t)1, &localStatus
);
502 UnicodeString groupingSep
=
503 ures_getUnicodeStringByIndex(currency
.getAlias(), (int32_t)2, &localStatus
);
504 if(U_SUCCESS(localStatus
)){
505 fSymbols
[kMonetaryGroupingSeparatorSymbol
] = groupingSep
;
506 fSymbols
[kMonetarySeparatorSymbol
] = decimalSep
;
507 //pattern.setTo(TRUE, currPattern, currPatternLen);
508 status
= localStatus
;
511 /* else An explicit currency was requested and is unknown or locale data is malformed. */
512 /* ucurr_* API will get the correct value later on. */
514 // else ignore the error if no currency
517 LocalUResourceBundlePointer
currencyResource(ures_open(U_ICUDATA_CURR
, locStr
, &status
));
518 CurrencySpacingSink
currencySink(*this);
519 ures_getAllItemsWithFallback(currencyResource
.getAlias(), gCurrencySpacingTag
, currencySink
, status
);
520 currencySink
.resolveMissing();
521 if (U_FAILURE(status
)) { return; }
525 DecimalFormatSymbols::initialize() {
527 * These strings used to be in static arrays, but the HP/UX aCC compiler
528 * cannot initialize a static array with class constructors.
531 fSymbols
[kDecimalSeparatorSymbol
] = (UChar
)0x2e; // '.' decimal separator
532 fSymbols
[kGroupingSeparatorSymbol
].remove(); // group (thousands) separator
533 fSymbols
[kPatternSeparatorSymbol
] = (UChar
)0x3b; // ';' pattern separator
534 fSymbols
[kPercentSymbol
] = (UChar
)0x25; // '%' percent sign
535 fSymbols
[kZeroDigitSymbol
] = (UChar
)0x30; // '0' native 0 digit
536 fSymbols
[kOneDigitSymbol
] = (UChar
)0x31; // '1' native 1 digit
537 fSymbols
[kTwoDigitSymbol
] = (UChar
)0x32; // '2' native 2 digit
538 fSymbols
[kThreeDigitSymbol
] = (UChar
)0x33; // '3' native 3 digit
539 fSymbols
[kFourDigitSymbol
] = (UChar
)0x34; // '4' native 4 digit
540 fSymbols
[kFiveDigitSymbol
] = (UChar
)0x35; // '5' native 5 digit
541 fSymbols
[kSixDigitSymbol
] = (UChar
)0x36; // '6' native 6 digit
542 fSymbols
[kSevenDigitSymbol
] = (UChar
)0x37; // '7' native 7 digit
543 fSymbols
[kEightDigitSymbol
] = (UChar
)0x38; // '8' native 8 digit
544 fSymbols
[kNineDigitSymbol
] = (UChar
)0x39; // '9' native 9 digit
545 fSymbols
[kDigitSymbol
] = (UChar
)0x23; // '#' pattern digit
546 fSymbols
[kPlusSignSymbol
] = (UChar
)0x002b; // '+' plus sign
547 fSymbols
[kMinusSignSymbol
] = (UChar
)0x2d; // '-' minus sign
548 fSymbols
[kCurrencySymbol
] = (UChar
)0xa4; // 'OX' currency symbol
549 fSymbols
[kIntlCurrencySymbol
].setTo(TRUE
, INTL_CURRENCY_SYMBOL_STR
, 2);
550 fSymbols
[kMonetarySeparatorSymbol
] = (UChar
)0x2e; // '.' monetary decimal separator
551 fSymbols
[kExponentialSymbol
] = (UChar
)0x45; // 'E' exponential
552 fSymbols
[kPerMillSymbol
] = (UChar
)0x2030; // '%o' per mill
553 fSymbols
[kPadEscapeSymbol
] = (UChar
)0x2a; // '*' pad escape symbol
554 fSymbols
[kInfinitySymbol
] = (UChar
)0x221e; // 'oo' infinite
555 fSymbols
[kNaNSymbol
] = (UChar
)0xfffd; // SUB NaN
556 fSymbols
[kSignificantDigitSymbol
] = (UChar
)0x0040; // '@' significant digit
557 fSymbols
[kMonetaryGroupingSeparatorSymbol
].remove(); //
558 fSymbols
[kExponentMultiplicationSymbol
] = (UChar
)0xd7; // 'x' multiplication symbol for exponents
559 fIsCustomCurrencySymbol
= FALSE
;
560 fIsCustomIntlCurrencySymbol
= FALSE
;
561 fCodePointZero
= 0x30;
562 U_ASSERT(fCodePointZero
== fSymbols
[kZeroDigitSymbol
].char32At(0));
567 DecimalFormatSymbols::getLocale(ULocDataLocaleType type
, UErrorCode
& status
) const {
568 U_LOCALE_BASED(locBased
, *this);
569 return locBased
.getLocale(type
, status
);
573 DecimalFormatSymbols::getPatternForCurrencySpacing(UCurrencySpacing type
,
574 UBool beforeCurrency
,
575 UErrorCode
& status
) const {
576 if (U_FAILURE(status
)) {
577 return fNoSymbol
; // always empty.
579 if (beforeCurrency
) {
580 return currencySpcBeforeSym
[(int32_t)type
];
582 return currencySpcAfterSym
[(int32_t)type
];
587 DecimalFormatSymbols::setPatternForCurrencySpacing(UCurrencySpacing type
,
588 UBool beforeCurrency
,
589 const UnicodeString
& pattern
) {
590 if (beforeCurrency
) {
591 currencySpcBeforeSym
[(int32_t)type
] = pattern
;
593 currencySpcAfterSym
[(int32_t)type
] = pattern
;
598 #endif /* #if !UCONFIG_NO_FORMATTING */