Line data Source code
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-2015, International Business Machines Corporation and
6 : * others. All Rights Reserved.
7 : *******************************************************************************
8 : *
9 : * File NUMFMT.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 : * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accomodate the
17 : * largest double, by default.
18 : * Changed DigitCount to int per code review.
19 : * 07/20/98 stephen Changed operator== to check for grouping
20 : * Changed setMaxIntegerDigits per Java implementation.
21 : * Changed setMinIntegerDigits per Java implementation.
22 : * Changed setMinFractionDigits per Java implementation.
23 : * Changed setMaxFractionDigits per Java implementation.
24 : ********************************************************************************
25 : */
26 :
27 : #include "unicode/utypes.h"
28 :
29 : #if !UCONFIG_NO_FORMATTING
30 :
31 : #include "unicode/numfmt.h"
32 : #include "unicode/locid.h"
33 : #include "unicode/dcfmtsym.h"
34 : #include "unicode/decimfmt.h"
35 : #include "unicode/ustring.h"
36 : #include "unicode/ucurr.h"
37 : #include "unicode/curramt.h"
38 : #include "unicode/numsys.h"
39 : #include "unicode/rbnf.h"
40 : #include "unicode/localpointer.h"
41 : #include "unicode/udisplaycontext.h"
42 : #include "charstr.h"
43 : #include "winnmfmt.h"
44 : #include "uresimp.h"
45 : #include "uhash.h"
46 : #include "cmemory.h"
47 : #include "servloc.h"
48 : #include "ucln_in.h"
49 : #include "cstring.h"
50 : #include "putilimp.h"
51 : #include "uassert.h"
52 : #include "umutex.h"
53 : #include "mutex.h"
54 : #include "digitlst.h"
55 : #include <float.h>
56 : #include "sharednumberformat.h"
57 : #include "unifiedcache.h"
58 :
59 : //#define FMT_DEBUG
60 :
61 : #ifdef FMT_DEBUG
62 : #include <stdio.h>
63 : static inline void debugout(UnicodeString s) {
64 : char buf[2000];
65 : s.extract((int32_t) 0, s.length(), buf);
66 : printf("%s", buf);
67 : }
68 : #define debug(x) printf("%s", x);
69 : #else
70 : #define debugout(x)
71 : #define debug(x)
72 : #endif
73 :
74 : // If no number pattern can be located for a locale, this is the last
75 : // resort. The patterns are same as the ones in root locale.
76 : static const UChar gLastResortDecimalPat[] = {
77 : 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */
78 : };
79 : static const UChar gLastResortCurrencyPat[] = {
80 : 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
81 : };
82 : static const UChar gLastResortPercentPat[] = {
83 : 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */
84 : };
85 : static const UChar gLastResortScientificPat[] = {
86 : 0x23, 0x45, 0x30, 0 /* "#E0" */
87 : };
88 : static const UChar gLastResortIsoCurrencyPat[] = {
89 : 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */
90 : };
91 : static const UChar gLastResortPluralCurrencyPat[] = {
92 : 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/
93 : };
94 : static const UChar gLastResortAccountingCurrencyPat[] = {
95 : 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
96 : };
97 :
98 : static const UChar gSingleCurrencySign[] = {0xA4, 0};
99 : static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0};
100 :
101 : static const UChar gSlash = 0x2f;
102 :
103 : // If the maximum base 10 exponent were 4, then the largest number would
104 : // be 99,999 which has 5 digits.
105 : // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
106 : // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999
107 : const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits = 2000000000;
108 : const int32_t icu::NumberFormat::gDefaultMinIntegerDigits = 127;
109 :
110 : static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = {
111 : NULL, // UNUM_PATTERN_DECIMAL
112 : gLastResortDecimalPat, // UNUM_DECIMAL
113 : gLastResortCurrencyPat, // UNUM_CURRENCY
114 : gLastResortPercentPat, // UNUM_PERCENT
115 : gLastResortScientificPat, // UNUM_SCIENTIFIC
116 : NULL, // UNUM_SPELLOUT
117 : NULL, // UNUM_ORDINAL
118 : NULL, // UNUM_DURATION
119 : NULL, // UNUM_NUMBERING_SYSTEM
120 : NULL, // UNUM_PATTERN_RULEBASED
121 : gLastResortIsoCurrencyPat, // UNUM_CURRENCY_ISO
122 : gLastResortPluralCurrencyPat, // UNUM_CURRENCY_PLURAL
123 : gLastResortAccountingCurrencyPat, // UNUM_CURRENCY_ACCOUNTING
124 : gLastResortCurrencyPat, // UNUM_CASH_CURRENCY
125 : NULL, // UNUM_DECIMAL_COMPACT_SHORT
126 : NULL, // UNUM_DECIMAL_COMPACT_LONG
127 : gLastResortCurrencyPat, // UNUM_CURRENCY_STANDARD
128 : };
129 :
130 : // Keys used for accessing resource bundles
131 :
132 : static const char *gNumberElements = "NumberElements";
133 : static const char *gLatn = "latn";
134 : static const char *gPatterns = "patterns";
135 : static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = {
136 : NULL, // UNUM_PATTERN_DECIMAL
137 : "decimalFormat", // UNUM_DECIMAL
138 : "currencyFormat", // UNUM_CURRENCY
139 : "percentFormat", // UNUM_PERCENT
140 : "scientificFormat", // UNUM_SCIENTIFIC
141 : NULL, // UNUM_SPELLOUT
142 : NULL, // UNUM_ORDINAL
143 : NULL, // UNUM_DURATION
144 : NULL, // UNUM_NUMBERING_SYSTEM
145 : NULL, // UNUM_PATTERN_RULEBASED
146 : // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
147 : // the pattern is the same as the pattern of UNUM_CURRENCY
148 : // except for replacing the single currency sign with
149 : // double currency sign or triple currency sign.
150 : "currencyFormat", // UNUM_CURRENCY_ISO
151 : "currencyFormat", // UNUM_CURRENCY_PLURAL
152 : "accountingFormat", // UNUM_CURRENCY_ACCOUNTING
153 : "currencyFormat", // UNUM_CASH_CURRENCY
154 : NULL, // UNUM_DECIMAL_COMPACT_SHORT
155 : NULL, // UNUM_DECIMAL_COMPACT_LONG
156 : "currencyFormat", // UNUM_CURRENCY_STANDARD
157 : };
158 :
159 : // Static hashtable cache of NumberingSystem objects used by NumberFormat
160 : static UHashtable * NumberingSystem_cache = NULL;
161 : static UMutex nscacheMutex = U_MUTEX_INITIALIZER;
162 : static icu::UInitOnce gNSCacheInitOnce = U_INITONCE_INITIALIZER;
163 :
164 : #if !UCONFIG_NO_SERVICE
165 : static icu::ICULocaleService* gService = NULL;
166 : static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
167 : #endif
168 :
169 : /**
170 : * Release all static memory held by Number Format.
171 : */
172 : U_CDECL_BEGIN
173 : static void U_CALLCONV
174 0 : deleteNumberingSystem(void *obj) {
175 0 : delete (icu::NumberingSystem *)obj;
176 0 : }
177 :
178 0 : static UBool U_CALLCONV numfmt_cleanup(void) {
179 : #if !UCONFIG_NO_SERVICE
180 0 : gServiceInitOnce.reset();
181 0 : if (gService) {
182 0 : delete gService;
183 0 : gService = NULL;
184 : }
185 : #endif
186 0 : gNSCacheInitOnce.reset();
187 0 : if (NumberingSystem_cache) {
188 : // delete NumberingSystem_cache;
189 0 : uhash_close(NumberingSystem_cache);
190 0 : NumberingSystem_cache = NULL;
191 : }
192 0 : return TRUE;
193 : }
194 : U_CDECL_END
195 :
196 : // *****************************************************************************
197 : // class NumberFormat
198 : // *****************************************************************************
199 :
200 : U_NAMESPACE_BEGIN
201 :
202 0 : UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)
203 :
204 : #if !UCONFIG_NO_SERVICE
205 : // -------------------------------------
206 : // SimpleNumberFormatFactory implementation
207 0 : NumberFormatFactory::~NumberFormatFactory() {}
208 0 : SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible)
209 0 : : _visible(visible)
210 : {
211 0 : LocaleUtility::initNameFromLocale(locale, _id);
212 0 : }
213 :
214 0 : SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
215 :
216 0 : UBool SimpleNumberFormatFactory::visible(void) const {
217 0 : return _visible;
218 : }
219 :
220 : const UnicodeString *
221 0 : SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const
222 : {
223 0 : if (U_SUCCESS(status)) {
224 0 : count = 1;
225 0 : return &_id;
226 : }
227 0 : count = 0;
228 0 : return NULL;
229 : }
230 : #endif /* #if !UCONFIG_NO_SERVICE */
231 :
232 : // -------------------------------------
233 : // default constructor
234 0 : NumberFormat::NumberFormat()
235 : : fGroupingUsed(TRUE),
236 : fMaxIntegerDigits(gDefaultMaxIntegerDigits),
237 : fMinIntegerDigits(1),
238 : fMaxFractionDigits(3), // invariant, >= minFractionDigits
239 : fMinFractionDigits(0),
240 : fParseIntegerOnly(FALSE),
241 : fLenient(FALSE),
242 0 : fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
243 : {
244 0 : fCurrency[0] = 0;
245 0 : }
246 :
247 : // -------------------------------------
248 :
249 0 : NumberFormat::~NumberFormat()
250 : {
251 0 : }
252 :
253 0 : SharedNumberFormat::~SharedNumberFormat() {
254 0 : delete ptr;
255 0 : }
256 :
257 : // -------------------------------------
258 : // copy constructor
259 :
260 0 : NumberFormat::NumberFormat(const NumberFormat &source)
261 0 : : Format(source)
262 : {
263 0 : *this = source;
264 0 : }
265 :
266 : // -------------------------------------
267 : // assignment operator
268 :
269 : NumberFormat&
270 0 : NumberFormat::operator=(const NumberFormat& rhs)
271 : {
272 0 : if (this != &rhs)
273 : {
274 0 : Format::operator=(rhs);
275 0 : fGroupingUsed = rhs.fGroupingUsed;
276 0 : fMaxIntegerDigits = rhs.fMaxIntegerDigits;
277 0 : fMinIntegerDigits = rhs.fMinIntegerDigits;
278 0 : fMaxFractionDigits = rhs.fMaxFractionDigits;
279 0 : fMinFractionDigits = rhs.fMinFractionDigits;
280 0 : fParseIntegerOnly = rhs.fParseIntegerOnly;
281 0 : u_strncpy(fCurrency, rhs.fCurrency, 3);
282 0 : fCurrency[3] = 0;
283 0 : fLenient = rhs.fLenient;
284 0 : fCapitalizationContext = rhs.fCapitalizationContext;
285 : }
286 0 : return *this;
287 : }
288 :
289 : // -------------------------------------
290 :
291 : UBool
292 0 : NumberFormat::operator==(const Format& that) const
293 : {
294 : // Format::operator== guarantees this cast is safe
295 0 : NumberFormat* other = (NumberFormat*)&that;
296 :
297 : #ifdef FMT_DEBUG
298 : // This code makes it easy to determine why two format objects that should
299 : // be equal aren't.
300 : UBool first = TRUE;
301 : if (!Format::operator==(that)) {
302 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
303 : debug("Format::!=");
304 : }
305 : if (!(fMaxIntegerDigits == other->fMaxIntegerDigits &&
306 : fMinIntegerDigits == other->fMinIntegerDigits)) {
307 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
308 : debug("Integer digits !=");
309 : }
310 : if (!(fMaxFractionDigits == other->fMaxFractionDigits &&
311 : fMinFractionDigits == other->fMinFractionDigits)) {
312 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
313 : debug("Fraction digits !=");
314 : }
315 : if (!(fGroupingUsed == other->fGroupingUsed)) {
316 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
317 : debug("fGroupingUsed != ");
318 : }
319 : if (!(fParseIntegerOnly == other->fParseIntegerOnly)) {
320 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
321 : debug("fParseIntegerOnly != ");
322 : }
323 : if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) {
324 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
325 : debug("fCurrency !=");
326 : }
327 : if (!(fLenient == other->fLenient)) {
328 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
329 : debug("fLenient != ");
330 : }
331 : if (!(fCapitalizationContext == other->fCapitalizationContext)) {
332 : if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
333 : debug("fCapitalizationContext != ");
334 : }
335 : if (!first) { printf(" ]"); }
336 : #endif
337 :
338 0 : return ((this == &that) ||
339 0 : ((Format::operator==(that) &&
340 0 : fMaxIntegerDigits == other->fMaxIntegerDigits &&
341 0 : fMinIntegerDigits == other->fMinIntegerDigits &&
342 0 : fMaxFractionDigits == other->fMaxFractionDigits &&
343 0 : fMinFractionDigits == other->fMinFractionDigits &&
344 0 : fGroupingUsed == other->fGroupingUsed &&
345 0 : fParseIntegerOnly == other->fParseIntegerOnly &&
346 0 : u_strcmp(fCurrency, other->fCurrency) == 0 &&
347 0 : fLenient == other->fLenient &&
348 0 : fCapitalizationContext == other->fCapitalizationContext)));
349 : }
350 :
351 : // -------------------------------------
352 : // Default implementation sets unsupported error; subclasses should
353 : // override.
354 :
355 : UnicodeString&
356 0 : NumberFormat::format(double /* unused number */,
357 : UnicodeString& toAppendTo,
358 : FieldPositionIterator* /* unused posIter */,
359 : UErrorCode& status) const
360 : {
361 0 : if (!U_FAILURE(status)) {
362 0 : status = U_UNSUPPORTED_ERROR;
363 : }
364 0 : return toAppendTo;
365 : }
366 :
367 : // -------------------------------------
368 : // Default implementation sets unsupported error; subclasses should
369 : // override.
370 :
371 : UnicodeString&
372 0 : NumberFormat::format(int32_t /* unused number */,
373 : UnicodeString& toAppendTo,
374 : FieldPositionIterator* /* unused posIter */,
375 : UErrorCode& status) const
376 : {
377 0 : if (!U_FAILURE(status)) {
378 0 : status = U_UNSUPPORTED_ERROR;
379 : }
380 0 : return toAppendTo;
381 : }
382 :
383 : // -------------------------------------
384 : // Default implementation sets unsupported error; subclasses should
385 : // override.
386 :
387 : UnicodeString&
388 0 : NumberFormat::format(int64_t /* unused number */,
389 : UnicodeString& toAppendTo,
390 : FieldPositionIterator* /* unused posIter */,
391 : UErrorCode& status) const
392 : {
393 0 : if (!U_FAILURE(status)) {
394 0 : status = U_UNSUPPORTED_ERROR;
395 : }
396 0 : return toAppendTo;
397 : }
398 :
399 : // ------------------------------------------
400 : // These functions add the status code, just fall back to the non-status versions
401 : UnicodeString&
402 0 : NumberFormat::format(double number,
403 : UnicodeString& appendTo,
404 : FieldPosition& pos,
405 : UErrorCode &status) const {
406 0 : if(U_SUCCESS(status)) {
407 0 : return format(number,appendTo,pos);
408 : } else {
409 0 : return appendTo;
410 : }
411 : }
412 :
413 : UnicodeString&
414 0 : NumberFormat::format(int32_t number,
415 : UnicodeString& appendTo,
416 : FieldPosition& pos,
417 : UErrorCode &status) const {
418 0 : if(U_SUCCESS(status)) {
419 0 : return format(number,appendTo,pos);
420 : } else {
421 0 : return appendTo;
422 : }
423 : }
424 :
425 : UnicodeString&
426 0 : NumberFormat::format(int64_t number,
427 : UnicodeString& appendTo,
428 : FieldPosition& pos,
429 : UErrorCode &status) const {
430 0 : if(U_SUCCESS(status)) {
431 0 : return format(number,appendTo,pos);
432 : } else {
433 0 : return appendTo;
434 : }
435 : }
436 :
437 :
438 :
439 : // -------------------------------------
440 : // Decimal Number format() default implementation
441 : // Subclasses do not normally override this function, but rather the DigitList
442 : // formatting functions..
443 : // The expected call chain from here is
444 : // this function ->
445 : // NumberFormat::format(Formattable ->
446 : // DecimalFormat::format(DigitList
447 : //
448 : // Or, for subclasses of Formattable that do not know about DigitList,
449 : // this Function ->
450 : // NumberFormat::format(Formattable ->
451 : // NumberFormat::format(DigitList ->
452 : // XXXFormat::format(double
453 :
454 : UnicodeString&
455 0 : NumberFormat::format(StringPiece decimalNum,
456 : UnicodeString& toAppendTo,
457 : FieldPositionIterator* fpi,
458 : UErrorCode& status) const
459 : {
460 0 : Formattable f;
461 0 : f.setDecimalNumber(decimalNum, status);
462 0 : format(f, toAppendTo, fpi, status);
463 0 : return toAppendTo;
464 : }
465 :
466 : /**
467 : *
468 : // Formats the number object and save the format
469 : // result in the toAppendTo string buffer.
470 :
471 : // utility to save/restore state, used in two overloads
472 : // of format(const Formattable&...) below.
473 : *
474 : * Old purpose of ArgExtractor was to avoid const. Not thread safe!
475 : *
476 : * keeping it around as a shim.
477 : */
478 : class ArgExtractor {
479 : const Formattable* num;
480 : UChar save[4];
481 : UBool fWasCurrency;
482 :
483 : public:
484 : ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status);
485 : ~ArgExtractor();
486 :
487 : const Formattable* number(void) const;
488 : const UChar *iso(void) const;
489 : UBool wasCurrency(void) const;
490 : };
491 :
492 : inline const Formattable*
493 0 : ArgExtractor::number(void) const {
494 0 : return num;
495 : }
496 :
497 : inline UBool
498 0 : ArgExtractor::wasCurrency(void) const {
499 0 : return fWasCurrency;
500 : }
501 :
502 : inline const UChar *
503 0 : ArgExtractor::iso(void) const {
504 0 : return save;
505 : }
506 :
507 0 : ArgExtractor::ArgExtractor(const NumberFormat& /*nf*/, const Formattable& obj, UErrorCode& /*status*/)
508 0 : : num(&obj), fWasCurrency(FALSE) {
509 :
510 0 : const UObject* o = obj.getObject(); // most commonly o==NULL
511 : const CurrencyAmount* amt;
512 0 : if (o != NULL && (amt = dynamic_cast<const CurrencyAmount*>(o)) != NULL) {
513 : // getISOCurrency() returns a pointer to internal storage, so we
514 : // copy it to retain it across the call to setCurrency().
515 : //const UChar* curr = amt->getISOCurrency();
516 0 : u_strcpy(save, amt->getISOCurrency());
517 0 : num = &amt->getNumber();
518 0 : fWasCurrency=TRUE;
519 : } else {
520 0 : save[0]=0;
521 : }
522 0 : }
523 :
524 0 : ArgExtractor::~ArgExtractor() {
525 0 : }
526 :
527 0 : UnicodeString& NumberFormat::format(const DigitList &number,
528 : UnicodeString& appendTo,
529 : FieldPositionIterator* posIter,
530 : UErrorCode& status) const {
531 : // DecimalFormat overrides this function, and handles DigitList based big decimals.
532 : // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
533 : // so this default implementation falls back to formatting decimal numbers as doubles.
534 0 : if (U_FAILURE(status)) {
535 0 : return appendTo;
536 : }
537 0 : double dnum = number.getDouble();
538 0 : format(dnum, appendTo, posIter, status);
539 0 : return appendTo;
540 : }
541 :
542 :
543 :
544 : UnicodeString&
545 0 : NumberFormat::format(const DigitList &number,
546 : UnicodeString& appendTo,
547 : FieldPosition& pos,
548 : UErrorCode &status) const {
549 : // DecimalFormat overrides this function, and handles DigitList based big decimals.
550 : // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
551 : // so this default implementation falls back to formatting decimal numbers as doubles.
552 0 : if (U_FAILURE(status)) {
553 0 : return appendTo;
554 : }
555 0 : double dnum = number.getDouble();
556 0 : format(dnum, appendTo, pos, status);
557 0 : return appendTo;
558 : }
559 :
560 : UnicodeString&
561 0 : NumberFormat::format(const Formattable& obj,
562 : UnicodeString& appendTo,
563 : FieldPosition& pos,
564 : UErrorCode& status) const
565 : {
566 0 : if (U_FAILURE(status)) return appendTo;
567 :
568 0 : ArgExtractor arg(*this, obj, status);
569 0 : const Formattable *n = arg.number();
570 0 : const UChar *iso = arg.iso();
571 :
572 0 : if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) {
573 : // trying to format a different currency.
574 : // Right now, we clone.
575 0 : LocalPointer<NumberFormat> cloneFmt((NumberFormat*)this->clone());
576 0 : cloneFmt->setCurrency(iso, status);
577 : // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
578 0 : return cloneFmt->format(*n, appendTo, pos, status);
579 : }
580 :
581 0 : if (n->isNumeric() && n->getDigitList() != NULL) {
582 : // Decimal Number. We will have a DigitList available if the value was
583 : // set to a decimal number, or if the value originated with a parse.
584 : //
585 : // The default implementation for formatting a DigitList converts it
586 : // to a double, and formats that, allowing formatting classes that don't
587 : // know about DigitList to continue to operate as they had.
588 : //
589 : // DecimalFormat overrides the DigitList formatting functions.
590 0 : format(*n->getDigitList(), appendTo, pos, status);
591 : } else {
592 0 : switch (n->getType()) {
593 : case Formattable::kDouble:
594 0 : format(n->getDouble(), appendTo, pos);
595 0 : break;
596 : case Formattable::kLong:
597 0 : format(n->getLong(), appendTo, pos);
598 0 : break;
599 : case Formattable::kInt64:
600 0 : format(n->getInt64(), appendTo, pos);
601 0 : break;
602 : default:
603 0 : status = U_INVALID_FORMAT_ERROR;
604 0 : break;
605 : }
606 : }
607 :
608 0 : return appendTo;
609 : }
610 :
611 : // -------------------------------------x
612 : // Formats the number object and save the format
613 : // result in the toAppendTo string buffer.
614 :
615 : UnicodeString&
616 0 : NumberFormat::format(const Formattable& obj,
617 : UnicodeString& appendTo,
618 : FieldPositionIterator* posIter,
619 : UErrorCode& status) const
620 : {
621 0 : if (U_FAILURE(status)) return appendTo;
622 :
623 0 : ArgExtractor arg(*this, obj, status);
624 0 : const Formattable *n = arg.number();
625 0 : const UChar *iso = arg.iso();
626 :
627 0 : if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) {
628 : // trying to format a different currency.
629 : // Right now, we clone.
630 0 : LocalPointer<NumberFormat> cloneFmt((NumberFormat*)this->clone());
631 0 : cloneFmt->setCurrency(iso, status);
632 : // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
633 0 : return cloneFmt->format(*n, appendTo, posIter, status);
634 : }
635 :
636 0 : if (n->isNumeric() && n->getDigitList() != NULL) {
637 : // Decimal Number
638 0 : format(*n->getDigitList(), appendTo, posIter, status);
639 : } else {
640 0 : switch (n->getType()) {
641 : case Formattable::kDouble:
642 0 : format(n->getDouble(), appendTo, posIter, status);
643 0 : break;
644 : case Formattable::kLong:
645 0 : format(n->getLong(), appendTo, posIter, status);
646 0 : break;
647 : case Formattable::kInt64:
648 0 : format(n->getInt64(), appendTo, posIter, status);
649 0 : break;
650 : default:
651 0 : status = U_INVALID_FORMAT_ERROR;
652 0 : break;
653 : }
654 : }
655 :
656 0 : return appendTo;
657 : }
658 :
659 : // -------------------------------------
660 :
661 : UnicodeString&
662 0 : NumberFormat::format(int64_t number,
663 : UnicodeString& appendTo,
664 : FieldPosition& pos) const
665 : {
666 : // default so we don't introduce a new abstract method
667 0 : return format((int32_t)number, appendTo, pos);
668 : }
669 :
670 : // -------------------------------------
671 : // Parses the string and save the result object as well
672 : // as the final parsed position.
673 :
674 : void
675 0 : NumberFormat::parseObject(const UnicodeString& source,
676 : Formattable& result,
677 : ParsePosition& parse_pos) const
678 : {
679 0 : parse(source, result, parse_pos);
680 0 : }
681 :
682 : // -------------------------------------
683 : // Formats a double number and save the result in a string.
684 :
685 : UnicodeString&
686 0 : NumberFormat::format(double number, UnicodeString& appendTo) const
687 : {
688 0 : FieldPosition pos(FieldPosition::DONT_CARE);
689 0 : return format(number, appendTo, pos);
690 : }
691 :
692 : // -------------------------------------
693 : // Formats a long number and save the result in a string.
694 :
695 : UnicodeString&
696 0 : NumberFormat::format(int32_t number, UnicodeString& appendTo) const
697 : {
698 0 : FieldPosition pos(FieldPosition::DONT_CARE);
699 0 : return format(number, appendTo, pos);
700 : }
701 :
702 : // -------------------------------------
703 : // Formats a long number and save the result in a string.
704 :
705 : UnicodeString&
706 0 : NumberFormat::format(int64_t number, UnicodeString& appendTo) const
707 : {
708 0 : FieldPosition pos(FieldPosition::DONT_CARE);
709 0 : return format(number, appendTo, pos);
710 : }
711 :
712 : // -------------------------------------
713 : // Parses the text and save the result object. If the returned
714 : // parse position is 0, that means the parsing failed, the status
715 : // code needs to be set to failure. Ignores the returned parse
716 : // position, otherwise.
717 :
718 : void
719 0 : NumberFormat::parse(const UnicodeString& text,
720 : Formattable& result,
721 : UErrorCode& status) const
722 : {
723 0 : if (U_FAILURE(status)) return;
724 :
725 0 : ParsePosition parsePosition(0);
726 0 : parse(text, result, parsePosition);
727 0 : if (parsePosition.getIndex() == 0) {
728 0 : status = U_INVALID_FORMAT_ERROR;
729 : }
730 : }
731 :
732 0 : CurrencyAmount* NumberFormat::parseCurrency(const UnicodeString& text,
733 : ParsePosition& pos) const {
734 : // Default implementation only -- subclasses should override
735 0 : Formattable parseResult;
736 0 : int32_t start = pos.getIndex();
737 0 : parse(text, parseResult, pos);
738 0 : if (pos.getIndex() != start) {
739 : UChar curr[4];
740 0 : UErrorCode ec = U_ZERO_ERROR;
741 0 : getEffectiveCurrency(curr, ec);
742 0 : if (U_SUCCESS(ec)) {
743 0 : LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curr, ec), ec);
744 0 : if (U_FAILURE(ec)) {
745 0 : pos.setIndex(start); // indicate failure
746 : } else {
747 0 : return currAmt.orphan();
748 : }
749 : }
750 : }
751 0 : return NULL;
752 : }
753 :
754 : // -------------------------------------
755 : // Sets to only parse integers.
756 :
757 : void
758 0 : NumberFormat::setParseIntegerOnly(UBool value)
759 : {
760 0 : fParseIntegerOnly = value;
761 0 : }
762 :
763 : // -------------------------------------
764 : // Sets whether lenient parse is enabled.
765 :
766 : void
767 0 : NumberFormat::setLenient(UBool enable)
768 : {
769 0 : fLenient = enable;
770 0 : }
771 :
772 : // -------------------------------------
773 : // Create a number style NumberFormat instance with the default locale.
774 :
775 : NumberFormat* U_EXPORT2
776 0 : NumberFormat::createInstance(UErrorCode& status)
777 : {
778 0 : return createInstance(Locale::getDefault(), UNUM_DECIMAL, status);
779 : }
780 :
781 : // -------------------------------------
782 : // Create a number style NumberFormat instance with the inLocale locale.
783 :
784 : NumberFormat* U_EXPORT2
785 0 : NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status)
786 : {
787 0 : return createInstance(inLocale, UNUM_DECIMAL, status);
788 : }
789 :
790 : // -------------------------------------
791 : // Create a currency style NumberFormat instance with the default locale.
792 :
793 : NumberFormat* U_EXPORT2
794 0 : NumberFormat::createCurrencyInstance(UErrorCode& status)
795 : {
796 0 : return createCurrencyInstance(Locale::getDefault(), status);
797 : }
798 :
799 : // -------------------------------------
800 : // Create a currency style NumberFormat instance with the inLocale locale.
801 :
802 : NumberFormat* U_EXPORT2
803 0 : NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status)
804 : {
805 0 : return createInstance(inLocale, UNUM_CURRENCY, status);
806 : }
807 :
808 : // -------------------------------------
809 : // Create a percent style NumberFormat instance with the default locale.
810 :
811 : NumberFormat* U_EXPORT2
812 0 : NumberFormat::createPercentInstance(UErrorCode& status)
813 : {
814 0 : return createInstance(Locale::getDefault(), UNUM_PERCENT, status);
815 : }
816 :
817 : // -------------------------------------
818 : // Create a percent style NumberFormat instance with the inLocale locale.
819 :
820 : NumberFormat* U_EXPORT2
821 0 : NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status)
822 : {
823 0 : return createInstance(inLocale, UNUM_PERCENT, status);
824 : }
825 :
826 : // -------------------------------------
827 : // Create a scientific style NumberFormat instance with the default locale.
828 :
829 : NumberFormat* U_EXPORT2
830 0 : NumberFormat::createScientificInstance(UErrorCode& status)
831 : {
832 0 : return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC, status);
833 : }
834 :
835 : // -------------------------------------
836 : // Create a scientific style NumberFormat instance with the inLocale locale.
837 :
838 : NumberFormat* U_EXPORT2
839 0 : NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status)
840 : {
841 0 : return createInstance(inLocale, UNUM_SCIENTIFIC, status);
842 : }
843 :
844 : // -------------------------------------
845 :
846 : const Locale* U_EXPORT2
847 0 : NumberFormat::getAvailableLocales(int32_t& count)
848 : {
849 0 : return Locale::getAvailableLocales(count);
850 : }
851 :
852 : // ------------------------------------------
853 : //
854 : // Registration
855 : //
856 : //-------------------------------------------
857 :
858 : #if !UCONFIG_NO_SERVICE
859 :
860 : // -------------------------------------
861 :
862 0 : class ICUNumberFormatFactory : public ICUResourceBundleFactory {
863 : public:
864 : virtual ~ICUNumberFormatFactory();
865 : protected:
866 0 : virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const {
867 0 : return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status);
868 : }
869 : };
870 :
871 0 : ICUNumberFormatFactory::~ICUNumberFormatFactory() {}
872 :
873 : // -------------------------------------
874 :
875 : class NFFactory : public LocaleKeyFactory {
876 : private:
877 : NumberFormatFactory* _delegate;
878 : Hashtable* _ids;
879 :
880 : public:
881 0 : NFFactory(NumberFormatFactory* delegate)
882 0 : : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
883 : , _delegate(delegate)
884 0 : , _ids(NULL)
885 : {
886 0 : }
887 :
888 : virtual ~NFFactory();
889 :
890 0 : virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
891 : {
892 0 : if (handlesKey(key, status)) {
893 0 : const LocaleKey& lkey = (const LocaleKey&)key;
894 0 : Locale loc;
895 0 : lkey.canonicalLocale(loc);
896 0 : int32_t kind = lkey.kind();
897 :
898 0 : UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)kind);
899 0 : if (result == NULL) {
900 0 : result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status);
901 : }
902 0 : return result;
903 : }
904 0 : return NULL;
905 : }
906 :
907 : protected:
908 : /**
909 : * Return the set of ids that this factory supports (visible or
910 : * otherwise). This can be called often and might need to be
911 : * cached if it is expensive to create.
912 : */
913 0 : virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
914 : {
915 0 : if (U_SUCCESS(status)) {
916 0 : if (!_ids) {
917 0 : int32_t count = 0;
918 0 : const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status);
919 0 : ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */
920 0 : if (_ids) {
921 0 : for (int i = 0; i < count; ++i) {
922 0 : _ids->put(idlist[i], (void*)this, status);
923 : }
924 : }
925 : }
926 0 : return _ids;
927 : }
928 0 : return NULL;
929 : }
930 : };
931 :
932 0 : NFFactory::~NFFactory()
933 : {
934 0 : delete _delegate;
935 0 : delete _ids;
936 0 : }
937 :
938 : class ICUNumberFormatService : public ICULocaleService {
939 : public:
940 0 : ICUNumberFormatService()
941 0 : : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
942 : {
943 0 : UErrorCode status = U_ZERO_ERROR;
944 0 : registerFactory(new ICUNumberFormatFactory(), status);
945 0 : }
946 :
947 : virtual ~ICUNumberFormatService();
948 :
949 0 : virtual UObject* cloneInstance(UObject* instance) const {
950 0 : return ((NumberFormat*)instance)->clone();
951 : }
952 :
953 0 : virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const {
954 0 : LocaleKey& lkey = (LocaleKey&)key;
955 0 : int32_t kind = lkey.kind();
956 0 : Locale loc;
957 0 : lkey.currentLocale(loc);
958 0 : return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status);
959 : }
960 :
961 0 : virtual UBool isDefault() const {
962 0 : return countFactories() == 1;
963 : }
964 : };
965 :
966 0 : ICUNumberFormatService::~ICUNumberFormatService() {}
967 :
968 : // -------------------------------------
969 :
970 0 : static void U_CALLCONV initNumberFormatService() {
971 0 : U_ASSERT(gService == NULL);
972 0 : ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
973 0 : gService = new ICUNumberFormatService();
974 0 : }
975 :
976 : static ICULocaleService*
977 0 : getNumberFormatService(void)
978 : {
979 0 : umtx_initOnce(gServiceInitOnce, &initNumberFormatService);
980 0 : return gService;
981 : }
982 :
983 0 : static UBool haveService() {
984 0 : return !gServiceInitOnce.isReset() && (getNumberFormatService() != NULL);
985 : }
986 :
987 : // -------------------------------------
988 :
989 : URegistryKey U_EXPORT2
990 0 : NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
991 : {
992 0 : ICULocaleService *service = getNumberFormatService();
993 0 : if (service) {
994 0 : NFFactory *tempnnf = new NFFactory(toAdopt);
995 0 : if (tempnnf != NULL) {
996 0 : return service->registerFactory(tempnnf, status);
997 : }
998 : }
999 0 : status = U_MEMORY_ALLOCATION_ERROR;
1000 0 : return NULL;
1001 : }
1002 :
1003 : // -------------------------------------
1004 :
1005 : UBool U_EXPORT2
1006 0 : NumberFormat::unregister(URegistryKey key, UErrorCode& status)
1007 : {
1008 0 : if (U_FAILURE(status)) {
1009 0 : return FALSE;
1010 : }
1011 0 : if (haveService()) {
1012 0 : return gService->unregister(key, status);
1013 : } else {
1014 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
1015 0 : return FALSE;
1016 : }
1017 : }
1018 :
1019 : // -------------------------------------
1020 : StringEnumeration* U_EXPORT2
1021 0 : NumberFormat::getAvailableLocales(void)
1022 : {
1023 0 : ICULocaleService *service = getNumberFormatService();
1024 0 : if (service) {
1025 0 : return service->getAvailableLocales();
1026 : }
1027 0 : return NULL; // no way to return error condition
1028 : }
1029 : #endif /* UCONFIG_NO_SERVICE */
1030 : // -------------------------------------
1031 :
1032 : enum { kKeyValueLenMax = 32 };
1033 :
1034 : NumberFormat*
1035 0 : NumberFormat::internalCreateInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
1036 0 : if (kind == UNUM_CURRENCY) {
1037 0 : char cfKeyValue[kKeyValueLenMax] = {0};
1038 0 : UErrorCode kvStatus = U_ZERO_ERROR;
1039 0 : int32_t kLen = loc.getKeywordValue("cf", cfKeyValue, kKeyValueLenMax, kvStatus);
1040 0 : if (U_SUCCESS(kvStatus) && kLen > 0 && uprv_strcmp(cfKeyValue,"account")==0) {
1041 0 : kind = UNUM_CURRENCY_ACCOUNTING;
1042 : }
1043 : }
1044 : #if !UCONFIG_NO_SERVICE
1045 0 : if (haveService()) {
1046 0 : return (NumberFormat*)gService->get(loc, kind, status);
1047 : }
1048 : #endif
1049 0 : return makeInstance(loc, kind, status);
1050 : }
1051 :
1052 : NumberFormat* U_EXPORT2
1053 0 : NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
1054 0 : if (kind != UNUM_DECIMAL) {
1055 0 : return internalCreateInstance(loc, kind, status);
1056 : }
1057 0 : const SharedNumberFormat *shared = createSharedInstance(loc, kind, status);
1058 0 : if (U_FAILURE(status)) {
1059 0 : return NULL;
1060 : }
1061 0 : NumberFormat *result = static_cast<NumberFormat *>((*shared)->clone());
1062 0 : shared->removeRef();
1063 0 : if (result == NULL) {
1064 0 : status = U_MEMORY_ALLOCATION_ERROR;
1065 : }
1066 0 : return result;
1067 : }
1068 :
1069 :
1070 : // -------------------------------------
1071 : // Checks if the thousand/10 thousand grouping is used in the
1072 : // NumberFormat instance.
1073 :
1074 : UBool
1075 0 : NumberFormat::isGroupingUsed() const
1076 : {
1077 0 : return fGroupingUsed;
1078 : }
1079 :
1080 : // -------------------------------------
1081 : // Sets to use the thousand/10 thousand grouping in the
1082 : // NumberFormat instance.
1083 :
1084 : void
1085 0 : NumberFormat::setGroupingUsed(UBool newValue)
1086 : {
1087 0 : fGroupingUsed = newValue;
1088 0 : }
1089 :
1090 : // -------------------------------------
1091 : // Gets the maximum number of digits for the integral part for
1092 : // this NumberFormat instance.
1093 :
1094 0 : int32_t NumberFormat::getMaximumIntegerDigits() const
1095 : {
1096 0 : return fMaxIntegerDigits;
1097 : }
1098 :
1099 : // -------------------------------------
1100 : // Sets the maximum number of digits for the integral part for
1101 : // this NumberFormat instance.
1102 :
1103 : void
1104 0 : NumberFormat::setMaximumIntegerDigits(int32_t newValue)
1105 : {
1106 0 : fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gDefaultMaxIntegerDigits));
1107 0 : if(fMinIntegerDigits > fMaxIntegerDigits)
1108 0 : fMinIntegerDigits = fMaxIntegerDigits;
1109 0 : }
1110 :
1111 : // -------------------------------------
1112 : // Gets the minimum number of digits for the integral part for
1113 : // this NumberFormat instance.
1114 :
1115 : int32_t
1116 0 : NumberFormat::getMinimumIntegerDigits() const
1117 : {
1118 0 : return fMinIntegerDigits;
1119 : }
1120 :
1121 : // -------------------------------------
1122 : // Sets the minimum number of digits for the integral part for
1123 : // this NumberFormat instance.
1124 :
1125 : void
1126 0 : NumberFormat::setMinimumIntegerDigits(int32_t newValue)
1127 : {
1128 0 : fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gDefaultMinIntegerDigits));
1129 0 : if(fMinIntegerDigits > fMaxIntegerDigits)
1130 0 : fMaxIntegerDigits = fMinIntegerDigits;
1131 0 : }
1132 :
1133 : // -------------------------------------
1134 : // Gets the maximum number of digits for the fractional part for
1135 : // this NumberFormat instance.
1136 :
1137 : int32_t
1138 0 : NumberFormat::getMaximumFractionDigits() const
1139 : {
1140 0 : return fMaxFractionDigits;
1141 : }
1142 :
1143 : // -------------------------------------
1144 : // Sets the maximum number of digits for the fractional part for
1145 : // this NumberFormat instance.
1146 :
1147 : void
1148 0 : NumberFormat::setMaximumFractionDigits(int32_t newValue)
1149 : {
1150 0 : fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gDefaultMaxIntegerDigits));
1151 0 : if(fMaxFractionDigits < fMinFractionDigits)
1152 0 : fMinFractionDigits = fMaxFractionDigits;
1153 0 : }
1154 :
1155 : // -------------------------------------
1156 : // Gets the minimum number of digits for the fractional part for
1157 : // this NumberFormat instance.
1158 :
1159 : int32_t
1160 0 : NumberFormat::getMinimumFractionDigits() const
1161 : {
1162 0 : return fMinFractionDigits;
1163 : }
1164 :
1165 : // -------------------------------------
1166 : // Sets the minimum number of digits for the fractional part for
1167 : // this NumberFormat instance.
1168 :
1169 : void
1170 0 : NumberFormat::setMinimumFractionDigits(int32_t newValue)
1171 : {
1172 0 : fMinFractionDigits = uprv_max(0, uprv_min(newValue, gDefaultMinIntegerDigits));
1173 0 : if (fMaxFractionDigits < fMinFractionDigits)
1174 0 : fMaxFractionDigits = fMinFractionDigits;
1175 0 : }
1176 :
1177 : // -------------------------------------
1178 :
1179 0 : void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
1180 0 : if (U_FAILURE(ec)) {
1181 0 : return;
1182 : }
1183 0 : if (theCurrency) {
1184 0 : u_strncpy(fCurrency, theCurrency, 3);
1185 0 : fCurrency[3] = 0;
1186 : } else {
1187 0 : fCurrency[0] = 0;
1188 : }
1189 : }
1190 :
1191 0 : const char16_t* NumberFormat::getCurrency() const {
1192 0 : return fCurrency;
1193 : }
1194 :
1195 0 : void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
1196 0 : const UChar* c = getCurrency();
1197 0 : if (*c != 0) {
1198 0 : u_strncpy(result, c, 3);
1199 0 : result[3] = 0;
1200 : } else {
1201 0 : const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
1202 0 : if (loc == NULL) {
1203 0 : loc = uloc_getDefault();
1204 : }
1205 0 : ucurr_forLocale(loc, result, 4, &ec);
1206 : }
1207 0 : }
1208 :
1209 : //----------------------------------------------------------------------
1210 :
1211 :
1212 0 : void NumberFormat::setContext(UDisplayContext value, UErrorCode& status)
1213 : {
1214 0 : if (U_FAILURE(status))
1215 0 : return;
1216 0 : if ( (UDisplayContextType)((uint32_t)value >> 8) == UDISPCTX_TYPE_CAPITALIZATION ) {
1217 0 : fCapitalizationContext = value;
1218 : } else {
1219 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
1220 : }
1221 : }
1222 :
1223 :
1224 0 : UDisplayContext NumberFormat::getContext(UDisplayContextType type, UErrorCode& status) const
1225 : {
1226 0 : if (U_FAILURE(status))
1227 0 : return (UDisplayContext)0;
1228 0 : if (type != UDISPCTX_TYPE_CAPITALIZATION) {
1229 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
1230 0 : return (UDisplayContext)0;
1231 : }
1232 0 : return fCapitalizationContext;
1233 : }
1234 :
1235 :
1236 : // -------------------------------------
1237 : // Creates the NumberFormat instance of the specified style (number, currency,
1238 : // or percent) for the desired locale.
1239 :
1240 0 : static void U_CALLCONV nscacheInit() {
1241 0 : U_ASSERT(NumberingSystem_cache == NULL);
1242 0 : ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
1243 0 : UErrorCode status = U_ZERO_ERROR;
1244 0 : NumberingSystem_cache = uhash_open(uhash_hashLong,
1245 : uhash_compareLong,
1246 : NULL,
1247 : &status);
1248 0 : if (U_FAILURE(status)) {
1249 : // Number Format code will run with no cache if creation fails.
1250 0 : NumberingSystem_cache = NULL;
1251 0 : return;
1252 : }
1253 0 : uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem);
1254 : }
1255 :
1256 : template<> U_I18N_API
1257 0 : const SharedNumberFormat *LocaleCacheKey<SharedNumberFormat>::createObject(
1258 : const void * /*unused*/, UErrorCode &status) const {
1259 0 : const char *localeId = fLoc.getName();
1260 0 : NumberFormat *nf = NumberFormat::internalCreateInstance(
1261 0 : localeId, UNUM_DECIMAL, status);
1262 0 : if (U_FAILURE(status)) {
1263 0 : return NULL;
1264 : }
1265 0 : SharedNumberFormat *result = new SharedNumberFormat(nf);
1266 0 : if (result == NULL) {
1267 0 : status = U_MEMORY_ALLOCATION_ERROR;
1268 0 : delete nf;
1269 0 : return NULL;
1270 : }
1271 0 : result->addRef();
1272 0 : return result;
1273 : }
1274 :
1275 : const SharedNumberFormat* U_EXPORT2
1276 0 : NumberFormat::createSharedInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
1277 0 : if (U_FAILURE(status)) {
1278 0 : return NULL;
1279 : }
1280 0 : if (kind != UNUM_DECIMAL) {
1281 0 : status = U_UNSUPPORTED_ERROR;
1282 0 : return NULL;
1283 : }
1284 0 : const SharedNumberFormat *result = NULL;
1285 0 : UnifiedCache::getByLocale(loc, result, status);
1286 0 : return result;
1287 : }
1288 :
1289 : UBool
1290 0 : NumberFormat::isStyleSupported(UNumberFormatStyle style) {
1291 0 : return gLastResortNumberPatterns[style] != NULL;
1292 : }
1293 :
1294 : NumberFormat*
1295 0 : NumberFormat::makeInstance(const Locale& desiredLocale,
1296 : UNumberFormatStyle style,
1297 : UErrorCode& status) {
1298 0 : return makeInstance(desiredLocale, style, false, status);
1299 : }
1300 :
1301 : NumberFormat*
1302 0 : NumberFormat::makeInstance(const Locale& desiredLocale,
1303 : UNumberFormatStyle style,
1304 : UBool mustBeDecimalFormat,
1305 : UErrorCode& status) {
1306 0 : if (U_FAILURE(status)) return NULL;
1307 :
1308 0 : if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) {
1309 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
1310 0 : return NULL;
1311 : }
1312 :
1313 : // Some styles are not supported. This is a result of merging
1314 : // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
1315 : // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
1316 : // this one and unum_open().
1317 : // The UNUM_PATTERN_ styles are not supported here
1318 : // because this method does not take a pattern string.
1319 0 : if (!isStyleSupported(style)) {
1320 0 : status = U_UNSUPPORTED_ERROR;
1321 0 : return NULL;
1322 : }
1323 :
1324 : #if U_PLATFORM_USES_ONLY_WIN32_API
1325 : if (!mustBeDecimalFormat) {
1326 : char buffer[8];
1327 : int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);
1328 :
1329 : // if the locale has "@compat=host", create a host-specific NumberFormat
1330 : if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) {
1331 : Win32NumberFormat *f = NULL;
1332 : UBool curr = TRUE;
1333 :
1334 : switch (style) {
1335 : case UNUM_DECIMAL:
1336 : curr = FALSE;
1337 : // fall-through
1338 :
1339 : case UNUM_CURRENCY:
1340 : case UNUM_CURRENCY_ISO: // do not support plural formatting here
1341 : case UNUM_CURRENCY_PLURAL:
1342 : case UNUM_CURRENCY_ACCOUNTING:
1343 : case UNUM_CASH_CURRENCY:
1344 : case UNUM_CURRENCY_STANDARD:
1345 : f = new Win32NumberFormat(desiredLocale, curr, status);
1346 :
1347 : if (U_SUCCESS(status)) {
1348 : return f;
1349 : }
1350 :
1351 : delete f;
1352 : break;
1353 : default:
1354 : break;
1355 : }
1356 : }
1357 : }
1358 : #endif
1359 : // Use numbering system cache hashtable
1360 0 : umtx_initOnce(gNSCacheInitOnce, &nscacheInit);
1361 :
1362 : // Get cached numbering system
1363 0 : LocalPointer<NumberingSystem> ownedNs;
1364 0 : NumberingSystem *ns = NULL;
1365 0 : if (NumberingSystem_cache != NULL) {
1366 : // TODO: Bad hash key usage, see ticket #8504.
1367 0 : int32_t hashKey = desiredLocale.hashCode();
1368 :
1369 0 : Mutex lock(&nscacheMutex);
1370 0 : ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey);
1371 0 : if (ns == NULL) {
1372 0 : ns = NumberingSystem::createInstance(desiredLocale,status);
1373 0 : uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status);
1374 : }
1375 : } else {
1376 0 : ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status));
1377 0 : ns = ownedNs.getAlias();
1378 : }
1379 :
1380 : // check results of getting a numbering system
1381 0 : if (U_FAILURE(status)) {
1382 0 : return NULL;
1383 : }
1384 :
1385 0 : if (mustBeDecimalFormat && ns->isAlgorithmic()) {
1386 0 : status = U_UNSUPPORTED_ERROR;
1387 0 : return NULL;
1388 : }
1389 :
1390 0 : LocalPointer<DecimalFormatSymbols> symbolsToAdopt;
1391 0 : UnicodeString pattern;
1392 0 : LocalUResourceBundlePointer ownedResource(ures_open(NULL, desiredLocale.getName(), &status));
1393 0 : if (U_FAILURE(status)) {
1394 0 : return NULL;
1395 : }
1396 : else {
1397 : // Loads the decimal symbols of the desired locale.
1398 0 : symbolsToAdopt.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(desiredLocale, status), status);
1399 0 : if (U_FAILURE(status)) {
1400 0 : return NULL;
1401 : }
1402 :
1403 0 : UResourceBundle *resource = ownedResource.orphan();
1404 0 : UResourceBundle *numElements = ures_getByKeyWithFallback(resource, gNumberElements, NULL, &status);
1405 0 : resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &status);
1406 0 : resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status);
1407 0 : ownedResource.adoptInstead(resource);
1408 :
1409 0 : int32_t patLen = 0;
1410 0 : const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status);
1411 :
1412 : // Didn't find a pattern specific to the numbering system, so fall back to "latn"
1413 0 : if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(gLatn,ns->getName())) {
1414 0 : status = U_ZERO_ERROR;
1415 0 : resource = ures_getByKeyWithFallback(numElements, gLatn, resource, &status);
1416 0 : resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status);
1417 0 : patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status);
1418 : }
1419 :
1420 0 : ures_close(numElements);
1421 :
1422 : // Creates the specified decimal format style of the desired locale.
1423 0 : pattern.setTo(TRUE, patResStr, patLen);
1424 : }
1425 0 : if (U_FAILURE(status)) {
1426 0 : return NULL;
1427 : }
1428 0 : if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO || style == UNUM_CURRENCY_ACCOUNTING
1429 0 : || style == UNUM_CASH_CURRENCY || style == UNUM_CURRENCY_STANDARD){
1430 0 : const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
1431 0 : if(currPattern!=NULL){
1432 0 : pattern.setTo(currPattern, u_strlen(currPattern));
1433 : }
1434 : }
1435 :
1436 :
1437 : NumberFormat *f;
1438 0 : if (ns->isAlgorithmic()) {
1439 0 : UnicodeString nsDesc;
1440 0 : UnicodeString nsRuleSetGroup;
1441 0 : UnicodeString nsRuleSetName;
1442 0 : Locale nsLoc;
1443 0 : URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;
1444 :
1445 0 : nsDesc.setTo(ns->getDescription());
1446 0 : int32_t firstSlash = nsDesc.indexOf(gSlash);
1447 0 : int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
1448 0 : if ( lastSlash > firstSlash ) {
1449 0 : CharString nsLocID;
1450 :
1451 0 : nsLocID.appendInvariantChars(nsDesc.tempSubString(0, firstSlash), status);
1452 0 : nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
1453 0 : nsRuleSetName.setTo(nsDesc,lastSlash+1);
1454 :
1455 0 : nsLoc = Locale::createFromName(nsLocID.data());
1456 :
1457 0 : UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
1458 0 : if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
1459 0 : desiredRulesType = URBNF_SPELLOUT;
1460 : }
1461 : } else {
1462 0 : nsLoc = desiredLocale;
1463 0 : nsRuleSetName.setTo(nsDesc);
1464 : }
1465 :
1466 0 : RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
1467 0 : if (r == NULL) {
1468 0 : status = U_MEMORY_ALLOCATION_ERROR;
1469 0 : return NULL;
1470 : }
1471 0 : r->setDefaultRuleSet(nsRuleSetName,status);
1472 0 : f = r;
1473 : } else {
1474 : // replace single currency sign in the pattern with double currency sign
1475 : // if the style is UNUM_CURRENCY_ISO
1476 0 : if (style == UNUM_CURRENCY_ISO) {
1477 0 : pattern.findAndReplace(UnicodeString(TRUE, gSingleCurrencySign, 1),
1478 0 : UnicodeString(TRUE, gDoubleCurrencySign, 2));
1479 : }
1480 :
1481 : // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails.
1482 0 : DecimalFormatSymbols *syms = symbolsToAdopt.orphan();
1483 0 : DecimalFormat* df = new DecimalFormat(pattern, syms, style, status);
1484 :
1485 : // if it is cash currency style, setCurrencyUsage with usage
1486 0 : if (style == UNUM_CASH_CURRENCY){
1487 0 : df->setCurrencyUsage(UCURR_USAGE_CASH, &status);
1488 : }
1489 :
1490 0 : if (U_FAILURE(status)) {
1491 0 : delete df;
1492 0 : return NULL;
1493 : }
1494 :
1495 0 : f = df;
1496 0 : if (f == NULL) {
1497 0 : delete syms;
1498 0 : status = U_MEMORY_ALLOCATION_ERROR;
1499 0 : return NULL;
1500 : }
1501 : }
1502 :
1503 0 : f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status),
1504 0 : ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status));
1505 0 : if (U_FAILURE(status)) {
1506 0 : delete f;
1507 0 : return NULL;
1508 : }
1509 0 : return f;
1510 : }
1511 :
1512 : U_NAMESPACE_END
1513 :
1514 : #endif /* #if !UCONFIG_NO_FORMATTING */
1515 :
1516 : //eof
|