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