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