• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 
DecimalFormatSymbols(UErrorCode & status)99 DecimalFormatSymbols::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 
DecimalFormatSymbols(const Locale & loc,UErrorCode & status)107 DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status)
108         : UObject(), locale(loc) {
109     initialize(locale, status);
110 }
111 
DecimalFormatSymbols(const Locale & loc,const NumberingSystem & ns,UErrorCode & status)112 DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, const NumberingSystem& ns, UErrorCode& status)
113         : UObject(), locale(loc) {
114     initialize(locale, status, FALSE, &ns);
115 }
116 
DecimalFormatSymbols()117 DecimalFormatSymbols::DecimalFormatSymbols()
118         : UObject(), locale(Locale::getRoot()), currPattern(NULL) {
119     *validLocale = *actualLocale = 0;
120     initialize();
121 }
122 
123 DecimalFormatSymbols*
createWithLastResortData(UErrorCode & status)124 DecimalFormatSymbols::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 
~DecimalFormatSymbols()135 DecimalFormatSymbols::~DecimalFormatSymbols()
136 {
137 }
138 
139 // -------------------------------------
140 // copy constructor
141 
DecimalFormatSymbols(const DecimalFormatSymbols & source)142 DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols &source)
143     : UObject(source)
144 {
145     *this = source;
146 }
147 
148 // -------------------------------------
149 // assignment operator
150 
151 DecimalFormatSymbols&
operator =(const DecimalFormatSymbols & rhs)152 DecimalFormatSymbols::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 
174 UBool
operator ==(const DecimalFormatSymbols & that) const175 DecimalFormatSymbols::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 
206 namespace {
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  */
215 struct 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
DecFmtSymDataSink__anon84fb7f8c0111::DecFmtSymDataSink224     DecFmtSymDataSink(DecimalFormatSymbols& _dfs) : dfs(_dfs) {
225         uprv_memset(seenSymbol, FALSE, sizeof(seenSymbol));
226     }
227     virtual ~DecFmtSymDataSink();
228 
put__anon84fb7f8c0111::DecFmtSymDataSink229     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.
seenAll__anon84fb7f8c0111::DecFmtSymDataSink250     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.
resolveMissingMonetarySeparators__anon84fb7f8c0111::DecFmtSymDataSink261     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 
275 struct CurrencySpacingSink : public ResourceSink {
276     DecimalFormatSymbols& dfs;
277     UBool hasBeforeCurrency;
278     UBool hasAfterCurrency;
279 
CurrencySpacingSink__anon84fb7f8c0111::CurrencySpacingSink280     CurrencySpacingSink(DecimalFormatSymbols& _dfs)
281         : dfs(_dfs), hasBeforeCurrency(FALSE), hasAfterCurrency(FALSE) {}
282     virtual ~CurrencySpacingSink();
283 
put__anon84fb7f8c0111::CurrencySpacingSink284     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 
resolveMissing__anon84fb7f8c0111::CurrencySpacingSink322     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.
~DecFmtSymDataSink()338 DecFmtSymDataSink::~DecFmtSymDataSink() {}
~CurrencySpacingSink()339 CurrencySpacingSink::~CurrencySpacingSink() {}
340 
341 } // namespace
342 
343 void
initialize(const Locale & loc,UErrorCode & status,UBool useLastResortData,const NumberingSystem * ns)344 DecimalFormatSymbols::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 
496 void
initialize()497 DecimalFormatSymbols::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 
536 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const537 DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
538     U_LOCALE_BASED(locBased, *this);
539     return locBased.getLocale(type, status);
540 }
541 
542 const UnicodeString&
getPatternForCurrencySpacing(UCurrencySpacing type,UBool beforeCurrency,UErrorCode & status) const543 DecimalFormatSymbols::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 
556 void
setPatternForCurrencySpacing(UCurrencySpacing type,UBool beforeCurrency,const UnicodeString & pattern)557 DecimalFormatSymbols::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 }
566 U_NAMESPACE_END
567 
568 #endif /* #if !UCONFIG_NO_FORMATTING */
569 
570 //eof
571