• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2012, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 *
7 * File DECIMFMT.CPP
8 *
9 * Modification History:
10 *
11 *   Date        Name        Description
12 *   02/19/97    aliu        Converted from java.
13 *   03/20/97    clhuang     Implemented with new APIs.
14 *   03/31/97    aliu        Moved isLONG_MIN to DigitList, and fixed it.
15 *   04/3/97     aliu        Rewrote parsing and formatting completely, and
16 *                           cleaned up and debugged.  Actually works now.
17 *                           Implemented NAN and INF handling, for both parsing
18 *                           and formatting.  Extensive testing & debugging.
19 *   04/10/97    aliu        Modified to compile on AIX.
20 *   04/16/97    aliu        Rewrote to use DigitList, which has been resurrected.
21 *                           Changed DigitCount to int per code review.
22 *   07/09/97    helena      Made ParsePosition into a class.
23 *   08/26/97    aliu        Extensive changes to applyPattern; completely
24 *                           rewritten from the Java.
25 *   09/09/97    aliu        Ported over support for exponential formats.
26 *   07/20/98    stephen     JDK 1.2 sync up.
27 *                             Various instances of '0' replaced with 'NULL'
28 *                             Check for grouping size in subFormat()
29 *                             Brought subParse() in line with Java 1.2
30 *                             Added method appendAffix()
31 *   08/24/1998  srl         Removed Mutex calls. This is not a thread safe class!
32 *   02/22/99    stephen     Removed character literals for EBCDIC safety
33 *   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
34 *   06/28/99    stephen     Fixed bugs in toPattern().
35 *   06/29/99    stephen     Fixed operator= to copy fFormatWidth, fPad,
36 *                             fPadPosition
37 ********************************************************************************
38 */
39 
40 #include "unicode/utypes.h"
41 
42 #if !UCONFIG_NO_FORMATTING
43 
44 #include "fphdlimp.h"
45 #include "unicode/decimfmt.h"
46 #include "unicode/choicfmt.h"
47 #include "unicode/ucurr.h"
48 #include "unicode/ustring.h"
49 #include "unicode/dcfmtsym.h"
50 #include "unicode/ures.h"
51 #include "unicode/uchar.h"
52 #include "unicode/uniset.h"
53 #include "unicode/curramt.h"
54 #include "unicode/currpinf.h"
55 #include "unicode/plurrule.h"
56 #include "unicode/utf16.h"
57 #include "unicode/numsys.h"
58 #include "unicode/localpointer.h"
59 #include "uresimp.h"
60 #include "ucurrimp.h"
61 #include "charstr.h"
62 #include "cmemory.h"
63 #include "patternprops.h"
64 #include "digitlst.h"
65 #include "cstring.h"
66 #include "umutex.h"
67 #include "uassert.h"
68 #include "putilimp.h"
69 #include <math.h>
70 #include "hash.h"
71 #include "decfmtst.h"
72 #include "dcfmtimp.h"
73 
74 U_NAMESPACE_BEGIN
75 
76 
77 /* == Fastpath calculation. ==
78  */
79 #if UCONFIG_FORMAT_FASTPATHS_49
internalData(uint8_t * reserved)80 inline DecimalFormatInternal& internalData(uint8_t *reserved) {
81   return *reinterpret_cast<DecimalFormatInternal*>(reserved);
82 }
internalData(const uint8_t * reserved)83 inline const DecimalFormatInternal& internalData(const uint8_t *reserved) {
84   return *reinterpret_cast<const DecimalFormatInternal*>(reserved);
85 }
86 #else
87 #endif
88 
89 /* For currency parsing purose,
90  * Need to remember all prefix patterns and suffix patterns of
91  * every currency format pattern,
92  * including the pattern of default currecny style
93  * and plural currency style. And the patterns are set through applyPattern.
94  */
95 struct AffixPatternsForCurrency : public UMemory {
96 	// negative prefix pattern
97 	UnicodeString negPrefixPatternForCurrency;
98 	// negative suffix pattern
99 	UnicodeString negSuffixPatternForCurrency;
100 	// positive prefix pattern
101 	UnicodeString posPrefixPatternForCurrency;
102 	// positive suffix pattern
103 	UnicodeString posSuffixPatternForCurrency;
104 	int8_t patternType;
105 
AffixPatternsForCurrencyAffixPatternsForCurrency106 	AffixPatternsForCurrency(const UnicodeString& negPrefix,
107 							 const UnicodeString& negSuffix,
108 							 const UnicodeString& posPrefix,
109 							 const UnicodeString& posSuffix,
110 							 int8_t type) {
111 		negPrefixPatternForCurrency = negPrefix;
112 		negSuffixPatternForCurrency = negSuffix;
113 		posPrefixPatternForCurrency = posPrefix;
114 		posSuffixPatternForCurrency = posSuffix;
115 		patternType = type;
116 	}
117 };
118 
119 /* affix for currency formatting when the currency sign in the pattern
120  * equals to 3, such as the pattern contains 3 currency sign or
121  * the formatter style is currency plural format style.
122  */
123 struct AffixesForCurrency : public UMemory {
124 	// negative prefix
125 	UnicodeString negPrefixForCurrency;
126 	// negative suffix
127 	UnicodeString negSuffixForCurrency;
128 	// positive prefix
129 	UnicodeString posPrefixForCurrency;
130 	// positive suffix
131 	UnicodeString posSuffixForCurrency;
132 
133 	int32_t formatWidth;
134 
AffixesForCurrencyAffixesForCurrency135 	AffixesForCurrency(const UnicodeString& negPrefix,
136 					   const UnicodeString& negSuffix,
137 					   const UnicodeString& posPrefix,
138 					   const UnicodeString& posSuffix) {
139 		negPrefixForCurrency = negPrefix;
140 		negSuffixForCurrency = negSuffix;
141 		posPrefixForCurrency = posPrefix;
142 		posSuffixForCurrency = posSuffix;
143 	}
144 };
145 
146 U_CDECL_BEGIN
147 
148 /**
149  * @internal ICU 4.2
150  */
151 static UBool U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2);
152 
153 /**
154  * @internal ICU 4.2
155  */
156 static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2);
157 
158 
159 static UBool
decimfmtAffixValueComparator(UHashTok val1,UHashTok val2)160 U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2) {
161     const AffixesForCurrency* affix_1 =
162         (AffixesForCurrency*)val1.pointer;
163     const AffixesForCurrency* affix_2 =
164         (AffixesForCurrency*)val2.pointer;
165     return affix_1->negPrefixForCurrency == affix_2->negPrefixForCurrency &&
166            affix_1->negSuffixForCurrency == affix_2->negSuffixForCurrency &&
167            affix_1->posPrefixForCurrency == affix_2->posPrefixForCurrency &&
168            affix_1->posSuffixForCurrency == affix_2->posSuffixForCurrency;
169 }
170 
171 
172 static UBool
decimfmtAffixPatternValueComparator(UHashTok val1,UHashTok val2)173 U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
174     const AffixPatternsForCurrency* affix_1 =
175         (AffixPatternsForCurrency*)val1.pointer;
176     const AffixPatternsForCurrency* affix_2 =
177         (AffixPatternsForCurrency*)val2.pointer;
178     return affix_1->negPrefixPatternForCurrency ==
179            affix_2->negPrefixPatternForCurrency &&
180            affix_1->negSuffixPatternForCurrency ==
181            affix_2->negSuffixPatternForCurrency &&
182            affix_1->posPrefixPatternForCurrency ==
183            affix_2->posPrefixPatternForCurrency &&
184            affix_1->posSuffixPatternForCurrency ==
185            affix_2->posSuffixPatternForCurrency &&
186            affix_1->patternType == affix_2->patternType;
187 }
188 
189 U_CDECL_END
190 
191 #ifdef FMT_DEBUG
192 #include <stdio.h>
_debugout(const char * f,int l,const UnicodeString & s)193 static void _debugout(const char *f, int l, const UnicodeString& s) {
194     char buf[2000];
195     s.extract((int32_t) 0, s.length(), buf);
196     printf("%s:%d: %s\n", f,l, buf);
197 }
198 #define debugout(x) _debugout(__FILE__,__LINE__,x)
199 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
200 static const UnicodeString dbg_null("<NULL>","");
201 #define DEREFSTR(x)   ((x!=NULL)?(*x):(dbg_null))
202 #else
203 #define debugout(x)
204 #define debug(x)
205 #endif
206 
207 
208 
209 // *****************************************************************************
210 // class DecimalFormat
211 // *****************************************************************************
212 
213 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
214 
215 // Constants for characters used in programmatic (unlocalized) patterns.
216 #define kPatternZeroDigit            ((UChar)0x0030) /*'0'*/
217 #define kPatternSignificantDigit     ((UChar)0x0040) /*'@'*/
218 #define kPatternGroupingSeparator    ((UChar)0x002C) /*','*/
219 #define kPatternDecimalSeparator     ((UChar)0x002E) /*'.'*/
220 #define kPatternPerMill              ((UChar)0x2030)
221 #define kPatternPercent              ((UChar)0x0025) /*'%'*/
222 #define kPatternDigit                ((UChar)0x0023) /*'#'*/
223 #define kPatternSeparator            ((UChar)0x003B) /*';'*/
224 #define kPatternExponent             ((UChar)0x0045) /*'E'*/
225 #define kPatternPlus                 ((UChar)0x002B) /*'+'*/
226 #define kPatternMinus                ((UChar)0x002D) /*'-'*/
227 #define kPatternPadEscape            ((UChar)0x002A) /*'*'*/
228 #define kQuote                       ((UChar)0x0027) /*'\''*/
229 /**
230  * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
231  * is used in patterns and substitued with either the currency symbol,
232  * or if it is doubled, with the international currency symbol.  If the
233  * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
234  * replaced with the monetary decimal separator.
235  */
236 #define kCurrencySign                ((UChar)0x00A4)
237 #define kDefaultPad                  ((UChar)0x0020) /* */
238 
239 const int32_t DecimalFormat::kDoubleIntegerDigits  = 309;
240 const int32_t DecimalFormat::kDoubleFractionDigits = 340;
241 
242 const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
243 
244 /**
245  * These are the tags we expect to see in normal resource bundle files associated
246  * with a locale.
247  */
248 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used
249 static const char fgNumberElements[]="NumberElements";
250 static const char fgLatn[]="latn";
251 static const char fgPatterns[]="patterns";
252 static const char fgDecimalFormat[]="decimalFormat";
253 static const char fgCurrencyFormat[]="currencyFormat";
254 static const UChar fgTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
255 
_min(int32_t a,int32_t b)256 inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
_max(int32_t a,int32_t b)257 inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
258 
259 //------------------------------------------------------------------------------
260 // Constructs a DecimalFormat instance in the default locale.
261 
DecimalFormat(UErrorCode & status)262 DecimalFormat::DecimalFormat(UErrorCode& status) {
263     init(status);
264     UParseError parseError;
265     construct(status, parseError);
266 }
267 
268 //------------------------------------------------------------------------------
269 // Constructs a DecimalFormat instance with the specified number format
270 // pattern in the default locale.
271 
DecimalFormat(const UnicodeString & pattern,UErrorCode & status)272 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
273                              UErrorCode& status) {
274     init(status);
275     UParseError parseError;
276     construct(status, parseError, &pattern);
277 }
278 
279 //------------------------------------------------------------------------------
280 // Constructs a DecimalFormat instance with the specified number format
281 // pattern and the number format symbols in the default locale.  The
282 // created instance owns the symbols.
283 
DecimalFormat(const UnicodeString & pattern,DecimalFormatSymbols * symbolsToAdopt,UErrorCode & status)284 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
285                              DecimalFormatSymbols* symbolsToAdopt,
286                              UErrorCode& status) {
287     init(status);
288     UParseError parseError;
289     if (symbolsToAdopt == NULL)
290         status = U_ILLEGAL_ARGUMENT_ERROR;
291     construct(status, parseError, &pattern, symbolsToAdopt);
292 }
293 
DecimalFormat(const UnicodeString & pattern,DecimalFormatSymbols * symbolsToAdopt,UParseError & parseErr,UErrorCode & status)294 DecimalFormat::DecimalFormat(  const UnicodeString& pattern,
295                     DecimalFormatSymbols* symbolsToAdopt,
296                     UParseError& parseErr,
297                     UErrorCode& status) {
298     init(status);
299     if (symbolsToAdopt == NULL)
300         status = U_ILLEGAL_ARGUMENT_ERROR;
301     construct(status,parseErr, &pattern, symbolsToAdopt);
302 }
303 
304 //------------------------------------------------------------------------------
305 // Constructs a DecimalFormat instance with the specified number format
306 // pattern and the number format symbols in the default locale.  The
307 // created instance owns the clone of the symbols.
308 
DecimalFormat(const UnicodeString & pattern,const DecimalFormatSymbols & symbols,UErrorCode & status)309 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
310                              const DecimalFormatSymbols& symbols,
311                              UErrorCode& status) {
312     init(status);
313     UParseError parseError;
314     construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
315 }
316 
317 //------------------------------------------------------------------------------
318 // Constructs a DecimalFormat instance with the specified number format
319 // pattern, the number format symbols, and the number format style.
320 // The created instance owns the clone of the symbols.
321 
DecimalFormat(const UnicodeString & pattern,DecimalFormatSymbols * symbolsToAdopt,UNumberFormatStyle style,UErrorCode & status)322 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
323                              DecimalFormatSymbols* symbolsToAdopt,
324                              UNumberFormatStyle style,
325                              UErrorCode& status) {
326     init(status);
327     fStyle = style;
328     UParseError parseError;
329     construct(status, parseError, &pattern, symbolsToAdopt);
330 }
331 
332 //-----------------------------------------------------------------------------
333 // Common DecimalFormat initialization.
334 //    Put all fields of an uninitialized object into a known state.
335 //    Common code, shared by all constructors.
336 void
init(UErrorCode & status)337 DecimalFormat::init(UErrorCode &status) {
338     fPosPrefixPattern = 0;
339     fPosSuffixPattern = 0;
340     fNegPrefixPattern = 0;
341     fNegSuffixPattern = 0;
342     fCurrencyChoice = 0;
343     fMultiplier = NULL;
344     fGroupingSize = 0;
345     fGroupingSize2 = 0;
346     fDecimalSeparatorAlwaysShown = FALSE;
347     fSymbols = NULL;
348     fUseSignificantDigits = FALSE;
349     fMinSignificantDigits = 1;
350     fMaxSignificantDigits = 6;
351     fUseExponentialNotation = FALSE;
352     fMinExponentDigits = 0;
353     fExponentSignAlwaysShown = FALSE;
354     fBoolFlags.clear();
355     fRoundingIncrement = 0;
356     fRoundingMode = kRoundHalfEven;
357     fPad = 0;
358     fFormatWidth = 0;
359     fPadPosition = kPadBeforePrefix;
360     fStyle = UNUM_DECIMAL;
361     fCurrencySignCount = 0;
362     fAffixPatternsForCurrency = NULL;
363     fAffixesForCurrency = NULL;
364     fPluralAffixesForCurrency = NULL;
365     fCurrencyPluralInfo = NULL;
366 #if UCONFIG_HAVE_PARSEALLINPUT
367     fParseAllInput = UNUM_MAYBE;
368 #endif
369 
370 #if UCONFIG_FORMAT_FASTPATHS_49
371     DecimalFormatInternal &data = internalData(fReserved);
372     data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
373     data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
374 #endif
375     // only do this once per obj.
376     DecimalFormatStaticSets::initSets(&status);
377 }
378 
379 //------------------------------------------------------------------------------
380 // Constructs a DecimalFormat instance with the specified number format
381 // pattern and the number format symbols in the desired locale.  The
382 // created instance owns the symbols.
383 
384 void
construct(UErrorCode & status,UParseError & parseErr,const UnicodeString * pattern,DecimalFormatSymbols * symbolsToAdopt)385 DecimalFormat::construct(UErrorCode&             status,
386                          UParseError&           parseErr,
387                          const UnicodeString*   pattern,
388                          DecimalFormatSymbols*  symbolsToAdopt)
389 {
390     fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!!
391     fRoundingIncrement = NULL;
392     fRoundingMode = kRoundHalfEven;
393     fPad = kPatternPadEscape;
394     fPadPosition = kPadBeforePrefix;
395     if (U_FAILURE(status))
396         return;
397 
398     fPosPrefixPattern = fPosSuffixPattern = NULL;
399     fNegPrefixPattern = fNegSuffixPattern = NULL;
400     setMultiplier(1);
401     fGroupingSize = 3;
402     fGroupingSize2 = 0;
403     fDecimalSeparatorAlwaysShown = FALSE;
404     fUseExponentialNotation = FALSE;
405     fMinExponentDigits = 0;
406 
407     if (fSymbols == NULL)
408     {
409         fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
410         /* test for NULL */
411         if (fSymbols == 0) {
412             status = U_MEMORY_ALLOCATION_ERROR;
413             return;
414         }
415     }
416     UErrorCode nsStatus = U_ZERO_ERROR;
417     NumberingSystem *ns = NumberingSystem::createInstance(nsStatus);
418     if (U_FAILURE(nsStatus)) {
419         status = nsStatus;
420         return;
421     }
422 
423     UnicodeString str;
424     // Uses the default locale's number format pattern if there isn't
425     // one specified.
426     if (pattern == NULL)
427     {
428         int32_t len = 0;
429         UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status);
430 
431         UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status);
432         resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status);
433         resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
434         const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
435         if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) {
436             status = U_ZERO_ERROR;
437             resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status);
438             resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status);
439             resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
440             resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
441         }
442         str.setTo(TRUE, resStr, len);
443         pattern = &str;
444         ures_close(resource);
445         ures_close(top);
446     }
447 
448     delete ns;
449 
450     if (U_FAILURE(status))
451     {
452         return;
453     }
454 
455     if (pattern->indexOf((UChar)kCurrencySign) >= 0) {
456         // If it looks like we are going to use a currency pattern
457         // then do the time consuming lookup.
458         setCurrencyForSymbols();
459     } else {
460         setCurrencyInternally(NULL, status);
461     }
462 
463     const UnicodeString* patternUsed;
464     UnicodeString currencyPluralPatternForOther;
465     // apply pattern
466     if (fStyle == UNUM_CURRENCY_PLURAL) {
467         fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
468         if (U_FAILURE(status)) {
469             return;
470         }
471 
472         // the pattern used in format is not fixed until formatting,
473         // in which, the number is known and
474         // will be used to pick the right pattern based on plural count.
475         // Here, set the pattern as the pattern of plural count == "other".
476         // For most locale, the patterns are probably the same for all
477         // plural count. If not, the right pattern need to be re-applied
478         // during format.
479         fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther);
480         patternUsed = &currencyPluralPatternForOther;
481         // TODO: not needed?
482         setCurrencyForSymbols();
483 
484     } else {
485         patternUsed = pattern;
486     }
487 
488     if (patternUsed->indexOf(kCurrencySign) != -1) {
489         // initialize for currency, not only for plural format,
490         // but also for mix parsing
491         if (fCurrencyPluralInfo == NULL) {
492            fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
493            if (U_FAILURE(status)) {
494                return;
495            }
496         }
497         // need it for mix parsing
498         setupCurrencyAffixPatterns(status);
499         // expanded affixes for plural names
500         if (patternUsed->indexOf(fgTripleCurrencySign, 3, 0) != -1) {
501             setupCurrencyAffixes(*patternUsed, TRUE, TRUE, status);
502         }
503     }
504 
505     applyPatternWithoutExpandAffix(*patternUsed,FALSE, parseErr, status);
506 
507     // expand affixes
508     if (fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
509         expandAffixAdjustWidth(NULL);
510     }
511 
512     // If it was a currency format, apply the appropriate rounding by
513     // resetting the currency. NOTE: this copies fCurrency on top of itself.
514     if (fCurrencySignCount > fgCurrencySignCountZero) {
515         setCurrencyInternally(getCurrency(), status);
516     }
517 #if UCONFIG_FORMAT_FASTPATHS_49
518     DecimalFormatInternal &data = internalData(fReserved);
519     data.fFastFormatStatus = kFastpathNO; // allow it to be calculated
520     data.fFastParseStatus = kFastpathNO; // allow it to be calculated
521     handleChanged();
522 #endif
523 }
524 
525 
526 void
setupCurrencyAffixPatterns(UErrorCode & status)527 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
528     if (U_FAILURE(status)) {
529         return;
530     }
531     UParseError parseErr;
532     fAffixPatternsForCurrency = initHashForAffixPattern(status);
533     if (U_FAILURE(status)) {
534         return;
535     }
536 
537     NumberingSystem *ns = NumberingSystem::createInstance(fSymbols->getLocale(),status);
538     if (U_FAILURE(status)) {
539         return;
540     }
541 
542     // Save the default currency patterns of this locale.
543     // Here, chose onlyApplyPatternWithoutExpandAffix without
544     // expanding the affix patterns into affixes.
545     UnicodeString currencyPattern;
546     UErrorCode error = U_ZERO_ERROR;
547 
548     UResourceBundle *resource = ures_open(NULL, fSymbols->getLocale().getName(), &error);
549     UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error);
550     resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error);
551     resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
552     int32_t patLen = 0;
553     const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat,  &patLen, &error);
554     if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) {
555         error = U_ZERO_ERROR;
556         resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error);
557         resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
558         patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat,  &patLen, &error);
559     }
560     ures_close(numElements);
561     ures_close(resource);
562     delete ns;
563 
564     if (U_SUCCESS(error)) {
565         applyPatternWithoutExpandAffix(UnicodeString(patResStr, patLen), false,
566                                        parseErr, status);
567         AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
568                                                     *fNegPrefixPattern,
569                                                     *fNegSuffixPattern,
570                                                     *fPosPrefixPattern,
571                                                     *fPosSuffixPattern,
572                                                     UCURR_SYMBOL_NAME);
573         fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status);
574     }
575 
576     // save the unique currency plural patterns of this locale.
577     Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern;
578     const UHashElement* element = NULL;
579     int32_t pos = -1;
580     Hashtable pluralPatternSet;
581     while ((element = pluralPtn->nextElement(pos)) != NULL) {
582         const UHashTok valueTok = element->value;
583         const UnicodeString* value = (UnicodeString*)valueTok.pointer;
584         const UHashTok keyTok = element->key;
585         const UnicodeString* key = (UnicodeString*)keyTok.pointer;
586         if (pluralPatternSet.geti(*value) != 1) {
587             pluralPatternSet.puti(*value, 1, status);
588             applyPatternWithoutExpandAffix(*value, false, parseErr, status);
589             AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
590                                                     *fNegPrefixPattern,
591                                                     *fNegSuffixPattern,
592                                                     *fPosPrefixPattern,
593                                                     *fPosSuffixPattern,
594                                                     UCURR_LONG_NAME);
595             fAffixPatternsForCurrency->put(*key, affixPtn, status);
596         }
597     }
598 }
599 
600 
601 void
setupCurrencyAffixes(const UnicodeString & pattern,UBool setupForCurrentPattern,UBool setupForPluralPattern,UErrorCode & status)602 DecimalFormat::setupCurrencyAffixes(const UnicodeString& pattern,
603                                     UBool setupForCurrentPattern,
604                                     UBool setupForPluralPattern,
605                                     UErrorCode& status) {
606     if (U_FAILURE(status)) {
607         return;
608     }
609     UParseError parseErr;
610     if (setupForCurrentPattern) {
611         if (fAffixesForCurrency) {
612             deleteHashForAffix(fAffixesForCurrency);
613         }
614         fAffixesForCurrency = initHashForAffix(status);
615         if (U_SUCCESS(status)) {
616             applyPatternWithoutExpandAffix(pattern, false, parseErr, status);
617             const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules();
618             StringEnumeration* keywords = pluralRules->getKeywords(status);
619             if (U_SUCCESS(status)) {
620                 const UnicodeString* pluralCount;
621                 while ((pluralCount = keywords->snext(status)) != NULL) {
622                     if ( U_SUCCESS(status) ) {
623                         expandAffixAdjustWidth(pluralCount);
624                         AffixesForCurrency* affix = new AffixesForCurrency(
625                             fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix);
626                         fAffixesForCurrency->put(*pluralCount, affix, status);
627                     }
628                 }
629             }
630             delete keywords;
631         }
632     }
633 
634     if (U_FAILURE(status)) {
635         return;
636     }
637 
638     if (setupForPluralPattern) {
639         if (fPluralAffixesForCurrency) {
640             deleteHashForAffix(fPluralAffixesForCurrency);
641         }
642         fPluralAffixesForCurrency = initHashForAffix(status);
643         if (U_SUCCESS(status)) {
644             const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules();
645             StringEnumeration* keywords = pluralRules->getKeywords(status);
646             if (U_SUCCESS(status)) {
647                 const UnicodeString* pluralCount;
648                 while ((pluralCount = keywords->snext(status)) != NULL) {
649                     if ( U_SUCCESS(status) ) {
650                         UnicodeString ptn;
651                         fCurrencyPluralInfo->getCurrencyPluralPattern(*pluralCount, ptn);
652                         applyPatternInternally(*pluralCount, ptn, false, parseErr, status);
653                         AffixesForCurrency* affix = new AffixesForCurrency(
654                             fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix);
655                         fPluralAffixesForCurrency->put(*pluralCount, affix, status);
656                     }
657                 }
658             }
659             delete keywords;
660         }
661     }
662 }
663 
664 
665 //------------------------------------------------------------------------------
666 
~DecimalFormat()667 DecimalFormat::~DecimalFormat()
668 {
669     delete fPosPrefixPattern;
670     delete fPosSuffixPattern;
671     delete fNegPrefixPattern;
672     delete fNegSuffixPattern;
673     delete fCurrencyChoice;
674     delete fMultiplier;
675     delete fSymbols;
676     delete fRoundingIncrement;
677     deleteHashForAffixPattern();
678     deleteHashForAffix(fAffixesForCurrency);
679     deleteHashForAffix(fPluralAffixesForCurrency);
680     delete fCurrencyPluralInfo;
681 }
682 
683 //------------------------------------------------------------------------------
684 // copy constructor
685 
DecimalFormat(const DecimalFormat & source)686 DecimalFormat::DecimalFormat(const DecimalFormat &source) :
687     NumberFormat(source) {
688     UErrorCode status = U_ZERO_ERROR;
689     init(status); // if this fails, 'source' isn't initialized properly either.
690     *this = source;
691 }
692 
693 //------------------------------------------------------------------------------
694 // assignment operator
695 
696 template <class T>
_copy_ptr(T ** pdest,const T * source)697 static void _copy_ptr(T** pdest, const T* source) {
698     if (source == NULL) {
699         delete *pdest;
700         *pdest = NULL;
701     } else if (*pdest == NULL) {
702         *pdest = new T(*source);
703     } else {
704         **pdest = *source;
705     }
706 }
707 
708 template <class T>
_clone_ptr(T ** pdest,const T * source)709 static void _clone_ptr(T** pdest, const T* source) {
710     delete *pdest;
711     if (source == NULL) {
712         *pdest = NULL;
713     } else {
714         *pdest = static_cast<T*>(source->clone());
715     }
716 }
717 
718 DecimalFormat&
operator =(const DecimalFormat & rhs)719 DecimalFormat::operator=(const DecimalFormat& rhs)
720 {
721     if(this != &rhs) {
722         NumberFormat::operator=(rhs);
723         fPositivePrefix = rhs.fPositivePrefix;
724         fPositiveSuffix = rhs.fPositiveSuffix;
725         fNegativePrefix = rhs.fNegativePrefix;
726         fNegativeSuffix = rhs.fNegativeSuffix;
727         _copy_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern);
728         _copy_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern);
729         _copy_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern);
730         _copy_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern);
731         _clone_ptr(&fCurrencyChoice, rhs.fCurrencyChoice);
732         setRoundingIncrement(rhs.getRoundingIncrement());
733         fRoundingMode = rhs.fRoundingMode;
734         setMultiplier(rhs.getMultiplier());
735         fGroupingSize = rhs.fGroupingSize;
736         fGroupingSize2 = rhs.fGroupingSize2;
737         fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown;
738         _copy_ptr(&fSymbols, rhs.fSymbols);
739         fUseExponentialNotation = rhs.fUseExponentialNotation;
740         fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown;
741         fBoolFlags = rhs.fBoolFlags;
742         /*Bertrand A. D. Update 98.03.17*/
743         fCurrencySignCount = rhs.fCurrencySignCount;
744         /*end of Update*/
745         fMinExponentDigits = rhs.fMinExponentDigits;
746 
747         /* sfb 990629 */
748         fFormatWidth = rhs.fFormatWidth;
749         fPad = rhs.fPad;
750         fPadPosition = rhs.fPadPosition;
751         /* end sfb */
752         fMinSignificantDigits = rhs.fMinSignificantDigits;
753         fMaxSignificantDigits = rhs.fMaxSignificantDigits;
754         fUseSignificantDigits = rhs.fUseSignificantDigits;
755         fFormatPattern = rhs.fFormatPattern;
756         fStyle = rhs.fStyle;
757         fCurrencySignCount = rhs.fCurrencySignCount;
758         _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo);
759         deleteHashForAffixPattern();
760         if (rhs.fAffixPatternsForCurrency) {
761             UErrorCode status = U_ZERO_ERROR;
762             fAffixPatternsForCurrency = initHashForAffixPattern(status);
763             copyHashForAffixPattern(rhs.fAffixPatternsForCurrency,
764                                     fAffixPatternsForCurrency, status);
765         }
766         deleteHashForAffix(fAffixesForCurrency);
767         if (rhs.fAffixesForCurrency) {
768             UErrorCode status = U_ZERO_ERROR;
769             fAffixesForCurrency = initHashForAffixPattern(status);
770             copyHashForAffix(rhs.fAffixesForCurrency, fAffixesForCurrency, status);
771         }
772         deleteHashForAffix(fPluralAffixesForCurrency);
773         if (rhs.fPluralAffixesForCurrency) {
774             UErrorCode status = U_ZERO_ERROR;
775             fPluralAffixesForCurrency = initHashForAffixPattern(status);
776             copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCurrency, status);
777         }
778     }
779 #if UCONFIG_FORMAT_FASTPATHS_49
780     handleChanged();
781 #endif
782     return *this;
783 }
784 
785 //------------------------------------------------------------------------------
786 
787 UBool
operator ==(const Format & that) const788 DecimalFormat::operator==(const Format& that) const
789 {
790     if (this == &that)
791         return TRUE;
792 
793     // NumberFormat::operator== guarantees this cast is safe
794     const DecimalFormat* other = (DecimalFormat*)&that;
795 
796 #ifdef FMT_DEBUG
797     // This code makes it easy to determine why two format objects that should
798     // be equal aren't.
799     UBool first = TRUE;
800     if (!NumberFormat::operator==(that)) {
801         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
802         debug("NumberFormat::!=");
803     } else {
804     if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null
805               fPositivePrefix == other->fPositivePrefix)
806            || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
807                *fPosPrefixPattern  == *other->fPosPrefixPattern))) {
808         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
809         debug("Pos Prefix !=");
810     }
811     if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null
812            fPositiveSuffix == other->fPositiveSuffix)
813           || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
814               *fPosSuffixPattern  == *other->fPosSuffixPattern))) {
815         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
816         debug("Pos Suffix !=");
817     }
818     if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null
819            fNegativePrefix == other->fNegativePrefix)
820           || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
821               *fNegPrefixPattern  == *other->fNegPrefixPattern))) {
822         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
823         debug("Neg Prefix ");
824         if (fNegPrefixPattern == NULL) {
825             debug("NULL(");
826             debugout(fNegativePrefix);
827             debug(")");
828         } else {
829             debugout(*fNegPrefixPattern);
830         }
831         debug(" != ");
832         if (other->fNegPrefixPattern == NULL) {
833             debug("NULL(");
834             debugout(other->fNegativePrefix);
835             debug(")");
836         } else {
837             debugout(*other->fNegPrefixPattern);
838         }
839     }
840     if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null
841            fNegativeSuffix == other->fNegativeSuffix)
842           || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
843               *fNegSuffixPattern  == *other->fNegSuffixPattern))) {
844         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
845         debug("Neg Suffix ");
846         if (fNegSuffixPattern == NULL) {
847             debug("NULL(");
848             debugout(fNegativeSuffix);
849             debug(")");
850         } else {
851             debugout(*fNegSuffixPattern);
852         }
853         debug(" != ");
854         if (other->fNegSuffixPattern == NULL) {
855             debug("NULL(");
856             debugout(other->fNegativeSuffix);
857             debug(")");
858         } else {
859             debugout(*other->fNegSuffixPattern);
860         }
861     }
862     if (!((fRoundingIncrement == other->fRoundingIncrement) // both null
863           || (fRoundingIncrement != NULL &&
864               other->fRoundingIncrement != NULL &&
865               *fRoundingIncrement == *other->fRoundingIncrement))) {
866         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
867         debug("Rounding Increment !=");
868               }
869     if (getMultiplier() != other->getMultiplier()) {
870         if (first) { printf("[ "); first = FALSE; }
871         printf("Multiplier %ld != %ld", getMultiplier(), other->getMultiplier());
872     }
873     if (fGroupingSize != other->fGroupingSize) {
874         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
875         printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize);
876     }
877     if (fGroupingSize2 != other->fGroupingSize2) {
878         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
879         printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGroupingSize2);
880     }
881     if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) {
882         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
883         printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown);
884     }
885     if (fUseExponentialNotation != other->fUseExponentialNotation) {
886         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
887         debug("Use Exp !=");
888     }
889     if (!(!fUseExponentialNotation ||
890           fMinExponentDigits != other->fMinExponentDigits)) {
891         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
892         debug("Exp Digits !=");
893     }
894     if (*fSymbols != *(other->fSymbols)) {
895         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
896         debug("Symbols !=");
897     }
898     // TODO Add debug stuff for significant digits here
899     if (fUseSignificantDigits != other->fUseSignificantDigits) {
900         debug("fUseSignificantDigits !=");
901     }
902     if (fUseSignificantDigits &&
903         fMinSignificantDigits != other->fMinSignificantDigits) {
904         debug("fMinSignificantDigits !=");
905     }
906     if (fUseSignificantDigits &&
907         fMaxSignificantDigits != other->fMaxSignificantDigits) {
908         debug("fMaxSignificantDigits !=");
909     }
910 
911     if (!first) { printf(" ]"); }
912     if (fCurrencySignCount != other->fCurrencySignCount) {
913         debug("fCurrencySignCount !=");
914     }
915     if (fCurrencyPluralInfo == other->fCurrencyPluralInfo) {
916         debug("fCurrencyPluralInfo == ");
917         if (fCurrencyPluralInfo == NULL) {
918             debug("fCurrencyPluralInfo == NULL");
919         }
920     }
921     if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL &&
922          *fCurrencyPluralInfo != *(other->fCurrencyPluralInfo)) {
923         debug("fCurrencyPluralInfo !=");
924     }
925     if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo == NULL ||
926         fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo != NULL) {
927         debug("fCurrencyPluralInfo one NULL, the other not");
928     }
929     if (fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo == NULL) {
930         debug("fCurrencyPluralInfo == ");
931     }
932     }
933 #endif
934 
935     return (NumberFormat::operator==(that) &&
936             ((fCurrencySignCount == fgCurrencySignCountInPluralFormat) ?
937             (fAffixPatternsForCurrency->equals(*other->fAffixPatternsForCurrency)) :
938             (((fPosPrefixPattern == other->fPosPrefixPattern && // both null
939               fPositivePrefix == other->fPositivePrefix)
940              || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
941                  *fPosPrefixPattern  == *other->fPosPrefixPattern)) &&
942             ((fPosSuffixPattern == other->fPosSuffixPattern && // both null
943               fPositiveSuffix == other->fPositiveSuffix)
944              || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
945                  *fPosSuffixPattern  == *other->fPosSuffixPattern)) &&
946             ((fNegPrefixPattern == other->fNegPrefixPattern && // both null
947               fNegativePrefix == other->fNegativePrefix)
948              || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
949                  *fNegPrefixPattern  == *other->fNegPrefixPattern)) &&
950             ((fNegSuffixPattern == other->fNegSuffixPattern && // both null
951               fNegativeSuffix == other->fNegativeSuffix)
952              || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
953                  *fNegSuffixPattern  == *other->fNegSuffixPattern)))) &&
954             ((fRoundingIncrement == other->fRoundingIncrement) // both null
955              || (fRoundingIncrement != NULL &&
956                  other->fRoundingIncrement != NULL &&
957                  *fRoundingIncrement == *other->fRoundingIncrement)) &&
958         getMultiplier() == other->getMultiplier() &&
959         fGroupingSize == other->fGroupingSize &&
960         fGroupingSize2 == other->fGroupingSize2 &&
961         fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown &&
962         fUseExponentialNotation == other->fUseExponentialNotation &&
963         (!fUseExponentialNotation ||
964          fMinExponentDigits == other->fMinExponentDigits) &&
965         *fSymbols == *(other->fSymbols) &&
966         fUseSignificantDigits == other->fUseSignificantDigits &&
967         (!fUseSignificantDigits ||
968          (fMinSignificantDigits == other->fMinSignificantDigits &&
969           fMaxSignificantDigits == other->fMaxSignificantDigits)) &&
970         fCurrencySignCount == other->fCurrencySignCount &&
971         ((fCurrencyPluralInfo == other->fCurrencyPluralInfo &&
972           fCurrencyPluralInfo == NULL) ||
973          (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL &&
974          *fCurrencyPluralInfo == *(other->fCurrencyPluralInfo))));
975 }
976 
977 //------------------------------------------------------------------------------
978 
979 Format*
clone() const980 DecimalFormat::clone() const
981 {
982     return new DecimalFormat(*this);
983 }
984 
985 //------------------------------------------------------------------------------
986 
987 UnicodeString&
format(int32_t number,UnicodeString & appendTo,FieldPosition & fieldPosition) const988 DecimalFormat::format(int32_t number,
989                       UnicodeString& appendTo,
990                       FieldPosition& fieldPosition) const
991 {
992     return format((int64_t)number, appendTo, fieldPosition);
993 }
994 
995 UnicodeString&
format(int32_t number,UnicodeString & appendTo,FieldPosition & fieldPosition,UErrorCode & status) const996 DecimalFormat::format(int32_t number,
997                       UnicodeString& appendTo,
998                       FieldPosition& fieldPosition,
999                       UErrorCode& status) const
1000 {
1001     return format((int64_t)number, appendTo, fieldPosition, status);
1002 }
1003 
1004 UnicodeString&
format(int32_t number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const1005 DecimalFormat::format(int32_t number,
1006                       UnicodeString& appendTo,
1007                       FieldPositionIterator* posIter,
1008                       UErrorCode& status) const
1009 {
1010     return format((int64_t)number, appendTo, posIter, status);
1011 }
1012 
1013 
1014 #if UCONFIG_FORMAT_FASTPATHS_49
handleChanged()1015 void DecimalFormat::handleChanged() {
1016   DecimalFormatInternal &data = internalData(fReserved);
1017 
1018   if(data.fFastFormatStatus == kFastpathUNKNOWN || data.fFastParseStatus == kFastpathUNKNOWN) {
1019     return; // still constructing. Wait.
1020   }
1021 
1022   data.fFastParseStatus = data.fFastFormatStatus = kFastpathNO;
1023 
1024 #if UCONFIG_HAVE_PARSEALLINPUT
1025   if(fParseAllInput == UNUM_NO) {
1026     debug("No Parse fastpath: fParseAllInput==UNUM_NO");
1027   } else
1028 #endif
1029   if (fFormatWidth!=0) {
1030       debug("No Parse fastpath: fFormatWidth");
1031   } else if(fPositivePrefix.length()>0) {
1032     debug("No Parse fastpath: positive prefix");
1033   } else if(fPositiveSuffix.length()>0) {
1034     debug("No Parse fastpath: positive suffix");
1035   } else if(fNegativePrefix.length()>1
1036             || ((fNegativePrefix.length()==1) && (fNegativePrefix.charAt(0)!=0x002D))) {
1037     debug("No Parse fastpath: negative prefix that isn't '-'");
1038   } else if(fNegativeSuffix.length()>0) {
1039     debug("No Parse fastpath: negative suffix");
1040   } else {
1041     data.fFastParseStatus = kFastpathYES;
1042     debug("parse fastpath: YES");
1043   }
1044 
1045   if (fGroupingSize!=0 && isGroupingUsed()) {
1046     debug("No format fastpath: fGroupingSize!=0 and grouping is used");
1047 #ifdef FMT_DEBUG
1048     printf("groupingsize=%d\n", fGroupingSize);
1049 #endif
1050   } else if(fGroupingSize2!=0 && isGroupingUsed()) {
1051     debug("No format fastpath: fGroupingSize2!=0");
1052   } else if(fUseExponentialNotation) {
1053     debug("No format fastpath: fUseExponentialNotation");
1054   } else if(fFormatWidth!=0) {
1055     debug("No format fastpath: fFormatWidth!=0");
1056   } else if(fMinSignificantDigits!=1) {
1057     debug("No format fastpath: fMinSignificantDigits!=1");
1058   } else if(fMultiplier!=NULL) {
1059     debug("No format fastpath: fMultiplier!=NULL");
1060   } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)) {
1061     debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)");
1062   } else if(fDecimalSeparatorAlwaysShown) {
1063     debug("No format fastpath: fDecimalSeparatorAlwaysShown");
1064   } else if(getMinimumFractionDigits()>0) {
1065     debug("No format fastpath: fMinFractionDigits>0");
1066   } else if(fCurrencySignCount > fgCurrencySignCountZero) {
1067     debug("No format fastpath: fCurrencySignCount > fgCurrencySignCountZero");
1068   } else if(fRoundingIncrement!=0) {
1069     debug("No format fastpath: fRoundingIncrement!=0");
1070   } else {
1071     data.fFastFormatStatus = kFastpathYES;
1072     debug("format:kFastpathYES!");
1073   }
1074 
1075 
1076 }
1077 #endif
1078 //------------------------------------------------------------------------------
1079 
1080 UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPosition & fieldPosition) const1081 DecimalFormat::format(int64_t number,
1082                       UnicodeString& appendTo,
1083                       FieldPosition& fieldPosition) const
1084 {
1085     UErrorCode status = U_ZERO_ERROR; /* ignored */
1086     FieldPositionOnlyHandler handler(fieldPosition);
1087     return _format(number, appendTo, handler, status);
1088 }
1089 
1090 UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPosition & fieldPosition,UErrorCode & status) const1091 DecimalFormat::format(int64_t number,
1092                       UnicodeString& appendTo,
1093                       FieldPosition& fieldPosition,
1094                       UErrorCode& status) const
1095 {
1096     FieldPositionOnlyHandler handler(fieldPosition);
1097     return _format(number, appendTo, handler, status);
1098 }
1099 
1100 UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const1101 DecimalFormat::format(int64_t number,
1102                       UnicodeString& appendTo,
1103                       FieldPositionIterator* posIter,
1104                       UErrorCode& status) const
1105 {
1106     FieldPositionIteratorHandler handler(posIter, status);
1107     return _format(number, appendTo, handler, status);
1108 }
1109 
1110 UnicodeString&
_format(int64_t number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const1111 DecimalFormat::_format(int64_t number,
1112                        UnicodeString& appendTo,
1113                        FieldPositionHandler& handler,
1114                        UErrorCode &status) const
1115 {
1116     // Bottleneck function for formatting int64_t
1117     if (U_FAILURE(status)) {
1118         return appendTo;
1119     }
1120 
1121 #if UCONFIG_FORMAT_FASTPATHS_49
1122   // const UnicodeString *posPrefix = fPosPrefixPattern;
1123   // const UnicodeString *posSuffix = fPosSuffixPattern;
1124   // const UnicodeString *negSuffix = fNegSuffixPattern;
1125 
1126   const DecimalFormatInternal &data = internalData(fReserved);
1127 
1128 #ifdef FMT_DEBUG
1129   data.dump();
1130   printf("fastpath? [%d]\n", number);
1131 #endif
1132 
1133   if( data.fFastFormatStatus==kFastpathYES) {
1134 
1135 #define kZero 0x0030
1136     const int32_t MAX_IDX = MAX_DIGITS+2;
1137     UChar outputStr[MAX_IDX];
1138     int32_t destIdx = MAX_IDX;
1139     outputStr[--destIdx] = 0;  // term
1140 
1141     int64_t  n = number;
1142     if (number < 1) {
1143       // Negative numbers are slightly larger than positive
1144       // output the first digit (or the leading zero)
1145       outputStr[--destIdx] = (-(n % 10) + kZero);
1146       n /= -10;
1147     }
1148     // get any remaining digits
1149     while (n > 0) {
1150       outputStr[--destIdx] = (n % 10) + kZero;
1151       n /= 10;
1152     }
1153 
1154 
1155         // Slide the number to the start of the output str
1156     U_ASSERT(destIdx >= 0);
1157     int32_t length = MAX_IDX - destIdx -1;
1158     /*int32_t prefixLen = */ appendAffix(appendTo, number, handler, number<0, TRUE);
1159     int32_t maxIntDig = getMaximumIntegerDigits();
1160     int32_t destlength = length<=maxIntDig?length:maxIntDig; // dest length pinned to max int digits
1161 
1162     if(length>maxIntDig && fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) {
1163       status = U_ILLEGAL_ARGUMENT_ERROR;
1164     }
1165 
1166     int32_t prependZero = getMinimumIntegerDigits() - destlength;
1167 
1168 #ifdef FMT_DEBUG
1169     printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d skip=%d\n", prependZero, length, getMinimumIntegerDigits(), maxIntDig, destlength, length-destlength);
1170 #endif
1171     int32_t intBegin = appendTo.length();
1172 
1173     while((prependZero--)>0) {
1174       appendTo.append((UChar)0x0030); // '0'
1175     }
1176 
1177     appendTo.append(outputStr+destIdx+
1178                     (length-destlength), // skip any leading digits
1179                     destlength);
1180     handler.addAttribute(kIntegerField, intBegin, appendTo.length());
1181 
1182     /*int32_t suffixLen =*/ appendAffix(appendTo, number, handler, number<0, FALSE);
1183 
1184     //outputStr[length]=0;
1185 
1186 #ifdef FMT_DEBUG
1187         printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr+destIdx, length, MAX_IDX, number);
1188 #endif
1189 
1190 #undef kZero
1191 
1192     return appendTo;
1193   } // end fastpath
1194 #endif
1195 
1196   // Else the slow way - via DigitList
1197     DigitList digits;
1198     digits.set(number);
1199     return _format(digits, appendTo, handler, status);
1200 }
1201 
1202 //------------------------------------------------------------------------------
1203 
1204 UnicodeString&
format(double number,UnicodeString & appendTo,FieldPosition & fieldPosition) const1205 DecimalFormat::format(  double number,
1206                         UnicodeString& appendTo,
1207                         FieldPosition& fieldPosition) const
1208 {
1209     UErrorCode status = U_ZERO_ERROR; /* ignored */
1210     FieldPositionOnlyHandler handler(fieldPosition);
1211     return _format(number, appendTo, handler, status);
1212 }
1213 
1214 UnicodeString&
format(double number,UnicodeString & appendTo,FieldPosition & fieldPosition,UErrorCode & status) const1215 DecimalFormat::format(  double number,
1216                         UnicodeString& appendTo,
1217                         FieldPosition& fieldPosition,
1218                         UErrorCode& status) const
1219 {
1220     FieldPositionOnlyHandler handler(fieldPosition);
1221     return _format(number, appendTo, handler, status);
1222 }
1223 
1224 UnicodeString&
format(double number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const1225 DecimalFormat::format(  double number,
1226                         UnicodeString& appendTo,
1227                         FieldPositionIterator* posIter,
1228                         UErrorCode& status) const
1229 {
1230   FieldPositionIteratorHandler handler(posIter, status);
1231   return _format(number, appendTo, handler, status);
1232 }
1233 
1234 UnicodeString&
_format(double number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const1235 DecimalFormat::_format( double number,
1236                         UnicodeString& appendTo,
1237                         FieldPositionHandler& handler,
1238                         UErrorCode &status) const
1239 {
1240     if (U_FAILURE(status)) {
1241         return appendTo;
1242     }
1243     // Special case for NaN, sets the begin and end index to be the
1244     // the string length of localized name of NaN.
1245     // TODO:  let NaNs go through DigitList.
1246     if (uprv_isNaN(number))
1247     {
1248         int begin = appendTo.length();
1249         appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1250 
1251         handler.addAttribute(kIntegerField, begin, appendTo.length());
1252 
1253         addPadding(appendTo, handler, 0, 0);
1254         return appendTo;
1255     }
1256 
1257     DigitList digits;
1258     digits.set(number);
1259     _format(digits, appendTo, handler, status);
1260     // No way to return status from here.
1261     return appendTo;
1262 }
1263 
1264 //------------------------------------------------------------------------------
1265 
1266 
1267 UnicodeString&
format(const StringPiece & number,UnicodeString & toAppendTo,FieldPositionIterator * posIter,UErrorCode & status) const1268 DecimalFormat::format(const StringPiece &number,
1269                       UnicodeString &toAppendTo,
1270                       FieldPositionIterator *posIter,
1271                       UErrorCode &status) const
1272 {
1273 #if UCONFIG_FORMAT_FASTPATHS_49
1274   // don't bother if the int64 path is not optimized
1275   int32_t len    = number.length();
1276 
1277   if(len>0&&len<10) { /* 10 or more digits may not be an int64 */
1278     const char *data = number.data();
1279     int64_t num = 0;
1280     UBool neg = FALSE;
1281     UBool ok = TRUE;
1282 
1283     int32_t start  = 0;
1284 
1285     if(data[start]=='+') {
1286       start++;
1287     } else if(data[start]=='-') {
1288       neg=TRUE;
1289       start++;
1290     }
1291 
1292     int32_t place = 1; /* 1, 10, ... */
1293     for(int32_t i=len-1;i>=start;i--) {
1294       if(data[i]>='0'&&data[i]<='9') {
1295         num+=place*(int64_t)(data[i]-'0');
1296       } else {
1297         ok=FALSE;
1298         break;
1299       }
1300       place *= 10;
1301     }
1302 
1303     if(ok) {
1304       if(neg) {
1305         num = -num;// add minus bit
1306       }
1307       // format as int64_t
1308       return format(num, toAppendTo, posIter, status);
1309     }
1310     // else fall through
1311   }
1312 #endif
1313 
1314     DigitList   dnum;
1315     dnum.set(number, status);
1316     if (U_FAILURE(status)) {
1317         return toAppendTo;
1318     }
1319     FieldPositionIteratorHandler handler(posIter, status);
1320     _format(dnum, toAppendTo, handler, status);
1321     return toAppendTo;
1322 }
1323 
1324 
1325 UnicodeString&
format(const DigitList & number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const1326 DecimalFormat::format(const DigitList &number,
1327                       UnicodeString &appendTo,
1328                       FieldPositionIterator *posIter,
1329                       UErrorCode &status) const {
1330     FieldPositionIteratorHandler handler(posIter, status);
1331     _format(number, appendTo, handler, status);
1332     return appendTo;
1333 }
1334 
1335 
1336 
1337 UnicodeString&
format(const DigitList & number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const1338 DecimalFormat::format(const DigitList &number,
1339                      UnicodeString& appendTo,
1340                      FieldPosition& pos,
1341                      UErrorCode &status) const {
1342     FieldPositionOnlyHandler handler(pos);
1343     _format(number, appendTo, handler, status);
1344     return appendTo;
1345 }
1346 
1347 
1348 
1349 UnicodeString&
_format(const DigitList & number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const1350 DecimalFormat::_format(const DigitList &number,
1351                         UnicodeString& appendTo,
1352                         FieldPositionHandler& handler,
1353                         UErrorCode &status) const
1354 {
1355     // Special case for NaN, sets the begin and end index to be the
1356     // the string length of localized name of NaN.
1357     if (number.isNaN())
1358     {
1359         int begin = appendTo.length();
1360         appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1361 
1362         handler.addAttribute(kIntegerField, begin, appendTo.length());
1363 
1364         addPadding(appendTo, handler, 0, 0);
1365         return appendTo;
1366     }
1367 
1368     // Do this BEFORE checking to see if value is infinite or negative! Sets the
1369     // begin and end index to be length of the string composed of
1370     // localized name of Infinite and the positive/negative localized
1371     // signs.
1372 
1373     DigitList adjustedNum(number);  // Copy, so we do not alter the original.
1374     adjustedNum.setRoundingMode(fRoundingMode);
1375     if (fMultiplier != NULL) {
1376         adjustedNum.mult(*fMultiplier, status);
1377     }
1378 
1379     /*
1380      * Note: sign is important for zero as well as non-zero numbers.
1381      * Proper detection of -0.0 is needed to deal with the
1382      * issues raised by bugs 4106658, 4106667, and 4147706.  Liu 7/6/98.
1383      */
1384     UBool isNegative = !adjustedNum.isPositive();
1385 
1386     // Apply rounding after multiplier
1387 
1388     adjustedNum.fContext.status &= ~DEC_Inexact;
1389     if (fRoundingIncrement != NULL) {
1390         adjustedNum.div(*fRoundingIncrement, status);
1391         adjustedNum.toIntegralValue();
1392         adjustedNum.mult(*fRoundingIncrement, status);
1393         adjustedNum.trim();
1394     }
1395     if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) {
1396         status = U_FORMAT_INEXACT_ERROR;
1397         return appendTo;
1398     }
1399 
1400 
1401     // Special case for INFINITE,
1402     if (adjustedNum.isInfinite()) {
1403         int32_t prefixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, TRUE);
1404 
1405         int begin = appendTo.length();
1406         appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
1407 
1408         handler.addAttribute(kIntegerField, begin, appendTo.length());
1409 
1410         int32_t suffixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, FALSE);
1411 
1412         addPadding(appendTo, handler, prefixLen, suffixLen);
1413         return appendTo;
1414     }
1415 
1416     if (fUseExponentialNotation || areSignificantDigitsUsed()) {
1417         int32_t sigDigits = precision();
1418         if (sigDigits > 0) {
1419             adjustedNum.round(sigDigits);
1420         }
1421     } else {
1422         // Fixed point format.  Round to a set number of fraction digits.
1423         int32_t numFractionDigits = precision();
1424         adjustedNum.roundFixedPoint(numFractionDigits);
1425     }
1426     if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) {
1427         status = U_FORMAT_INEXACT_ERROR;
1428         return appendTo;
1429     }
1430 
1431     return subformat(appendTo, handler, adjustedNum, FALSE, status);
1432 }
1433 
1434 
1435 UnicodeString&
format(const Formattable & obj,UnicodeString & appendTo,FieldPosition & fieldPosition,UErrorCode & status) const1436 DecimalFormat::format(  const Formattable& obj,
1437                         UnicodeString& appendTo,
1438                         FieldPosition& fieldPosition,
1439                         UErrorCode& status) const
1440 {
1441     return NumberFormat::format(obj, appendTo, fieldPosition, status);
1442 }
1443 
1444 /**
1445  * Return true if a grouping separator belongs at the given
1446  * position, based on whether grouping is in use and the values of
1447  * the primary and secondary grouping interval.
1448  * @param pos the number of integer digits to the right of
1449  * the current position.  Zero indicates the position after the
1450  * rightmost integer digit.
1451  * @return true if a grouping character belongs at the current
1452  * position.
1453  */
isGroupingPosition(int32_t pos) const1454 UBool DecimalFormat::isGroupingPosition(int32_t pos) const {
1455     UBool result = FALSE;
1456     if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) {
1457         if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) {
1458             result = ((pos - fGroupingSize) % fGroupingSize2) == 0;
1459         } else {
1460             result = pos % fGroupingSize == 0;
1461         }
1462     }
1463     return result;
1464 }
1465 
1466 //------------------------------------------------------------------------------
1467 
1468 /**
1469  * Complete the formatting of a finite number.  On entry, the DigitList must
1470  * be filled in with the correct digits.
1471  */
1472 UnicodeString&
subformat(UnicodeString & appendTo,FieldPositionHandler & handler,DigitList & digits,UBool isInteger,UErrorCode & status) const1473 DecimalFormat::subformat(UnicodeString& appendTo,
1474                          FieldPositionHandler& handler,
1475                          DigitList&     digits,
1476                          UBool          isInteger,
1477                          UErrorCode& status) const
1478 {
1479     // char zero = '0';
1480     // DigitList returns digits as '0' thru '9', so we will need to
1481     // always need to subtract the character 0 to get the numeric value to use for indexing.
1482 
1483     UChar32 localizedDigits[10];
1484     localizedDigits[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
1485     localizedDigits[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0);
1486     localizedDigits[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0);
1487     localizedDigits[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0);
1488     localizedDigits[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0);
1489     localizedDigits[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0);
1490     localizedDigits[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0);
1491     localizedDigits[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0);
1492     localizedDigits[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0);
1493     localizedDigits[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0);
1494 
1495     const UnicodeString *grouping ;
1496     if(fCurrencySignCount > fgCurrencySignCountZero) {
1497         grouping = &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
1498     }else{
1499         grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
1500     }
1501     const UnicodeString *decimal;
1502     if(fCurrencySignCount > fgCurrencySignCountZero) {
1503         decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1504     } else {
1505         decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1506     }
1507     UBool useSigDig = areSignificantDigitsUsed();
1508     int32_t maxIntDig = getMaximumIntegerDigits();
1509     int32_t minIntDig = getMinimumIntegerDigits();
1510 
1511     // Appends the prefix.
1512     double doubleValue = digits.getDouble();
1513     int32_t prefixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), TRUE);
1514 
1515     if (fUseExponentialNotation)
1516     {
1517         int currentLength = appendTo.length();
1518         int intBegin = currentLength;
1519         int intEnd = -1;
1520         int fracBegin = -1;
1521 
1522         int32_t minFracDig = 0;
1523         if (useSigDig) {
1524             maxIntDig = minIntDig = 1;
1525             minFracDig = getMinimumSignificantDigits() - 1;
1526         } else {
1527             minFracDig = getMinimumFractionDigits();
1528             if (maxIntDig > kMaxScientificIntegerDigits) {
1529                 maxIntDig = 1;
1530                 if (maxIntDig < minIntDig) {
1531                     maxIntDig = minIntDig;
1532                 }
1533             }
1534             if (maxIntDig > minIntDig) {
1535                 minIntDig = 1;
1536             }
1537         }
1538 
1539         // Minimum integer digits are handled in exponential format by
1540         // adjusting the exponent.  For example, 0.01234 with 3 minimum
1541         // integer digits is "123.4E-4".
1542 
1543         // Maximum integer digits are interpreted as indicating the
1544         // repeating range.  This is useful for engineering notation, in
1545         // which the exponent is restricted to a multiple of 3.  For
1546         // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1547         // If maximum integer digits are defined and are larger than
1548         // minimum integer digits, then minimum integer digits are
1549         // ignored.
1550         digits.reduce();   // Removes trailing zero digits.
1551         int32_t exponent = digits.getDecimalAt();
1552         if (maxIntDig > 1 && maxIntDig != minIntDig) {
1553             // A exponent increment is defined; adjust to it.
1554             exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
1555                                       : (exponent / maxIntDig) - 1;
1556             exponent *= maxIntDig;
1557         } else {
1558             // No exponent increment is defined; use minimum integer digits.
1559             // If none is specified, as in "#E0", generate 1 integer digit.
1560             exponent -= (minIntDig > 0 || minFracDig > 0)
1561                         ? minIntDig : 1;
1562         }
1563 
1564         // We now output a minimum number of digits, and more if there
1565         // are more digits, up to the maximum number of digits.  We
1566         // place the decimal point after the "integer" digits, which
1567         // are the first (decimalAt - exponent) digits.
1568         int32_t minimumDigits =  minIntDig + minFracDig;
1569         // The number of integer digits is handled specially if the number
1570         // is zero, since then there may be no digits.
1571         int32_t integerDigits = digits.isZero() ? minIntDig :
1572             digits.getDecimalAt() - exponent;
1573         int32_t totalDigits = digits.getCount();
1574         if (minimumDigits > totalDigits)
1575             totalDigits = minimumDigits;
1576         if (integerDigits > totalDigits)
1577             totalDigits = integerDigits;
1578 
1579         // totalDigits records total number of digits needs to be processed
1580         int32_t i;
1581         for (i=0; i<totalDigits; ++i)
1582         {
1583             if (i == integerDigits)
1584             {
1585                 intEnd = appendTo.length();
1586                 handler.addAttribute(kIntegerField, intBegin, intEnd);
1587 
1588                 appendTo += *decimal;
1589 
1590                 fracBegin = appendTo.length();
1591                 handler.addAttribute(kDecimalSeparatorField, fracBegin - 1, fracBegin);
1592             }
1593             // Restores the digit character or pads the buffer with zeros.
1594             UChar32 c = (UChar32)((i < digits.getCount()) ?
1595                           localizedDigits[digits.getDigitValue(i)] :
1596                           localizedDigits[0]);
1597             appendTo += c;
1598         }
1599 
1600         currentLength = appendTo.length();
1601 
1602         if (intEnd < 0) {
1603             handler.addAttribute(kIntegerField, intBegin, currentLength);
1604         }
1605         if (fracBegin > 0) {
1606             handler.addAttribute(kFractionField, fracBegin, currentLength);
1607         }
1608 
1609         // The exponent is output using the pattern-specified minimum
1610         // exponent digits.  There is no maximum limit to the exponent
1611         // digits, since truncating the exponent would appendTo in an
1612         // unacceptable inaccuracy.
1613         appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
1614 
1615         handler.addAttribute(kExponentSymbolField, currentLength, appendTo.length());
1616         currentLength = appendTo.length();
1617 
1618         // For zero values, we force the exponent to zero.  We
1619         // must do this here, and not earlier, because the value
1620         // is used to determine integer digit count above.
1621         if (digits.isZero())
1622             exponent = 0;
1623 
1624         if (exponent < 0) {
1625             appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1626             handler.addAttribute(kExponentSignField, currentLength, appendTo.length());
1627         } else if (fExponentSignAlwaysShown) {
1628             appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1629             handler.addAttribute(kExponentSignField, currentLength, appendTo.length());
1630         }
1631 
1632         currentLength = appendTo.length();
1633 
1634         DigitList expDigits;
1635         expDigits.set(exponent);
1636         {
1637             int expDig = fMinExponentDigits;
1638             if (fUseExponentialNotation && expDig < 1) {
1639                 expDig = 1;
1640             }
1641             for (i=expDigits.getDecimalAt(); i<expDig; ++i)
1642                 appendTo += (localizedDigits[0]);
1643         }
1644         for (i=0; i<expDigits.getDecimalAt(); ++i)
1645         {
1646             UChar32 c = (UChar32)((i < expDigits.getCount()) ?
1647                           localizedDigits[expDigits.getDigitValue(i)] :
1648                           localizedDigits[0]);
1649             appendTo += c;
1650         }
1651 
1652         handler.addAttribute(kExponentField, currentLength, appendTo.length());
1653     }
1654     else  // Not using exponential notation
1655     {
1656         int currentLength = appendTo.length();
1657         int intBegin = currentLength;
1658 
1659         int32_t sigCount = 0;
1660         int32_t minSigDig = getMinimumSignificantDigits();
1661         int32_t maxSigDig = getMaximumSignificantDigits();
1662         if (!useSigDig) {
1663             minSigDig = 0;
1664             maxSigDig = INT32_MAX;
1665         }
1666 
1667         // Output the integer portion.  Here 'count' is the total
1668         // number of integer digits we will display, including both
1669         // leading zeros required to satisfy getMinimumIntegerDigits,
1670         // and actual digits present in the number.
1671         int32_t count = useSigDig ?
1672             _max(1, digits.getDecimalAt()) : minIntDig;
1673         if (digits.getDecimalAt() > 0 && count < digits.getDecimalAt()) {
1674             count = digits.getDecimalAt();
1675         }
1676 
1677         // Handle the case where getMaximumIntegerDigits() is smaller
1678         // than the real number of integer digits.  If this is so, we
1679         // output the least significant max integer digits.  For example,
1680         // the value 1997 printed with 2 max integer digits is just "97".
1681 
1682         int32_t digitIndex = 0; // Index into digitList.fDigits[]
1683         if (count > maxIntDig && maxIntDig >= 0) {
1684             count = maxIntDig;
1685             digitIndex = digits.getDecimalAt() - count;
1686             if(fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) {
1687                 status = U_ILLEGAL_ARGUMENT_ERROR;
1688             }
1689         }
1690 
1691         int32_t sizeBeforeIntegerPart = appendTo.length();
1692 
1693         int32_t i;
1694         for (i=count-1; i>=0; --i)
1695         {
1696             if (i < digits.getDecimalAt() && digitIndex < digits.getCount() &&
1697                 sigCount < maxSigDig) {
1698                 // Output a real digit
1699                 appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)];
1700                 ++sigCount;
1701             }
1702             else
1703             {
1704                 // Output a zero (leading or trailing)
1705                 appendTo += localizedDigits[0];
1706                 if (sigCount > 0) {
1707                     ++sigCount;
1708                 }
1709             }
1710 
1711             // Output grouping separator if necessary.
1712             if (isGroupingPosition(i)) {
1713                 currentLength = appendTo.length();
1714                 appendTo.append(*grouping);
1715                 handler.addAttribute(kGroupingSeparatorField, currentLength, appendTo.length());
1716             }
1717         }
1718 
1719         // TODO(dlf): this looks like it was a bug, we marked the int field as ending
1720         // before the zero was generated.
1721         // Record field information for caller.
1722         // if (fieldPosition.getField() == NumberFormat::kIntegerField)
1723         //     fieldPosition.setEndIndex(appendTo.length());
1724 
1725         // Determine whether or not there are any printable fractional
1726         // digits.  If we've used up the digits we know there aren't.
1727         UBool fractionPresent = (!isInteger && digitIndex < digits.getCount()) ||
1728             (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
1729 
1730         // If there is no fraction present, and we haven't printed any
1731         // integer digits, then print a zero.  Otherwise we won't print
1732         // _any_ digits, and we won't be able to parse this string.
1733         if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart)
1734             appendTo += localizedDigits[0];
1735 
1736         currentLength = appendTo.length();
1737         handler.addAttribute(kIntegerField, intBegin, currentLength);
1738 
1739         // Output the decimal separator if we always do so.
1740         if (fDecimalSeparatorAlwaysShown || fractionPresent) {
1741             appendTo += *decimal;
1742             handler.addAttribute(kDecimalSeparatorField, currentLength, appendTo.length());
1743             currentLength = appendTo.length();
1744         }
1745 
1746         int fracBegin = currentLength;
1747 
1748         count = useSigDig ? INT32_MAX : getMaximumFractionDigits();
1749         if (useSigDig && (sigCount == maxSigDig ||
1750                           (sigCount >= minSigDig && digitIndex == digits.getCount()))) {
1751             count = 0;
1752         }
1753 
1754         for (i=0; i < count; ++i) {
1755             // Here is where we escape from the loop.  We escape
1756             // if we've output the maximum fraction digits
1757             // (specified in the for expression above).  We also
1758             // stop when we've output the minimum digits and
1759             // either: we have an integer, so there is no
1760             // fractional stuff to display, or we're out of
1761             // significant digits.
1762             if (!useSigDig && i >= getMinimumFractionDigits() &&
1763                 (isInteger || digitIndex >= digits.getCount())) {
1764                 break;
1765             }
1766 
1767             // Output leading fractional zeros.  These are zeros
1768             // that come after the decimal but before any
1769             // significant digits.  These are only output if
1770             // abs(number being formatted) < 1.0.
1771             if (-1-i > (digits.getDecimalAt()-1)) {
1772                 appendTo += localizedDigits[0];
1773                 continue;
1774             }
1775 
1776             // Output a digit, if we have any precision left, or a
1777             // zero if we don't.  We don't want to output noise digits.
1778             if (!isInteger && digitIndex < digits.getCount()) {
1779                 appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)];
1780             } else {
1781                 appendTo += localizedDigits[0];
1782             }
1783 
1784             // If we reach the maximum number of significant
1785             // digits, or if we output all the real digits and
1786             // reach the minimum, then we are done.
1787             ++sigCount;
1788             if (useSigDig &&
1789                 (sigCount == maxSigDig ||
1790                  (digitIndex == digits.getCount() && sigCount >= minSigDig))) {
1791                 break;
1792             }
1793         }
1794 
1795         handler.addAttribute(kFractionField, fracBegin, appendTo.length());
1796     }
1797 
1798     int32_t suffixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), FALSE);
1799 
1800     addPadding(appendTo, handler, prefixLen, suffixLen);
1801     return appendTo;
1802 }
1803 
1804 /**
1805  * Inserts the character fPad as needed to expand result to fFormatWidth.
1806  * @param result the string to be padded
1807  */
addPadding(UnicodeString & appendTo,FieldPositionHandler & handler,int32_t prefixLen,int32_t suffixLen) const1808 void DecimalFormat::addPadding(UnicodeString& appendTo,
1809                                FieldPositionHandler& handler,
1810                                int32_t prefixLen,
1811                                int32_t suffixLen) const
1812 {
1813     if (fFormatWidth > 0) {
1814         int32_t len = fFormatWidth - appendTo.length();
1815         if (len > 0) {
1816             UnicodeString padding;
1817             for (int32_t i=0; i<len; ++i) {
1818                 padding += fPad;
1819             }
1820             switch (fPadPosition) {
1821             case kPadAfterPrefix:
1822                 appendTo.insert(prefixLen, padding);
1823                 break;
1824             case kPadBeforePrefix:
1825                 appendTo.insert(0, padding);
1826                 break;
1827             case kPadBeforeSuffix:
1828                 appendTo.insert(appendTo.length() - suffixLen, padding);
1829                 break;
1830             case kPadAfterSuffix:
1831                 appendTo += padding;
1832                 break;
1833             }
1834             if (fPadPosition == kPadBeforePrefix || fPadPosition == kPadAfterPrefix) {
1835                 handler.shiftLast(len);
1836             }
1837         }
1838     }
1839 }
1840 
1841 //------------------------------------------------------------------------------
1842 
1843 void
parse(const UnicodeString & text,Formattable & result,UErrorCode & status) const1844 DecimalFormat::parse(const UnicodeString& text,
1845                      Formattable& result,
1846                      UErrorCode& status) const
1847 {
1848     NumberFormat::parse(text, result, status);
1849 }
1850 
1851 void
parse(const UnicodeString & text,Formattable & result,ParsePosition & parsePosition) const1852 DecimalFormat::parse(const UnicodeString& text,
1853                      Formattable& result,
1854                      ParsePosition& parsePosition) const {
1855     parse(text, result, parsePosition, NULL);
1856 }
1857 
parseCurrency(const UnicodeString & text,ParsePosition & pos) const1858 CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
1859                                              ParsePosition& pos) const {
1860     Formattable parseResult;
1861     int32_t start = pos.getIndex();
1862     UChar curbuf[4];
1863     parse(text, parseResult, pos, curbuf);
1864     if (pos.getIndex() != start) {
1865         UErrorCode ec = U_ZERO_ERROR;
1866         LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec));
1867         if (U_FAILURE(ec)) {
1868             pos.setIndex(start); // indicate failure
1869         } else {
1870             return currAmt.orphan();
1871         }
1872     }
1873     return NULL;
1874 }
1875 
1876 /**
1877  * Parses the given text as a number, optionally providing a currency amount.
1878  * @param text the string to parse
1879  * @param result output parameter for the numeric result.
1880  * @param parsePosition input-output position; on input, the
1881  * position within text to match; must have 0 <= pos.getIndex() <
1882  * text.length(); on output, the position after the last matched
1883  * character. If the parse fails, the position in unchanged upon
1884  * output.
1885  * @param currency if non-NULL, it should point to a 4-UChar buffer.
1886  * In this case the text is parsed as a currency format, and the
1887  * ISO 4217 code for the parsed currency is put into the buffer.
1888  * Otherwise the text is parsed as a non-currency format.
1889  */
parse(const UnicodeString & text,Formattable & result,ParsePosition & parsePosition,UChar * currency) const1890 void DecimalFormat::parse(const UnicodeString& text,
1891                           Formattable& result,
1892                           ParsePosition& parsePosition,
1893                           UChar* currency) const {
1894     int32_t startIdx, backup;
1895     int32_t i = startIdx = backup = parsePosition.getIndex();
1896 
1897     // clear any old contents in the result.  In particular, clears any DigitList
1898     //   that it may be holding.
1899     result.setLong(0);
1900 
1901     // Handle NaN as a special case:
1902 
1903     // Skip padding characters, if around prefix
1904     if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix ||
1905                              fPadPosition == kPadAfterPrefix)) {
1906         i = skipPadding(text, i);
1907     }
1908 
1909     if (isLenient()) {
1910         // skip any leading whitespace
1911         i = backup = skipUWhiteSpace(text, i);
1912     }
1913 
1914     // If the text is composed of the representation of NaN, returns NaN.length
1915     const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1916     int32_t nanLen = (text.compare(i, nan->length(), *nan)
1917                       ? 0 : nan->length());
1918     if (nanLen) {
1919         i += nanLen;
1920         if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix ||
1921                                  fPadPosition == kPadAfterSuffix)) {
1922             i = skipPadding(text, i);
1923         }
1924         parsePosition.setIndex(i);
1925         result.setDouble(uprv_getNaN());
1926         return;
1927     }
1928 
1929     // NaN parse failed; start over
1930     i = backup;
1931     parsePosition.setIndex(i);
1932 
1933     // status is used to record whether a number is infinite.
1934     UBool status[fgStatusLength];
1935 
1936     DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
1937     if (digits == NULL) {
1938         return;    // no way to report error from here.
1939     }
1940 
1941     if (fCurrencySignCount > fgCurrencySignCountZero) {
1942         if (!parseForCurrency(text, parsePosition, *digits,
1943                               status, currency)) {
1944           return;
1945         }
1946     } else {
1947         if (!subparse(text,
1948                       fNegPrefixPattern, fNegSuffixPattern,
1949                       fPosPrefixPattern, fPosSuffixPattern,
1950                       FALSE, UCURR_SYMBOL_NAME,
1951                       parsePosition, *digits, status, currency)) {
1952             debug("!subparse(...) - rewind");
1953             parsePosition.setIndex(startIdx);
1954             return;
1955         }
1956     }
1957 
1958     // Handle infinity
1959     if (status[fgStatusInfinite]) {
1960         double inf = uprv_getInfinity();
1961         result.setDouble(digits->isPositive() ? inf : -inf);
1962         // TODO:  set the dl to infinity, and let it fall into the code below.
1963     }
1964 
1965     else {
1966 
1967         if (fMultiplier != NULL) {
1968             UErrorCode ec = U_ZERO_ERROR;
1969             digits->div(*fMultiplier, ec);
1970         }
1971 
1972         // Negative zero special case:
1973         //    if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1974         //    if not parsing integerOnly, leave as -0, which a double can represent.
1975         if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) {
1976             digits->setPositive(TRUE);
1977         }
1978         result.adoptDigitList(digits);
1979     }
1980 }
1981 
1982 
1983 
1984 UBool
parseForCurrency(const UnicodeString & text,ParsePosition & parsePosition,DigitList & digits,UBool * status,UChar * currency) const1985 DecimalFormat::parseForCurrency(const UnicodeString& text,
1986                                 ParsePosition& parsePosition,
1987                                 DigitList& digits,
1988                                 UBool* status,
1989                                 UChar* currency) const {
1990     int origPos = parsePosition.getIndex();
1991     int maxPosIndex = origPos;
1992     int maxErrorPos = -1;
1993     // First, parse against current pattern.
1994     // Since current pattern could be set by applyPattern(),
1995     // it could be an arbitrary pattern, and it may not be the one
1996     // defined in current locale.
1997     UBool tmpStatus[fgStatusLength];
1998     ParsePosition tmpPos(origPos);
1999     DigitList tmpDigitList;
2000     UBool found;
2001     if (fStyle == UNUM_CURRENCY_PLURAL) {
2002         found = subparse(text,
2003                          fNegPrefixPattern, fNegSuffixPattern,
2004                          fPosPrefixPattern, fPosSuffixPattern,
2005                          TRUE, UCURR_LONG_NAME,
2006                          tmpPos, tmpDigitList, tmpStatus, currency);
2007     } else {
2008         found = subparse(text,
2009                          fNegPrefixPattern, fNegSuffixPattern,
2010                          fPosPrefixPattern, fPosSuffixPattern,
2011                          TRUE, UCURR_SYMBOL_NAME,
2012                          tmpPos, tmpDigitList, tmpStatus, currency);
2013     }
2014     if (found) {
2015         if (tmpPos.getIndex() > maxPosIndex) {
2016             maxPosIndex = tmpPos.getIndex();
2017             for (int32_t i = 0; i < fgStatusLength; ++i) {
2018                 status[i] = tmpStatus[i];
2019             }
2020             digits = tmpDigitList;
2021         }
2022     } else {
2023         maxErrorPos = tmpPos.getErrorIndex();
2024     }
2025     // Then, parse against affix patterns.
2026     // Those are currency patterns and currency plural patterns.
2027     int32_t pos = -1;
2028     const UHashElement* element = NULL;
2029     while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
2030         const UHashTok valueTok = element->value;
2031         const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer;
2032         UBool tmpStatus[fgStatusLength];
2033         ParsePosition tmpPos(origPos);
2034         DigitList tmpDigitList;
2035         UBool result = subparse(text,
2036                                 &affixPtn->negPrefixPatternForCurrency,
2037                                 &affixPtn->negSuffixPatternForCurrency,
2038                                 &affixPtn->posPrefixPatternForCurrency,
2039                                 &affixPtn->posSuffixPatternForCurrency,
2040                                 TRUE, affixPtn->patternType,
2041                                 tmpPos, tmpDigitList, tmpStatus, currency);
2042         if (result) {
2043             found = true;
2044             if (tmpPos.getIndex() > maxPosIndex) {
2045                 maxPosIndex = tmpPos.getIndex();
2046                 for (int32_t i = 0; i < fgStatusLength; ++i) {
2047                     status[i] = tmpStatus[i];
2048                 }
2049                 digits = tmpDigitList;
2050             }
2051         } else {
2052             maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
2053                           tmpPos.getErrorIndex() : maxErrorPos;
2054         }
2055     }
2056     // Finally, parse against simple affix to find the match.
2057     // For example, in TestMonster suite,
2058     // if the to-be-parsed text is "-\u00A40,00".
2059     // complexAffixCompare will not find match,
2060     // since there is no ISO code matches "\u00A4",
2061     // and the parse stops at "\u00A4".
2062     // We will just use simple affix comparison (look for exact match)
2063     // to pass it.
2064     UBool tmpStatus_2[fgStatusLength];
2065     ParsePosition tmpPos_2(origPos);
2066     DigitList tmpDigitList_2;
2067     // set currencySignCount to 0 so that compareAffix function will
2068     // fall to compareSimpleAffix path, not compareComplexAffix path.
2069     // ?? TODO: is it right? need "false"?
2070     UBool result = subparse(text,
2071                             &fNegativePrefix, &fNegativeSuffix,
2072                             &fPositivePrefix, &fPositiveSuffix,
2073                             FALSE, UCURR_SYMBOL_NAME,
2074                             tmpPos_2, tmpDigitList_2, tmpStatus_2,
2075                             currency);
2076     if (result) {
2077         if (tmpPos_2.getIndex() > maxPosIndex) {
2078             maxPosIndex = tmpPos_2.getIndex();
2079             for (int32_t i = 0; i < fgStatusLength; ++i) {
2080                 status[i] = tmpStatus_2[i];
2081             }
2082             digits = tmpDigitList_2;
2083         }
2084         found = true;
2085     } else {
2086             maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ?
2087                           tmpPos_2.getErrorIndex() : maxErrorPos;
2088     }
2089 
2090     if (!found) {
2091         //parsePosition.setIndex(origPos);
2092         parsePosition.setErrorIndex(maxErrorPos);
2093     } else {
2094         parsePosition.setIndex(maxPosIndex);
2095         parsePosition.setErrorIndex(-1);
2096     }
2097     return found;
2098 }
2099 
2100 
2101 /**
2102  * Parse the given text into a number.  The text is parsed beginning at
2103  * parsePosition, until an unparseable character is seen.
2104  * @param text the string to parse.
2105  * @param negPrefix negative prefix.
2106  * @param negSuffix negative suffix.
2107  * @param posPrefix positive prefix.
2108  * @param posSuffix positive suffix.
2109  * @param currencyParsing whether it is currency parsing or not.
2110  * @param type the currency type to parse against, LONG_NAME only or not.
2111  * @param parsePosition The position at which to being parsing.  Upon
2112  * return, the first unparsed character.
2113  * @param digits the DigitList to set to the parsed value.
2114  * @param status output param containing boolean status flags indicating
2115  * whether the value was infinite and whether it was positive.
2116  * @param currency return value for parsed currency, for generic
2117  * currency parsing mode, or NULL for normal parsing. In generic
2118  * currency parsing mode, any currency is parsed, not just the
2119  * currency that this formatter is set to.
2120  */
subparse(const UnicodeString & text,const UnicodeString * negPrefix,const UnicodeString * negSuffix,const UnicodeString * posPrefix,const UnicodeString * posSuffix,UBool currencyParsing,int8_t type,ParsePosition & parsePosition,DigitList & digits,UBool * status,UChar * currency) const2121 UBool DecimalFormat::subparse(const UnicodeString& text,
2122                               const UnicodeString* negPrefix,
2123                               const UnicodeString* negSuffix,
2124                               const UnicodeString* posPrefix,
2125                               const UnicodeString* posSuffix,
2126                               UBool currencyParsing,
2127                               int8_t type,
2128                               ParsePosition& parsePosition,
2129                               DigitList& digits, UBool* status,
2130                               UChar* currency) const
2131 {
2132     //  The parsing process builds up the number as char string, in the neutral format that
2133     //  will be acceptable to the decNumber library, then at the end passes that string
2134     //  off for conversion to a decNumber.
2135     UErrorCode err = U_ZERO_ERROR;
2136     CharString parsedNum;
2137     digits.setToZero();
2138 
2139     int32_t position = parsePosition.getIndex();
2140     int32_t oldStart = position;
2141     int32_t textLength = text.length(); // One less pointer to follow
2142     UBool strictParse = !isLenient();
2143     UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
2144     const UnicodeString *groupingString = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
2145     UChar32 groupingChar = groupingString->char32At(0);
2146     int32_t groupingStringLength = groupingString->length();
2147     int32_t groupingCharLength   = U16_LENGTH(groupingChar);
2148     UBool   groupingUsed = isGroupingUsed();
2149 #ifdef FMT_DEBUG
2150     UChar dbgbuf[300];
2151     UnicodeString s(dbgbuf,0,300);;
2152     s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " );
2153 #define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "="));  if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeString(" ")); } else { s.append(UnicodeString(#x "=NULL ")); }
2154     DBGAPPD(negPrefix);
2155     DBGAPPD(negSuffix);
2156     DBGAPPD(posPrefix);
2157     DBGAPPD(posSuffix);
2158     debugout(s);
2159     printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, (isParseIntegerOnly())?'Y':'N', text.length(),  negPrefix!=NULL?negPrefix->length():-1);
2160 #endif
2161 
2162     UBool fastParseOk = false; /* TRUE iff fast parse is OK */
2163     UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
2164     const DecimalFormatInternal &data = internalData(fReserved);
2165     if((data.fFastParseStatus==kFastpathYES) &&
2166        !currencyParsing &&
2167        //       (negPrefix!=NULL&&negPrefix->isEmpty()) ||
2168        text.length()>0 &&
2169        text.length()<32 &&
2170        (posPrefix==NULL||posPrefix->isEmpty()) &&
2171        (posSuffix==NULL||posSuffix->isEmpty()) &&
2172        //            (negPrefix==NULL||negPrefix->isEmpty()) &&
2173        //            (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
2174        TRUE) {  // optimized path
2175       int j=position;
2176       int l=text.length();
2177       int digitCount=0;
2178       UChar32 ch = text.char32At(j);
2179       const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
2180       UChar32 decimalChar = 0;
2181       UBool intOnly = FALSE;
2182       UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0;
2183 
2184       int32_t decimalCount = decimalString->countChar32(0,3);
2185       if(isParseIntegerOnly()) {
2186         decimalChar = 0; // not allowed
2187         intOnly = TRUE; // Don't look for decimals.
2188       } else if(decimalCount==1) {
2189         decimalChar = decimalString->char32At(0); // Look for this decimal
2190       } else if(decimalCount==0) {
2191         decimalChar=0; // NO decimal set
2192       } else {
2193         j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation.
2194       }
2195 
2196 #ifdef FMT_DEBUG
2197       printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
2198         decimalChar, groupingChar, ch,
2199         (intOnly)?'y':'n',
2200         (strictParse)?'y':'n');
2201 #endif
2202       if(ch==0x002D) { // '-'
2203         j=l+1;//=break - negative number.
2204 
2205         /*
2206           parsedNum.append('-',err);
2207           j+=U16_LENGTH(ch);
2208           if(j<l) ch = text.char32At(j);
2209         */
2210       } else {
2211         parsedNum.append('+',err);
2212       }
2213       while(j<l) {
2214         int32_t digit = ch - zero;
2215         if(digit >=0 && digit <= 9) {
2216           parsedNum.append((char)(digit + '0'), err);
2217           if((digitCount>0) || digit!=0 || j==(l-1)) {
2218             digitCount++;
2219           }
2220         } else if(ch == 0) { // break out
2221           digitCount=-1;
2222           break;
2223         } else if(ch == decimalChar) {
2224           parsedNum.append((char)('.'), err);
2225           decimalChar=0; // no more decimals.
2226           fastParseHadDecimal=TRUE;
2227         } else if(ch == lookForGroup) {
2228           // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
2229         } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) {
2230           // parsing integer only and can fall through
2231         } else {
2232           digitCount=-1; // fail - fall through to slow parse
2233           break;
2234         }
2235         j+=U16_LENGTH(ch);
2236         ch = text.char32At(j); // for next
2237       }
2238       if(
2239          ((j==l)||intOnly) // end OR only parsing integer
2240          && (digitCount>0)) { // and have at least one digit
2241 #ifdef FMT_DEBUG
2242         printf("PP -> %d, good = [%s]  digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2);
2243 #endif
2244         fastParseOk=true; // Fast parse OK!
2245 
2246 #ifdef SKIP_OPT
2247         debug("SKIP_OPT");
2248         /* for testing, try it the slow way. also */
2249         fastParseOk=false;
2250         parsedNum.clear();
2251 #else
2252         parsePosition.setIndex(position=j);
2253         status[fgStatusInfinite]=false;
2254 #endif
2255       } else {
2256         // was not OK. reset, retry
2257 #ifdef FMT_DEBUG
2258         printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount);
2259 #endif
2260         parsedNum.clear();
2261       }
2262     } else {
2263 #ifdef FMT_DEBUG
2264       printf("Could not fastpath parse. ");
2265       printf("fFormatWidth=%d ", fFormatWidth);
2266       printf("text.length()=%d ", text.length());
2267       printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
2268 
2269       printf("\n");
2270 #endif
2271     }
2272 
2273   if(!fastParseOk
2274 #if UCONFIG_HAVE_PARSEALLINPUT
2275      && fParseAllInput!=UNUM_YES
2276 #endif
2277      )
2278   {
2279     // Match padding before prefix
2280     if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) {
2281         position = skipPadding(text, position);
2282     }
2283 
2284     // Match positive and negative prefixes; prefer longest match.
2285     int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, currencyParsing, type, currency);
2286     int32_t negMatch = compareAffix(text, position, TRUE,  TRUE, negPrefix, currencyParsing, type, currency);
2287     if (posMatch >= 0 && negMatch >= 0) {
2288         if (posMatch > negMatch) {
2289             negMatch = -1;
2290         } else if (negMatch > posMatch) {
2291             posMatch = -1;
2292         }
2293     }
2294     if (posMatch >= 0) {
2295         position += posMatch;
2296         parsedNum.append('+', err);
2297     } else if (negMatch >= 0) {
2298         position += negMatch;
2299         parsedNum.append('-', err);
2300     } else if (strictParse){
2301         parsePosition.setErrorIndex(position);
2302         return FALSE;
2303     } else {
2304         // Temporary set positive. This might be changed after checking suffix
2305         parsedNum.append('+', err);
2306     }
2307 
2308     // Match padding before prefix
2309     if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) {
2310         position = skipPadding(text, position);
2311     }
2312 
2313     if (! strictParse) {
2314         position = skipUWhiteSpace(text, position);
2315     }
2316 
2317     // process digits or Inf, find decimal position
2318     const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
2319     int32_t infLen = (text.compare(position, inf->length(), *inf)
2320         ? 0 : inf->length());
2321     position += infLen; // infLen is non-zero when it does equal to infinity
2322     status[fgStatusInfinite] = infLen != 0;
2323 
2324     if (infLen != 0) {
2325         parsedNum.append("Infinity", err);
2326     } else {
2327         // We now have a string of digits, possibly with grouping symbols,
2328         // and decimal points.  We want to process these into a DigitList.
2329         // We don't want to put a bunch of leading zeros into the DigitList
2330         // though, so we keep track of the location of the decimal point,
2331         // put only significant digits into the DigitList, and adjust the
2332         // exponent as needed.
2333 
2334 
2335         UBool strictFail = FALSE; // did we exit with a strict parse failure?
2336         int32_t lastGroup = -1; // where did we last see a grouping separator?
2337         int32_t digitStart = position;
2338         int32_t gs2 = fGroupingSize2 == 0 ? fGroupingSize : fGroupingSize2;
2339 
2340         const UnicodeString *decimalString;
2341         if (fCurrencySignCount > fgCurrencySignCountZero) {
2342             decimalString = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
2343         } else {
2344             decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
2345         }
2346         UChar32 decimalChar = decimalString->char32At(0);
2347         int32_t decimalStringLength = decimalString->length();
2348         int32_t decimalCharLength   = U16_LENGTH(decimalChar);
2349 
2350         UBool sawDecimal = FALSE;
2351         UChar32 sawDecimalChar = 0xFFFF;
2352         UBool sawGrouping = FALSE;
2353         UChar32 sawGroupingChar = 0xFFFF;
2354         UBool sawDigit = FALSE;
2355         int32_t backup = -1;
2356         int32_t digit;
2357 
2358         // equivalent grouping and decimal support
2359         const UnicodeSet *decimalSet = NULL;
2360         const UnicodeSet *groupingSet = NULL;
2361 
2362         if (decimalCharLength == decimalStringLength) {
2363             decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse);
2364         }
2365 
2366         if (groupingCharLength == groupingStringLength) {
2367             if (strictParse) {
2368                 groupingSet = DecimalFormatStaticSets::gStaticSets->fStrictDefaultGroupingSeparators;
2369             } else {
2370                 groupingSet = DecimalFormatStaticSets::gStaticSets->fDefaultGroupingSeparators;
2371             }
2372         }
2373 
2374         // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
2375         // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
2376         // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
2377 
2378         // We have to track digitCount ourselves, because digits.fCount will
2379         // pin when the maximum allowable digits is reached.
2380         int32_t digitCount = 0;
2381         int32_t integerDigitCount = 0;
2382 
2383         for (; position < textLength; )
2384         {
2385             UChar32 ch = text.char32At(position);
2386 
2387             /* We recognize all digit ranges, not only the Latin digit range
2388              * '0'..'9'.  We do so by using the Character.digit() method,
2389              * which converts a valid Unicode digit to the range 0..9.
2390              *
2391              * The character 'ch' may be a digit.  If so, place its value
2392              * from 0 to 9 in 'digit'.  First try using the locale digit,
2393              * which may or MAY NOT be a standard Unicode digit range.  If
2394              * this fails, try using the standard Unicode digit ranges by
2395              * calling Character.digit().  If this also fails, digit will
2396              * have a value outside the range 0..9.
2397              */
2398             digit = ch - zero;
2399             if (digit < 0 || digit > 9)
2400             {
2401                 digit = u_charDigitValue(ch);
2402             }
2403 
2404             // As a last resort, look through the localized digits if the zero digit
2405             // is not a "standard" Unicode digit.
2406             if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) {
2407                 digit = 0;
2408                 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) {
2409                     break;
2410                 }
2411                 for (digit = 1 ; digit < 10 ; digit++ ) {
2412                     if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
2413                         break;
2414                     }
2415                 }
2416             }
2417 
2418             if (digit >= 0 && digit <= 9)
2419             {
2420                 if (strictParse && backup != -1) {
2421                     // comma followed by digit, so group before comma is a
2422                     // secondary group.  If there was a group separator
2423                     // before that, the group must == the secondary group
2424                     // length, else it can be <= the the secondary group
2425                     // length.
2426                     if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
2427                         (lastGroup == -1 && position - digitStart - 1 > gs2)) {
2428                         strictFail = TRUE;
2429                         break;
2430                     }
2431 
2432                     lastGroup = backup;
2433                 }
2434 
2435                 // Cancel out backup setting (see grouping handler below)
2436                 backup = -1;
2437                 sawDigit = TRUE;
2438 
2439                 // Note: this will append leading zeros
2440                 parsedNum.append((char)(digit + '0'), err);
2441 
2442                 // count any digit that's not a leading zero
2443                 if (digit > 0 || digitCount > 0 || sawDecimal) {
2444                     digitCount += 1;
2445 
2446                     // count any integer digit that's not a leading zero
2447                     if (! sawDecimal) {
2448                         integerDigitCount += 1;
2449                     }
2450                 }
2451 
2452                 position += U16_LENGTH(ch);
2453             }
2454             else if (groupingStringLength > 0 &&
2455                 matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet,
2456                             decimalChar, decimalSet,
2457                             ch) && groupingUsed)
2458             {
2459                 if (sawDecimal) {
2460                     break;
2461                 }
2462 
2463                 if (strictParse) {
2464                     if ((!sawDigit || backup != -1)) {
2465                         // leading group, or two group separators in a row
2466                         strictFail = TRUE;
2467                         break;
2468                     }
2469                 }
2470 
2471                 // Ignore grouping characters, if we are using them, but require
2472                 // that they be followed by a digit.  Otherwise we backup and
2473                 // reprocess them.
2474                 backup = position;
2475                 position += groupingStringLength;
2476                 sawGrouping=TRUE;
2477                 // Once we see a grouping character, we only accept that grouping character from then on.
2478                 sawGroupingChar=ch;
2479             }
2480             else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch))
2481             {
2482                 if (strictParse) {
2483                     if (backup != -1 ||
2484                         (lastGroup != -1 && position - lastGroup != fGroupingSize + 1)) {
2485                         strictFail = TRUE;
2486                         break;
2487                     }
2488                 }
2489 
2490                 // If we're only parsing integers, or if we ALREADY saw the
2491                 // decimal, then don't parse this one.
2492                 if (isParseIntegerOnly() || sawDecimal) {
2493                     break;
2494                 }
2495 
2496                 parsedNum.append('.', err);
2497                 position += decimalStringLength;
2498                 sawDecimal = TRUE;
2499                 // Once we see a decimal character, we only accept that decimal character from then on.
2500                 sawDecimalChar=ch;
2501                 // decimalSet is considered to consist of (ch,ch)
2502             }
2503             else {
2504 
2505                 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless..
2506                     fUseExponentialNotation /* should be:  isScientificNotation() but it is not const (?!) see bug #9619 */) { // .. it's an exponent format - ignore setting and parse anyways
2507                     const UnicodeString *tmp;
2508                     tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
2509                     // TODO: CASE
2510                     if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT))    // error code is set below if !sawDigit
2511                     {
2512                         // Parse sign, if present
2513                         int32_t pos = position + tmp->length();
2514                         char exponentSign = '+';
2515 
2516                         if (pos < textLength)
2517                         {
2518                             tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2519                             if (!text.compare(pos, tmp->length(), *tmp))
2520                             {
2521                                 pos += tmp->length();
2522                             }
2523                             else {
2524                                 tmp = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2525                                 if (!text.compare(pos, tmp->length(), *tmp))
2526                                 {
2527                                     exponentSign = '-';
2528                                     pos += tmp->length();
2529                                 }
2530                             }
2531                         }
2532 
2533                         UBool sawExponentDigit = FALSE;
2534                         while (pos < textLength) {
2535                             ch = text[(int32_t)pos];
2536                             digit = ch - zero;
2537 
2538                             if (digit < 0 || digit > 9) {
2539                                 digit = u_charDigitValue(ch);
2540                             }
2541                             if (0 <= digit && digit <= 9) {
2542                                 if (!sawExponentDigit) {
2543                                     parsedNum.append('E', err);
2544                                     parsedNum.append(exponentSign, err);
2545                                     sawExponentDigit = TRUE;
2546                                 }
2547                                 ++pos;
2548                                 parsedNum.append((char)(digit + '0'), err);
2549                             } else {
2550                                 break;
2551                             }
2552                         }
2553 
2554                         if (sawExponentDigit) {
2555                             position = pos; // Advance past the exponent
2556                         }
2557 
2558                         break; // Whether we fail or succeed, we exit this loop
2559                     } else {
2560                         break;
2561                     }
2562                 } else { // not parsing exponent
2563                     break;
2564               }
2565             }
2566         }
2567 
2568         if (backup != -1)
2569         {
2570             position = backup;
2571         }
2572 
2573         if (strictParse && !sawDecimal) {
2574             if (lastGroup != -1 && position - lastGroup != fGroupingSize + 1) {
2575                 strictFail = TRUE;
2576             }
2577         }
2578 
2579         if (strictFail) {
2580             // only set with strictParse and a grouping separator error
2581 
2582             parsePosition.setIndex(oldStart);
2583             parsePosition.setErrorIndex(position);
2584             debug("strictFail!");
2585             return FALSE;
2586         }
2587 
2588         // If there was no decimal point we have an integer
2589 
2590         // If none of the text string was recognized.  For example, parse
2591         // "x" with pattern "#0.00" (return index and error index both 0)
2592         // parse "$" with pattern "$#0.00". (return index 0 and error index
2593         // 1).
2594         if (!sawDigit && digitCount == 0) {
2595 #ifdef FMT_DEBUG
2596             debug("none of text rec");
2597             printf("position=%d\n",position);
2598 #endif
2599             parsePosition.setIndex(oldStart);
2600             parsePosition.setErrorIndex(oldStart);
2601             return FALSE;
2602         }
2603     }
2604 
2605     // Match padding before suffix
2606     if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) {
2607         position = skipPadding(text, position);
2608     }
2609 
2610     int32_t posSuffixMatch = -1, negSuffixMatch = -1;
2611 
2612     // Match positive and negative suffixes; prefer longest match.
2613     if (posMatch >= 0 || (!strictParse && negMatch < 0)) {
2614         posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, currencyParsing, type, currency);
2615     }
2616     if (negMatch >= 0) {
2617         negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, currencyParsing, type, currency);
2618     }
2619     if (posSuffixMatch >= 0 && negSuffixMatch >= 0) {
2620         if (posSuffixMatch > negSuffixMatch) {
2621             negSuffixMatch = -1;
2622         } else if (negSuffixMatch > posSuffixMatch) {
2623             posSuffixMatch = -1;
2624         }
2625     }
2626 
2627     // Fail if neither or both
2628     if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) {
2629         parsePosition.setErrorIndex(position);
2630         debug("neither or both");
2631         return FALSE;
2632     }
2633 
2634     position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0));
2635 
2636     // Match padding before suffix
2637     if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) {
2638         position = skipPadding(text, position);
2639     }
2640 
2641     parsePosition.setIndex(position);
2642 
2643     parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-';
2644 #ifdef FMT_DEBUG
2645 printf("PP -> %d, SLOW = [%s]!    pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err));
2646 #endif
2647   } /* end SLOW parse */
2648   if(parsePosition.getIndex() == oldStart)
2649     {
2650 #ifdef FMT_DEBUG
2651       printf(" PP didnt move, err\n");
2652 #endif
2653         parsePosition.setErrorIndex(position);
2654         return FALSE;
2655     }
2656 #if UCONFIG_HAVE_PARSEALLINPUT
2657   else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength)
2658     {
2659 #ifdef FMT_DEBUG
2660       printf(" PP didnt consume all (UNUM_YES), err\n");
2661 #endif
2662         parsePosition.setErrorIndex(position);
2663         return FALSE;
2664     }
2665 #endif
2666     // uint32_t bits = (fastParseOk?kFastpathOk:0) |
2667     //   (fastParseHadDecimal?0:kNoDecimal);
2668     //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
2669     digits.set(parsedNum.toStringPiece(),
2670                err,
2671                0//bits
2672                );
2673 
2674     if (U_FAILURE(err)) {
2675 #ifdef FMT_DEBUG
2676       printf(" err setting %s\n", u_errorName(err));
2677 #endif
2678         parsePosition.setErrorIndex(position);
2679         return FALSE;
2680     }
2681     return TRUE;
2682 }
2683 
2684 /**
2685  * Starting at position, advance past a run of pad characters, if any.
2686  * Return the index of the first character after position that is not a pad
2687  * character.  Result is >= position.
2688  */
skipPadding(const UnicodeString & text,int32_t position) const2689 int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
2690     int32_t padLen = U16_LENGTH(fPad);
2691     while (position < text.length() &&
2692            text.char32At(position) == fPad) {
2693         position += padLen;
2694     }
2695     return position;
2696 }
2697 
2698 /**
2699  * Return the length matched by the given affix, or -1 if none.
2700  * Runs of white space in the affix, match runs of white space in
2701  * the input.  Pattern white space and input white space are
2702  * determined differently; see code.
2703  * @param text input text
2704  * @param pos offset into input at which to begin matching
2705  * @param isNegative
2706  * @param isPrefix
2707  * @param affixPat affix pattern used for currency affix comparison.
2708  * @param currencyParsing whether it is currency parsing or not
2709  * @param type the currency type to parse against, LONG_NAME only or not.
2710  * @param currency return value for parsed currency, for generic
2711  * currency parsing mode, or null for normal parsing. In generic
2712  * currency parsing mode, any currency is parsed, not just the
2713  * currency that this formatter is set to.
2714  * @return length of input that matches, or -1 if match failure
2715  */
compareAffix(const UnicodeString & text,int32_t pos,UBool isNegative,UBool isPrefix,const UnicodeString * affixPat,UBool currencyParsing,int8_t type,UChar * currency) const2716 int32_t DecimalFormat::compareAffix(const UnicodeString& text,
2717                                     int32_t pos,
2718                                     UBool isNegative,
2719                                     UBool isPrefix,
2720                                     const UnicodeString* affixPat,
2721                                     UBool currencyParsing,
2722                                     int8_t type,
2723                                     UChar* currency) const
2724 {
2725     const UnicodeString *patternToCompare;
2726     if (fCurrencyChoice != NULL || currency != NULL ||
2727         (fCurrencySignCount > fgCurrencySignCountZero && currencyParsing)) {
2728 
2729         if (affixPat != NULL) {
2730             return compareComplexAffix(*affixPat, text, pos, type, currency);
2731         }
2732     }
2733 
2734     if (isNegative) {
2735         if (isPrefix) {
2736             patternToCompare = &fNegativePrefix;
2737         }
2738         else {
2739             patternToCompare = &fNegativeSuffix;
2740         }
2741     }
2742     else {
2743         if (isPrefix) {
2744             patternToCompare = &fPositivePrefix;
2745         }
2746         else {
2747             patternToCompare = &fPositiveSuffix;
2748         }
2749     }
2750     return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
2751 }
2752 
2753 /**
2754  * Return the length matched by the given affix, or -1 if none.
2755  * Runs of white space in the affix, match runs of white space in
2756  * the input.  Pattern white space and input white space are
2757  * determined differently; see code.
2758  * @param affix pattern string, taken as a literal
2759  * @param input input text
2760  * @param pos offset into input at which to begin matching
2761  * @return length of input that matches, or -1 if match failure
2762  */
compareSimpleAffix(const UnicodeString & affix,const UnicodeString & input,int32_t pos,UBool lenient)2763 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
2764                                           const UnicodeString& input,
2765                                           int32_t pos,
2766                                           UBool lenient) {
2767     int32_t start = pos;
2768     UChar32 affixChar = affix.char32At(0);
2769     int32_t affixLength = affix.length();
2770     int32_t inputLength = input.length();
2771     int32_t affixCharLength = U16_LENGTH(affixChar);
2772     UnicodeSet *affixSet;
2773 
2774     if (!lenient) {
2775         affixSet = DecimalFormatStaticSets::gStaticSets->fStrictDashEquivalents;
2776 
2777         // If the affix is exactly one character long and that character
2778         // is in the dash set and the very next input character is also
2779         // in the dash set, return a match.
2780         if (affixCharLength == affixLength && affixSet->contains(affixChar))  {
2781             if (affixSet->contains(input.char32At(pos))) {
2782                 return 1;
2783             }
2784         }
2785 
2786         for (int32_t i = 0; i < affixLength; ) {
2787             UChar32 c = affix.char32At(i);
2788             int32_t len = U16_LENGTH(c);
2789             if (PatternProps::isWhiteSpace(c)) {
2790                 // We may have a pattern like: \u200F \u0020
2791                 //        and input text like: \u200F \u0020
2792                 // Note that U+200F and U+0020 are Pattern_White_Space but only
2793                 // U+0020 is UWhiteSpace.  So we have to first do a direct
2794                 // match of the run of Pattern_White_Space in the pattern,
2795                 // then match any extra characters.
2796                 UBool literalMatch = FALSE;
2797                 while (pos < inputLength &&
2798                        input.char32At(pos) == c) {
2799                     literalMatch = TRUE;
2800                     i += len;
2801                     pos += len;
2802                     if (i == affixLength) {
2803                         break;
2804                     }
2805                     c = affix.char32At(i);
2806                     len = U16_LENGTH(c);
2807                     if (!PatternProps::isWhiteSpace(c)) {
2808                         break;
2809                     }
2810                 }
2811 
2812                 // Advance over run in pattern
2813                 i = skipPatternWhiteSpace(affix, i);
2814 
2815                 // Advance over run in input text
2816                 // Must see at least one white space char in input,
2817                 // unless we've already matched some characters literally.
2818                 int32_t s = pos;
2819                 pos = skipUWhiteSpace(input, pos);
2820                 if (pos == s && !literalMatch) {
2821                     return -1;
2822                 }
2823 
2824                 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2825                 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2826                 // is also in the affix.
2827                 i = skipUWhiteSpace(affix, i);
2828             } else {
2829                 if (pos < inputLength &&
2830                     input.char32At(pos) == c) {
2831                     i += len;
2832                     pos += len;
2833                 } else {
2834                     return -1;
2835                 }
2836             }
2837         }
2838     } else {
2839         UBool match = FALSE;
2840 
2841         affixSet = DecimalFormatStaticSets::gStaticSets->fDashEquivalents;
2842 
2843         if (affixCharLength == affixLength && affixSet->contains(affixChar))  {
2844             pos = skipUWhiteSpace(input, pos);
2845 
2846             if (affixSet->contains(input.char32At(pos))) {
2847                 return pos - start + 1;
2848             }
2849         }
2850 
2851         for (int32_t i = 0; i < affixLength; )
2852         {
2853             //i = skipRuleWhiteSpace(affix, i);
2854             i = skipUWhiteSpace(affix, i);
2855             pos = skipUWhiteSpace(input, pos);
2856 
2857             if (i >= affixLength || pos >= inputLength) {
2858                 break;
2859             }
2860 
2861             UChar32 c = affix.char32At(i);
2862             int32_t len = U16_LENGTH(c);
2863 
2864             if (input.char32At(pos) != c) {
2865                 return -1;
2866             }
2867 
2868             match = TRUE;
2869             i += len;
2870             pos += len;
2871         }
2872 
2873         if (affixLength > 0 && ! match) {
2874             return -1;
2875         }
2876     }
2877     return pos - start;
2878 }
2879 
2880 /**
2881  * Skip over a run of zero or more Pattern_White_Space characters at
2882  * pos in text.
2883  */
skipPatternWhiteSpace(const UnicodeString & text,int32_t pos)2884 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) {
2885     const UChar* s = text.getBuffer();
2886     return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s);
2887 }
2888 
2889 /**
2890  * Skip over a run of zero or more isUWhiteSpace() characters at pos
2891  * in text.
2892  */
skipUWhiteSpace(const UnicodeString & text,int32_t pos)2893 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) {
2894     while (pos < text.length()) {
2895         UChar32 c = text.char32At(pos);
2896         if (!u_isUWhiteSpace(c)) {
2897             break;
2898         }
2899         pos += U16_LENGTH(c);
2900     }
2901     return pos;
2902 }
2903 
2904 /**
2905  * Return the length matched by the given affix, or -1 if none.
2906  * @param affixPat pattern string
2907  * @param input input text
2908  * @param pos offset into input at which to begin matching
2909  * @param type the currency type to parse against, LONG_NAME only or not.
2910  * @param currency return value for parsed currency, for generic
2911  * currency parsing mode, or null for normal parsing. In generic
2912  * currency parsing mode, any currency is parsed, not just the
2913  * currency that this formatter is set to.
2914  * @return length of input that matches, or -1 if match failure
2915  */
compareComplexAffix(const UnicodeString & affixPat,const UnicodeString & text,int32_t pos,int8_t type,UChar * currency) const2916 int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
2917                                            const UnicodeString& text,
2918                                            int32_t pos,
2919                                            int8_t type,
2920                                            UChar* currency) const
2921 {
2922     int32_t start = pos;
2923     U_ASSERT(currency != NULL ||
2924              (fCurrencyChoice != NULL && *getCurrency() != 0) ||
2925              fCurrencySignCount > fgCurrencySignCountZero);
2926 
2927     for (int32_t i=0;
2928          i<affixPat.length() && pos >= 0; ) {
2929         UChar32 c = affixPat.char32At(i);
2930         i += U16_LENGTH(c);
2931 
2932         if (c == kQuote) {
2933             U_ASSERT(i <= affixPat.length());
2934             c = affixPat.char32At(i);
2935             i += U16_LENGTH(c);
2936 
2937             const UnicodeString* affix = NULL;
2938 
2939             switch (c) {
2940             case kCurrencySign: {
2941                 // since the currency names in choice format is saved
2942                 // the same way as other currency names,
2943                 // do not need to do currency choice parsing here.
2944                 // the general currency parsing parse against all names,
2945                 // including names in choice format.
2946                 UBool intl = i<affixPat.length() &&
2947                     affixPat.char32At(i) == kCurrencySign;
2948                 if (intl) {
2949                     ++i;
2950                 }
2951                 UBool plural = i<affixPat.length() &&
2952                     affixPat.char32At(i) == kCurrencySign;
2953                 if (plural) {
2954                     ++i;
2955                     intl = FALSE;
2956                 }
2957                 // Parse generic currency -- anything for which we
2958                 // have a display name, or any 3-letter ISO code.
2959                 // Try to parse display name for our locale; first
2960                 // determine our locale.
2961                 const char* loc = fCurrencyPluralInfo->getLocale().getName();
2962                 ParsePosition ppos(pos);
2963                 UChar curr[4];
2964                 UErrorCode ec = U_ZERO_ERROR;
2965                 // Delegate parse of display name => ISO code to Currency
2966                 uprv_parseCurrency(loc, text, ppos, type, curr, ec);
2967 
2968                 // If parse succeeds, populate currency[0]
2969                 if (U_SUCCESS(ec) && ppos.getIndex() != pos) {
2970                     if (currency) {
2971                         u_strcpy(currency, curr);
2972                     } else {
2973                         // The formatter is currency-style but the client has not requested
2974                         // the value of the parsed currency. In this case, if that value does
2975                         // not match the formatter's current value, then the parse fails.
2976                         UChar effectiveCurr[4];
2977                         getEffectiveCurrency(effectiveCurr, ec);
2978                         if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) {
2979                         	pos = -1;
2980                         	continue;
2981                         }
2982                     }
2983                     pos = ppos.getIndex();
2984                 } else if (!isLenient()){
2985                     pos = -1;
2986                 }
2987                 continue;
2988             }
2989             case kPatternPercent:
2990                 affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2991                 break;
2992             case kPatternPerMill:
2993                 affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2994                 break;
2995             case kPatternPlus:
2996                 affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2997                 break;
2998             case kPatternMinus:
2999                 affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
3000                 break;
3001             default:
3002                 // fall through to affix!=0 test, which will fail
3003                 break;
3004             }
3005 
3006             if (affix != NULL) {
3007                 pos = match(text, pos, *affix);
3008                 continue;
3009             }
3010         }
3011 
3012         pos = match(text, pos, c);
3013         if (PatternProps::isWhiteSpace(c)) {
3014             i = skipPatternWhiteSpace(affixPat, i);
3015         }
3016     }
3017     return pos - start;
3018 }
3019 
3020 /**
3021  * Match a single character at text[pos] and return the index of the
3022  * next character upon success.  Return -1 on failure.  If
3023  * ch is a Pattern_White_Space then match a run of white space in text.
3024  */
match(const UnicodeString & text,int32_t pos,UChar32 ch)3025 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) {
3026     if (PatternProps::isWhiteSpace(ch)) {
3027         // Advance over run of white space in input text
3028         // Must see at least one white space char in input
3029         int32_t s = pos;
3030         pos = skipPatternWhiteSpace(text, pos);
3031         if (pos == s) {
3032             return -1;
3033         }
3034         return pos;
3035     }
3036     return (pos >= 0 && text.char32At(pos) == ch) ?
3037         (pos + U16_LENGTH(ch)) : -1;
3038 }
3039 
3040 /**
3041  * Match a string at text[pos] and return the index of the next
3042  * character upon success.  Return -1 on failure.  Match a run of
3043  * white space in str with a run of white space in text.
3044  */
match(const UnicodeString & text,int32_t pos,const UnicodeString & str)3045 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) {
3046     for (int32_t i=0; i<str.length() && pos >= 0; ) {
3047         UChar32 ch = str.char32At(i);
3048         i += U16_LENGTH(ch);
3049         if (PatternProps::isWhiteSpace(ch)) {
3050             i = skipPatternWhiteSpace(str, i);
3051         }
3052         pos = match(text, pos, ch);
3053     }
3054     return pos;
3055 }
3056 
matchSymbol(const UnicodeString & text,int32_t position,int32_t length,const UnicodeString & symbol,UnicodeSet * sset,UChar32 schar)3057 UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol,
3058                          UnicodeSet *sset, UChar32 schar)
3059 {
3060     if (sset != NULL) {
3061         return sset->contains(schar);
3062     }
3063 
3064     return text.compare(position, length, symbol) == 0;
3065 }
3066 
matchDecimal(UChar32 symbolChar,UBool sawDecimal,UChar32 sawDecimalChar,const UnicodeSet * sset,UChar32 schar)3067 UBool DecimalFormat::matchDecimal(UChar32 symbolChar,
3068                             UBool sawDecimal,  UChar32 sawDecimalChar,
3069                              const UnicodeSet *sset, UChar32 schar) {
3070    if(sawDecimal) {
3071        return schar==sawDecimalChar;
3072    } else if(schar==symbolChar) {
3073        return TRUE;
3074    } else if(sset!=NULL) {
3075         return sset->contains(schar);
3076    } else {
3077        return FALSE;
3078    }
3079 }
3080 
matchGrouping(UChar32 groupingChar,UBool sawGrouping,UChar32 sawGroupingChar,const UnicodeSet * sset,UChar32,const UnicodeSet * decimalSet,UChar32 schar)3081 UBool DecimalFormat::matchGrouping(UChar32 groupingChar,
3082                             UBool sawGrouping, UChar32 sawGroupingChar,
3083                              const UnicodeSet *sset,
3084                              UChar32 /*decimalChar*/, const UnicodeSet *decimalSet,
3085                              UChar32 schar) {
3086     if(sawGrouping) {
3087         return schar==sawGroupingChar;  // previously found
3088     } else if(schar==groupingChar) {
3089         return TRUE; // char from symbols
3090     } else if(sset!=NULL) {
3091         return sset->contains(schar) &&  // in groupingSet but...
3092            ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet
3093     } else {
3094         return FALSE;
3095     }
3096 }
3097 
3098 
3099 
3100 //------------------------------------------------------------------------------
3101 // Gets the pointer to the localized decimal format symbols
3102 
3103 const DecimalFormatSymbols*
getDecimalFormatSymbols() const3104 DecimalFormat::getDecimalFormatSymbols() const
3105 {
3106     return fSymbols;
3107 }
3108 
3109 //------------------------------------------------------------------------------
3110 // De-owning the current localized symbols and adopt the new symbols.
3111 
3112 void
adoptDecimalFormatSymbols(DecimalFormatSymbols * symbolsToAdopt)3113 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
3114 {
3115     if (symbolsToAdopt == NULL) {
3116         return; // do not allow caller to set fSymbols to NULL
3117     }
3118 
3119     UBool sameSymbols = FALSE;
3120     if (fSymbols != NULL) {
3121         sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
3122             symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
3123             getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
3124             symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
3125         delete fSymbols;
3126     }
3127 
3128     fSymbols = symbolsToAdopt;
3129     if (!sameSymbols) {
3130         // If the currency symbols are the same, there is no need to recalculate.
3131         setCurrencyForSymbols();
3132     }
3133     expandAffixes(NULL);
3134 #if UCONFIG_FORMAT_FASTPATHS_49
3135     handleChanged();
3136 #endif
3137 }
3138 //------------------------------------------------------------------------------
3139 // Setting the symbols is equlivalent to adopting a newly created localized
3140 // symbols.
3141 
3142 void
setDecimalFormatSymbols(const DecimalFormatSymbols & symbols)3143 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
3144 {
3145     adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
3146 #if UCONFIG_FORMAT_FASTPATHS_49
3147     handleChanged();
3148 #endif
3149 }
3150 
3151 
3152 const CurrencyPluralInfo*
getCurrencyPluralInfo(void) const3153 DecimalFormat::getCurrencyPluralInfo(void) const
3154 {
3155     return fCurrencyPluralInfo;
3156 }
3157 
3158 
3159 void
adoptCurrencyPluralInfo(CurrencyPluralInfo * toAdopt)3160 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt)
3161 {
3162     if (toAdopt != NULL) {
3163         delete fCurrencyPluralInfo;
3164         fCurrencyPluralInfo = toAdopt;
3165         // re-set currency affix patterns and currency affixes.
3166         if (fCurrencySignCount > fgCurrencySignCountZero) {
3167             UErrorCode status = U_ZERO_ERROR;
3168             if (fAffixPatternsForCurrency) {
3169                 deleteHashForAffixPattern();
3170             }
3171             setupCurrencyAffixPatterns(status);
3172             if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
3173                 // only setup the affixes of the plural pattern.
3174                 setupCurrencyAffixes(fFormatPattern, FALSE, TRUE, status);
3175             }
3176         }
3177     }
3178 #if UCONFIG_FORMAT_FASTPATHS_49
3179     handleChanged();
3180 #endif
3181 }
3182 
3183 void
setCurrencyPluralInfo(const CurrencyPluralInfo & info)3184 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
3185 {
3186     adoptCurrencyPluralInfo(info.clone());
3187 #if UCONFIG_FORMAT_FASTPATHS_49
3188     handleChanged();
3189 #endif
3190 }
3191 
3192 
3193 /**
3194  * Update the currency object to match the symbols.  This method
3195  * is used only when the caller has passed in a symbols object
3196  * that may not be the default object for its locale.
3197  */
3198 void
setCurrencyForSymbols()3199 DecimalFormat::setCurrencyForSymbols() {
3200     /*Bug 4212072
3201       Update the affix strings accroding to symbols in order to keep
3202       the affix strings up to date.
3203       [Richard/GCL]
3204     */
3205 
3206     // With the introduction of the Currency object, the currency
3207     // symbols in the DFS object are ignored.  For backward
3208     // compatibility, we check any explicitly set DFS object.  If it
3209     // is a default symbols object for its locale, we change the
3210     // currency object to one for that locale.  If it is custom,
3211     // we set the currency to null.
3212     UErrorCode ec = U_ZERO_ERROR;
3213     const UChar* c = NULL;
3214     const char* loc = fSymbols->getLocale().getName();
3215     UChar intlCurrencySymbol[4];
3216     ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec);
3217     UnicodeString currencySymbol;
3218 
3219     uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec);
3220     if (U_SUCCESS(ec)
3221         && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol
3222         && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == UnicodeString(intlCurrencySymbol))
3223     {
3224         // Trap an error in mapping locale to currency.  If we can't
3225         // map, then don't fail and set the currency to "".
3226         c = intlCurrencySymbol;
3227     }
3228     ec = U_ZERO_ERROR; // reset local error code!
3229     setCurrencyInternally(c, ec);
3230 #if UCONFIG_FORMAT_FASTPATHS_49
3231     handleChanged();
3232 #endif
3233 }
3234 
3235 
3236 //------------------------------------------------------------------------------
3237 // Gets the positive prefix of the number pattern.
3238 
3239 UnicodeString&
getPositivePrefix(UnicodeString & result) const3240 DecimalFormat::getPositivePrefix(UnicodeString& result) const
3241 {
3242     result = fPositivePrefix;
3243     return result;
3244 }
3245 
3246 //------------------------------------------------------------------------------
3247 // Sets the positive prefix of the number pattern.
3248 
3249 void
setPositivePrefix(const UnicodeString & newValue)3250 DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
3251 {
3252     fPositivePrefix = newValue;
3253     delete fPosPrefixPattern;
3254     fPosPrefixPattern = 0;
3255 #if UCONFIG_FORMAT_FASTPATHS_49
3256     handleChanged();
3257 #endif
3258 }
3259 
3260 //------------------------------------------------------------------------------
3261 // Gets the negative prefix  of the number pattern.
3262 
3263 UnicodeString&
getNegativePrefix(UnicodeString & result) const3264 DecimalFormat::getNegativePrefix(UnicodeString& result) const
3265 {
3266     result = fNegativePrefix;
3267     return result;
3268 }
3269 
3270 //------------------------------------------------------------------------------
3271 // Gets the negative prefix  of the number pattern.
3272 
3273 void
setNegativePrefix(const UnicodeString & newValue)3274 DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
3275 {
3276     fNegativePrefix = newValue;
3277     delete fNegPrefixPattern;
3278     fNegPrefixPattern = 0;
3279 #if UCONFIG_FORMAT_FASTPATHS_49
3280     handleChanged();
3281 #endif
3282 }
3283 
3284 //------------------------------------------------------------------------------
3285 // Gets the positive suffix of the number pattern.
3286 
3287 UnicodeString&
getPositiveSuffix(UnicodeString & result) const3288 DecimalFormat::getPositiveSuffix(UnicodeString& result) const
3289 {
3290     result = fPositiveSuffix;
3291     return result;
3292 }
3293 
3294 //------------------------------------------------------------------------------
3295 // Sets the positive suffix of the number pattern.
3296 
3297 void
setPositiveSuffix(const UnicodeString & newValue)3298 DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
3299 {
3300     fPositiveSuffix = newValue;
3301     delete fPosSuffixPattern;
3302     fPosSuffixPattern = 0;
3303 #if UCONFIG_FORMAT_FASTPATHS_49
3304     handleChanged();
3305 #endif
3306 }
3307 
3308 //------------------------------------------------------------------------------
3309 // Gets the negative suffix of the number pattern.
3310 
3311 UnicodeString&
getNegativeSuffix(UnicodeString & result) const3312 DecimalFormat::getNegativeSuffix(UnicodeString& result) const
3313 {
3314     result = fNegativeSuffix;
3315     return result;
3316 }
3317 
3318 //------------------------------------------------------------------------------
3319 // Sets the negative suffix of the number pattern.
3320 
3321 void
setNegativeSuffix(const UnicodeString & newValue)3322 DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
3323 {
3324     fNegativeSuffix = newValue;
3325     delete fNegSuffixPattern;
3326     fNegSuffixPattern = 0;
3327 #if UCONFIG_FORMAT_FASTPATHS_49
3328     handleChanged();
3329 #endif
3330 }
3331 
3332 //------------------------------------------------------------------------------
3333 // Gets the multiplier of the number pattern.
3334 //   Multipliers are stored as decimal numbers (DigitLists) because that
3335 //      is the most convenient for muliplying or dividing the numbers to be formatted.
3336 //   A NULL multiplier implies one, and the scaling operations are skipped.
3337 
3338 int32_t
getMultiplier() const3339 DecimalFormat::getMultiplier() const
3340 {
3341     if (fMultiplier == NULL) {
3342         return 1;
3343     } else {
3344         return fMultiplier->getLong();
3345     }
3346 }
3347 
3348 //------------------------------------------------------------------------------
3349 // Sets the multiplier of the number pattern.
3350 void
setMultiplier(int32_t newValue)3351 DecimalFormat::setMultiplier(int32_t newValue)
3352 {
3353 //  if (newValue == 0) {
3354 //      throw new IllegalArgumentException("Bad multiplier: " + newValue);
3355 //  }
3356     if (newValue == 0) {
3357         newValue = 1;     // one being the benign default value for a multiplier.
3358     }
3359     if (newValue == 1) {
3360         delete fMultiplier;
3361         fMultiplier = NULL;
3362     } else {
3363         if (fMultiplier == NULL) {
3364             fMultiplier = new DigitList;
3365         }
3366         if (fMultiplier != NULL) {
3367             fMultiplier->set(newValue);
3368         }
3369     }
3370 #if UCONFIG_FORMAT_FASTPATHS_49
3371     handleChanged();
3372 #endif
3373 }
3374 
3375 /**
3376  * Get the rounding increment.
3377  * @return A positive rounding increment, or 0.0 if rounding
3378  * is not in effect.
3379  * @see #setRoundingIncrement
3380  * @see #getRoundingMode
3381  * @see #setRoundingMode
3382  */
getRoundingIncrement() const3383 double DecimalFormat::getRoundingIncrement() const {
3384     if (fRoundingIncrement == NULL) {
3385         return 0.0;
3386     } else {
3387         return fRoundingIncrement->getDouble();
3388     }
3389 }
3390 
3391 /**
3392  * Set the rounding increment.  This method also controls whether
3393  * rounding is enabled.
3394  * @param newValue A positive rounding increment, or 0.0 to disable rounding.
3395  * Negative increments are equivalent to 0.0.
3396  * @see #getRoundingIncrement
3397  * @see #getRoundingMode
3398  * @see #setRoundingMode
3399  */
setRoundingIncrement(double newValue)3400 void DecimalFormat::setRoundingIncrement(double newValue) {
3401     if (newValue > 0.0) {
3402         if (fRoundingIncrement == NULL) {
3403             fRoundingIncrement = new DigitList();
3404         }
3405         if (fRoundingIncrement != NULL) {
3406             fRoundingIncrement->set(newValue);
3407             return;
3408         }
3409     }
3410     // These statements are executed if newValue is less than 0.0
3411     // or fRoundingIncrement could not be created.
3412     delete fRoundingIncrement;
3413     fRoundingIncrement = NULL;
3414 #if UCONFIG_FORMAT_FASTPATHS_49
3415     handleChanged();
3416 #endif
3417 }
3418 
3419 /**
3420  * Get the rounding mode.
3421  * @return A rounding mode
3422  * @see #setRoundingIncrement
3423  * @see #getRoundingIncrement
3424  * @see #setRoundingMode
3425  */
getRoundingMode() const3426 DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
3427     return fRoundingMode;
3428 }
3429 
3430 /**
3431  * Set the rounding mode.  This has no effect unless the rounding
3432  * increment is greater than zero.
3433  * @param roundingMode A rounding mode
3434  * @see #setRoundingIncrement
3435  * @see #getRoundingIncrement
3436  * @see #getRoundingMode
3437  */
setRoundingMode(ERoundingMode roundingMode)3438 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
3439     fRoundingMode = roundingMode;
3440 #if UCONFIG_FORMAT_FASTPATHS_49
3441     handleChanged();
3442 #endif
3443 }
3444 
3445 /**
3446  * Get the width to which the output of <code>format()</code> is padded.
3447  * @return the format width, or zero if no padding is in effect
3448  * @see #setFormatWidth
3449  * @see #getPadCharacter
3450  * @see #setPadCharacter
3451  * @see #getPadPosition
3452  * @see #setPadPosition
3453  */
getFormatWidth() const3454 int32_t DecimalFormat::getFormatWidth() const {
3455     return fFormatWidth;
3456 }
3457 
3458 /**
3459  * Set the width to which the output of <code>format()</code> is padded.
3460  * This method also controls whether padding is enabled.
3461  * @param width the width to which to pad the result of
3462  * <code>format()</code>, or zero to disable padding.  A negative
3463  * width is equivalent to 0.
3464  * @see #getFormatWidth
3465  * @see #getPadCharacter
3466  * @see #setPadCharacter
3467  * @see #getPadPosition
3468  * @see #setPadPosition
3469  */
setFormatWidth(int32_t width)3470 void DecimalFormat::setFormatWidth(int32_t width) {
3471     fFormatWidth = (width > 0) ? width : 0;
3472 #if UCONFIG_FORMAT_FASTPATHS_49
3473     handleChanged();
3474 #endif
3475 }
3476 
getPadCharacterString() const3477 UnicodeString DecimalFormat::getPadCharacterString() const {
3478     return UnicodeString(fPad);
3479 }
3480 
setPadCharacter(const UnicodeString & padChar)3481 void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
3482     if (padChar.length() > 0) {
3483         fPad = padChar.char32At(0);
3484     }
3485     else {
3486         fPad = kDefaultPad;
3487     }
3488 #if UCONFIG_FORMAT_FASTPATHS_49
3489     handleChanged();
3490 #endif
3491 }
3492 
3493 /**
3494  * Get the position at which padding will take place.  This is the location
3495  * at which padding will be inserted if the result of <code>format()</code>
3496  * is shorter than the format width.
3497  * @return the pad position, one of <code>kPadBeforePrefix</code>,
3498  * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3499  * <code>kPadAfterSuffix</code>.
3500  * @see #setFormatWidth
3501  * @see #getFormatWidth
3502  * @see #setPadCharacter
3503  * @see #getPadCharacter
3504  * @see #setPadPosition
3505  * @see #kPadBeforePrefix
3506  * @see #kPadAfterPrefix
3507  * @see #kPadBeforeSuffix
3508  * @see #kPadAfterSuffix
3509  */
getPadPosition() const3510 DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
3511     return fPadPosition;
3512 }
3513 
3514 /**
3515  * <strong><font face=helvetica color=red>NEW</font></strong>
3516  * Set the position at which padding will take place.  This is the location
3517  * at which padding will be inserted if the result of <code>format()</code>
3518  * is shorter than the format width.  This has no effect unless padding is
3519  * enabled.
3520  * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
3521  * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3522  * <code>kPadAfterSuffix</code>.
3523  * @see #setFormatWidth
3524  * @see #getFormatWidth
3525  * @see #setPadCharacter
3526  * @see #getPadCharacter
3527  * @see #getPadPosition
3528  * @see #kPadBeforePrefix
3529  * @see #kPadAfterPrefix
3530  * @see #kPadBeforeSuffix
3531  * @see #kPadAfterSuffix
3532  */
setPadPosition(EPadPosition padPos)3533 void DecimalFormat::setPadPosition(EPadPosition padPos) {
3534     fPadPosition = padPos;
3535 #if UCONFIG_FORMAT_FASTPATHS_49
3536     handleChanged();
3537 #endif
3538 }
3539 
3540 /**
3541  * Return whether or not scientific notation is used.
3542  * @return TRUE if this object formats and parses scientific notation
3543  * @see #setScientificNotation
3544  * @see #getMinimumExponentDigits
3545  * @see #setMinimumExponentDigits
3546  * @see #isExponentSignAlwaysShown
3547  * @see #setExponentSignAlwaysShown
3548  */
isScientificNotation()3549 UBool DecimalFormat::isScientificNotation() {
3550     return fUseExponentialNotation;
3551 }
3552 
3553 /**
3554  * Set whether or not scientific notation is used.
3555  * @param useScientific TRUE if this object formats and parses scientific
3556  * notation
3557  * @see #isScientificNotation
3558  * @see #getMinimumExponentDigits
3559  * @see #setMinimumExponentDigits
3560  * @see #isExponentSignAlwaysShown
3561  * @see #setExponentSignAlwaysShown
3562  */
setScientificNotation(UBool useScientific)3563 void DecimalFormat::setScientificNotation(UBool useScientific) {
3564     fUseExponentialNotation = useScientific;
3565 #if UCONFIG_FORMAT_FASTPATHS_49
3566     handleChanged();
3567 #endif
3568 }
3569 
3570 /**
3571  * Return the minimum exponent digits that will be shown.
3572  * @return the minimum exponent digits that will be shown
3573  * @see #setScientificNotation
3574  * @see #isScientificNotation
3575  * @see #setMinimumExponentDigits
3576  * @see #isExponentSignAlwaysShown
3577  * @see #setExponentSignAlwaysShown
3578  */
getMinimumExponentDigits() const3579 int8_t DecimalFormat::getMinimumExponentDigits() const {
3580     return fMinExponentDigits;
3581 }
3582 
3583 /**
3584  * Set the minimum exponent digits that will be shown.  This has no
3585  * effect unless scientific notation is in use.
3586  * @param minExpDig a value >= 1 indicating the fewest exponent digits
3587  * that will be shown.  Values less than 1 will be treated as 1.
3588  * @see #setScientificNotation
3589  * @see #isScientificNotation
3590  * @see #getMinimumExponentDigits
3591  * @see #isExponentSignAlwaysShown
3592  * @see #setExponentSignAlwaysShown
3593  */
setMinimumExponentDigits(int8_t minExpDig)3594 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
3595     fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
3596 #if UCONFIG_FORMAT_FASTPATHS_49
3597     handleChanged();
3598 #endif
3599 }
3600 
3601 /**
3602  * Return whether the exponent sign is always shown.
3603  * @return TRUE if the exponent is always prefixed with either the
3604  * localized minus sign or the localized plus sign, false if only negative
3605  * exponents are prefixed with the localized minus sign.
3606  * @see #setScientificNotation
3607  * @see #isScientificNotation
3608  * @see #setMinimumExponentDigits
3609  * @see #getMinimumExponentDigits
3610  * @see #setExponentSignAlwaysShown
3611  */
isExponentSignAlwaysShown()3612 UBool DecimalFormat::isExponentSignAlwaysShown() {
3613     return fExponentSignAlwaysShown;
3614 }
3615 
3616 /**
3617  * Set whether the exponent sign is always shown.  This has no effect
3618  * unless scientific notation is in use.
3619  * @param expSignAlways TRUE if the exponent is always prefixed with either
3620  * the localized minus sign or the localized plus sign, false if only
3621  * negative exponents are prefixed with the localized minus sign.
3622  * @see #setScientificNotation
3623  * @see #isScientificNotation
3624  * @see #setMinimumExponentDigits
3625  * @see #getMinimumExponentDigits
3626  * @see #isExponentSignAlwaysShown
3627  */
setExponentSignAlwaysShown(UBool expSignAlways)3628 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
3629     fExponentSignAlwaysShown = expSignAlways;
3630 #if UCONFIG_FORMAT_FASTPATHS_49
3631     handleChanged();
3632 #endif
3633 }
3634 
3635 //------------------------------------------------------------------------------
3636 // Gets the grouping size of the number pattern.  For example, thousand or 10
3637 // thousand groupings.
3638 
3639 int32_t
getGroupingSize() const3640 DecimalFormat::getGroupingSize() const
3641 {
3642     return fGroupingSize;
3643 }
3644 
3645 //------------------------------------------------------------------------------
3646 // Gets the grouping size of the number pattern.
3647 
3648 void
setGroupingSize(int32_t newValue)3649 DecimalFormat::setGroupingSize(int32_t newValue)
3650 {
3651     fGroupingSize = newValue;
3652 #if UCONFIG_FORMAT_FASTPATHS_49
3653     handleChanged();
3654 #endif
3655 }
3656 
3657 //------------------------------------------------------------------------------
3658 
3659 int32_t
getSecondaryGroupingSize() const3660 DecimalFormat::getSecondaryGroupingSize() const
3661 {
3662     return fGroupingSize2;
3663 }
3664 
3665 //------------------------------------------------------------------------------
3666 
3667 void
setSecondaryGroupingSize(int32_t newValue)3668 DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
3669 {
3670     fGroupingSize2 = newValue;
3671 #if UCONFIG_FORMAT_FASTPATHS_49
3672     handleChanged();
3673 #endif
3674 }
3675 
3676 //------------------------------------------------------------------------------
3677 // Checks if to show the decimal separator.
3678 
3679 UBool
isDecimalSeparatorAlwaysShown() const3680 DecimalFormat::isDecimalSeparatorAlwaysShown() const
3681 {
3682     return fDecimalSeparatorAlwaysShown;
3683 }
3684 
3685 //------------------------------------------------------------------------------
3686 // Sets to always show the decimal separator.
3687 
3688 void
setDecimalSeparatorAlwaysShown(UBool newValue)3689 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
3690 {
3691     fDecimalSeparatorAlwaysShown = newValue;
3692 #if UCONFIG_FORMAT_FASTPATHS_49
3693     handleChanged();
3694 #endif
3695 }
3696 
3697 //------------------------------------------------------------------------------
3698 // Emits the pattern of this DecimalFormat instance.
3699 
3700 UnicodeString&
toPattern(UnicodeString & result) const3701 DecimalFormat::toPattern(UnicodeString& result) const
3702 {
3703     return toPattern(result, FALSE);
3704 }
3705 
3706 //------------------------------------------------------------------------------
3707 // Emits the localized pattern this DecimalFormat instance.
3708 
3709 UnicodeString&
toLocalizedPattern(UnicodeString & result) const3710 DecimalFormat::toLocalizedPattern(UnicodeString& result) const
3711 {
3712     return toPattern(result, TRUE);
3713 }
3714 
3715 //------------------------------------------------------------------------------
3716 /**
3717  * Expand the affix pattern strings into the expanded affix strings.  If any
3718  * affix pattern string is null, do not expand it.  This method should be
3719  * called any time the symbols or the affix patterns change in order to keep
3720  * the expanded affix strings up to date.
3721  * This method also will be called before formatting if format currency
3722  * plural names, since the plural name is not a static one, it is
3723  * based on the currency plural count, the affix will be known only
3724  * after the currency plural count is know.
3725  * In which case, the parameter
3726  * 'pluralCount' will be a non-null currency plural count.
3727  * In all other cases, the 'pluralCount' is null, which means it is not needed.
3728  */
expandAffixes(const UnicodeString * pluralCount)3729 void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
3730     FieldPositionHandler none;
3731     if (fPosPrefixPattern != 0) {
3732       expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCount);
3733     }
3734     if (fPosSuffixPattern != 0) {
3735       expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCount);
3736     }
3737     if (fNegPrefixPattern != 0) {
3738       expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCount);
3739     }
3740     if (fNegSuffixPattern != 0) {
3741       expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCount);
3742     }
3743 #ifdef FMT_DEBUG
3744     UnicodeString s;
3745     s.append(UnicodeString("["))
3746       .append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fPosSuffixPattern))
3747       .append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fNegSuffixPattern))
3748         .append((UnicodeString)"]->[")
3749         .append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuffix)
3750         .append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeString)"|").append(fNegativeSuffix)
3751         .append((UnicodeString)"]\n");
3752     debugout(s);
3753 #endif
3754 }
3755 
3756 /**
3757  * Expand an affix pattern into an affix string.  All characters in the
3758  * pattern are literal unless prefixed by kQuote.  The following characters
3759  * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
3760  * PATTERN_MINUS, and kCurrencySign.  If kCurrencySign is doubled (kQuote +
3761  * kCurrencySign + kCurrencySign), it is interpreted as an international
3762  * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
3763  * currency plural long names, such as "US Dollars".
3764  * Any other character after a kQuote represents itself.
3765  * kQuote must be followed by another character; kQuote may not occur by
3766  * itself at the end of the pattern.
3767  *
3768  * This method is used in two distinct ways.  First, it is used to expand
3769  * the stored affix patterns into actual affixes.  For this usage, doFormat
3770  * must be false.  Second, it is used to expand the stored affix patterns
3771  * given a specific number (doFormat == true), for those rare cases in
3772  * which a currency format references a ChoiceFormat (e.g., en_IN display
3773  * name for INR).  The number itself is taken from digitList.
3774  *
3775  * When used in the first way, this method has a side effect: It sets
3776  * currencyChoice to a ChoiceFormat object, if the currency's display name
3777  * in this locale is a ChoiceFormat pattern (very rare).  It only does this
3778  * if currencyChoice is null to start with.
3779  *
3780  * @param pattern the non-null, fPossibly empty pattern
3781  * @param affix string to receive the expanded equivalent of pattern.
3782  * Previous contents are deleted.
3783  * @param doFormat if false, then the pattern will be expanded, and if a
3784  * currency symbol is encountered that expands to a ChoiceFormat, the
3785  * currencyChoice member variable will be initialized if it is null.  If
3786  * doFormat is true, then it is assumed that the currencyChoice has been
3787  * created, and it will be used to format the value in digitList.
3788  * @param pluralCount the plural count. It is only used for currency
3789  *                    plural format. In which case, it is the plural
3790  *                    count of the currency amount. For example,
3791  *                    in en_US, it is the singular "one", or the plural
3792  *                    "other". For all other cases, it is null, and
3793  *                    is not being used.
3794  */
expandAffix(const UnicodeString & pattern,UnicodeString & affix,double number,FieldPositionHandler & handler,UBool doFormat,const UnicodeString * pluralCount) const3795 void DecimalFormat::expandAffix(const UnicodeString& pattern,
3796                                 UnicodeString& affix,
3797                                 double number,
3798                                 FieldPositionHandler& handler,
3799                                 UBool doFormat,
3800                                 const UnicodeString* pluralCount) const {
3801     affix.remove();
3802     for (int i=0; i<pattern.length(); ) {
3803         UChar32 c = pattern.char32At(i);
3804         i += U16_LENGTH(c);
3805         if (c == kQuote) {
3806             c = pattern.char32At(i);
3807             i += U16_LENGTH(c);
3808             int beginIdx = affix.length();
3809             switch (c) {
3810             case kCurrencySign: {
3811                 // As of ICU 2.2 we use the currency object, and
3812                 // ignore the currency symbols in the DFS, unless
3813                 // we have a null currency object.  This occurs if
3814                 // resurrecting a pre-2.2 object or if the user
3815                 // sets a custom DFS.
3816                 UBool intl = i<pattern.length() &&
3817                     pattern.char32At(i) == kCurrencySign;
3818                 UBool plural = FALSE;
3819                 if (intl) {
3820                     ++i;
3821                     plural = i<pattern.length() &&
3822                         pattern.char32At(i) == kCurrencySign;
3823                     if (plural) {
3824                         intl = FALSE;
3825                         ++i;
3826                     }
3827                 }
3828                 const UChar* currencyUChars = getCurrency();
3829                 if (currencyUChars[0] != 0) {
3830                     UErrorCode ec = U_ZERO_ERROR;
3831                     if (plural && pluralCount != NULL) {
3832                         // plural name is only needed when pluralCount != null,
3833                         // which means when formatting currency plural names.
3834                         // For other cases, pluralCount == null,
3835                         // and plural names are not needed.
3836                         int32_t len;
3837                         CharString pluralCountChar;
3838                         pluralCountChar.appendInvariantChars(*pluralCount, ec);
3839                         UBool isChoiceFormat;
3840                         const UChar* s = ucurr_getPluralName(currencyUChars,
3841                             fSymbols != NULL ? fSymbols->getLocale().getName() :
3842                             Locale::getDefault().getName(), &isChoiceFormat,
3843                             pluralCountChar.data(), &len, &ec);
3844                         affix += UnicodeString(s, len);
3845                         handler.addAttribute(kCurrencyField, beginIdx, affix.length());
3846                     } else if(intl) {
3847                         affix.append(currencyUChars, -1);
3848                         handler.addAttribute(kCurrencyField, beginIdx, affix.length());
3849                     } else {
3850                         int32_t len;
3851                         UBool isChoiceFormat;
3852                         // If fSymbols is NULL, use default locale
3853                         const UChar* s = ucurr_getName(currencyUChars,
3854                             fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(),
3855                             UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
3856                         if (isChoiceFormat) {
3857                             // Two modes here: If doFormat is false, we set up
3858                             // currencyChoice.  If doFormat is true, we use the
3859                             // previously created currencyChoice to format the
3860                             // value in digitList.
3861                             if (!doFormat) {
3862                                 // If the currency is handled by a ChoiceFormat,
3863                                 // then we're not going to use the expanded
3864                                 // patterns.  Instantiate the ChoiceFormat and
3865                                 // return.
3866                                 if (fCurrencyChoice == NULL) {
3867                                     // TODO Replace double-check with proper thread-safe code
3868                                     ChoiceFormat* fmt = new ChoiceFormat(UnicodeString(s), ec);
3869                                     if (U_SUCCESS(ec)) {
3870                                         umtx_lock(NULL);
3871                                         if (fCurrencyChoice == NULL) {
3872                                             // Cast away const
3873                                             ((DecimalFormat*)this)->fCurrencyChoice = fmt;
3874                                             fmt = NULL;
3875                                         }
3876                                         umtx_unlock(NULL);
3877                                         delete fmt;
3878                                     }
3879                                 }
3880                                 // We could almost return null or "" here, since the
3881                                 // expanded affixes are almost not used at all
3882                                 // in this situation.  However, one method --
3883                                 // toPattern() -- still does use the expanded
3884                                 // affixes, in order to set up a padding
3885                                 // pattern.  We use the CURRENCY_SIGN as a
3886                                 // placeholder.
3887                                 affix.append(kCurrencySign);
3888                             } else {
3889                                 if (fCurrencyChoice != NULL) {
3890                                     FieldPosition pos(0); // ignored
3891                                     if (number < 0) {
3892                                         number = -number;
3893                                     }
3894                                     fCurrencyChoice->format(number, affix, pos);
3895                                 } else {
3896                                     // We only arrive here if the currency choice
3897                                     // format in the locale data is INVALID.
3898                                     affix.append(currencyUChars, -1);
3899                                     handler.addAttribute(kCurrencyField, beginIdx, affix.length());
3900                                 }
3901                             }
3902                             continue;
3903                         }
3904                         affix += UnicodeString(s, len);
3905                         handler.addAttribute(kCurrencyField, beginIdx, affix.length());
3906                     }
3907                 } else {
3908                     if(intl) {
3909                         affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
3910                     } else {
3911                         affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
3912                     }
3913                     handler.addAttribute(kCurrencyField, beginIdx, affix.length());
3914                 }
3915                 break;
3916             }
3917             case kPatternPercent:
3918                 affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
3919                 handler.addAttribute(kPercentField, beginIdx, affix.length());
3920                 break;
3921             case kPatternPerMill:
3922                 affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
3923                 handler.addAttribute(kPermillField, beginIdx, affix.length());
3924                 break;
3925             case kPatternPlus:
3926                 affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
3927                 handler.addAttribute(kSignField, beginIdx, affix.length());
3928                 break;
3929             case kPatternMinus:
3930                 affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
3931                 handler.addAttribute(kSignField, beginIdx, affix.length());
3932                 break;
3933             default:
3934                 affix.append(c);
3935                 break;
3936             }
3937         }
3938         else {
3939             affix.append(c);
3940         }
3941     }
3942 }
3943 
3944 /**
3945  * Append an affix to the given StringBuffer.
3946  * @param buf buffer to append to
3947  * @param isNegative
3948  * @param isPrefix
3949  */
appendAffix(UnicodeString & buf,double number,FieldPositionHandler & handler,UBool isNegative,UBool isPrefix) const3950 int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
3951                                    FieldPositionHandler& handler,
3952                                    UBool isNegative, UBool isPrefix) const {
3953     // plural format precedes choice format
3954     if (fCurrencyChoice != 0 &&
3955         fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
3956         const UnicodeString* affixPat;
3957         if (isPrefix) {
3958             affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern;
3959         } else {
3960             affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern;
3961         }
3962         if (affixPat) {
3963             UnicodeString affixBuf;
3964             expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL);
3965             buf.append(affixBuf);
3966             return affixBuf.length();
3967         }
3968         // else someone called a function that reset the pattern.
3969     }
3970 
3971     const UnicodeString* affix;
3972     if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
3973         UnicodeString pluralCount = fCurrencyPluralInfo->getPluralRules()->select(number);
3974         AffixesForCurrency* oneSet;
3975         if (fStyle == UNUM_CURRENCY_PLURAL) {
3976             oneSet = (AffixesForCurrency*)fPluralAffixesForCurrency->get(pluralCount);
3977         } else {
3978             oneSet = (AffixesForCurrency*)fAffixesForCurrency->get(pluralCount);
3979         }
3980         if (isPrefix) {
3981             affix = isNegative ? &oneSet->negPrefixForCurrency :
3982                                  &oneSet->posPrefixForCurrency;
3983         } else {
3984             affix = isNegative ? &oneSet->negSuffixForCurrency :
3985                                  &oneSet->posSuffixForCurrency;
3986         }
3987     } else {
3988         if (isPrefix) {
3989             affix = isNegative ? &fNegativePrefix : &fPositivePrefix;
3990         } else {
3991             affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
3992         }
3993     }
3994 
3995     int32_t begin = (int) buf.length();
3996 
3997     buf.append(*affix);
3998 
3999     if (handler.isRecording()) {
4000       int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
4001       if (offset > -1) {
4002         UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
4003         handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
4004       }
4005 
4006       offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
4007       if (offset > -1) {
4008         UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
4009         handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
4010       }
4011 
4012       offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
4013       if (offset > -1) {
4014         UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
4015         handler.addAttribute(kSignField, begin + offset, begin + offset + aff.length());
4016       }
4017 
4018       offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
4019       if (offset > -1) {
4020         UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
4021         handler.addAttribute(kPercentField, begin + offset, begin + offset + aff.length());
4022       }
4023 
4024       offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
4025       if (offset > -1) {
4026         UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
4027         handler.addAttribute(kPermillField, begin + offset, begin + offset + aff.length());
4028       }
4029     }
4030     return affix->length();
4031 }
4032 
4033 /**
4034  * Appends an affix pattern to the given StringBuffer, quoting special
4035  * characters as needed.  Uses the internal affix pattern, if that exists,
4036  * or the literal affix, if the internal affix pattern is null.  The
4037  * appended string will generate the same affix pattern (or literal affix)
4038  * when passed to toPattern().
4039  *
4040  * @param appendTo the affix string is appended to this
4041  * @param affixPattern a pattern such as fPosPrefixPattern; may be null
4042  * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
4043  * Ignored unless affixPattern is null.  If affixPattern is null, then
4044  * expAffix is appended as a literal affix.
4045  * @param localized true if the appended pattern should contain localized
4046  * pattern characters; otherwise, non-localized pattern chars are appended
4047  */
appendAffixPattern(UnicodeString & appendTo,const UnicodeString * affixPattern,const UnicodeString & expAffix,UBool localized) const4048 void DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
4049                                        const UnicodeString* affixPattern,
4050                                        const UnicodeString& expAffix,
4051                                        UBool localized) const {
4052     if (affixPattern == 0) {
4053         appendAffixPattern(appendTo, expAffix, localized);
4054     } else {
4055         int i;
4056         for (int pos=0; pos<affixPattern->length(); pos=i) {
4057             i = affixPattern->indexOf(kQuote, pos);
4058             if (i < 0) {
4059                 UnicodeString s;
4060                 affixPattern->extractBetween(pos, affixPattern->length(), s);
4061                 appendAffixPattern(appendTo, s, localized);
4062                 break;
4063             }
4064             if (i > pos) {
4065                 UnicodeString s;
4066                 affixPattern->extractBetween(pos, i, s);
4067                 appendAffixPattern(appendTo, s, localized);
4068             }
4069             UChar32 c = affixPattern->char32At(++i);
4070             ++i;
4071             if (c == kQuote) {
4072                 appendTo.append(c).append(c);
4073                 // Fall through and append another kQuote below
4074             } else if (c == kCurrencySign &&
4075                        i<affixPattern->length() &&
4076                        affixPattern->char32At(i) == kCurrencySign) {
4077                 ++i;
4078                 appendTo.append(c).append(c);
4079             } else if (localized) {
4080                 switch (c) {
4081                 case kPatternPercent:
4082                     appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
4083                     break;
4084                 case kPatternPerMill:
4085                     appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
4086                     break;
4087                 case kPatternPlus:
4088                     appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
4089                     break;
4090                 case kPatternMinus:
4091                     appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
4092                     break;
4093                 default:
4094                     appendTo.append(c);
4095                 }
4096             } else {
4097                 appendTo.append(c);
4098             }
4099         }
4100     }
4101 }
4102 
4103 /**
4104  * Append an affix to the given StringBuffer, using quotes if
4105  * there are special characters.  Single quotes themselves must be
4106  * escaped in either case.
4107  */
4108 void
appendAffixPattern(UnicodeString & appendTo,const UnicodeString & affix,UBool localized) const4109 DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
4110                                   const UnicodeString& affix,
4111                                   UBool localized) const {
4112     UBool needQuote;
4113     if(localized) {
4114         needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0
4115             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0
4116             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0
4117             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0
4118             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0
4119             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0
4120             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0
4121             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0
4122             || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0
4123             || affix.indexOf(kCurrencySign) >= 0;
4124     }
4125     else {
4126         needQuote = affix.indexOf(kPatternZeroDigit) >= 0
4127             || affix.indexOf(kPatternGroupingSeparator) >= 0
4128             || affix.indexOf(kPatternDecimalSeparator) >= 0
4129             || affix.indexOf(kPatternPercent) >= 0
4130             || affix.indexOf(kPatternPerMill) >= 0
4131             || affix.indexOf(kPatternDigit) >= 0
4132             || affix.indexOf(kPatternSeparator) >= 0
4133             || affix.indexOf(kPatternExponent) >= 0
4134             || affix.indexOf(kPatternPlus) >= 0
4135             || affix.indexOf(kPatternMinus) >= 0
4136             || affix.indexOf(kCurrencySign) >= 0;
4137     }
4138     if (needQuote)
4139         appendTo += (UChar)0x0027 /*'\''*/;
4140     if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0)
4141         appendTo += affix;
4142     else {
4143         for (int32_t j = 0; j < affix.length(); ) {
4144             UChar32 c = affix.char32At(j);
4145             j += U16_LENGTH(c);
4146             appendTo += c;
4147             if (c == 0x0027 /*'\''*/)
4148                 appendTo += c;
4149         }
4150     }
4151     if (needQuote)
4152         appendTo += (UChar)0x0027 /*'\''*/;
4153 }
4154 
4155 //------------------------------------------------------------------------------
4156 
4157 UnicodeString&
toPattern(UnicodeString & result,UBool localized) const4158 DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
4159 {
4160     if (fStyle == UNUM_CURRENCY_PLURAL) {
4161         // the prefix or suffix pattern might not be defined yet,
4162         // so they can not be synthesized,
4163         // instead, get them directly.
4164         // but it might not be the actual pattern used in formatting.
4165         // the actual pattern used in formatting depends on the
4166         // formatted number's plural count.
4167         result = fFormatPattern;
4168         return result;
4169     }
4170     result.remove();
4171     UChar32 zero, sigDigit = kPatternSignificantDigit;
4172     UnicodeString digit, group;
4173     int32_t i;
4174     int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits
4175     UnicodeString roundingDigits;
4176     int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1;
4177     UnicodeString padSpec;
4178     UBool useSigDig = areSignificantDigitsUsed();
4179 
4180     if (localized) {
4181         digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
4182         group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
4183         zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
4184         if (useSigDig) {
4185             sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
4186         }
4187     }
4188     else {
4189         digit.append((UChar)kPatternDigit);
4190         group.append((UChar)kPatternGroupingSeparator);
4191         zero = (UChar32)kPatternZeroDigit;
4192     }
4193     if (fFormatWidth > 0) {
4194         if (localized) {
4195             padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
4196         }
4197         else {
4198             padSpec.append((UChar)kPatternPadEscape);
4199         }
4200         padSpec.append(fPad);
4201     }
4202     if (fRoundingIncrement != NULL) {
4203         for(i=0; i<fRoundingIncrement->getCount(); ++i) {
4204           roundingDigits.append(zero+(fRoundingIncrement->getDigitValue(i))); // Convert to Unicode digit
4205         }
4206         roundingDecimalPos = fRoundingIncrement->getDecimalAt();
4207     }
4208     for (int32_t part=0; part<2; ++part) {
4209         if (padPos == kPadBeforePrefix) {
4210             result.append(padSpec);
4211         }
4212         appendAffixPattern(result,
4213                     (part==0 ? fPosPrefixPattern : fNegPrefixPattern),
4214                     (part==0 ? fPositivePrefix : fNegativePrefix),
4215                     localized);
4216         if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) {
4217             result.append(padSpec);
4218         }
4219         int32_t sub0Start = result.length();
4220         int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0;
4221         if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
4222             g += fGroupingSize2;
4223         }
4224         int32_t maxDig = 0, minDig = 0, maxSigDig = 0;
4225         if (useSigDig) {
4226             minDig = getMinimumSignificantDigits();
4227             maxDig = maxSigDig = getMaximumSignificantDigits();
4228         } else {
4229             minDig = getMinimumIntegerDigits();
4230             maxDig = getMaximumIntegerDigits();
4231         }
4232         if (fUseExponentialNotation) {
4233             if (maxDig > kMaxScientificIntegerDigits) {
4234                 maxDig = 1;
4235             }
4236         } else if (useSigDig) {
4237             maxDig = _max(maxDig, g+1);
4238         } else {
4239             maxDig = _max(_max(g, getMinimumIntegerDigits()),
4240                           roundingDecimalPos) + 1;
4241         }
4242         for (i = maxDig; i > 0; --i) {
4243             if (!fUseExponentialNotation && i<maxDig &&
4244                 isGroupingPosition(i)) {
4245                 result.append(group);
4246             }
4247             if (useSigDig) {
4248                 //  #@,@###   (maxSigDig == 5, minSigDig == 2)
4249                 //  65 4321   (1-based pos, count from the right)
4250                 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
4251                 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
4252                 if (maxSigDig >= i && i > (maxSigDig - minDig)) {
4253                     result.append(sigDigit);
4254                 } else {
4255                     result.append(digit);
4256                 }
4257             } else {
4258                 if (! roundingDigits.isEmpty()) {
4259                     int32_t pos = roundingDecimalPos - i;
4260                     if (pos >= 0 && pos < roundingDigits.length()) {
4261                         result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
4262                         continue;
4263                     }
4264                 }
4265                 if (i<=minDig) {
4266                     result.append(zero);
4267                 } else {
4268                     result.append(digit);
4269                 }
4270             }
4271         }
4272         if (!useSigDig) {
4273             if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) {
4274                 if (localized) {
4275                     result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
4276                 }
4277                 else {
4278                     result.append((UChar)kPatternDecimalSeparator);
4279                 }
4280             }
4281             int32_t pos = roundingDecimalPos;
4282             for (i = 0; i < getMaximumFractionDigits(); ++i) {
4283                 if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) {
4284                     if (pos < 0) {
4285                         result.append(zero);
4286                     }
4287                     else {
4288                         result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
4289                     }
4290                     ++pos;
4291                     continue;
4292                 }
4293                 if (i<getMinimumFractionDigits()) {
4294                     result.append(zero);
4295                 }
4296                 else {
4297                     result.append(digit);
4298                 }
4299             }
4300         }
4301         if (fUseExponentialNotation) {
4302             if (localized) {
4303                 result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
4304             }
4305             else {
4306                 result.append((UChar)kPatternExponent);
4307             }
4308             if (fExponentSignAlwaysShown) {
4309                 if (localized) {
4310                     result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
4311                 }
4312                 else {
4313                     result.append((UChar)kPatternPlus);
4314                 }
4315             }
4316             for (i=0; i<fMinExponentDigits; ++i) {
4317                 result.append(zero);
4318             }
4319         }
4320         if (! padSpec.isEmpty() && !fUseExponentialNotation) {
4321             int32_t add = fFormatWidth - result.length() + sub0Start
4322                 - ((part == 0)
4323                    ? fPositivePrefix.length() + fPositiveSuffix.length()
4324                    : fNegativePrefix.length() + fNegativeSuffix.length());
4325             while (add > 0) {
4326                 result.insert(sub0Start, digit);
4327                 ++maxDig;
4328                 --add;
4329                 // Only add a grouping separator if we have at least
4330                 // 2 additional characters to be added, so we don't
4331                 // end up with ",###".
4332                 if (add>1 && isGroupingPosition(maxDig)) {
4333                     result.insert(sub0Start, group);
4334                     --add;
4335                 }
4336             }
4337         }
4338         if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) {
4339             result.append(padSpec);
4340         }
4341         if (part == 0) {
4342             appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized);
4343             if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
4344                 result.append(padSpec);
4345             }
4346             UBool isDefault = FALSE;
4347             if ((fNegSuffixPattern == fPosSuffixPattern && // both null
4348                  fNegativeSuffix == fPositiveSuffix)
4349                 || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 &&
4350                     *fNegSuffixPattern == *fPosSuffixPattern))
4351             {
4352                 if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL)
4353                 {
4354                     int32_t length = fPosPrefixPattern->length();
4355                     isDefault = fNegPrefixPattern->length() == (length+2) &&
4356                         (*fNegPrefixPattern)[(int32_t)0] == kQuote &&
4357                         (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus &&
4358                         fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0;
4359                 }
4360                 if (!isDefault &&
4361                     fNegPrefixPattern == NULL && fPosPrefixPattern == NULL)
4362                 {
4363                     int32_t length = fPositivePrefix.length();
4364                     isDefault = fNegativePrefix.length() == (length+1) &&
4365                         fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 &&
4366                         fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0;
4367                 }
4368             }
4369             if (isDefault) {
4370                 break; // Don't output default negative subpattern
4371             } else {
4372                 if (localized) {
4373                     result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
4374                 }
4375                 else {
4376                     result.append((UChar)kPatternSeparator);
4377                 }
4378             }
4379         } else {
4380             appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized);
4381             if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
4382                 result.append(padSpec);
4383             }
4384         }
4385     }
4386 
4387     return result;
4388 }
4389 
4390 //------------------------------------------------------------------------------
4391 
4392 void
applyPattern(const UnicodeString & pattern,UErrorCode & status)4393 DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
4394 {
4395     UParseError parseError;
4396     applyPattern(pattern, FALSE, parseError, status);
4397 }
4398 
4399 //------------------------------------------------------------------------------
4400 
4401 void
applyPattern(const UnicodeString & pattern,UParseError & parseError,UErrorCode & status)4402 DecimalFormat::applyPattern(const UnicodeString& pattern,
4403                             UParseError& parseError,
4404                             UErrorCode& status)
4405 {
4406     applyPattern(pattern, FALSE, parseError, status);
4407 }
4408 //------------------------------------------------------------------------------
4409 
4410 void
applyLocalizedPattern(const UnicodeString & pattern,UErrorCode & status)4411 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
4412 {
4413     UParseError parseError;
4414     applyPattern(pattern, TRUE,parseError,status);
4415 }
4416 
4417 //------------------------------------------------------------------------------
4418 
4419 void
applyLocalizedPattern(const UnicodeString & pattern,UParseError & parseError,UErrorCode & status)4420 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
4421                                      UParseError& parseError,
4422                                      UErrorCode& status)
4423 {
4424     applyPattern(pattern, TRUE,parseError,status);
4425 }
4426 
4427 //------------------------------------------------------------------------------
4428 
4429 void
applyPatternWithoutExpandAffix(const UnicodeString & pattern,UBool localized,UParseError & parseError,UErrorCode & status)4430 DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern,
4431                                               UBool localized,
4432                                               UParseError& parseError,
4433                                               UErrorCode& status)
4434 {
4435     if (U_FAILURE(status))
4436     {
4437         return;
4438     }
4439     // Clear error struct
4440     parseError.offset = -1;
4441     parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
4442 
4443     // Set the significant pattern symbols
4444     UChar32 zeroDigit               = kPatternZeroDigit; // '0'
4445     UChar32 sigDigit                = kPatternSignificantDigit; // '@'
4446     UnicodeString groupingSeparator ((UChar)kPatternGroupingSeparator);
4447     UnicodeString decimalSeparator  ((UChar)kPatternDecimalSeparator);
4448     UnicodeString percent           ((UChar)kPatternPercent);
4449     UnicodeString perMill           ((UChar)kPatternPerMill);
4450     UnicodeString digit             ((UChar)kPatternDigit); // '#'
4451     UnicodeString separator         ((UChar)kPatternSeparator);
4452     UnicodeString exponent          ((UChar)kPatternExponent);
4453     UnicodeString plus              ((UChar)kPatternPlus);
4454     UnicodeString minus             ((UChar)kPatternMinus);
4455     UnicodeString padEscape         ((UChar)kPatternPadEscape);
4456     // Substitute with the localized symbols if necessary
4457     if (localized) {
4458         zeroDigit = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
4459         sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
4460         groupingSeparator.  remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
4461         decimalSeparator.   remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
4462         percent.            remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
4463         perMill.            remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
4464         digit.              remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
4465         separator.          remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
4466         exponent.           remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol));
4467         plus.               remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol));
4468         minus.              remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
4469         padEscape.          remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
4470     }
4471     UChar nineDigit = (UChar)(zeroDigit + 9);
4472     int32_t digitLen = digit.length();
4473     int32_t groupSepLen = groupingSeparator.length();
4474     int32_t decimalSepLen = decimalSeparator.length();
4475 
4476     int32_t pos = 0;
4477     int32_t patLen = pattern.length();
4478     // Part 0 is the positive pattern.  Part 1, if present, is the negative
4479     // pattern.
4480     for (int32_t part=0; part<2 && pos<patLen; ++part) {
4481         // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
4482         // 2=suffix, 3=prefix in quote, 4=suffix in quote.  Subpart 0 is
4483         // between the prefix and suffix, and consists of pattern
4484         // characters.  In the prefix and suffix, percent, perMill, and
4485         // currency symbols are recognized and translated.
4486         int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
4487 
4488         // It's important that we don't change any fields of this object
4489         // prematurely.  We set the following variables for the multiplier,
4490         // grouping, etc., and then only change the actual object fields if
4491         // everything parses correctly.  This also lets us register
4492         // the data from part 0 and ignore the part 1, except for the
4493         // prefix and suffix.
4494         UnicodeString prefix;
4495         UnicodeString suffix;
4496         int32_t decimalPos = -1;
4497         int32_t multiplier = 1;
4498         int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
4499         int8_t groupingCount = -1;
4500         int8_t groupingCount2 = -1;
4501         int32_t padPos = -1;
4502         UChar32 padChar = 0;
4503         int32_t roundingPos = -1;
4504         DigitList roundingInc;
4505         int8_t expDigits = -1;
4506         UBool expSignAlways = FALSE;
4507 
4508         // The affix is either the prefix or the suffix.
4509         UnicodeString* affix = &prefix;
4510 
4511         int32_t start = pos;
4512         UBool isPartDone = FALSE;
4513         UChar32 ch;
4514 
4515         for (; !isPartDone && pos < patLen; ) {
4516             // Todo: account for surrogate pairs
4517             ch = pattern.char32At(pos);
4518             switch (subpart) {
4519             case 0: // Pattern proper subpart (between prefix & suffix)
4520                 // Process the digits, decimal, and grouping characters.  We
4521                 // record five pieces of information.  We expect the digits
4522                 // to occur in the pattern ####00.00####, and we record the
4523                 // number of left digits, zero (central) digits, and right
4524                 // digits.  The position of the last grouping character is
4525                 // recorded (should be somewhere within the first two blocks
4526                 // of characters), as is the position of the decimal point,
4527                 // if any (should be in the zero digits).  If there is no
4528                 // decimal point, then there should be no right digits.
4529                 if (pattern.compare(pos, digitLen, digit) == 0) {
4530                     if (zeroDigitCount > 0 || sigDigitCount > 0) {
4531                         ++digitRightCount;
4532                     } else {
4533                         ++digitLeftCount;
4534                     }
4535                     if (groupingCount >= 0 && decimalPos < 0) {
4536                         ++groupingCount;
4537                     }
4538                     pos += digitLen;
4539                 } else if ((ch >= zeroDigit && ch <= nineDigit) ||
4540                            ch == sigDigit) {
4541                     if (digitRightCount > 0) {
4542                         // Unexpected '0'
4543                         debug("Unexpected '0'")
4544                         status = U_UNEXPECTED_TOKEN;
4545                         syntaxError(pattern,pos,parseError);
4546                         return;
4547                     }
4548                     if (ch == sigDigit) {
4549                         ++sigDigitCount;
4550                     } else {
4551                         if (ch != zeroDigit && roundingPos < 0) {
4552                             roundingPos = digitLeftCount + zeroDigitCount;
4553                         }
4554                         if (roundingPos >= 0) {
4555                             roundingInc.append((char)(ch - zeroDigit + '0'));
4556                         }
4557                         ++zeroDigitCount;
4558                     }
4559                     if (groupingCount >= 0 && decimalPos < 0) {
4560                         ++groupingCount;
4561                     }
4562                     pos += U16_LENGTH(ch);
4563                 } else if (pattern.compare(pos, groupSepLen, groupingSeparator) == 0) {
4564                     if (decimalPos >= 0) {
4565                         // Grouping separator after decimal
4566                         debug("Grouping separator after decimal")
4567                         status = U_UNEXPECTED_TOKEN;
4568                         syntaxError(pattern,pos,parseError);
4569                         return;
4570                     }
4571                     groupingCount2 = groupingCount;
4572                     groupingCount = 0;
4573                     pos += groupSepLen;
4574                 } else if (pattern.compare(pos, decimalSepLen, decimalSeparator) == 0) {
4575                     if (decimalPos >= 0) {
4576                         // Multiple decimal separators
4577                         debug("Multiple decimal separators")
4578                         status = U_MULTIPLE_DECIMAL_SEPARATORS;
4579                         syntaxError(pattern,pos,parseError);
4580                         return;
4581                     }
4582                     // Intentionally incorporate the digitRightCount,
4583                     // even though it is illegal for this to be > 0
4584                     // at this point.  We check pattern syntax below.
4585                     decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
4586                     pos += decimalSepLen;
4587                 } else {
4588                     if (pattern.compare(pos, exponent.length(), exponent) == 0) {
4589                         if (expDigits >= 0) {
4590                             // Multiple exponential symbols
4591                             debug("Multiple exponential symbols")
4592                             status = U_MULTIPLE_EXPONENTIAL_SYMBOLS;
4593                             syntaxError(pattern,pos,parseError);
4594                             return;
4595                         }
4596                         if (groupingCount >= 0) {
4597                             // Grouping separator in exponential pattern
4598                             debug("Grouping separator in exponential pattern")
4599                             status = U_MALFORMED_EXPONENTIAL_PATTERN;
4600                             syntaxError(pattern,pos,parseError);
4601                             return;
4602                         }
4603                         pos += exponent.length();
4604                         // Check for positive prefix
4605                         if (pos < patLen
4606                             && pattern.compare(pos, plus.length(), plus) == 0) {
4607                             expSignAlways = TRUE;
4608                             pos += plus.length();
4609                         }
4610                         // Use lookahead to parse out the exponential part of the
4611                         // pattern, then jump into suffix subpart.
4612                         expDigits = 0;
4613                         while (pos < patLen &&
4614                                pattern.char32At(pos) == zeroDigit) {
4615                             ++expDigits;
4616                             pos += U16_LENGTH(zeroDigit);
4617                         }
4618 
4619                         // 1. Require at least one mantissa pattern digit
4620                         // 2. Disallow "#+ @" in mantissa
4621                         // 3. Require at least one exponent pattern digit
4622                         if (((digitLeftCount + zeroDigitCount) < 1 &&
4623                              (sigDigitCount + digitRightCount) < 1) ||
4624                             (sigDigitCount > 0 && digitLeftCount > 0) ||
4625                             expDigits < 1) {
4626                             // Malformed exponential pattern
4627                             debug("Malformed exponential pattern")
4628                             status = U_MALFORMED_EXPONENTIAL_PATTERN;
4629                             syntaxError(pattern,pos,parseError);
4630                             return;
4631                         }
4632                     }
4633                     // Transition to suffix subpart
4634                     subpart = 2; // suffix subpart
4635                     affix = &suffix;
4636                     sub0Limit = pos;
4637                     continue;
4638                 }
4639                 break;
4640             case 1: // Prefix subpart
4641             case 2: // Suffix subpart
4642                 // Process the prefix / suffix characters
4643                 // Process unquoted characters seen in prefix or suffix
4644                 // subpart.
4645 
4646                 // Several syntax characters implicitly begins the
4647                 // next subpart if we are in the prefix; otherwise
4648                 // they are illegal if unquoted.
4649                 if (!pattern.compare(pos, digitLen, digit) ||
4650                     !pattern.compare(pos, groupSepLen, groupingSeparator) ||
4651                     !pattern.compare(pos, decimalSepLen, decimalSeparator) ||
4652                     (ch >= zeroDigit && ch <= nineDigit) ||
4653                     ch == sigDigit) {
4654                     if (subpart == 1) { // prefix subpart
4655                         subpart = 0; // pattern proper subpart
4656                         sub0Start = pos; // Reprocess this character
4657                         continue;
4658                     } else {
4659                         status = U_UNQUOTED_SPECIAL;
4660                         syntaxError(pattern,pos,parseError);
4661                         return;
4662                     }
4663                 } else if (ch == kCurrencySign) {
4664                     affix->append(kQuote); // Encode currency
4665                     // Use lookahead to determine if the currency sign is
4666                     // doubled or not.
4667                     U_ASSERT(U16_LENGTH(kCurrencySign) == 1);
4668                     if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) {
4669                         affix->append(kCurrencySign);
4670                         ++pos; // Skip over the doubled character
4671                         if ((pos+1) < pattern.length() &&
4672                             pattern[pos+1] == kCurrencySign) {
4673                             affix->append(kCurrencySign);
4674                             ++pos; // Skip over the doubled character
4675                             fCurrencySignCount = fgCurrencySignCountInPluralFormat;
4676                         } else {
4677                             fCurrencySignCount = fgCurrencySignCountInISOFormat;
4678                         }
4679                     } else {
4680                         fCurrencySignCount = fgCurrencySignCountInSymbolFormat;
4681                     }
4682                     // Fall through to append(ch)
4683                 } else if (ch == kQuote) {
4684                     // A quote outside quotes indicates either the opening
4685                     // quote or two quotes, which is a quote literal.  That is,
4686                     // we have the first quote in 'do' or o''clock.
4687                     U_ASSERT(U16_LENGTH(kQuote) == 1);
4688                     ++pos;
4689                     if (pos < pattern.length() && pattern[pos] == kQuote) {
4690                         affix->append(kQuote); // Encode quote
4691                         // Fall through to append(ch)
4692                     } else {
4693                         subpart += 2; // open quote
4694                         continue;
4695                     }
4696                 } else if (pattern.compare(pos, separator.length(), separator) == 0) {
4697                     // Don't allow separators in the prefix, and don't allow
4698                     // separators in the second pattern (part == 1).
4699                     if (subpart == 1 || part == 1) {
4700                         // Unexpected separator
4701                         debug("Unexpected separator")
4702                         status = U_UNEXPECTED_TOKEN;
4703                         syntaxError(pattern,pos,parseError);
4704                         return;
4705                     }
4706                     sub2Limit = pos;
4707                     isPartDone = TRUE; // Go to next part
4708                     pos += separator.length();
4709                     break;
4710                 } else if (pattern.compare(pos, percent.length(), percent) == 0) {
4711                     // Next handle characters which are appended directly.
4712                     if (multiplier != 1) {
4713                         // Too many percent/perMill characters
4714                         debug("Too many percent characters")
4715                         status = U_MULTIPLE_PERCENT_SYMBOLS;
4716                         syntaxError(pattern,pos,parseError);
4717                         return;
4718                     }
4719                     affix->append(kQuote); // Encode percent/perMill
4720                     affix->append(kPatternPercent); // Use unlocalized pattern char
4721                     multiplier = 100;
4722                     pos += percent.length();
4723                     break;
4724                 } else if (pattern.compare(pos, perMill.length(), perMill) == 0) {
4725                     // Next handle characters which are appended directly.
4726                     if (multiplier != 1) {
4727                         // Too many percent/perMill characters
4728                         debug("Too many perMill characters")
4729                         status = U_MULTIPLE_PERMILL_SYMBOLS;
4730                         syntaxError(pattern,pos,parseError);
4731                         return;
4732                     }
4733                     affix->append(kQuote); // Encode percent/perMill
4734                     affix->append(kPatternPerMill); // Use unlocalized pattern char
4735                     multiplier = 1000;
4736                     pos += perMill.length();
4737                     break;
4738                 } else if (pattern.compare(pos, padEscape.length(), padEscape) == 0) {
4739                     if (padPos >= 0 ||               // Multiple pad specifiers
4740                         (pos+1) == pattern.length()) { // Nothing after padEscape
4741                         debug("Multiple pad specifiers")
4742                         status = U_MULTIPLE_PAD_SPECIFIERS;
4743                         syntaxError(pattern,pos,parseError);
4744                         return;
4745                     }
4746                     padPos = pos;
4747                     pos += padEscape.length();
4748                     padChar = pattern.char32At(pos);
4749                     pos += U16_LENGTH(padChar);
4750                     break;
4751                 } else if (pattern.compare(pos, minus.length(), minus) == 0) {
4752                     affix->append(kQuote); // Encode minus
4753                     affix->append(kPatternMinus);
4754                     pos += minus.length();
4755                     break;
4756                 } else if (pattern.compare(pos, plus.length(), plus) == 0) {
4757                     affix->append(kQuote); // Encode plus
4758                     affix->append(kPatternPlus);
4759                     pos += plus.length();
4760                     break;
4761                 }
4762                 // Unquoted, non-special characters fall through to here, as
4763                 // well as other code which needs to append something to the
4764                 // affix.
4765                 affix->append(ch);
4766                 pos += U16_LENGTH(ch);
4767                 break;
4768             case 3: // Prefix subpart, in quote
4769             case 4: // Suffix subpart, in quote
4770                 // A quote within quotes indicates either the closing
4771                 // quote or two quotes, which is a quote literal.  That is,
4772                 // we have the second quote in 'do' or 'don''t'.
4773                 if (ch == kQuote) {
4774                     ++pos;
4775                     if (pos < pattern.length() && pattern[pos] == kQuote) {
4776                         affix->append(kQuote); // Encode quote
4777                         // Fall through to append(ch)
4778                     } else {
4779                         subpart -= 2; // close quote
4780                         continue;
4781                     }
4782                 }
4783                 affix->append(ch);
4784                 pos += U16_LENGTH(ch);
4785                 break;
4786             }
4787         }
4788 
4789         if (sub0Limit == 0) {
4790             sub0Limit = pattern.length();
4791         }
4792 
4793         if (sub2Limit == 0) {
4794             sub2Limit = pattern.length();
4795         }
4796 
4797         /* Handle patterns with no '0' pattern character.  These patterns
4798          * are legal, but must be recodified to make sense.  "##.###" ->
4799          * "#0.###".  ".###" -> ".0##".
4800          *
4801          * We allow patterns of the form "####" to produce a zeroDigitCount
4802          * of zero (got that?); although this seems like it might make it
4803          * possible for format() to produce empty strings, format() checks
4804          * for this condition and outputs a zero digit in this situation.
4805          * Having a zeroDigitCount of zero yields a minimum integer digits
4806          * of zero, which allows proper round-trip patterns.  We don't want
4807          * "#" to become "#0" when toPattern() is called (even though that's
4808          * what it really is, semantically).
4809          */
4810         if (zeroDigitCount == 0 && sigDigitCount == 0 &&
4811             digitLeftCount > 0 && decimalPos >= 0) {
4812             // Handle "###.###" and "###." and ".###"
4813             int n = decimalPos;
4814             if (n == 0)
4815                 ++n; // Handle ".###"
4816             digitRightCount = digitLeftCount - n;
4817             digitLeftCount = n - 1;
4818             zeroDigitCount = 1;
4819         }
4820 
4821         // Do syntax checking on the digits, decimal points, and quotes.
4822         if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
4823             (decimalPos >= 0 &&
4824              (sigDigitCount > 0 ||
4825               decimalPos < digitLeftCount ||
4826               decimalPos > (digitLeftCount + zeroDigitCount))) ||
4827             groupingCount == 0 || groupingCount2 == 0 ||
4828             (sigDigitCount > 0 && zeroDigitCount > 0) ||
4829             subpart > 2)
4830         { // subpart > 2 == unmatched quote
4831             debug("Syntax error")
4832             status = U_PATTERN_SYNTAX_ERROR;
4833             syntaxError(pattern,pos,parseError);
4834             return;
4835         }
4836 
4837         // Make sure pad is at legal position before or after affix.
4838         if (padPos >= 0) {
4839             if (padPos == start) {
4840                 padPos = kPadBeforePrefix;
4841             } else if (padPos+2 == sub0Start) {
4842                 padPos = kPadAfterPrefix;
4843             } else if (padPos == sub0Limit) {
4844                 padPos = kPadBeforeSuffix;
4845             } else if (padPos+2 == sub2Limit) {
4846                 padPos = kPadAfterSuffix;
4847             } else {
4848                 // Illegal pad position
4849                 debug("Illegal pad position")
4850                 status = U_ILLEGAL_PAD_POSITION;
4851                 syntaxError(pattern,pos,parseError);
4852                 return;
4853             }
4854         }
4855 
4856         if (part == 0) {
4857             delete fPosPrefixPattern;
4858             delete fPosSuffixPattern;
4859             delete fNegPrefixPattern;
4860             delete fNegSuffixPattern;
4861             fPosPrefixPattern = new UnicodeString(prefix);
4862             /* test for NULL */
4863             if (fPosPrefixPattern == 0) {
4864                 status = U_MEMORY_ALLOCATION_ERROR;
4865                 return;
4866             }
4867             fPosSuffixPattern = new UnicodeString(suffix);
4868             /* test for NULL */
4869             if (fPosSuffixPattern == 0) {
4870                 status = U_MEMORY_ALLOCATION_ERROR;
4871                 delete fPosPrefixPattern;
4872                 return;
4873             }
4874             fNegPrefixPattern = 0;
4875             fNegSuffixPattern = 0;
4876 
4877             fUseExponentialNotation = (expDigits >= 0);
4878             if (fUseExponentialNotation) {
4879                 fMinExponentDigits = expDigits;
4880             }
4881             fExponentSignAlwaysShown = expSignAlways;
4882             int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
4883             // The effectiveDecimalPos is the position the decimal is at or
4884             // would be at if there is no decimal.  Note that if
4885             // decimalPos<0, then digitTotalCount == digitLeftCount +
4886             // zeroDigitCount.
4887             int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
4888             UBool isSigDig = (sigDigitCount > 0);
4889             setSignificantDigitsUsed(isSigDig);
4890             if (isSigDig) {
4891                 setMinimumSignificantDigits(sigDigitCount);
4892                 setMaximumSignificantDigits(sigDigitCount + digitRightCount);
4893             } else {
4894                 int32_t minInt = effectiveDecimalPos - digitLeftCount;
4895                 setMinimumIntegerDigits(minInt);
4896                 setMaximumIntegerDigits(fUseExponentialNotation
4897                     ? digitLeftCount + getMinimumIntegerDigits()
4898                     : kDoubleIntegerDigits);
4899                 setMaximumFractionDigits(decimalPos >= 0
4900                     ? (digitTotalCount - decimalPos) : 0);
4901                 setMinimumFractionDigits(decimalPos >= 0
4902                     ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
4903             }
4904             setGroupingUsed(groupingCount > 0);
4905             fGroupingSize = (groupingCount > 0) ? groupingCount : 0;
4906             fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
4907                 ? groupingCount2 : 0;
4908             setMultiplier(multiplier);
4909             setDecimalSeparatorAlwaysShown(decimalPos == 0
4910                     || decimalPos == digitTotalCount);
4911             if (padPos >= 0) {
4912                 fPadPosition = (EPadPosition) padPos;
4913                 // To compute the format width, first set up sub0Limit -
4914                 // sub0Start.  Add in prefix/suffix length later.
4915 
4916                 // fFormatWidth = prefix.length() + suffix.length() +
4917                 //    sub0Limit - sub0Start;
4918                 fFormatWidth = sub0Limit - sub0Start;
4919                 fPad = padChar;
4920             } else {
4921                 fFormatWidth = 0;
4922             }
4923             if (roundingPos >= 0) {
4924                 roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos);
4925                 if (fRoundingIncrement != NULL) {
4926                     *fRoundingIncrement = roundingInc;
4927                 } else {
4928                     fRoundingIncrement = new DigitList(roundingInc);
4929                     /* test for NULL */
4930                     if (fRoundingIncrement == NULL) {
4931                         status = U_MEMORY_ALLOCATION_ERROR;
4932                         delete fPosPrefixPattern;
4933                         delete fPosSuffixPattern;
4934                         return;
4935                     }
4936                 }
4937                 fRoundingMode = kRoundHalfEven;
4938             } else {
4939                 setRoundingIncrement(0.0);
4940             }
4941         } else {
4942             fNegPrefixPattern = new UnicodeString(prefix);
4943             /* test for NULL */
4944             if (fNegPrefixPattern == 0) {
4945                 status = U_MEMORY_ALLOCATION_ERROR;
4946                 return;
4947             }
4948             fNegSuffixPattern = new UnicodeString(suffix);
4949             /* test for NULL */
4950             if (fNegSuffixPattern == 0) {
4951                 delete fNegPrefixPattern;
4952                 status = U_MEMORY_ALLOCATION_ERROR;
4953                 return;
4954             }
4955         }
4956     }
4957 
4958     if (pattern.length() == 0) {
4959         delete fNegPrefixPattern;
4960         delete fNegSuffixPattern;
4961         fNegPrefixPattern = NULL;
4962         fNegSuffixPattern = NULL;
4963         if (fPosPrefixPattern != NULL) {
4964             fPosPrefixPattern->remove();
4965         } else {
4966             fPosPrefixPattern = new UnicodeString();
4967             /* test for NULL */
4968             if (fPosPrefixPattern == 0) {
4969                 status = U_MEMORY_ALLOCATION_ERROR;
4970                 return;
4971             }
4972         }
4973         if (fPosSuffixPattern != NULL) {
4974             fPosSuffixPattern->remove();
4975         } else {
4976             fPosSuffixPattern = new UnicodeString();
4977             /* test for NULL */
4978             if (fPosSuffixPattern == 0) {
4979                 delete fPosPrefixPattern;
4980                 status = U_MEMORY_ALLOCATION_ERROR;
4981                 return;
4982             }
4983         }
4984 
4985         setMinimumIntegerDigits(0);
4986         setMaximumIntegerDigits(kDoubleIntegerDigits);
4987         setMinimumFractionDigits(0);
4988         setMaximumFractionDigits(kDoubleFractionDigits);
4989 
4990         fUseExponentialNotation = FALSE;
4991         fCurrencySignCount = 0;
4992         setGroupingUsed(FALSE);
4993         fGroupingSize = 0;
4994         fGroupingSize2 = 0;
4995         setMultiplier(1);
4996         setDecimalSeparatorAlwaysShown(FALSE);
4997         fFormatWidth = 0;
4998         setRoundingIncrement(0.0);
4999     }
5000 
5001     // If there was no negative pattern, or if the negative pattern is
5002     // identical to the positive pattern, then prepend the minus sign to the
5003     // positive pattern to form the negative pattern.
5004     if (fNegPrefixPattern == NULL ||
5005         (*fNegPrefixPattern == *fPosPrefixPattern
5006          && *fNegSuffixPattern == *fPosSuffixPattern)) {
5007         _copy_ptr(&fNegSuffixPattern, fPosSuffixPattern);
5008         if (fNegPrefixPattern == NULL) {
5009             fNegPrefixPattern = new UnicodeString();
5010             /* test for NULL */
5011             if (fNegPrefixPattern == 0) {
5012                 status = U_MEMORY_ALLOCATION_ERROR;
5013                 return;
5014             }
5015         } else {
5016             fNegPrefixPattern->remove();
5017         }
5018         fNegPrefixPattern->append(kQuote).append(kPatternMinus)
5019             .append(*fPosPrefixPattern);
5020     }
5021 #ifdef FMT_DEBUG
5022     UnicodeString s;
5023     s.append((UnicodeString)"\"").append(pattern).append((UnicodeString)"\"->");
5024     debugout(s);
5025 #endif
5026 
5027     // save the pattern
5028     fFormatPattern = pattern;
5029 }
5030 
5031 
5032 void
expandAffixAdjustWidth(const UnicodeString * pluralCount)5033 DecimalFormat::expandAffixAdjustWidth(const UnicodeString* pluralCount) {
5034     expandAffixes(pluralCount);
5035     if (fFormatWidth > 0) {
5036         // Finish computing format width (see above)
5037             // TODO: how to handle fFormatWidth,
5038             // need to save in f(Plural)AffixesForCurrecy?
5039             fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length();
5040     }
5041 }
5042 
5043 
5044 void
applyPattern(const UnicodeString & pattern,UBool localized,UParseError & parseError,UErrorCode & status)5045 DecimalFormat::applyPattern(const UnicodeString& pattern,
5046                             UBool localized,
5047                             UParseError& parseError,
5048                             UErrorCode& status)
5049 {
5050     // do the following re-set first. since they change private data by
5051     // apply pattern again.
5052     if (pattern.indexOf(kCurrencySign) != -1) {
5053         if (fCurrencyPluralInfo == NULL) {
5054             // initialize currencyPluralInfo if needed
5055             fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
5056         }
5057         if (fAffixPatternsForCurrency == NULL) {
5058             setupCurrencyAffixPatterns(status);
5059         }
5060         if (pattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) {
5061             // only setup the affixes of the current pattern.
5062             setupCurrencyAffixes(pattern, TRUE, FALSE, status);
5063         }
5064     }
5065     applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
5066     expandAffixAdjustWidth(NULL);
5067 #if UCONFIG_FORMAT_FASTPATHS_49
5068     handleChanged();
5069 #endif
5070 }
5071 
5072 
5073 void
applyPatternInternally(const UnicodeString & pluralCount,const UnicodeString & pattern,UBool localized,UParseError & parseError,UErrorCode & status)5074 DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount,
5075                                       const UnicodeString& pattern,
5076                                       UBool localized,
5077                                       UParseError& parseError,
5078                                       UErrorCode& status) {
5079     applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
5080     expandAffixAdjustWidth(&pluralCount);
5081 #if UCONFIG_FORMAT_FASTPATHS_49
5082     handleChanged();
5083 #endif
5084 }
5085 
5086 
5087 /**
5088  * Sets the maximum number of digits allowed in the integer portion of a
5089  * number. This override limits the integer digit count to 309.
5090  * @see NumberFormat#setMaximumIntegerDigits
5091  */
setMaximumIntegerDigits(int32_t newValue)5092 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
5093     NumberFormat::setMaximumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
5094 #if UCONFIG_FORMAT_FASTPATHS_49
5095     handleChanged();
5096 #endif
5097 }
5098 
5099 /**
5100  * Sets the minimum number of digits allowed in the integer portion of a
5101  * number. This override limits the integer digit count to 309.
5102  * @see NumberFormat#setMinimumIntegerDigits
5103  */
setMinimumIntegerDigits(int32_t newValue)5104 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
5105     NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
5106 #if UCONFIG_FORMAT_FASTPATHS_49
5107     handleChanged();
5108 #endif
5109 }
5110 
5111 /**
5112  * Sets the maximum number of digits allowed in the fraction portion of a
5113  * number. This override limits the fraction digit count to 340.
5114  * @see NumberFormat#setMaximumFractionDigits
5115  */
setMaximumFractionDigits(int32_t newValue)5116 void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
5117     NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits));
5118 #if UCONFIG_FORMAT_FASTPATHS_49
5119     handleChanged();
5120 #endif
5121 }
5122 
5123 /**
5124  * Sets the minimum number of digits allowed in the fraction portion of a
5125  * number. This override limits the fraction digit count to 340.
5126  * @see NumberFormat#setMinimumFractionDigits
5127  */
setMinimumFractionDigits(int32_t newValue)5128 void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
5129     NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits));
5130 #if UCONFIG_FORMAT_FASTPATHS_49
5131     handleChanged();
5132 #endif
5133 }
5134 
getMinimumSignificantDigits() const5135 int32_t DecimalFormat::getMinimumSignificantDigits() const {
5136     return fMinSignificantDigits;
5137 }
5138 
getMaximumSignificantDigits() const5139 int32_t DecimalFormat::getMaximumSignificantDigits() const {
5140     return fMaxSignificantDigits;
5141 }
5142 
setMinimumSignificantDigits(int32_t min)5143 void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
5144     if (min < 1) {
5145         min = 1;
5146     }
5147     // pin max sig dig to >= min
5148     int32_t max = _max(fMaxSignificantDigits, min);
5149     fMinSignificantDigits = min;
5150     fMaxSignificantDigits = max;
5151 #if UCONFIG_FORMAT_FASTPATHS_49
5152     handleChanged();
5153 #endif
5154 }
5155 
setMaximumSignificantDigits(int32_t max)5156 void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
5157     if (max < 1) {
5158         max = 1;
5159     }
5160     // pin min sig dig to 1..max
5161     U_ASSERT(fMinSignificantDigits >= 1);
5162     int32_t min = _min(fMinSignificantDigits, max);
5163     fMinSignificantDigits = min;
5164     fMaxSignificantDigits = max;
5165 #if UCONFIG_FORMAT_FASTPATHS_49
5166     handleChanged();
5167 #endif
5168 }
5169 
areSignificantDigitsUsed() const5170 UBool DecimalFormat::areSignificantDigitsUsed() const {
5171     return fUseSignificantDigits;
5172 }
5173 
setSignificantDigitsUsed(UBool useSignificantDigits)5174 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
5175     fUseSignificantDigits = useSignificantDigits;
5176 #if UCONFIG_FORMAT_FASTPATHS_49
5177     handleChanged();
5178 #endif
5179 }
5180 
setCurrencyInternally(const UChar * theCurrency,UErrorCode & ec)5181 void DecimalFormat::setCurrencyInternally(const UChar* theCurrency,
5182                                           UErrorCode& ec) {
5183     // If we are a currency format, then modify our affixes to
5184     // encode the currency symbol for the given currency in our
5185     // locale, and adjust the decimal digits and rounding for the
5186     // given currency.
5187 
5188     // Note: The code is ordered so that this object is *not changed*
5189     // until we are sure we are going to succeed.
5190 
5191     // NULL or empty currency is *legal* and indicates no currency.
5192     UBool isCurr = (theCurrency && *theCurrency);
5193 
5194     double rounding = 0.0;
5195     int32_t frac = 0;
5196     if (fCurrencySignCount > fgCurrencySignCountZero && isCurr) {
5197         rounding = ucurr_getRoundingIncrement(theCurrency, &ec);
5198         frac = ucurr_getDefaultFractionDigits(theCurrency, &ec);
5199     }
5200 
5201     NumberFormat::setCurrency(theCurrency, ec);
5202     if (U_FAILURE(ec)) return;
5203 
5204     if (fCurrencySignCount > fgCurrencySignCountZero) {
5205         // NULL or empty currency is *legal* and indicates no currency.
5206         if (isCurr) {
5207             setRoundingIncrement(rounding);
5208             setMinimumFractionDigits(frac);
5209             setMaximumFractionDigits(frac);
5210         }
5211         expandAffixes(NULL);
5212     }
5213 #if UCONFIG_FORMAT_FASTPATHS_49
5214     handleChanged();
5215 #endif
5216 }
5217 
setCurrency(const UChar * theCurrency,UErrorCode & ec)5218 void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
5219     // set the currency before compute affixes to get the right currency names
5220     NumberFormat::setCurrency(theCurrency, ec);
5221     if (fFormatPattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) {
5222         UnicodeString savedPtn = fFormatPattern;
5223         setupCurrencyAffixes(fFormatPattern, TRUE, TRUE, ec);
5224         UParseError parseErr;
5225         applyPattern(savedPtn, FALSE, parseErr, ec);
5226     }
5227     // set the currency after apply pattern to get the correct rounding/fraction
5228     setCurrencyInternally(theCurrency, ec);
5229 #if UCONFIG_FORMAT_FASTPATHS_49
5230     handleChanged();
5231 #endif
5232 }
5233 
5234 // Deprecated variant with no UErrorCode parameter
setCurrency(const UChar * theCurrency)5235 void DecimalFormat::setCurrency(const UChar* theCurrency) {
5236     UErrorCode ec = U_ZERO_ERROR;
5237     setCurrency(theCurrency, ec);
5238 #if UCONFIG_FORMAT_FASTPATHS_49
5239     handleChanged();
5240 #endif
5241 }
5242 
getEffectiveCurrency(UChar * result,UErrorCode & ec) const5243 void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
5244     if (fSymbols == NULL) {
5245         ec = U_MEMORY_ALLOCATION_ERROR;
5246         return;
5247     }
5248     ec = U_ZERO_ERROR;
5249     const UChar* c = getCurrency();
5250     if (*c == 0) {
5251         const UnicodeString &intl =
5252             fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
5253         c = intl.getBuffer(); // ok for intl to go out of scope
5254     }
5255     u_strncpy(result, c, 3);
5256     result[3] = 0;
5257 }
5258 
5259 /**
5260  * Return the number of fraction digits to display, or the total
5261  * number of digits for significant digit formats and exponential
5262  * formats.
5263  */
5264 int32_t
precision() const5265 DecimalFormat::precision() const {
5266     if (areSignificantDigitsUsed()) {
5267         return getMaximumSignificantDigits();
5268     } else if (fUseExponentialNotation) {
5269         return getMinimumIntegerDigits() + getMaximumFractionDigits();
5270     } else {
5271         return getMaximumFractionDigits();
5272     }
5273 }
5274 
5275 
5276 // TODO: template algorithm
5277 Hashtable*
initHashForAffix(UErrorCode & status)5278 DecimalFormat::initHashForAffix(UErrorCode& status) {
5279     if ( U_FAILURE(status) ) {
5280         return NULL;
5281     }
5282     Hashtable* hTable;
5283     if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
5284         status = U_MEMORY_ALLOCATION_ERROR;
5285         return NULL;
5286     }
5287     if ( U_FAILURE(status) ) {
5288         delete hTable;
5289         return NULL;
5290     }
5291     hTable->setValueComparator(decimfmtAffixValueComparator);
5292     return hTable;
5293 }
5294 
5295 Hashtable*
initHashForAffixPattern(UErrorCode & status)5296 DecimalFormat::initHashForAffixPattern(UErrorCode& status) {
5297     if ( U_FAILURE(status) ) {
5298         return NULL;
5299     }
5300     Hashtable* hTable;
5301     if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
5302         status = U_MEMORY_ALLOCATION_ERROR;
5303         return NULL;
5304     }
5305     if ( U_FAILURE(status) ) {
5306         delete hTable;
5307         return NULL;
5308     }
5309     hTable->setValueComparator(decimfmtAffixPatternValueComparator);
5310     return hTable;
5311 }
5312 
5313 void
deleteHashForAffix(Hashtable * & table)5314 DecimalFormat::deleteHashForAffix(Hashtable*& table)
5315 {
5316     if ( table == NULL ) {
5317         return;
5318     }
5319     int32_t pos = -1;
5320     const UHashElement* element = NULL;
5321     while ( (element = table->nextElement(pos)) != NULL ) {
5322         const UHashTok valueTok = element->value;
5323         const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer;
5324         delete value;
5325     }
5326     delete table;
5327     table = NULL;
5328 }
5329 
5330 
5331 
5332 void
deleteHashForAffixPattern()5333 DecimalFormat::deleteHashForAffixPattern()
5334 {
5335     if ( fAffixPatternsForCurrency == NULL ) {
5336         return;
5337     }
5338     int32_t pos = -1;
5339     const UHashElement* element = NULL;
5340     while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
5341         const UHashTok valueTok = element->value;
5342         const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer;
5343         delete value;
5344     }
5345     delete fAffixPatternsForCurrency;
5346     fAffixPatternsForCurrency = NULL;
5347 }
5348 
5349 
5350 void
copyHashForAffixPattern(const Hashtable * source,Hashtable * target,UErrorCode & status)5351 DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
5352                                        Hashtable* target,
5353                                        UErrorCode& status) {
5354     if ( U_FAILURE(status) ) {
5355         return;
5356     }
5357     int32_t pos = -1;
5358     const UHashElement* element = NULL;
5359     if ( source ) {
5360         while ( (element = source->nextElement(pos)) != NULL ) {
5361             const UHashTok keyTok = element->key;
5362             const UnicodeString* key = (UnicodeString*)keyTok.pointer;
5363             const UHashTok valueTok = element->value;
5364             const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer;
5365             AffixPatternsForCurrency* copy = new AffixPatternsForCurrency(
5366                 value->negPrefixPatternForCurrency,
5367                 value->negSuffixPatternForCurrency,
5368                 value->posPrefixPatternForCurrency,
5369                 value->posSuffixPatternForCurrency,
5370                 value->patternType);
5371             target->put(UnicodeString(*key), copy, status);
5372             if ( U_FAILURE(status) ) {
5373                 return;
5374             }
5375         }
5376     }
5377 }
5378 
setAttribute(UNumberFormatAttribute attr,int32_t newValue,UErrorCode & status)5379 DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
5380                                             int32_t newValue,
5381                                             UErrorCode &status) {
5382   if(U_FAILURE(status)) return *this;
5383 
5384   switch(attr) {
5385   case UNUM_LENIENT_PARSE:
5386     setLenient(newValue!=0);
5387     break;
5388 
5389     case UNUM_PARSE_INT_ONLY:
5390       setParseIntegerOnly(newValue!=0);
5391       break;
5392 
5393     case UNUM_GROUPING_USED:
5394       setGroupingUsed(newValue!=0);
5395       break;
5396 
5397     case UNUM_DECIMAL_ALWAYS_SHOWN:
5398       setDecimalSeparatorAlwaysShown(newValue!=0);
5399         break;
5400 
5401     case UNUM_MAX_INTEGER_DIGITS:
5402       setMaximumIntegerDigits(newValue);
5403         break;
5404 
5405     case UNUM_MIN_INTEGER_DIGITS:
5406       setMinimumIntegerDigits(newValue);
5407         break;
5408 
5409     case UNUM_INTEGER_DIGITS:
5410       setMinimumIntegerDigits(newValue);
5411       setMaximumIntegerDigits(newValue);
5412         break;
5413 
5414     case UNUM_MAX_FRACTION_DIGITS:
5415       setMaximumFractionDigits(newValue);
5416         break;
5417 
5418     case UNUM_MIN_FRACTION_DIGITS:
5419       setMinimumFractionDigits(newValue);
5420         break;
5421 
5422     case UNUM_FRACTION_DIGITS:
5423       setMinimumFractionDigits(newValue);
5424       setMaximumFractionDigits(newValue);
5425       break;
5426 
5427     case UNUM_SIGNIFICANT_DIGITS_USED:
5428       setSignificantDigitsUsed(newValue!=0);
5429         break;
5430 
5431     case UNUM_MAX_SIGNIFICANT_DIGITS:
5432       setMaximumSignificantDigits(newValue);
5433         break;
5434 
5435     case UNUM_MIN_SIGNIFICANT_DIGITS:
5436       setMinimumSignificantDigits(newValue);
5437         break;
5438 
5439     case UNUM_MULTIPLIER:
5440       setMultiplier(newValue);
5441        break;
5442 
5443     case UNUM_GROUPING_SIZE:
5444       setGroupingSize(newValue);
5445         break;
5446 
5447     case UNUM_ROUNDING_MODE:
5448       setRoundingMode((DecimalFormat::ERoundingMode)newValue);
5449         break;
5450 
5451     case UNUM_FORMAT_WIDTH:
5452       setFormatWidth(newValue);
5453         break;
5454 
5455     case UNUM_PADDING_POSITION:
5456         /** The position at which padding will take place. */
5457       setPadPosition((DecimalFormat::EPadPosition)newValue);
5458         break;
5459 
5460     case UNUM_SECONDARY_GROUPING_SIZE:
5461       setSecondaryGroupingSize(newValue);
5462         break;
5463 
5464 #if UCONFIG_HAVE_PARSEALLINPUT
5465     case UNUM_PARSE_ALL_INPUT:
5466       setParseAllInput((UNumberFormatAttributeValue)newValue);
5467         break;
5468 #endif
5469 
5470     /* These are stored in fBoolFlags */
5471     case UNUM_PARSE_NO_EXPONENT:
5472     case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
5473       if(!fBoolFlags.isValidValue(newValue)) {
5474           status = U_ILLEGAL_ARGUMENT_ERROR;
5475       } else {
5476           fBoolFlags.set(attr, newValue);
5477       }
5478       break;
5479 
5480     default:
5481       status = U_UNSUPPORTED_ERROR;
5482       break;
5483   }
5484   return *this;
5485 }
5486 
getAttribute(UNumberFormatAttribute attr,UErrorCode & status) const5487 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
5488                                      UErrorCode &status ) const {
5489   if(U_FAILURE(status)) return -1;
5490   switch(attr) {
5491     case UNUM_LENIENT_PARSE:
5492         return isLenient();
5493 
5494     case UNUM_PARSE_INT_ONLY:
5495         return isParseIntegerOnly();
5496 
5497     case UNUM_GROUPING_USED:
5498         return isGroupingUsed();
5499 
5500     case UNUM_DECIMAL_ALWAYS_SHOWN:
5501         return isDecimalSeparatorAlwaysShown();
5502 
5503     case UNUM_MAX_INTEGER_DIGITS:
5504         return getMaximumIntegerDigits();
5505 
5506     case UNUM_MIN_INTEGER_DIGITS:
5507         return getMinimumIntegerDigits();
5508 
5509     case UNUM_INTEGER_DIGITS:
5510         // TBD: what should this return?
5511         return getMinimumIntegerDigits();
5512 
5513     case UNUM_MAX_FRACTION_DIGITS:
5514         return getMaximumFractionDigits();
5515 
5516     case UNUM_MIN_FRACTION_DIGITS:
5517         return getMinimumFractionDigits();
5518 
5519     case UNUM_FRACTION_DIGITS:
5520         // TBD: what should this return?
5521         return getMinimumFractionDigits();
5522 
5523     case UNUM_SIGNIFICANT_DIGITS_USED:
5524         return areSignificantDigitsUsed();
5525 
5526     case UNUM_MAX_SIGNIFICANT_DIGITS:
5527         return getMaximumSignificantDigits();
5528 
5529     case UNUM_MIN_SIGNIFICANT_DIGITS:
5530         return getMinimumSignificantDigits();
5531 
5532     case UNUM_MULTIPLIER:
5533         return getMultiplier();
5534 
5535     case UNUM_GROUPING_SIZE:
5536         return getGroupingSize();
5537 
5538     case UNUM_ROUNDING_MODE:
5539         return getRoundingMode();
5540 
5541     case UNUM_FORMAT_WIDTH:
5542         return getFormatWidth();
5543 
5544     case UNUM_PADDING_POSITION:
5545         return getPadPosition();
5546 
5547     case UNUM_SECONDARY_GROUPING_SIZE:
5548         return getSecondaryGroupingSize();
5549 
5550     /* These are stored in fBoolFlags */
5551     case UNUM_PARSE_NO_EXPONENT:
5552     case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
5553       return fBoolFlags.get(attr);
5554 
5555     default:
5556         status = U_UNSUPPORTED_ERROR;
5557         break;
5558   }
5559 
5560   return -1; /* undefined */
5561 }
5562 
5563 #if UCONFIG_HAVE_PARSEALLINPUT
setParseAllInput(UNumberFormatAttributeValue value)5564 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
5565   fParseAllInput = value;
5566 #if UCONFIG_FORMAT_FASTPATHS_49
5567   handleChanged();
5568 #endif
5569 }
5570 #endif
5571 
5572 void
copyHashForAffix(const Hashtable * source,Hashtable * target,UErrorCode & status)5573 DecimalFormat::copyHashForAffix(const Hashtable* source,
5574                                 Hashtable* target,
5575                                 UErrorCode& status) {
5576     if ( U_FAILURE(status) ) {
5577         return;
5578     }
5579     int32_t pos = -1;
5580     const UHashElement* element = NULL;
5581     if ( source ) {
5582         while ( (element = source->nextElement(pos)) != NULL ) {
5583             const UHashTok keyTok = element->key;
5584             const UnicodeString* key = (UnicodeString*)keyTok.pointer;
5585 
5586             const UHashTok valueTok = element->value;
5587             const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer;
5588             AffixesForCurrency* copy = new AffixesForCurrency(
5589                 value->negPrefixForCurrency,
5590                 value->negSuffixForCurrency,
5591                 value->posPrefixForCurrency,
5592                 value->posSuffixForCurrency);
5593             target->put(UnicodeString(*key), copy, status);
5594             if ( U_FAILURE(status) ) {
5595                 return;
5596             }
5597         }
5598     }
5599 }
5600 
5601 U_NAMESPACE_END
5602 
5603 #endif /* #if !UCONFIG_NO_FORMATTING */
5604 
5605 //eof
5606