• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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