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