]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/numfmt.cpp
ICU-461.17.tar.gz
[apple/icu.git] / icuSources / i18n / numfmt.cpp
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
6 *
7 * File NUMFMT.CPP
8 *
9 * Modification History:
10 *
11 * Date Name Description
12 * 02/19/97 aliu Converted from java.
13 * 03/18/97 clhuang Implemented with C++ APIs.
14 * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accomodate the
15 * largest double, by default.
16 * Changed DigitCount to int per code review.
17 * 07/20/98 stephen Changed operator== to check for grouping
18 * Changed setMaxIntegerDigits per Java implementation.
19 * Changed setMinIntegerDigits per Java implementation.
20 * Changed setMinFractionDigits per Java implementation.
21 * Changed setMaxFractionDigits per Java implementation.
22 ********************************************************************************
23 */
24
25 #include "unicode/utypes.h"
26
27 #if !UCONFIG_NO_FORMATTING
28
29 #include "unicode/numfmt.h"
30 #include "unicode/locid.h"
31 #include "unicode/dcfmtsym.h"
32 #include "unicode/decimfmt.h"
33 #include "unicode/ustring.h"
34 #include "unicode/ucurr.h"
35 #include "unicode/curramt.h"
36 #include "unicode/numsys.h"
37 #include "unicode/rbnf.h"
38 #include "winnmfmt.h"
39 #include "uresimp.h"
40 #include "uhash.h"
41 #include "cmemory.h"
42 #include "servloc.h"
43 #include "ucln_in.h"
44 #include "cstring.h"
45 #include "putilimp.h"
46 #include "umutex.h"
47 #include "digitlst.h"
48 #include <float.h>
49
50 //#define FMT_DEBUG
51
52 #ifdef FMT_DEBUG
53 #include <stdio.h>
54 static void debugout(UnicodeString s) {
55 char buf[2000];
56 s.extract((int32_t) 0, s.length(), buf);
57 printf("%s", buf);
58 }
59 #define debug(x) printf("%s", x);
60 #else
61 #define debugout(x)
62 #define debug(x)
63 #endif
64
65 // If no number pattern can be located for a locale, this is the last
66 // resort.
67 static const UChar gLastResortDecimalPat[] = {
68 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
69 };
70 static const UChar gLastResortCurrencyPat[] = {
71 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
72 };
73 static const UChar gLastResortPercentPat[] = {
74 0x23, 0x30, 0x25, 0 /* "#0%" */
75 };
76 static const UChar gLastResortScientificPat[] = {
77 0x23, 0x45, 0x30, 0 /* "#E0" */
78 };
79 static const UChar gLastResortIsoCurrencyPat[] = {
80 0xA4, 0xA4, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0xA4, 0xA4, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "\u00A4\u00A4#0.00;(\u00A4\u00A4#0.00)" */
81 };
82 static const UChar gLastResortPluralCurrencyPat[] = {
83 0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/
84 };
85
86 static const UChar gSingleCurrencySign[] = {0xA4, 0};
87 static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0};
88
89 static const UChar gSlash = 0x2f;
90
91 // If the maximum base 10 exponent were 4, then the largest number would
92 // be 99,999 which has 5 digits.
93 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
94 static const int32_t gMaxIntegerDigits = DBL_MAX_10_EXP + DBL_DIG + 1;
95 static const int32_t gMinIntegerDigits = 127;
96
97 static const UChar * const gLastResortNumberPatterns[] =
98 {
99 gLastResortDecimalPat,
100 gLastResortCurrencyPat,
101 gLastResortPercentPat,
102 gLastResortScientificPat,
103 gLastResortIsoCurrencyPat,
104 gLastResortPluralCurrencyPat,
105 };
106
107 // Keys used for accessing resource bundles
108
109 static const char *gNumberElements = "NumberElements";
110 static const char *gLatn = "latn";
111 static const char *gPatterns = "patterns";
112 static const char *gFormatKeys[] = { "decimalFormat", "currencyFormat", "percentFormat", "scientificFormat" };
113
114 // Static hashtable cache of NumberingSystem objects used by NumberFormat
115 static UHashtable * NumberingSystem_cache = NULL;
116
117 static UMTX nscacheMutex = NULL;
118
119 #if !UCONFIG_NO_SERVICE
120 static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL;
121 #endif
122
123 /**
124 * Release all static memory held by Number Format.
125 */
126 U_CDECL_BEGIN
127 static void U_CALLCONV
128 deleteNumberingSystem(void *obj) {
129 delete (U_NAMESPACE_QUALIFIER NumberingSystem *)obj;
130 }
131
132 static UBool U_CALLCONV numfmt_cleanup(void) {
133 #if !UCONFIG_NO_SERVICE
134 if (gService) {
135 delete gService;
136 gService = NULL;
137 }
138 #endif
139 if (NumberingSystem_cache) {
140 // delete NumberingSystem_cache;
141 uhash_close(NumberingSystem_cache);
142 NumberingSystem_cache = NULL;
143 }
144
145 return TRUE;
146 }
147 U_CDECL_END
148
149 // *****************************************************************************
150 // class NumberFormat
151 // *****************************************************************************
152
153 U_NAMESPACE_BEGIN
154
155 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)
156
157 #if !UCONFIG_NO_SERVICE
158 // -------------------------------------
159 // SimpleNumberFormatFactory implementation
160 NumberFormatFactory::~NumberFormatFactory() {}
161 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible)
162 : _visible(visible)
163 {
164 LocaleUtility::initNameFromLocale(locale, _id);
165 }
166
167 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
168
169 UBool SimpleNumberFormatFactory::visible(void) const {
170 return _visible;
171 }
172
173 const UnicodeString *
174 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const
175 {
176 if (U_SUCCESS(status)) {
177 count = 1;
178 return &_id;
179 }
180 count = 0;
181 return NULL;
182 }
183 #endif /* #if !UCONFIG_NO_SERVICE */
184
185 // -------------------------------------
186 // default constructor
187 NumberFormat::NumberFormat()
188 : fGroupingUsed(TRUE),
189 fMaxIntegerDigits(gMaxIntegerDigits),
190 fMinIntegerDigits(1),
191 fMaxFractionDigits(3), // invariant, >= minFractionDigits
192 fMinFractionDigits(0),
193 fParseIntegerOnly(FALSE),
194 fParseStrict(TRUE) // TODO: Should this be FALSE?
195 {
196 fCurrency[0] = 0;
197 }
198
199 // -------------------------------------
200
201 NumberFormat::~NumberFormat()
202 {
203 }
204
205 // -------------------------------------
206 // copy constructor
207
208 NumberFormat::NumberFormat(const NumberFormat &source)
209 : Format(source)
210 {
211 *this = source;
212 }
213
214 // -------------------------------------
215 // assignment operator
216
217 NumberFormat&
218 NumberFormat::operator=(const NumberFormat& rhs)
219 {
220 if (this != &rhs)
221 {
222 Format::operator=(rhs);
223 fGroupingUsed = rhs.fGroupingUsed;
224 fMaxIntegerDigits = rhs.fMaxIntegerDigits;
225 fMinIntegerDigits = rhs.fMinIntegerDigits;
226 fMaxFractionDigits = rhs.fMaxFractionDigits;
227 fMinFractionDigits = rhs.fMinFractionDigits;
228 fParseIntegerOnly = rhs.fParseIntegerOnly;
229 u_strncpy(fCurrency, rhs.fCurrency, 4);
230 }
231 return *this;
232 }
233
234 // -------------------------------------
235
236 UBool
237 NumberFormat::operator==(const Format& that) const
238 {
239 // Format::operator== guarantees this cast is safe
240 NumberFormat* other = (NumberFormat*)&that;
241
242 #ifdef FMT_DEBUG
243 // This code makes it easy to determine why two format objects that should
244 // be equal aren't.
245 UBool first = TRUE;
246 if (!Format::operator==(that)) {
247 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
248 debug("Format::!=");
249 }
250 if (!(fMaxIntegerDigits == other->fMaxIntegerDigits &&
251 fMinIntegerDigits == other->fMinIntegerDigits)) {
252 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
253 debug("Integer digits !=");
254 }
255 if (!(fMaxFractionDigits == other->fMaxFractionDigits &&
256 fMinFractionDigits == other->fMinFractionDigits)) {
257 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
258 debug("Fraction digits !=");
259 }
260 if (!(fGroupingUsed == other->fGroupingUsed)) {
261 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
262 debug("fGroupingUsed != ");
263 }
264 if (!(fParseIntegerOnly == other->fParseIntegerOnly)) {
265 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
266 debug("fParseIntegerOnly != ");
267 }
268 if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) {
269 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
270 debug("fCurrency !=");
271 }
272 if (!first) { printf(" ]"); }
273 #endif
274
275 return ((this == &that) ||
276 ((Format::operator==(that) &&
277 fMaxIntegerDigits == other->fMaxIntegerDigits &&
278 fMinIntegerDigits == other->fMinIntegerDigits &&
279 fMaxFractionDigits == other->fMaxFractionDigits &&
280 fMinFractionDigits == other->fMinFractionDigits &&
281 fGroupingUsed == other->fGroupingUsed &&
282 fParseIntegerOnly == other->fParseIntegerOnly &&
283 u_strcmp(fCurrency, other->fCurrency) == 0)));
284 }
285
286 // -------------------------------------
287 // Default implementation sets unsupported error; subclasses should
288 // override.
289
290 UnicodeString&
291 NumberFormat::format(double /* unused number */,
292 UnicodeString& toAppendTo,
293 FieldPositionIterator* /* unused posIter */,
294 UErrorCode& status) const
295 {
296 if (!U_FAILURE(status)) {
297 status = U_UNSUPPORTED_ERROR;
298 }
299 return toAppendTo;
300 }
301
302 // -------------------------------------
303 // Default implementation sets unsupported error; subclasses should
304 // override.
305
306 UnicodeString&
307 NumberFormat::format(int32_t /* unused number */,
308 UnicodeString& toAppendTo,
309 FieldPositionIterator* /* unused posIter */,
310 UErrorCode& status) const
311 {
312 if (!U_FAILURE(status)) {
313 status = U_UNSUPPORTED_ERROR;
314 }
315 return toAppendTo;
316 }
317
318 // -------------------------------------
319 // Default implementation sets unsupported error; subclasses should
320 // override.
321
322 UnicodeString&
323 NumberFormat::format(int64_t /* unused number */,
324 UnicodeString& toAppendTo,
325 FieldPositionIterator* /* unused posIter */,
326 UErrorCode& status) const
327 {
328 if (!U_FAILURE(status)) {
329 status = U_UNSUPPORTED_ERROR;
330 }
331 return toAppendTo;
332 }
333
334 // -------------------------------------
335 // Decimal Number format() default implementation
336 // Subclasses do not normally override this function, but rather the DigitList
337 // formatting functions..
338 // The expected call chain from here is
339 // this function ->
340 // NumberFormat::format(Formattable ->
341 // DecimalFormat::format(DigitList
342 //
343 // Or, for subclasses of Formattable that do not know about DigitList,
344 // this Function ->
345 // NumberFormat::format(Formattable ->
346 // NumberFormat::format(DigitList ->
347 // XXXFormat::format(double
348
349 UnicodeString&
350 NumberFormat::format(const StringPiece &decimalNum,
351 UnicodeString& toAppendTo,
352 FieldPositionIterator* fpi,
353 UErrorCode& status) const
354 {
355 Formattable f;
356 f.setDecimalNumber(decimalNum, status);
357 format(f, toAppendTo, fpi, status);
358 return toAppendTo;
359 }
360
361 // -------------------------------------
362 // Formats the number object and save the format
363 // result in the toAppendTo string buffer.
364
365 // utility to save/restore state, used in two overloads
366 // of format(const Formattable&...) below.
367
368 class ArgExtractor {
369 NumberFormat *ncnf;
370 const Formattable* num;
371 UBool setCurr;
372 UChar save[4];
373
374 public:
375 ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status);
376 ~ArgExtractor();
377
378 const Formattable* number(void) const;
379 };
380
381 inline const Formattable*
382 ArgExtractor::number(void) const {
383 return num;
384 }
385
386 ArgExtractor::ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status)
387 : ncnf((NumberFormat*) &nf), num(&obj), setCurr(FALSE) {
388
389 const UObject* o = obj.getObject(); // most commonly o==NULL
390 const CurrencyAmount* amt;
391 if (o != NULL && (amt = dynamic_cast<const CurrencyAmount*>(o)) != NULL) {
392 // getISOCurrency() returns a pointer to internal storage, so we
393 // copy it to retain it across the call to setCurrency().
394 const UChar* curr = amt->getISOCurrency();
395 u_strcpy(save, nf.getCurrency());
396 setCurr = (u_strcmp(curr, save) != 0);
397 if (setCurr) {
398 ncnf->setCurrency(curr, status);
399 }
400 num = &amt->getNumber();
401 }
402 }
403
404 ArgExtractor::~ArgExtractor() {
405 if (setCurr) {
406 UErrorCode ok = U_ZERO_ERROR;
407 ncnf->setCurrency(save, ok); // always restore currency
408 }
409 }
410
411 UnicodeString& NumberFormat::format(const DigitList &number,
412 UnicodeString& appendTo,
413 FieldPositionIterator* posIter,
414 UErrorCode& status) const {
415 // DecimalFormat overrides this function, and handles DigitList based big decimals.
416 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
417 // so this default implementation falls back to formatting decimal numbers as doubles.
418 if (U_FAILURE(status)) {
419 return appendTo;
420 }
421 double dnum = number.getDouble();
422 format(dnum, appendTo, posIter, status);
423 return appendTo;
424 }
425
426
427
428 UnicodeString&
429 NumberFormat::format(const DigitList &number,
430 UnicodeString& appendTo,
431 FieldPosition& pos,
432 UErrorCode &status) const {
433 // DecimalFormat overrides this function, and handles DigitList based big decimals.
434 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
435 // so this default implementation falls back to formatting decimal numbers as doubles.
436 if (U_FAILURE(status)) {
437 return appendTo;
438 }
439 double dnum = number.getDouble();
440 format(dnum, appendTo, pos, status);
441 return appendTo;
442 }
443
444 UnicodeString&
445 NumberFormat::format(const Formattable& obj,
446 UnicodeString& appendTo,
447 FieldPosition& pos,
448 UErrorCode& status) const
449 {
450 if (U_FAILURE(status)) return appendTo;
451
452 ArgExtractor arg(*this, obj, status);
453 const Formattable *n = arg.number();
454
455 if (n->isNumeric() && n->getDigitList() != NULL) {
456 // Decimal Number. We will have a DigitList available if the value was
457 // set to a decimal number, or if the value originated with a parse.
458 //
459 // The default implementation for formatting a DigitList converts it
460 // to a double, and formats that, allowing formatting classes that don't
461 // know about DigitList to continue to operate as they had.
462 //
463 // DecimalFormat overrides the DigitList formatting functions.
464 format(*n->getDigitList(), appendTo, pos, status);
465 } else {
466 switch (n->getType()) {
467 case Formattable::kDouble:
468 format(n->getDouble(), appendTo, pos);
469 break;
470 case Formattable::kLong:
471 format(n->getLong(), appendTo, pos);
472 break;
473 case Formattable::kInt64:
474 format(n->getInt64(), appendTo, pos);
475 break;
476 default:
477 status = U_INVALID_FORMAT_ERROR;
478 break;
479 }
480 }
481
482 return appendTo;
483 }
484
485 // -------------------------------------x
486 // Formats the number object and save the format
487 // result in the toAppendTo string buffer.
488
489 UnicodeString&
490 NumberFormat::format(const Formattable& obj,
491 UnicodeString& appendTo,
492 FieldPositionIterator* posIter,
493 UErrorCode& status) const
494 {
495 if (U_FAILURE(status)) return appendTo;
496
497 ArgExtractor arg(*this, obj, status);
498 const Formattable *n = arg.number();
499
500 if (n->isNumeric() && n->getDigitList() != NULL) {
501 // Decimal Number
502 format(*n->getDigitList(), appendTo, posIter, status);
503 } else {
504 switch (n->getType()) {
505 case Formattable::kDouble:
506 format(n->getDouble(), appendTo, posIter, status);
507 break;
508 case Formattable::kLong:
509 format(n->getLong(), appendTo, posIter, status);
510 break;
511 case Formattable::kInt64:
512 format(n->getInt64(), appendTo, posIter, status);
513 break;
514 default:
515 status = U_INVALID_FORMAT_ERROR;
516 break;
517 }
518 }
519
520 return appendTo;
521 }
522
523 // -------------------------------------
524
525 UnicodeString&
526 NumberFormat::format(int64_t number,
527 UnicodeString& appendTo,
528 FieldPosition& pos) const
529 {
530 // default so we don't introduce a new abstract method
531 return format((int32_t)number, appendTo, pos);
532 }
533
534 // -------------------------------------
535 // Parses the string and save the result object as well
536 // as the final parsed position.
537
538 void
539 NumberFormat::parseObject(const UnicodeString& source,
540 Formattable& result,
541 ParsePosition& parse_pos) const
542 {
543 parse(source, result, parse_pos);
544 }
545
546 // -------------------------------------
547 // Formats a double number and save the result in a string.
548
549 UnicodeString&
550 NumberFormat::format(double number, UnicodeString& appendTo) const
551 {
552 FieldPosition pos(0);
553 return format(number, appendTo, pos);
554 }
555
556 // -------------------------------------
557 // Formats a long number and save the result in a string.
558
559 UnicodeString&
560 NumberFormat::format(int32_t number, UnicodeString& appendTo) const
561 {
562 FieldPosition pos(0);
563 return format(number, appendTo, pos);
564 }
565
566 // -------------------------------------
567 // Formats a long number and save the result in a string.
568
569 UnicodeString&
570 NumberFormat::format(int64_t number, UnicodeString& appendTo) const
571 {
572 FieldPosition pos(0);
573 return format(number, appendTo, pos);
574 }
575
576 // -------------------------------------
577 // Parses the text and save the result object. If the returned
578 // parse position is 0, that means the parsing failed, the status
579 // code needs to be set to failure. Ignores the returned parse
580 // position, otherwise.
581
582 void
583 NumberFormat::parse(const UnicodeString& text,
584 Formattable& result,
585 UErrorCode& status) const
586 {
587 if (U_FAILURE(status)) return;
588
589 ParsePosition parsePosition(0);
590 parse(text, result, parsePosition);
591 if (parsePosition.getIndex() == 0) {
592 status = U_INVALID_FORMAT_ERROR;
593 }
594 }
595
596 Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
597 Formattable& result,
598 ParsePosition& pos) const {
599 // Default implementation only -- subclasses should override
600 int32_t start = pos.getIndex();
601 parse(text, result, pos);
602 if (pos.getIndex() != start) {
603 UChar curr[4];
604 UErrorCode ec = U_ZERO_ERROR;
605 getEffectiveCurrency(curr, ec);
606 if (U_SUCCESS(ec)) {
607 Formattable n(result);
608 CurrencyAmount *tempCurAmnt = new CurrencyAmount(n, curr, ec); // Use for null testing.
609 if (U_FAILURE(ec) || tempCurAmnt == NULL) {
610 pos.setIndex(start); // indicate failure
611 } else {
612 result.adoptObject(tempCurAmnt);
613 }
614 }
615 }
616 return result;
617 }
618
619 // -------------------------------------
620 // Sets to only parse integers.
621
622 void
623 NumberFormat::setParseIntegerOnly(UBool value)
624 {
625 fParseIntegerOnly = value;
626 }
627
628 // -------------------------------------
629 // Sets whether or not parse is strict.
630
631 void
632 NumberFormat::setParseStrict(UBool value)
633 {
634 fParseStrict = value;
635 }
636
637 // -------------------------------------
638 // Create a number style NumberFormat instance with the default locale.
639
640 NumberFormat* U_EXPORT2
641 NumberFormat::createInstance(UErrorCode& status)
642 {
643 return createInstance(Locale::getDefault(), kNumberStyle, status);
644 }
645
646 // -------------------------------------
647 // Create a number style NumberFormat instance with the inLocale locale.
648
649 NumberFormat* U_EXPORT2
650 NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status)
651 {
652 return createInstance(inLocale, kNumberStyle, status);
653 }
654
655 // -------------------------------------
656 // Create a currency style NumberFormat instance with the default locale.
657
658 NumberFormat* U_EXPORT2
659 NumberFormat::createCurrencyInstance(UErrorCode& status)
660 {
661 return createCurrencyInstance(Locale::getDefault(), status);
662 }
663
664 // -------------------------------------
665 // Create a currency style NumberFormat instance with the inLocale locale.
666
667 NumberFormat* U_EXPORT2
668 NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status)
669 {
670 return createInstance(inLocale, kCurrencyStyle, status);
671 }
672
673 // -------------------------------------
674 // Create a percent style NumberFormat instance with the default locale.
675
676 NumberFormat* U_EXPORT2
677 NumberFormat::createPercentInstance(UErrorCode& status)
678 {
679 return createInstance(Locale::getDefault(), kPercentStyle, status);
680 }
681
682 // -------------------------------------
683 // Create a percent style NumberFormat instance with the inLocale locale.
684
685 NumberFormat* U_EXPORT2
686 NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status)
687 {
688 return createInstance(inLocale, kPercentStyle, status);
689 }
690
691 // -------------------------------------
692 // Create a scientific style NumberFormat instance with the default locale.
693
694 NumberFormat* U_EXPORT2
695 NumberFormat::createScientificInstance(UErrorCode& status)
696 {
697 return createInstance(Locale::getDefault(), kScientificStyle, status);
698 }
699
700 // -------------------------------------
701 // Create a scientific style NumberFormat instance with the inLocale locale.
702
703 NumberFormat* U_EXPORT2
704 NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status)
705 {
706 return createInstance(inLocale, kScientificStyle, status);
707 }
708
709 // -------------------------------------
710
711 const Locale* U_EXPORT2
712 NumberFormat::getAvailableLocales(int32_t& count)
713 {
714 return Locale::getAvailableLocales(count);
715 }
716
717 // ------------------------------------------
718 //
719 // Registration
720 //
721 //-------------------------------------------
722
723 #if !UCONFIG_NO_SERVICE
724
725 // -------------------------------------
726
727 class ICUNumberFormatFactory : public ICUResourceBundleFactory {
728 protected:
729 virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const {
730 // !!! kind is not an EStyles, need to determine how to handle this
731 return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
732 }
733 };
734
735 // -------------------------------------
736
737 class NFFactory : public LocaleKeyFactory {
738 private:
739 NumberFormatFactory* _delegate;
740 Hashtable* _ids;
741
742 public:
743 NFFactory(NumberFormatFactory* delegate)
744 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
745 , _delegate(delegate)
746 , _ids(NULL)
747 {
748 }
749
750 virtual ~NFFactory()
751 {
752 delete _delegate;
753 delete _ids;
754 }
755
756 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
757 {
758 if (handlesKey(key, status)) {
759 const LocaleKey& lkey = (const LocaleKey&)key;
760 Locale loc;
761 lkey.canonicalLocale(loc);
762 int32_t kind = lkey.kind();
763
764 UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)(kind+1));
765 if (result == NULL) {
766 result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status);
767 }
768 return result;
769 }
770 return NULL;
771 }
772
773 protected:
774 /**
775 * Return the set of ids that this factory supports (visible or
776 * otherwise). This can be called often and might need to be
777 * cached if it is expensive to create.
778 */
779 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
780 {
781 if (U_SUCCESS(status)) {
782 if (!_ids) {
783 int32_t count = 0;
784 const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status);
785 ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */
786 if (_ids) {
787 for (int i = 0; i < count; ++i) {
788 _ids->put(idlist[i], (void*)this, status);
789 }
790 }
791 }
792 return _ids;
793 }
794 return NULL;
795 }
796 };
797
798 class ICUNumberFormatService : public ICULocaleService {
799 public:
800 ICUNumberFormatService()
801 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
802 {
803 UErrorCode status = U_ZERO_ERROR;
804 registerFactory(new ICUNumberFormatFactory(), status);
805 }
806
807 virtual UObject* cloneInstance(UObject* instance) const {
808 return ((NumberFormat*)instance)->clone();
809 }
810
811 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const {
812 LocaleKey& lkey = (LocaleKey&)key;
813 int32_t kind = lkey.kind();
814 Locale loc;
815 lkey.currentLocale(loc);
816 return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
817 }
818
819 virtual UBool isDefault() const {
820 return countFactories() == 1;
821 }
822 };
823
824 // -------------------------------------
825
826 static ICULocaleService*
827 getNumberFormatService(void)
828 {
829 UBool needInit;
830 UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
831 if (needInit) {
832 ICULocaleService * newservice = new ICUNumberFormatService();
833 if (newservice) {
834 umtx_lock(NULL);
835 if (gService == NULL) {
836 gService = newservice;
837 newservice = NULL;
838 }
839 umtx_unlock(NULL);
840 }
841 if (newservice) {
842 delete newservice;
843 } else {
844 // we won the contention, this thread can register cleanup.
845 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
846 }
847 }
848 return gService;
849 }
850
851 // -------------------------------------
852
853 URegistryKey U_EXPORT2
854 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
855 {
856 ICULocaleService *service = getNumberFormatService();
857 if (service) {
858 NFFactory *tempnnf = new NFFactory(toAdopt);
859 if (tempnnf != NULL) {
860 return service->registerFactory(tempnnf, status);
861 }
862 }
863 status = U_MEMORY_ALLOCATION_ERROR;
864 return NULL;
865 }
866
867 // -------------------------------------
868
869 UBool U_EXPORT2
870 NumberFormat::unregister(URegistryKey key, UErrorCode& status)
871 {
872 if (U_SUCCESS(status)) {
873 UBool haveService;
874 UMTX_CHECK(NULL, gService != NULL, haveService);
875 if (haveService) {
876 return gService->unregister(key, status);
877 }
878 status = U_ILLEGAL_ARGUMENT_ERROR;
879 }
880 return FALSE;
881 }
882
883 // -------------------------------------
884 StringEnumeration* U_EXPORT2
885 NumberFormat::getAvailableLocales(void)
886 {
887 ICULocaleService *service = getNumberFormatService();
888 if (service) {
889 return service->getAvailableLocales();
890 }
891 return NULL; // no way to return error condition
892 }
893 #endif /* UCONFIG_NO_SERVICE */
894 // -------------------------------------
895
896 NumberFormat* U_EXPORT2
897 NumberFormat::createInstance(const Locale& loc, EStyles kind, UErrorCode& status)
898 {
899 #if !UCONFIG_NO_SERVICE
900 UBool haveService;
901 UMTX_CHECK(NULL, gService != NULL, haveService);
902 if (haveService) {
903 return (NumberFormat*)gService->get(loc, kind, status);
904 }
905 else
906 #endif
907 {
908 return makeInstance(loc, kind, status);
909 }
910 }
911
912
913 // -------------------------------------
914 // Checks if the thousand/10 thousand grouping is used in the
915 // NumberFormat instance.
916
917 UBool
918 NumberFormat::isGroupingUsed() const
919 {
920 return fGroupingUsed;
921 }
922
923 // -------------------------------------
924 // Sets to use the thousand/10 thousand grouping in the
925 // NumberFormat instance.
926
927 void
928 NumberFormat::setGroupingUsed(UBool newValue)
929 {
930 fGroupingUsed = newValue;
931 }
932
933 // -------------------------------------
934 // Gets the maximum number of digits for the integral part for
935 // this NumberFormat instance.
936
937 int32_t NumberFormat::getMaximumIntegerDigits() const
938 {
939 return fMaxIntegerDigits;
940 }
941
942 // -------------------------------------
943 // Sets the maximum number of digits for the integral part for
944 // this NumberFormat instance.
945
946 void
947 NumberFormat::setMaximumIntegerDigits(int32_t newValue)
948 {
949 fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
950 if(fMinIntegerDigits > fMaxIntegerDigits)
951 fMinIntegerDigits = fMaxIntegerDigits;
952 }
953
954 // -------------------------------------
955 // Gets the minimum number of digits for the integral part for
956 // this NumberFormat instance.
957
958 int32_t
959 NumberFormat::getMinimumIntegerDigits() const
960 {
961 return fMinIntegerDigits;
962 }
963
964 // -------------------------------------
965 // Sets the minimum number of digits for the integral part for
966 // this NumberFormat instance.
967
968 void
969 NumberFormat::setMinimumIntegerDigits(int32_t newValue)
970 {
971 fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
972 if(fMinIntegerDigits > fMaxIntegerDigits)
973 fMaxIntegerDigits = fMinIntegerDigits;
974 }
975
976 // -------------------------------------
977 // Gets the maximum number of digits for the fractional part for
978 // this NumberFormat instance.
979
980 int32_t
981 NumberFormat::getMaximumFractionDigits() const
982 {
983 return fMaxFractionDigits;
984 }
985
986 // -------------------------------------
987 // Sets the maximum number of digits for the fractional part for
988 // this NumberFormat instance.
989
990 void
991 NumberFormat::setMaximumFractionDigits(int32_t newValue)
992 {
993 fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
994 if(fMaxFractionDigits < fMinFractionDigits)
995 fMinFractionDigits = fMaxFractionDigits;
996 }
997
998 // -------------------------------------
999 // Gets the minimum number of digits for the fractional part for
1000 // this NumberFormat instance.
1001
1002 int32_t
1003 NumberFormat::getMinimumFractionDigits() const
1004 {
1005 return fMinFractionDigits;
1006 }
1007
1008 // -------------------------------------
1009 // Sets the minimum number of digits for the fractional part for
1010 // this NumberFormat instance.
1011
1012 void
1013 NumberFormat::setMinimumFractionDigits(int32_t newValue)
1014 {
1015 fMinFractionDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
1016 if (fMaxFractionDigits < fMinFractionDigits)
1017 fMaxFractionDigits = fMinFractionDigits;
1018 }
1019
1020 // -------------------------------------
1021
1022 void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
1023 if (U_FAILURE(ec)) {
1024 return;
1025 }
1026 if (theCurrency) {
1027 u_strncpy(fCurrency, theCurrency, 3);
1028 fCurrency[3] = 0;
1029 } else {
1030 fCurrency[0] = 0;
1031 }
1032 }
1033
1034 const UChar* NumberFormat::getCurrency() const {
1035 return fCurrency;
1036 }
1037
1038 void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
1039 const UChar* c = getCurrency();
1040 if (*c != 0) {
1041 u_strncpy(result, c, 3);
1042 result[3] = 0;
1043 } else {
1044 const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
1045 if (loc == NULL) {
1046 loc = uloc_getDefault();
1047 }
1048 ucurr_forLocale(loc, result, 4, &ec);
1049 }
1050 }
1051
1052 // -------------------------------------
1053 // Creates the NumberFormat instance of the specified style (number, currency,
1054 // or percent) for the desired locale.
1055
1056 NumberFormat*
1057 NumberFormat::makeInstance(const Locale& desiredLocale,
1058 EStyles style,
1059 UErrorCode& status)
1060 {
1061 if (U_FAILURE(status)) return NULL;
1062
1063 if (style < 0 || style >= kStyleCount) {
1064 status = U_ILLEGAL_ARGUMENT_ERROR;
1065 return NULL;
1066 }
1067
1068 #ifdef U_WINDOWS
1069 char buffer[8];
1070 int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);
1071
1072 // if the locale has "@compat=host", create a host-specific NumberFormat
1073 if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
1074 Win32NumberFormat *f = NULL;
1075 UBool curr = TRUE;
1076
1077 switch (style) {
1078 case kNumberStyle:
1079 curr = FALSE;
1080 // fall-through
1081
1082 case kCurrencyStyle:
1083 case kIsoCurrencyStyle: // do not support plural formatting here
1084 case kPluralCurrencyStyle:
1085 f = new Win32NumberFormat(desiredLocale, curr, status);
1086
1087 if (U_SUCCESS(status)) {
1088 return f;
1089 }
1090
1091 delete f;
1092 break;
1093
1094 default:
1095 break;
1096 }
1097 }
1098 #endif
1099
1100 NumberFormat* f = NULL;
1101 DecimalFormatSymbols* symbolsToAdopt = NULL;
1102 UnicodeString pattern;
1103 UResourceBundle *resource = ures_open(NULL, desiredLocale.getName(), &status);
1104 NumberingSystem *ns = NULL;
1105 UBool deleteSymbols = TRUE;
1106 UHashtable * cache = NULL;
1107 int32_t hashKey;
1108 UBool getCache = FALSE;
1109 UBool deleteNS = FALSE;
1110
1111 if (U_FAILURE(status)) {
1112 // We don't appear to have resource data available -- use the last-resort data
1113 status = U_USING_FALLBACK_WARNING;
1114 // When the data is unavailable, and locale isn't passed in, last resort data is used.
1115 symbolsToAdopt = new DecimalFormatSymbols(status);
1116
1117 // Creates a DecimalFormat instance with the last resort number patterns.
1118 pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1);
1119 }
1120 else {
1121 // Loads the decimal symbols of the desired locale.
1122 symbolsToAdopt = new DecimalFormatSymbols(desiredLocale, status);
1123
1124 int32_t patLen = 0;
1125
1126 /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
1127 * the pattern is the same as the pattern of CURRENCYSTYLE
1128 * but by replacing the single currency sign with
1129 * double currency sign or triple currency sign.
1130 */
1131 int styleInNumberPattern = ((style == kIsoCurrencyStyle ||
1132 style == kPluralCurrencyStyle) ?
1133 kCurrencyStyle : style);
1134
1135 resource = ures_getByKeyWithFallback(resource, gNumberElements, resource, &status);
1136 // TODO : Get patterns on a per numbering system basis, for right now assumes "latn" for patterns
1137 resource = ures_getByKeyWithFallback(resource, gLatn, resource, &status);
1138 resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status);
1139
1140 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[styleInNumberPattern], &patLen, &status);
1141
1142 // Creates the specified decimal format style of the desired locale.
1143 pattern.setTo(TRUE, patResStr, patLen);
1144 }
1145 if (U_FAILURE(status) || symbolsToAdopt == NULL) {
1146 goto cleanup;
1147 }
1148 if(style==kCurrencyStyle || style == kIsoCurrencyStyle){
1149 const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
1150 if(currPattern!=NULL){
1151 pattern.setTo(currPattern, u_strlen(currPattern));
1152 }
1153 }
1154
1155 // Use numbering system cache hashtable
1156 UMTX_CHECK(&nscacheMutex, (UBool)(cache != NumberingSystem_cache), getCache);
1157 if (getCache) {
1158 umtx_lock(&nscacheMutex);
1159 cache = NumberingSystem_cache;
1160 umtx_unlock(&nscacheMutex);
1161 }
1162
1163 // Check cache we got, create if non-existant
1164 status = U_ZERO_ERROR;
1165 if (cache == NULL) {
1166 cache = uhash_open(uhash_hashLong,
1167 uhash_compareLong,
1168 NULL,
1169 &status);
1170
1171 if (cache == NULL || U_FAILURE(status)) {
1172 // cache not created - out of memory
1173 cache = NULL;
1174 }
1175 else {
1176 // cache created
1177 uhash_setValueDeleter(cache, deleteNumberingSystem);
1178
1179 // set final NumberingSystem_cache value
1180 UHashtable* h = NULL;
1181
1182 UMTX_CHECK(&nscacheMutex, (UBool)(h != NumberingSystem_cache), getCache);
1183 if (getCache) {
1184 umtx_lock(&nscacheMutex);
1185 h = NumberingSystem_cache;
1186 umtx_unlock(&nscacheMutex);
1187 }
1188 if (h == NULL) {
1189 umtx_lock(&nscacheMutex);
1190 NumberingSystem_cache = h = cache;
1191 cache = NULL;
1192 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
1193 umtx_unlock(&nscacheMutex);
1194 }
1195
1196 if(cache != NULL) {
1197 uhash_close(cache);
1198 }
1199 cache = h;
1200 }
1201 }
1202
1203 // Get cached numbering system
1204 if (cache != NULL) {
1205 hashKey = desiredLocale.hashCode();
1206
1207 umtx_lock(&nscacheMutex);
1208 ns = (NumberingSystem *)uhash_iget(cache, hashKey);
1209 if (ns == NULL) {
1210 ns = NumberingSystem::createInstance(desiredLocale,status);
1211 uhash_iput(cache, hashKey, (void*)ns, &status);
1212 }
1213 umtx_unlock(&nscacheMutex);
1214 }
1215 else {
1216 ns = NumberingSystem::createInstance(desiredLocale,status);
1217 deleteNS = TRUE;
1218 }
1219
1220 // check results of getting a numbering system
1221 if ((ns == NULL) || (U_FAILURE(status))) {
1222 goto cleanup;
1223 }
1224
1225 if (ns->isAlgorithmic()) {
1226 UnicodeString nsDesc;
1227 UnicodeString nsRuleSetGroup;
1228 UnicodeString nsRuleSetName;
1229 Locale nsLoc;
1230 URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;
1231
1232 nsDesc.setTo(ns->getDescription());
1233 int32_t firstSlash = nsDesc.indexOf(gSlash);
1234 int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
1235 if ( lastSlash > firstSlash ) {
1236 char nsLocID[ULOC_FULLNAME_CAPACITY];
1237
1238 nsDesc.extract(0,firstSlash,nsLocID,ULOC_FULLNAME_CAPACITY,US_INV);
1239 nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
1240 nsRuleSetName.setTo(nsDesc,lastSlash+1);
1241
1242 nsLoc = Locale::createFromName(nsLocID);
1243
1244 UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
1245 if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
1246 desiredRulesType = URBNF_SPELLOUT;
1247 }
1248 } else {
1249 nsLoc = desiredLocale;
1250 nsRuleSetName.setTo(nsDesc);
1251 }
1252
1253 RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
1254
1255 if (U_FAILURE(status) || r == NULL) {
1256 goto cleanup;
1257 }
1258 r->setDefaultRuleSet(nsRuleSetName,status);
1259 f = (NumberFormat *) r;
1260
1261 } else {
1262 // replace single currency sign in the pattern with double currency sign
1263 // if the style is kIsoCurrencyStyle
1264 if (style == kIsoCurrencyStyle) {
1265 pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign);
1266 }
1267
1268 f = new DecimalFormat(pattern, symbolsToAdopt, style, status);
1269 if (U_FAILURE(status) || f == NULL) {
1270 goto cleanup;
1271 }
1272 deleteSymbols = FALSE;
1273 }
1274
1275 f->setLocaleIDs(ures_getLocaleByType(resource, ULOC_VALID_LOCALE, &status),
1276 ures_getLocaleByType(resource, ULOC_ACTUAL_LOCALE, &status));
1277
1278 cleanup:
1279 ures_close(resource);
1280
1281 if (deleteNS && ns) {
1282 delete ns;
1283 }
1284
1285 if (U_FAILURE(status)) {
1286 /* If f exists, then it will delete the symbols */
1287 if (f==NULL) {
1288 delete symbolsToAdopt;
1289 }
1290 else {
1291 delete f;
1292 }
1293 return NULL;
1294 }
1295 if (f == NULL || symbolsToAdopt == NULL) {
1296 status = U_MEMORY_ALLOCATION_ERROR;
1297 f = NULL;
1298 }
1299 if (deleteSymbols && symbolsToAdopt != NULL) {
1300 delete symbolsToAdopt;
1301 }
1302 return f;
1303 }
1304
1305 U_NAMESPACE_END
1306
1307 #endif /* #if !UCONFIG_NO_FORMATTING */
1308
1309 //eof