1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2009, 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 <float.h>
47
48 //#define FMT_DEBUG
49
50 #ifdef FMT_DEBUG
51 #include <stdio.h>
debugout(UnicodeString s)52 static void debugout(UnicodeString s) {
53 char buf[2000];
54 s.extract((int32_t) 0, s.length(), buf);
55 printf("%s", buf);
56 }
57 #define debug(x) printf("%s", x);
58 #else
59 #define debugout(x)
60 #define debug(x)
61 #endif
62
63 // If no number pattern can be located for a locale, this is the last
64 // resort.
65 static const UChar gLastResortDecimalPat[] = {
66 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
67 };
68 static const UChar gLastResortCurrencyPat[] = {
69 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
70 };
71 static const UChar gLastResortPercentPat[] = {
72 0x23, 0x30, 0x25, 0 /* "#0%" */
73 };
74 static const UChar gLastResortScientificPat[] = {
75 0x23, 0x45, 0x30, 0 /* "#E0" */
76 };
77 static const UChar gLastResortIsoCurrencyPat[] = {
78 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)" */
79 };
80 static const UChar gLastResortPluralCurrencyPat[] = {
81 0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/
82 };
83
84 static const UChar gSingleCurrencySign[] = {0xA4, 0};
85 static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0};
86
87 static const UChar gSlash = 0x2f;
88
89 // If the maximum base 10 exponent were 4, then the largest number would
90 // be 99,999 which has 5 digits.
91 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
92 static const int32_t gMaxIntegerDigits = DBL_MAX_10_EXP + DBL_DIG + 1;
93 static const int32_t gMinIntegerDigits = 127;
94
95 static const UChar * const gLastResortNumberPatterns[] =
96 {
97 gLastResortDecimalPat,
98 gLastResortCurrencyPat,
99 gLastResortPercentPat,
100 gLastResortScientificPat,
101 gLastResortIsoCurrencyPat,
102 gLastResortPluralCurrencyPat,
103 };
104
105 // *****************************************************************************
106 // class NumberFormat
107 // *****************************************************************************
108
109 U_NAMESPACE_BEGIN
110
UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)111 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)
112
113 #if !UCONFIG_NO_SERVICE
114 // -------------------------------------
115 // SimpleNumberFormatFactory implementation
116 NumberFormatFactory::~NumberFormatFactory() {}
SimpleNumberFormatFactory(const Locale & locale,UBool visible)117 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible)
118 : _visible(visible)
119 {
120 LocaleUtility::initNameFromLocale(locale, _id);
121 }
122
~SimpleNumberFormatFactory()123 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
124
visible(void) const125 UBool SimpleNumberFormatFactory::visible(void) const {
126 return _visible;
127 }
128
129 const UnicodeString *
getSupportedIDs(int32_t & count,UErrorCode & status) const130 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const
131 {
132 if (U_SUCCESS(status)) {
133 count = 1;
134 return &_id;
135 }
136 count = 0;
137 return NULL;
138 }
139 #endif /* #if !UCONFIG_NO_SERVICE */
140
141 // -------------------------------------
142 // default constructor
NumberFormat()143 NumberFormat::NumberFormat()
144 : fGroupingUsed(TRUE),
145 fMaxIntegerDigits(gMaxIntegerDigits),
146 fMinIntegerDigits(1),
147 fMaxFractionDigits(3), // invariant, >= minFractionDigits
148 fMinFractionDigits(0),
149 fParseIntegerOnly(FALSE)
150 {
151 fCurrency[0] = 0;
152 }
153
154 // -------------------------------------
155
~NumberFormat()156 NumberFormat::~NumberFormat()
157 {
158 }
159
160 // -------------------------------------
161 // copy constructor
162
NumberFormat(const NumberFormat & source)163 NumberFormat::NumberFormat(const NumberFormat &source)
164 : Format(source)
165 {
166 *this = source;
167 }
168
169 // -------------------------------------
170 // assignment operator
171
172 NumberFormat&
operator =(const NumberFormat & rhs)173 NumberFormat::operator=(const NumberFormat& rhs)
174 {
175 if (this != &rhs)
176 {
177 fGroupingUsed = rhs.fGroupingUsed;
178 fMaxIntegerDigits = rhs.fMaxIntegerDigits;
179 fMinIntegerDigits = rhs.fMinIntegerDigits;
180 fMaxFractionDigits = rhs.fMaxFractionDigits;
181 fMinFractionDigits = rhs.fMinFractionDigits;
182 fParseIntegerOnly = rhs.fParseIntegerOnly;
183 u_strncpy(fCurrency, rhs.fCurrency, 4);
184 }
185 return *this;
186 }
187
188 // -------------------------------------
189
190 UBool
operator ==(const Format & that) const191 NumberFormat::operator==(const Format& that) const
192 {
193 // Format::operator== guarantees this cast is safe
194 NumberFormat* other = (NumberFormat*)&that;
195
196 #ifdef FMT_DEBUG
197 // This code makes it easy to determine why two format objects that should
198 // be equal aren't.
199 UBool first = TRUE;
200 if (!Format::operator==(that)) {
201 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
202 debug("Format::!=");
203 }
204 if (!(fMaxIntegerDigits == other->fMaxIntegerDigits &&
205 fMinIntegerDigits == other->fMinIntegerDigits)) {
206 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
207 debug("Integer digits !=");
208 }
209 if (!(fMaxFractionDigits == other->fMaxFractionDigits &&
210 fMinFractionDigits == other->fMinFractionDigits)) {
211 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
212 debug("Fraction digits !=");
213 }
214 if (!(fGroupingUsed == other->fGroupingUsed)) {
215 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
216 debug("fGroupingUsed != ");
217 }
218 if (!(fParseIntegerOnly == other->fParseIntegerOnly)) {
219 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
220 debug("fParseIntegerOnly != ");
221 }
222 if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) {
223 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
224 debug("fCurrency !=");
225 }
226 if (!first) { printf(" ]"); }
227 #endif
228
229 return ((this == &that) ||
230 ((Format::operator==(that) &&
231 fMaxIntegerDigits == other->fMaxIntegerDigits &&
232 fMinIntegerDigits == other->fMinIntegerDigits &&
233 fMaxFractionDigits == other->fMaxFractionDigits &&
234 fMinFractionDigits == other->fMinFractionDigits &&
235 fGroupingUsed == other->fGroupingUsed &&
236 fParseIntegerOnly == other->fParseIntegerOnly &&
237 u_strcmp(fCurrency, other->fCurrency) == 0)));
238 }
239
240 // -------------------------------------x
241 // Formats the number object and save the format
242 // result in the toAppendTo string buffer.
243
244 UnicodeString&
format(const Formattable & obj,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const245 NumberFormat::format(const Formattable& obj,
246 UnicodeString& appendTo,
247 FieldPosition& pos,
248 UErrorCode& status) const
249 {
250 if (U_FAILURE(status)) return appendTo;
251
252 NumberFormat* nonconst = (NumberFormat*) this;
253 const Formattable* n = &obj;
254
255 UChar save[4];
256 UBool setCurr = FALSE;
257 const UObject* o = obj.getObject(); // most commonly o==NULL
258 if (o != NULL &&
259 o->getDynamicClassID() == CurrencyAmount::getStaticClassID()) {
260 // getISOCurrency() returns a pointer to internal storage, so we
261 // copy it to retain it across the call to setCurrency().
262 const CurrencyAmount* amt = (const CurrencyAmount*) o;
263 const UChar* curr = amt->getISOCurrency();
264 u_strcpy(save, getCurrency());
265 setCurr = (u_strcmp(curr, save) != 0);
266 if (setCurr) {
267 nonconst->setCurrency(curr, status);
268 }
269 n = &amt->getNumber();
270 }
271
272 switch (n->getType()) {
273 case Formattable::kDouble:
274 format(n->getDouble(), appendTo, pos);
275 break;
276 case Formattable::kLong:
277 format(n->getLong(), appendTo, pos);
278 break;
279 case Formattable::kInt64:
280 format(n->getInt64(), appendTo, pos);
281 break;
282 default:
283 status = U_INVALID_FORMAT_ERROR;
284 break;
285 }
286
287 if (setCurr) {
288 UErrorCode ok = U_ZERO_ERROR;
289 nonconst->setCurrency(save, ok); // always restore currency
290 }
291 return appendTo;
292 }
293
294 // -------------------------------------
295
296 UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const297 NumberFormat::format(int64_t number,
298 UnicodeString& appendTo,
299 FieldPosition& pos) const
300 {
301 // default so we don't introduce a new abstract method
302 return format((int32_t)number, appendTo, pos);
303 }
304
305 // -------------------------------------
306 // Parses the string and save the result object as well
307 // as the final parsed position.
308
309 void
parseObject(const UnicodeString & source,Formattable & result,ParsePosition & parse_pos) const310 NumberFormat::parseObject(const UnicodeString& source,
311 Formattable& result,
312 ParsePosition& parse_pos) const
313 {
314 parse(source, result, parse_pos);
315 }
316
317 // -------------------------------------
318 // Formats a double number and save the result in a string.
319
320 UnicodeString&
format(double number,UnicodeString & appendTo) const321 NumberFormat::format(double number, UnicodeString& appendTo) const
322 {
323 FieldPosition pos(0);
324 return format(number, appendTo, pos);
325 }
326
327 // -------------------------------------
328 // Formats a long number and save the result in a string.
329
330 UnicodeString&
format(int32_t number,UnicodeString & appendTo) const331 NumberFormat::format(int32_t number, UnicodeString& appendTo) const
332 {
333 FieldPosition pos(0);
334 return format(number, appendTo, pos);
335 }
336
337 // -------------------------------------
338 // Formats a long number and save the result in a string.
339
340 UnicodeString&
format(int64_t number,UnicodeString & appendTo) const341 NumberFormat::format(int64_t number, UnicodeString& appendTo) const
342 {
343 FieldPosition pos(0);
344 return format(number, appendTo, pos);
345 }
346
347 // -------------------------------------
348 // Parses the text and save the result object. If the returned
349 // parse position is 0, that means the parsing failed, the status
350 // code needs to be set to failure. Ignores the returned parse
351 // position, otherwise.
352
353 void
parse(const UnicodeString & text,Formattable & result,UErrorCode & status) const354 NumberFormat::parse(const UnicodeString& text,
355 Formattable& result,
356 UErrorCode& status) const
357 {
358 if (U_FAILURE(status)) return;
359
360 ParsePosition parsePosition(0);
361 parse(text, result, parsePosition);
362 if (parsePosition.getIndex() == 0) {
363 status = U_INVALID_FORMAT_ERROR;
364 }
365 }
366
parseCurrency(const UnicodeString & text,Formattable & result,ParsePosition & pos) const367 Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
368 Formattable& result,
369 ParsePosition& pos) const {
370 // Default implementation only -- subclasses should override
371 int32_t start = pos.getIndex();
372 parse(text, result, pos);
373 if (pos.getIndex() != start) {
374 UChar curr[4];
375 UErrorCode ec = U_ZERO_ERROR;
376 getEffectiveCurrency(curr, ec);
377 if (U_SUCCESS(ec)) {
378 Formattable n(result);
379 CurrencyAmount *tempCurAmnt = new CurrencyAmount(n, curr, ec); // Use for null testing.
380 if (U_FAILURE(ec) || tempCurAmnt == NULL) {
381 pos.setIndex(start); // indicate failure
382 } else {
383 result.adoptObject(tempCurAmnt);
384 }
385 }
386 }
387 return result;
388 }
389
390 // -------------------------------------
391 // Sets to only parse integers.
392
393 void
setParseIntegerOnly(UBool value)394 NumberFormat::setParseIntegerOnly(UBool value)
395 {
396 fParseIntegerOnly = value;
397 }
398
399 // -------------------------------------
400 // Create a number style NumberFormat instance with the default locale.
401
402 NumberFormat* U_EXPORT2
createInstance(UErrorCode & status)403 NumberFormat::createInstance(UErrorCode& status)
404 {
405 return createInstance(Locale::getDefault(), kNumberStyle, status);
406 }
407
408 // -------------------------------------
409 // Create a number style NumberFormat instance with the inLocale locale.
410
411 NumberFormat* U_EXPORT2
createInstance(const Locale & inLocale,UErrorCode & status)412 NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status)
413 {
414 return createInstance(inLocale, kNumberStyle, status);
415 }
416
417 // -------------------------------------
418 // Create a currency style NumberFormat instance with the default locale.
419
420 NumberFormat* U_EXPORT2
createCurrencyInstance(UErrorCode & status)421 NumberFormat::createCurrencyInstance(UErrorCode& status)
422 {
423 return createCurrencyInstance(Locale::getDefault(), status);
424 }
425
426 // -------------------------------------
427 // Create a currency style NumberFormat instance with the inLocale locale.
428
429 NumberFormat* U_EXPORT2
createCurrencyInstance(const Locale & inLocale,UErrorCode & status)430 NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status)
431 {
432 return createInstance(inLocale, kCurrencyStyle, status);
433 }
434
435 // -------------------------------------
436 // Create a percent style NumberFormat instance with the default locale.
437
438 NumberFormat* U_EXPORT2
createPercentInstance(UErrorCode & status)439 NumberFormat::createPercentInstance(UErrorCode& status)
440 {
441 return createInstance(Locale::getDefault(), kPercentStyle, status);
442 }
443
444 // -------------------------------------
445 // Create a percent style NumberFormat instance with the inLocale locale.
446
447 NumberFormat* U_EXPORT2
createPercentInstance(const Locale & inLocale,UErrorCode & status)448 NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status)
449 {
450 return createInstance(inLocale, kPercentStyle, status);
451 }
452
453 // -------------------------------------
454 // Create a scientific style NumberFormat instance with the default locale.
455
456 NumberFormat* U_EXPORT2
createScientificInstance(UErrorCode & status)457 NumberFormat::createScientificInstance(UErrorCode& status)
458 {
459 return createInstance(Locale::getDefault(), kScientificStyle, status);
460 }
461
462 // -------------------------------------
463 // Create a scientific style NumberFormat instance with the inLocale locale.
464
465 NumberFormat* U_EXPORT2
createScientificInstance(const Locale & inLocale,UErrorCode & status)466 NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status)
467 {
468 return createInstance(inLocale, kScientificStyle, status);
469 }
470
471 // -------------------------------------
472
473 const Locale* U_EXPORT2
getAvailableLocales(int32_t & count)474 NumberFormat::getAvailableLocales(int32_t& count)
475 {
476 return Locale::getAvailableLocales(count);
477 }
478
479 // ------------------------------------------
480 //
481 // Registration
482 //
483 //-------------------------------------------
484
485 #if !UCONFIG_NO_SERVICE
486 static ICULocaleService* gService = NULL;
487
488 /**
489 * Release all static memory held by numberformat.
490 */
491 U_CDECL_BEGIN
numfmt_cleanup(void)492 static UBool U_CALLCONV numfmt_cleanup(void) {
493 if (gService) {
494 delete gService;
495 gService = NULL;
496 }
497 return TRUE;
498 }
499 U_CDECL_END
500
501 // -------------------------------------
502
503 class ICUNumberFormatFactory : public ICUResourceBundleFactory {
504 protected:
handleCreate(const Locale & loc,int32_t kind,const ICUService *,UErrorCode & status) const505 virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const {
506 // !!! kind is not an EStyles, need to determine how to handle this
507 return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
508 }
509 };
510
511 // -------------------------------------
512
513 class NFFactory : public LocaleKeyFactory {
514 private:
515 NumberFormatFactory* _delegate;
516 Hashtable* _ids;
517
518 public:
NFFactory(NumberFormatFactory * delegate)519 NFFactory(NumberFormatFactory* delegate)
520 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
521 , _delegate(delegate)
522 , _ids(NULL)
523 {
524 }
525
~NFFactory()526 virtual ~NFFactory()
527 {
528 delete _delegate;
529 delete _ids;
530 }
531
create(const ICUServiceKey & key,const ICUService * service,UErrorCode & status) const532 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
533 {
534 if (handlesKey(key, status)) {
535 const LocaleKey& lkey = (const LocaleKey&)key;
536 Locale loc;
537 lkey.canonicalLocale(loc);
538 int32_t kind = lkey.kind();
539
540 UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)(kind+1));
541 if (result == NULL) {
542 result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status);
543 }
544 return result;
545 }
546 return NULL;
547 }
548
549 protected:
550 /**
551 * Return the set of ids that this factory supports (visible or
552 * otherwise). This can be called often and might need to be
553 * cached if it is expensive to create.
554 */
getSupportedIDs(UErrorCode & status) const555 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
556 {
557 if (U_SUCCESS(status)) {
558 if (!_ids) {
559 int32_t count = 0;
560 const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status);
561 ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */
562 if (_ids) {
563 for (int i = 0; i < count; ++i) {
564 _ids->put(idlist[i], (void*)this, status);
565 }
566 }
567 }
568 return _ids;
569 }
570 return NULL;
571 }
572 };
573
574 class ICUNumberFormatService : public ICULocaleService {
575 public:
ICUNumberFormatService()576 ICUNumberFormatService()
577 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
578 {
579 UErrorCode status = U_ZERO_ERROR;
580 registerFactory(new ICUNumberFormatFactory(), status);
581 }
582
cloneInstance(UObject * instance) const583 virtual UObject* cloneInstance(UObject* instance) const {
584 return ((NumberFormat*)instance)->clone();
585 }
586
handleDefault(const ICUServiceKey & key,UnicodeString *,UErrorCode & status) const587 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const {
588 LocaleKey& lkey = (LocaleKey&)key;
589 int32_t kind = lkey.kind();
590 Locale loc;
591 lkey.currentLocale(loc);
592 return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
593 }
594
isDefault() const595 virtual UBool isDefault() const {
596 return countFactories() == 1;
597 }
598 };
599
600 // -------------------------------------
601
602 static ICULocaleService*
getNumberFormatService(void)603 getNumberFormatService(void)
604 {
605 UBool needInit;
606 UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
607 if (needInit) {
608 ICULocaleService * newservice = new ICUNumberFormatService();
609 if (newservice) {
610 umtx_lock(NULL);
611 if (gService == NULL) {
612 gService = newservice;
613 newservice = NULL;
614 }
615 umtx_unlock(NULL);
616 }
617 if (newservice) {
618 delete newservice;
619 } else {
620 // we won the contention, this thread can register cleanup.
621 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
622 }
623 }
624 return gService;
625 }
626
627 // -------------------------------------
628
629 URegistryKey U_EXPORT2
registerFactory(NumberFormatFactory * toAdopt,UErrorCode & status)630 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
631 {
632 ICULocaleService *service = getNumberFormatService();
633 if (service) {
634 NFFactory *tempnnf = new NFFactory(toAdopt);
635 if (tempnnf != NULL) {
636 return service->registerFactory(tempnnf, status);
637 }
638 }
639 status = U_MEMORY_ALLOCATION_ERROR;
640 return NULL;
641 }
642
643 // -------------------------------------
644
645 UBool U_EXPORT2
unregister(URegistryKey key,UErrorCode & status)646 NumberFormat::unregister(URegistryKey key, UErrorCode& status)
647 {
648 if (U_SUCCESS(status)) {
649 UBool haveService;
650 UMTX_CHECK(NULL, gService != NULL, haveService);
651 if (haveService) {
652 return gService->unregister(key, status);
653 }
654 status = U_ILLEGAL_ARGUMENT_ERROR;
655 }
656 return FALSE;
657 }
658
659 // -------------------------------------
660 StringEnumeration* U_EXPORT2
getAvailableLocales(void)661 NumberFormat::getAvailableLocales(void)
662 {
663 ICULocaleService *service = getNumberFormatService();
664 if (service) {
665 return service->getAvailableLocales();
666 }
667 return NULL; // no way to return error condition
668 }
669 #endif /* UCONFIG_NO_SERVICE */
670 // -------------------------------------
671
672 NumberFormat* U_EXPORT2
createInstance(const Locale & loc,EStyles kind,UErrorCode & status)673 NumberFormat::createInstance(const Locale& loc, EStyles kind, UErrorCode& status)
674 {
675 #if !UCONFIG_NO_SERVICE
676 UBool haveService;
677 UMTX_CHECK(NULL, gService != NULL, haveService);
678 if (haveService) {
679 return (NumberFormat*)gService->get(loc, kind, status);
680 }
681 else
682 #endif
683 {
684 return makeInstance(loc, kind, status);
685 }
686 }
687
688
689 // -------------------------------------
690 // Checks if the thousand/10 thousand grouping is used in the
691 // NumberFormat instance.
692
693 UBool
isGroupingUsed() const694 NumberFormat::isGroupingUsed() const
695 {
696 return fGroupingUsed;
697 }
698
699 // -------------------------------------
700 // Sets to use the thousand/10 thousand grouping in the
701 // NumberFormat instance.
702
703 void
setGroupingUsed(UBool newValue)704 NumberFormat::setGroupingUsed(UBool newValue)
705 {
706 fGroupingUsed = newValue;
707 }
708
709 // -------------------------------------
710 // Gets the maximum number of digits for the integral part for
711 // this NumberFormat instance.
712
getMaximumIntegerDigits() const713 int32_t NumberFormat::getMaximumIntegerDigits() const
714 {
715 return fMaxIntegerDigits;
716 }
717
718 // -------------------------------------
719 // Sets the maximum number of digits for the integral part for
720 // this NumberFormat instance.
721
722 void
setMaximumIntegerDigits(int32_t newValue)723 NumberFormat::setMaximumIntegerDigits(int32_t newValue)
724 {
725 fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
726 if(fMinIntegerDigits > fMaxIntegerDigits)
727 fMinIntegerDigits = fMaxIntegerDigits;
728 }
729
730 // -------------------------------------
731 // Gets the minimum number of digits for the integral part for
732 // this NumberFormat instance.
733
734 int32_t
getMinimumIntegerDigits() const735 NumberFormat::getMinimumIntegerDigits() const
736 {
737 return fMinIntegerDigits;
738 }
739
740 // -------------------------------------
741 // Sets the minimum number of digits for the integral part for
742 // this NumberFormat instance.
743
744 void
setMinimumIntegerDigits(int32_t newValue)745 NumberFormat::setMinimumIntegerDigits(int32_t newValue)
746 {
747 fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
748 if(fMinIntegerDigits > fMaxIntegerDigits)
749 fMaxIntegerDigits = fMinIntegerDigits;
750 }
751
752 // -------------------------------------
753 // Gets the maximum number of digits for the fractional part for
754 // this NumberFormat instance.
755
756 int32_t
getMaximumFractionDigits() const757 NumberFormat::getMaximumFractionDigits() const
758 {
759 return fMaxFractionDigits;
760 }
761
762 // -------------------------------------
763 // Sets the maximum number of digits for the fractional part for
764 // this NumberFormat instance.
765
766 void
setMaximumFractionDigits(int32_t newValue)767 NumberFormat::setMaximumFractionDigits(int32_t newValue)
768 {
769 fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
770 if(fMaxFractionDigits < fMinFractionDigits)
771 fMinFractionDigits = fMaxFractionDigits;
772 }
773
774 // -------------------------------------
775 // Gets the minimum number of digits for the fractional part for
776 // this NumberFormat instance.
777
778 int32_t
getMinimumFractionDigits() const779 NumberFormat::getMinimumFractionDigits() const
780 {
781 return fMinFractionDigits;
782 }
783
784 // -------------------------------------
785 // Sets the minimum number of digits for the fractional part for
786 // this NumberFormat instance.
787
788 void
setMinimumFractionDigits(int32_t newValue)789 NumberFormat::setMinimumFractionDigits(int32_t newValue)
790 {
791 fMinFractionDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
792 if (fMaxFractionDigits < fMinFractionDigits)
793 fMaxFractionDigits = fMinFractionDigits;
794 }
795
796 // -------------------------------------
797
setCurrency(const UChar * theCurrency,UErrorCode & ec)798 void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
799 if (U_FAILURE(ec)) {
800 return;
801 }
802 if (theCurrency) {
803 u_strncpy(fCurrency, theCurrency, 3);
804 fCurrency[3] = 0;
805 } else {
806 fCurrency[0] = 0;
807 }
808 }
809
getCurrency() const810 const UChar* NumberFormat::getCurrency() const {
811 return fCurrency;
812 }
813
getEffectiveCurrency(UChar * result,UErrorCode & ec) const814 void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
815 const UChar* c = getCurrency();
816 if (*c != 0) {
817 u_strncpy(result, c, 3);
818 result[3] = 0;
819 } else {
820 const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
821 if (loc == NULL) {
822 loc = uloc_getDefault();
823 }
824 ucurr_forLocale(loc, result, 4, &ec);
825 }
826 }
827
828 // -------------------------------------
829 // Creates the NumberFormat instance of the specified style (number, currency,
830 // or percent) for the desired locale.
831
832 NumberFormat*
makeInstance(const Locale & desiredLocale,EStyles style,UErrorCode & status)833 NumberFormat::makeInstance(const Locale& desiredLocale,
834 EStyles style,
835 UErrorCode& status)
836 {
837 if (U_FAILURE(status)) return NULL;
838
839 if (style < 0 || style >= kStyleCount) {
840 status = U_ILLEGAL_ARGUMENT_ERROR;
841 return NULL;
842 }
843
844 #ifdef U_WINDOWS
845 char buffer[8];
846 int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);
847
848 // if the locale has "@compat=host", create a host-specific NumberFormat
849 if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
850 Win32NumberFormat *f = NULL;
851 UBool curr = TRUE;
852
853 switch (style) {
854 case kNumberStyle:
855 curr = FALSE;
856 // fall-through
857
858 case kCurrencyStyle:
859 case kIsoCurrencyStyle: // do not support plural formatting here
860 case kPluralCurrencyStyle:
861 f = new Win32NumberFormat(desiredLocale, curr, status);
862
863 if (U_SUCCESS(status)) {
864 return f;
865 }
866
867 delete f;
868 break;
869
870 default:
871 break;
872 }
873 }
874 #endif
875
876 NumberFormat* f = NULL;
877 DecimalFormatSymbols* symbolsToAdopt = NULL;
878 UnicodeString pattern;
879 UResourceBundle *resource = ures_open((char *)0, desiredLocale.getName(), &status);
880 UResourceBundle *numberPatterns = ures_getByKey(resource, DecimalFormat::fgNumberPatterns, NULL, &status);
881 NumberingSystem *ns = NULL;
882 UBool deleteSymbols = TRUE;
883
884 if (U_FAILURE(status)) {
885 // We don't appear to have resource data available -- use the last-resort data
886 status = U_USING_FALLBACK_WARNING;
887 // When the data is unavailable, and locale isn't passed in, last resort data is used.
888 symbolsToAdopt = new DecimalFormatSymbols(status);
889
890 // Creates a DecimalFormat instance with the last resort number patterns.
891 pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1);
892 }
893 else {
894 // If not all the styled patterns exists for the NumberFormat in this locale,
895 // sets the status code to failure and returns nil.
896 if (ures_getSize(numberPatterns) < (int32_t)(sizeof(gLastResortNumberPatterns)/sizeof(gLastResortNumberPatterns[0])) -2 ) { //minus 2: ISO and plural
897 status = U_INVALID_FORMAT_ERROR;
898 goto cleanup;
899 }
900
901 // Loads the decimal symbols of the desired locale.
902 symbolsToAdopt = new DecimalFormatSymbols(desiredLocale, status);
903
904 int32_t patLen = 0;
905
906 /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
907 * the pattern is the same as the pattern of CURRENCYSTYLE
908 * but by replacing the single currency sign with
909 * double currency sign or triple currency sign.
910 */
911 int styleInNumberPattern = ((style == kIsoCurrencyStyle ||
912 style == kPluralCurrencyStyle) ?
913 kCurrencyStyle : style);
914
915 const UChar *patResStr = ures_getStringByIndex(numberPatterns, (int32_t)styleInNumberPattern, &patLen, &status);
916
917 // Creates the specified decimal format style of the desired locale.
918 pattern.setTo(TRUE, patResStr, patLen);
919 }
920 if (U_FAILURE(status) || symbolsToAdopt == NULL) {
921 goto cleanup;
922 }
923 if(style==kCurrencyStyle || style == kIsoCurrencyStyle){
924 const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
925 if(currPattern!=NULL){
926 pattern.setTo(currPattern, u_strlen(currPattern));
927 }
928 }
929
930 ns = NumberingSystem::createInstance(desiredLocale,status);
931
932 if (U_FAILURE(status)) {
933 goto cleanup;
934 }
935
936 if (ns->isAlgorithmic()) {
937 UnicodeString nsDesc;
938 UnicodeString nsRuleSetGroup;
939 UnicodeString nsRuleSetName;
940 Locale nsLoc;
941 URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;
942
943 nsDesc.setTo(ns->getDescription());
944 int32_t firstSlash = nsDesc.indexOf(gSlash);
945 int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
946 if ( lastSlash > firstSlash ) {
947 char nsLocID[ULOC_FULLNAME_CAPACITY];
948
949 nsDesc.extract(0,firstSlash,nsLocID,ULOC_FULLNAME_CAPACITY,US_INV);
950 nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
951 nsRuleSetName.setTo(nsDesc,lastSlash+1);
952
953 nsLoc = Locale::createFromName(nsLocID);
954
955 UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
956 if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
957 desiredRulesType = URBNF_SPELLOUT;
958 }
959 } else {
960 nsLoc = desiredLocale;
961 nsRuleSetName.setTo(nsDesc);
962 }
963
964 RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
965
966 if (U_FAILURE(status) || r == NULL) {
967 goto cleanup;
968 }
969 r->setDefaultRuleSet(nsRuleSetName,status);
970 f = (NumberFormat *) r;
971
972 } else {
973 // replace single currency sign in the pattern with double currency sign
974 // if the style is kIsoCurrencyStyle
975 if (style == kIsoCurrencyStyle) {
976 pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign);
977 }
978
979 f = new DecimalFormat(pattern, symbolsToAdopt, style, status);
980 if (U_FAILURE(status) || f == NULL) {
981 goto cleanup;
982 }
983 deleteSymbols = FALSE;
984 }
985
986 f->setLocaleIDs(ures_getLocaleByType(numberPatterns, ULOC_VALID_LOCALE, &status),
987 ures_getLocaleByType(numberPatterns, ULOC_ACTUAL_LOCALE, &status));
988
989 cleanup:
990 ures_close(numberPatterns);
991 ures_close(resource);
992 if (ns) {
993 delete ns;
994 }
995 if (U_FAILURE(status)) {
996 /* If f exists, then it will delete the symbols */
997 if (f==NULL) {
998 delete symbolsToAdopt;
999 }
1000 else {
1001 delete f;
1002 }
1003 return NULL;
1004 }
1005 if (f == NULL || symbolsToAdopt == NULL) {
1006 status = U_MEMORY_ALLOCATION_ERROR;
1007 f = NULL;
1008 }
1009 if (deleteSymbols && symbolsToAdopt != NULL) {
1010 delete symbolsToAdopt;
1011 }
1012 return f;
1013 }
1014
1015 U_NAMESPACE_END
1016
1017 #endif /* #if !UCONFIG_NO_FORMATTING */
1018
1019 //eof
1020