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