2 *******************************************************************************
3 * Copyright (C) 1997-2004, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
9 * Modification History:
11 * Date Name Description
12 * 02/19/97 aliu Converted from java.
13 * 03/18/97 clhuang Implemented with C++ APIs.
14 * 03/27/97 helena Updated to pass the simple test after code review.
15 * 08/26/97 aliu Added currency/intl currency symbol support.
16 * 07/20/98 stephen Slightly modified initialization of monetarySeparator
17 ********************************************************************************
20 #include "unicode/utypes.h"
22 #if !UCONFIG_NO_FORMATTING
24 #include "unicode/dcfmtsym.h"
25 #include "unicode/ures.h"
26 #include "unicode/decimfmt.h"
27 #include "unicode/ucurr.h"
28 #include "unicode/choicfmt.h"
33 // *****************************************************************************
34 // class DecimalFormatSymbols
35 // *****************************************************************************
39 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols
)
41 static const char gNumberElements
[] = "NumberElements";
43 static const UChar INTL_CURRENCY_SYMBOL_STR
[] = {0xa4, 0xa4, 0};
45 // -------------------------------------
46 // Initializes this with the decimal format symbols in the default locale.
48 DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode
& status
)
52 initialize(locale
, status
, TRUE
);
55 // -------------------------------------
56 // Initializes this with the decimal format symbols in the desired locale.
58 DecimalFormatSymbols::DecimalFormatSymbols(const Locale
& loc
, UErrorCode
& status
)
62 initialize(locale
, status
);
65 // -------------------------------------
67 DecimalFormatSymbols::~DecimalFormatSymbols()
71 // -------------------------------------
74 DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols
&source
)
80 // -------------------------------------
81 // assignment operator
84 DecimalFormatSymbols::operator=(const DecimalFormatSymbols
& rhs
)
87 for(int32_t i
= 0; i
< (int32_t)kFormatSymbolCount
; ++i
) {
88 // fastCopyFrom is safe, see docs on fSymbols
89 fSymbols
[(ENumberFormatSymbol
)i
].fastCopyFrom(rhs
.fSymbols
[(ENumberFormatSymbol
)i
]);
92 uprv_strcpy(validLocale
, rhs
.validLocale
);
93 uprv_strcpy(actualLocale
, rhs
.actualLocale
);
98 // -------------------------------------
101 DecimalFormatSymbols::operator==(const DecimalFormatSymbols
& that
) const
106 for(int32_t i
= 0; i
< (int32_t)kFormatSymbolCount
; ++i
) {
107 if(fSymbols
[(ENumberFormatSymbol
)i
] != that
.fSymbols
[(ENumberFormatSymbol
)i
]) {
111 return locale
== that
.locale
&&
112 uprv_strcmp(validLocale
, that
.validLocale
) == 0 &&
113 uprv_strcmp(actualLocale
, that
.actualLocale
) == 0;
116 // -------------------------------------
119 DecimalFormatSymbols::initialize(const Locale
& loc
, UErrorCode
& status
,
120 UBool useLastResortData
)
122 *validLocale
= *actualLocale
= 0;
124 if (U_FAILURE(status
))
127 const char* locStr
= loc
.getName();
128 UResourceBundle
*resource
= ures_open((char *)0, locStr
, &status
);
129 UResourceBundle
*numberElementsRes
= ures_getByKey(resource
, gNumberElements
, resource
, &status
);
130 if (U_FAILURE(status
))
132 // Initializes with last resort data if necessary.
133 if (useLastResortData
)
135 status
= U_USING_FALLBACK_WARNING
;
140 // Gets the number element array.
141 int32_t numberElementsLength
= ures_getSize(numberElementsRes
);
143 if (numberElementsLength
> (int32_t)kFormatSymbolCount
) {
144 /* Warning: Invalid format. Array too large. */
145 numberElementsLength
= (int32_t)kFormatSymbolCount
;
147 // If the array size is too small, something is wrong with the resource
148 // bundle, returns the failure error code.
149 if (numberElementsLength
!= 12 || U_FAILURE(status
)) {
150 status
= U_INVALID_FORMAT_ERROR
;
153 const UChar
*numberElements
[kFormatSymbolCount
];
154 int32_t numberElementsStrLen
[kFormatSymbolCount
];
156 for(i
= 0; i
<numberElementsLength
; i
++) {
157 numberElements
[i
] = ures_getStringByIndex(numberElementsRes
, i
, &numberElementsStrLen
[i
], &status
);
160 if (U_SUCCESS(status
)) {
161 initialize(numberElements
, numberElementsStrLen
, numberElementsLength
);
163 // Obtain currency data from the currency API. This is strictly
164 // for backward compatibility; we don't use DecimalFormatSymbols
165 // for currency data anymore.
166 UErrorCode internalStatus
= U_ZERO_ERROR
; // don't propagate failures out
168 UnicodeString tempStr
;
169 ucurr_forLocale(locStr
, curriso
, 4, &internalStatus
);
171 // Reuse numberElements[0] as a temporary buffer
172 uprv_getStaticCurrencyName(curriso
, locStr
, tempStr
, internalStatus
);
173 if (U_SUCCESS(internalStatus
)) {
174 fSymbols
[kIntlCurrencySymbol
] = curriso
;
175 fSymbols
[kCurrencySymbol
] = tempStr
;
177 /* else use the default values. */
180 U_LOCALE_BASED(locBased
, *this);
181 locBased
.setLocaleIDs(ures_getLocaleByType(numberElementsRes
,
182 ULOC_VALID_LOCALE
, &status
),
183 ures_getLocaleByType(numberElementsRes
,
184 ULOC_ACTUAL_LOCALE
, &status
));
187 ures_close(numberElementsRes
);
190 // Initializes the DecimalFormatSymbol instance with the data obtained
191 // from ResourceBundle in the desired locale.
194 DecimalFormatSymbols::initialize(const UChar
** numberElements
, int32_t *numberElementsStrLen
, int32_t numberElementsLength
)
196 static const int32_t TYPE_MAPPING
[][2] = {
197 {kDecimalSeparatorSymbol
, 0},
198 {kGroupingSeparatorSymbol
, 1},
199 {kPatternSeparatorSymbol
, 2},
201 {kZeroDigitSymbol
, 4},
203 {kMinusSignSymbol
, 6},
204 {kExponentialSymbol
, 7},
206 {kInfinitySymbol
, 9},
208 {kPlusSignSymbol
, 11},
209 {kMonetarySeparatorSymbol
, 0}
213 for (idx
= 0; idx
< (int32_t)(sizeof(TYPE_MAPPING
)/sizeof(TYPE_MAPPING
[0])); idx
++) {
214 if (TYPE_MAPPING
[idx
][1] < numberElementsLength
) {
215 fSymbols
[TYPE_MAPPING
[idx
][0]].setTo(TRUE
, numberElements
[TYPE_MAPPING
[idx
][1]], numberElementsStrLen
[TYPE_MAPPING
[idx
][1]]);
219 // Default values until it's set later on.
220 fSymbols
[kCurrencySymbol
] = (UChar
)0xa4; // 'OX' currency symbol
221 fSymbols
[kIntlCurrencySymbol
] = INTL_CURRENCY_SYMBOL_STR
;
222 // TODO: read from locale data, if this makes it into CLDR
223 fSymbols
[kSignificantDigitSymbol
] = (UChar
)0x0040; // '@' significant digit
224 fSymbols
[kPadEscapeSymbol
] = (UChar
)0x002a; // TODO: '*' Hard coded for now; get from resource later
227 // initialize with default values
229 DecimalFormatSymbols::initialize() {
231 * These strings used to be in static arrays, but the HP/UX aCC compiler
232 * cannot initialize a static array with class constructors.
235 fSymbols
[kDecimalSeparatorSymbol
] = (UChar
)0x2e; // '.' decimal separator
236 fSymbols
[kGroupingSeparatorSymbol
].remove(); // group (thousands) separator
237 fSymbols
[kPatternSeparatorSymbol
] = (UChar
)0x3b; // ';' pattern separator
238 fSymbols
[kPercentSymbol
] = (UChar
)0x25; // '%' percent sign
239 fSymbols
[kZeroDigitSymbol
] = (UChar
)0x30; // '0' native 0 digit
240 fSymbols
[kDigitSymbol
] = (UChar
)0x23; // '#' pattern digit
241 fSymbols
[kPlusSignSymbol
] = (UChar
)0x002b; // '+' plus sign
242 fSymbols
[kMinusSignSymbol
] = (UChar
)0x2d; // '-' minus sign
243 fSymbols
[kCurrencySymbol
] = (UChar
)0xa4; // 'OX' currency symbol
244 fSymbols
[kIntlCurrencySymbol
] = INTL_CURRENCY_SYMBOL_STR
;
245 fSymbols
[kMonetarySeparatorSymbol
] = (UChar
)0x2e; // '.' monetary decimal separator
246 fSymbols
[kExponentialSymbol
] = (UChar
)0x45; // 'E' exponential
247 fSymbols
[kPerMillSymbol
] = (UChar
)0x2030; // '%o' per mill
248 fSymbols
[kPadEscapeSymbol
] = (UChar
)0x2a; // '*' pad escape symbol
249 fSymbols
[kInfinitySymbol
] = (UChar
)0x221e; // 'oo' infinite
250 fSymbols
[kNaNSymbol
] = (UChar
)0xfffd; // SUB NaN
251 fSymbols
[kSignificantDigitSymbol
] = (UChar
)0x0040; // '@' significant digit
255 DecimalFormatSymbols::getLocale(ULocDataLocaleType type
, UErrorCode
& status
) const {
256 U_LOCALE_BASED(locBased
, *this);
257 return locBased
.getLocale(type
, status
);
262 #endif /* #if !UCONFIG_NO_FORMATTING */