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