]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/decimfmt.cpp
ICU-6.2.15.tar.gz
[apple/icu.git] / icuSources / i18n / decimfmt.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
374ca955 3* Copyright (C) 1997-2004, 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().
35* 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
36* fPadPosition
37********************************************************************************
38*/
39
40#include "unicode/utypes.h"
41
42#if !UCONFIG_NO_FORMATTING
43
44#include "unicode/decimfmt.h"
45#include "unicode/choicfmt.h"
46#include "unicode/ucurr.h"
47#include "unicode/ustring.h"
48#include "unicode/dcfmtsym.h"
374ca955 49#include "unicode/ures.h"
b75a7d8f 50#include "unicode/uchar.h"
374ca955
A
51#include "unicode/curramt.h"
52#include "ucurrimp.h"
53#include "util.h"
b75a7d8f
A
54#include "digitlst.h"
55#include "cmemory.h"
56#include "cstring.h"
57#include "umutex.h"
58#include "uassert.h"
374ca955 59#include "putilimp.h"
b75a7d8f
A
60
61U_NAMESPACE_BEGIN
62
63//#define FMT_DEBUG
64
65#ifdef FMT_DEBUG
66#include <stdio.h>
67static void debugout(UnicodeString s) {
68 char buf[2000];
69 s.extract((int32_t) 0, s.length(), buf);
70 printf("%s", buf);
71}
72#define debug(x) printf("%s", x);
73#else
74#define debugout(x)
75#define debug(x)
76#endif
77
78// *****************************************************************************
79// class DecimalFormat
80// *****************************************************************************
81
374ca955 82UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
b75a7d8f
A
83
84// Constants for characters used in programmatic (unlocalized) patterns.
374ca955
A
85#define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
86#define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
87#define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
88#define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
89#define kPatternPerMill ((UChar)0x2030)
90#define kPatternPercent ((UChar)0x0025) /*'%'*/
91#define kPatternDigit ((UChar)0x0023) /*'#'*/
92#define kPatternSeparator ((UChar)0x003B) /*';'*/
93#define kPatternExponent ((UChar)0x0045) /*'E'*/
94#define kPatternPlus ((UChar)0x002B) /*'+'*/
95#define kPatternMinus ((UChar)0x002D) /*'-'*/
96#define kPatternPadEscape ((UChar)0x002A) /*'*'*/
97#define kQuote ((UChar)0x0027) /*'\''*/
98/**
99 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
100 * is used in patterns and substitued with either the currency symbol,
101 * or if it is doubled, with the international currency symbol. If the
102 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
103 * replaced with the monetary decimal separator.
104 */
105#define kCurrencySign ((UChar)0x00A4)
106#define kDefaultPad ((UChar)0x0020) /* */
b75a7d8f
A
107
108const int32_t DecimalFormat::kDoubleIntegerDigits = 309;
109const int32_t DecimalFormat::kDoubleFractionDigits = 340;
110
374ca955
A
111const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
112
b75a7d8f
A
113/**
114 * These are the tags we expect to see in normal resource bundle files associated
115 * with a locale.
116 */
117const char DecimalFormat::fgNumberPatterns[]="NumberPatterns";
118
374ca955
A
119inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
120inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
b75a7d8f
A
121
122//------------------------------------------------------------------------------
123// Constructs a DecimalFormat instance in the default locale.
124
125DecimalFormat::DecimalFormat(UErrorCode& status)
126: NumberFormat(),
127 fPosPrefixPattern(0),
128 fPosSuffixPattern(0),
129 fNegPrefixPattern(0),
130 fNegSuffixPattern(0),
131 fCurrencyChoice(0),
132 fMultiplier(0),
133 fGroupingSize(0),
134 fGroupingSize2(0),
135 fSymbols(0),
374ca955
A
136 fUseSignificantDigits(FALSE),
137 fMinSignificantDigits(1),
138 fMaxSignificantDigits(6),
b75a7d8f
A
139 fMinExponentDigits(0),
140 fRoundingIncrement(0),
141 fPad(0),
142 fFormatWidth(0)
143{
144 UParseError parseError;
145 construct(status, parseError);
146}
147
148//------------------------------------------------------------------------------
149// Constructs a DecimalFormat instance with the specified number format
150// pattern in the default locale.
151
152DecimalFormat::DecimalFormat(const UnicodeString& pattern,
153 UErrorCode& status)
154: NumberFormat(),
155 fPosPrefixPattern(0),
156 fPosSuffixPattern(0),
157 fNegPrefixPattern(0),
158 fNegSuffixPattern(0),
159 fCurrencyChoice(0),
160 fMultiplier(0),
161 fGroupingSize(0),
162 fGroupingSize2(0),
163 fSymbols(0),
374ca955
A
164 fUseSignificantDigits(FALSE),
165 fMinSignificantDigits(1),
166 fMaxSignificantDigits(6),
b75a7d8f
A
167 fMinExponentDigits(0),
168 fRoundingIncrement(0),
169 fPad(0),
170 fFormatWidth(0)
171{
172 UParseError parseError;
173 construct(status, parseError, &pattern);
174}
175
176//------------------------------------------------------------------------------
177// Constructs a DecimalFormat instance with the specified number format
178// pattern and the number format symbols in the default locale. The
179// created instance owns the symbols.
180
181DecimalFormat::DecimalFormat(const UnicodeString& pattern,
182 DecimalFormatSymbols* symbolsToAdopt,
183 UErrorCode& status)
184: NumberFormat(),
185 fPosPrefixPattern(0),
186 fPosSuffixPattern(0),
187 fNegPrefixPattern(0),
188 fNegSuffixPattern(0),
189 fCurrencyChoice(0),
190 fMultiplier(0),
191 fGroupingSize(0),
192 fGroupingSize2(0),
193 fSymbols(0),
374ca955
A
194 fUseSignificantDigits(FALSE),
195 fMinSignificantDigits(1),
196 fMaxSignificantDigits(6),
b75a7d8f
A
197 fMinExponentDigits(0),
198 fRoundingIncrement(0),
199 fPad(0),
200 fFormatWidth(0)
201{
202 UParseError parseError;
203 if (symbolsToAdopt == NULL)
204 status = U_ILLEGAL_ARGUMENT_ERROR;
205 construct(status, parseError, &pattern, symbolsToAdopt);
206}
207
208DecimalFormat::DecimalFormat( const UnicodeString& pattern,
209 DecimalFormatSymbols* symbolsToAdopt,
210 UParseError& parseErr,
211 UErrorCode& status)
212: NumberFormat(),
213 fPosPrefixPattern(0),
214 fPosSuffixPattern(0),
215 fNegPrefixPattern(0),
216 fNegSuffixPattern(0),
217 fCurrencyChoice(0),
218 fMultiplier(0),
219 fGroupingSize(0),
220 fGroupingSize2(0),
221 fSymbols(0),
374ca955
A
222 fUseSignificantDigits(FALSE),
223 fMinSignificantDigits(1),
224 fMaxSignificantDigits(6),
b75a7d8f
A
225 fMinExponentDigits(0),
226 fRoundingIncrement(0),
227 fPad(0),
228 fFormatWidth(0)
229{
230 if (symbolsToAdopt == NULL)
231 status = U_ILLEGAL_ARGUMENT_ERROR;
232 construct(status,parseErr, &pattern, symbolsToAdopt);
233}
234//------------------------------------------------------------------------------
235// Constructs a DecimalFormat instance with the specified number format
236// pattern and the number format symbols in the default locale. The
237// created instance owns the clone of the symbols.
238
239DecimalFormat::DecimalFormat(const UnicodeString& pattern,
240 const DecimalFormatSymbols& symbols,
241 UErrorCode& status)
242: NumberFormat(),
243 fPosPrefixPattern(0),
244 fPosSuffixPattern(0),
245 fNegPrefixPattern(0),
246 fNegSuffixPattern(0),
247 fCurrencyChoice(0),
248 fMultiplier(0),
249 fGroupingSize(0),
250 fGroupingSize2(0),
251 fSymbols(0),
374ca955
A
252 fUseSignificantDigits(FALSE),
253 fMinSignificantDigits(1),
254 fMaxSignificantDigits(6),
b75a7d8f
A
255 fMinExponentDigits(0),
256 fRoundingIncrement(0),
257 fPad(0),
258 fFormatWidth(0)
259{
260 UParseError parseError;
261 construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
262}
263
264//------------------------------------------------------------------------------
265// Constructs a DecimalFormat instance with the specified number format
266// pattern and the number format symbols in the desired locale. The
267// created instance owns the symbols.
268
269void
270DecimalFormat::construct(UErrorCode& status,
271 UParseError& parseErr,
272 const UnicodeString* pattern,
273 DecimalFormatSymbols* symbolsToAdopt)
274{
275 fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!!
276// fDigitList = new DigitList(); // Do this BEFORE aborting on status failure!!!
277 fRoundingIncrement = NULL;
278 fRoundingDouble = 0.0;
279 fRoundingMode = kRoundHalfEven;
280 fPad = kPatternPadEscape;
281 fPadPosition = kPadBeforePrefix;
282 if (U_FAILURE(status))
283 return;
284
285 fPosPrefixPattern = fPosSuffixPattern = NULL;
286 fNegPrefixPattern = fNegSuffixPattern = NULL;
287 fMultiplier = 1;
288 fGroupingSize = 3;
289 fGroupingSize2 = 0;
290 fDecimalSeparatorAlwaysShown = FALSE;
291 fIsCurrencyFormat = FALSE;
292 fUseExponentialNotation = FALSE;
293 fMinExponentDigits = 0;
294
295 if (fSymbols == NULL)
296 {
297 fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
298 /* test for NULL */
299 if (fSymbols == 0) {
300 status = U_MEMORY_ALLOCATION_ERROR;
301 return;
302 }
303 }
304
305 UnicodeString str;
306 // Uses the default locale's number format pattern if there isn't
307 // one specified.
308 if (pattern == NULL)
309 {
374ca955
A
310 int32_t len = 0;
311 UResourceBundle *resource = ures_open(NULL, Locale::getDefault().getName(), &status);
b75a7d8f 312
374ca955
A
313 resource = ures_getByKey(resource, fgNumberPatterns, resource, &status);
314 const UChar *resStr = ures_getStringByIndex(resource, (int32_t)0, &len, &status);
315 str.setTo(TRUE, resStr, len);
b75a7d8f 316 pattern = &str;
374ca955 317 ures_close(resource);
b75a7d8f
A
318 }
319
320 if (U_FAILURE(status))
321 {
322 return;
323 }
324
374ca955
A
325 if (pattern->indexOf((UChar)kCurrencySign) >= 0) {
326 // If it looks like we are going to use a currency pattern
327 // then do the time consuming lookup.
328 if (symbolsToAdopt == NULL) {
329 setCurrencyForLocale(uloc_getDefault(), status);
330 } else {
331 setCurrencyForSymbols();
332 }
b75a7d8f 333 } else {
374ca955 334 setCurrency(NULL, status);
b75a7d8f
A
335 }
336
337 applyPattern(*pattern, FALSE /*not localized*/,parseErr, status);
338}
339
340/**
341 * Sets our currency to be the default currency for the given locale.
342 */
343void DecimalFormat::setCurrencyForLocale(const char* locale, UErrorCode& ec) {
344 const UChar* c = NULL;
345 if (U_SUCCESS(ec)) {
346 // Trap an error in mapping locale to currency. If we can't
347 // map, then don't fail and set the currency to "".
348 UErrorCode ec2 = U_ZERO_ERROR;
374ca955
A
349 UChar c[4];
350 ucurr_forLocale(locale, c, 4, &ec2);
b75a7d8f 351 }
374ca955 352 setCurrency(c, ec);
b75a7d8f
A
353}
354
355//------------------------------------------------------------------------------
356
357DecimalFormat::~DecimalFormat()
358{
359// delete fDigitList;
360 delete fPosPrefixPattern;
361 delete fPosSuffixPattern;
362 delete fNegPrefixPattern;
363 delete fNegSuffixPattern;
364 delete fCurrencyChoice;
365 delete fSymbols;
366 delete fRoundingIncrement;
367}
368
369//------------------------------------------------------------------------------
370// copy constructor
371
372DecimalFormat::DecimalFormat(const DecimalFormat &source)
373: NumberFormat(source),
374// fDigitList(NULL),
375 fPosPrefixPattern(NULL),
376 fPosSuffixPattern(NULL),
377 fNegPrefixPattern(NULL),
378 fNegSuffixPattern(NULL),
379 fCurrencyChoice(NULL),
380 fSymbols(NULL),
381 fRoundingIncrement(NULL)
382{
383 *this = source;
384}
385
386//------------------------------------------------------------------------------
387// assignment operator
388// Note that fDigitList is not considered a significant part of the
389// DecimalFormat because it's used as a buffer to process the numbers.
390
391static void _copy_us_ptr(UnicodeString** pdest, const UnicodeString* source) {
392 if (source == NULL) {
393 delete *pdest;
394 *pdest = NULL;
395 } else if (*pdest == NULL) {
396 *pdest = new UnicodeString(*source);
397 } else {
398 **pdest = *source;
399 }
400}
401
402DecimalFormat&
403DecimalFormat::operator=(const DecimalFormat& rhs)
404{
374ca955
A
405 if(this != &rhs) {
406 NumberFormat::operator=(rhs);
407 fPositivePrefix = rhs.fPositivePrefix;
408 fPositiveSuffix = rhs.fPositiveSuffix;
409 fNegativePrefix = rhs.fNegativePrefix;
410 fNegativeSuffix = rhs.fNegativeSuffix;
411 _copy_us_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern);
412 _copy_us_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern);
413 _copy_us_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern);
414 _copy_us_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern);
415 if (rhs.fCurrencyChoice == 0) {
416 delete fCurrencyChoice;
417 fCurrencyChoice = 0;
418 } else {
419 fCurrencyChoice = (ChoiceFormat*) rhs.fCurrencyChoice->clone();
420 }
421 if(rhs.fRoundingIncrement == NULL) {
422 delete fRoundingIncrement;
423 fRoundingIncrement = NULL;
424 }
425 else if(fRoundingIncrement == NULL) {
426 fRoundingIncrement = new DigitList(*rhs.fRoundingIncrement);
427 }
428 else {
429 *fRoundingIncrement = *rhs.fRoundingIncrement;
430 }
431 fRoundingDouble = rhs.fRoundingDouble;
03115e54 432 fRoundingMode = rhs.fRoundingMode;
374ca955
A
433 fMultiplier = rhs.fMultiplier;
434 fGroupingSize = rhs.fGroupingSize;
435 fGroupingSize2 = rhs.fGroupingSize2;
436 fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown;
437 if(fSymbols == NULL) {
438 fSymbols = new DecimalFormatSymbols(*rhs.fSymbols);
439 } else {
440 *fSymbols = *rhs.fSymbols;
441 }
442 fUseExponentialNotation = rhs.fUseExponentialNotation;
443 fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown;
444 /*Bertrand A. D. Update 98.03.17*/
445 fIsCurrencyFormat = rhs.fIsCurrencyFormat;
446 /*end of Update*/
447 fMinExponentDigits = rhs.fMinExponentDigits;
448 // if (fDigitList == NULL)
449 // fDigitList = new DigitList();
b75a7d8f 450
374ca955
A
451 /* sfb 990629 */
452 fFormatWidth = rhs.fFormatWidth;
453 fPad = rhs.fPad;
454 fPadPosition = rhs.fPadPosition;
455 /* end sfb */
456 fMinSignificantDigits = rhs.fMinSignificantDigits;
457 fMaxSignificantDigits = rhs.fMaxSignificantDigits;
458 fUseSignificantDigits = rhs.fUseSignificantDigits;
459 }
460 return *this;
b75a7d8f
A
461}
462
463//------------------------------------------------------------------------------
464
465UBool
466DecimalFormat::operator==(const Format& that) const
467{
468 if (this == &that)
469 return TRUE;
470
374ca955 471 // NumberFormat::operator== guarantees this cast is safe
b75a7d8f
A
472 const DecimalFormat* other = (DecimalFormat*)&that;
473
474#ifdef FMT_DEBUG
475 // This code makes it easy to determine why two format objects that should
476 // be equal aren't.
477 UBool first = TRUE;
478 if (!NumberFormat::operator==(that)) {
479 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
480 debug("NumberFormat::!=");
481 }
482 if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null
483 fPositivePrefix == other->fPositivePrefix)
484 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
485 *fPosPrefixPattern == *other->fPosPrefixPattern))) {
486 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
487 debug("Pos Prefix !=");
488 }
489 if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null
490 fPositiveSuffix == other->fPositiveSuffix)
491 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
492 *fPosSuffixPattern == *other->fPosSuffixPattern))) {
493 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
494 debug("Pos Suffix !=");
495 }
496 if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null
497 fNegativePrefix == other->fNegativePrefix)
498 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
499 *fNegPrefixPattern == *other->fNegPrefixPattern))) {
500 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
501 debug("Neg Prefix ");
502 if (fNegPrefixPattern == NULL) {
503 debug("NULL(");
504 debugout(fNegativePrefix);
505 debug(")");
506 } else {
507 debugout(*fNegPrefixPattern);
508 }
509 debug(" != ");
510 if (other->fNegPrefixPattern == NULL) {
511 debug("NULL(");
512 debugout(other->fNegativePrefix);
513 debug(")");
514 } else {
515 debugout(*other->fNegPrefixPattern);
516 }
517 }
518 if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null
519 fNegativeSuffix == other->fNegativeSuffix)
520 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
521 *fNegSuffixPattern == *other->fNegSuffixPattern))) {
522 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
523 debug("Neg Suffix ");
524 if (fNegSuffixPattern == NULL) {
525 debug("NULL(");
526 debugout(fNegativeSuffix);
527 debug(")");
528 } else {
529 debugout(*fNegSuffixPattern);
530 }
531 debug(" != ");
532 if (other->fNegSuffixPattern == NULL) {
533 debug("NULL(");
534 debugout(other->fNegativeSuffix);
535 debug(")");
536 } else {
537 debugout(*other->fNegSuffixPattern);
538 }
539 }
540 if (!((fRoundingIncrement == other->fRoundingIncrement) // both null
541 || (fRoundingIncrement != NULL &&
542 other->fRoundingIncrement != NULL &&
543 *fRoundingIncrement == *other->fRoundingIncrement))) {
544 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
545 debug("Rounding Increment !=");
546 }
547 if (fMultiplier != other->fMultiplier) {
548 if (first) { printf("[ "); first = FALSE; }
549 printf("Multiplier %ld != %ld", fMultiplier, other->fMultiplier);
550 }
551 if (fGroupingSize != other->fGroupingSize) {
552 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
553 printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize);
554 }
555 if (fGroupingSize2 != other->fGroupingSize2) {
556 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
557 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGroupingSize2);
558 }
559 if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) {
560 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
561 printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown);
562 }
563 if (fUseExponentialNotation != other->fUseExponentialNotation) {
564 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
565 debug("Use Exp !=");
566 }
567 if (!(!fUseExponentialNotation ||
568 fMinExponentDigits != other->fMinExponentDigits)) {
569 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
570 debug("Exp Digits !=");
571 }
572 if (*fSymbols != *(other->fSymbols)) {
573 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
574 debug("Symbols !=");
575 }
374ca955 576 // TODO Add debug stuff for significant digits here
b75a7d8f
A
577 if (!first) { printf(" ]"); }
578#endif
579
580 return (NumberFormat::operator==(that) &&
581 ((fPosPrefixPattern == other->fPosPrefixPattern && // both null
582 fPositivePrefix == other->fPositivePrefix)
583 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
584 *fPosPrefixPattern == *other->fPosPrefixPattern)) &&
585 ((fPosSuffixPattern == other->fPosSuffixPattern && // both null
586 fPositiveSuffix == other->fPositiveSuffix)
587 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
588 *fPosSuffixPattern == *other->fPosSuffixPattern)) &&
589 ((fNegPrefixPattern == other->fNegPrefixPattern && // both null
590 fNegativePrefix == other->fNegativePrefix)
591 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
592 *fNegPrefixPattern == *other->fNegPrefixPattern)) &&
593 ((fNegSuffixPattern == other->fNegSuffixPattern && // both null
594 fNegativeSuffix == other->fNegativeSuffix)
595 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
596 *fNegSuffixPattern == *other->fNegSuffixPattern)) &&
597 ((fRoundingIncrement == other->fRoundingIncrement) // both null
598 || (fRoundingIncrement != NULL &&
599 other->fRoundingIncrement != NULL &&
600 *fRoundingIncrement == *other->fRoundingIncrement)) &&
601 fMultiplier == other->fMultiplier &&
602 fGroupingSize == other->fGroupingSize &&
603 fGroupingSize2 == other->fGroupingSize2 &&
604 fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown &&
605 fUseExponentialNotation == other->fUseExponentialNotation &&
606 (!fUseExponentialNotation ||
607 fMinExponentDigits == other->fMinExponentDigits) &&
374ca955
A
608 *fSymbols == *(other->fSymbols) &&
609 fUseSignificantDigits == other->fUseSignificantDigits &&
610 (!fUseSignificantDigits ||
611 (fMinSignificantDigits == other->fMinSignificantDigits &&
612 fMaxSignificantDigits == other->fMaxSignificantDigits)));
b75a7d8f
A
613}
614
615//------------------------------------------------------------------------------
616
617Format*
618DecimalFormat::clone() const
619{
620 return new DecimalFormat(*this);
621}
622
623//------------------------------------------------------------------------------
624
625UnicodeString&
626DecimalFormat::format(int32_t number,
627 UnicodeString& appendTo,
628 FieldPosition& fieldPosition) const
374ca955
A
629{
630 return format((int64_t)number, appendTo, fieldPosition);
631}
632
633//------------------------------------------------------------------------------
634
635UnicodeString&
636DecimalFormat::format(int64_t number,
637 UnicodeString& appendTo,
638 FieldPosition& fieldPosition) const
b75a7d8f
A
639{
640 DigitList digits;
641
642 // Clears field positions.
643 fieldPosition.setBeginIndex(0);
644 fieldPosition.setEndIndex(0);
645
646 // If we are to do rounding, we need to move into the BigDecimal
647 // domain in order to do divide/multiply correctly.
648 // ||
649 // In general, long values always represent real finite numbers, so
650 // we don't have to check for +/- Infinity or NaN. However, there
651 // is one case we have to be careful of: The multiplier can push
652 // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
653 // check for this before multiplying, and if it happens we use doubles
654 // instead, trading off accuracy for range.
655 if (fRoundingIncrement != NULL
374ca955
A
656 || (fMultiplier != 0 && (number > (U_INT64_MAX / fMultiplier)
657 || number < (U_INT64_MIN / fMultiplier))))
b75a7d8f
A
658 {
659 digits.set(((double)number) * fMultiplier,
374ca955
A
660 precision(FALSE),
661 !fUseExponentialNotation && !areSignificantDigitsUsed());
b75a7d8f
A
662 }
663 else
664 {
374ca955 665 digits.set(number * fMultiplier, precision(TRUE));
b75a7d8f
A
666 }
667
668 return subformat(appendTo, fieldPosition, digits, TRUE);
669}
670
671//------------------------------------------------------------------------------
672
673UnicodeString&
674DecimalFormat::format( double number,
675 UnicodeString& appendTo,
676 FieldPosition& fieldPosition) const
677{
678 // Clears field positions.
679 fieldPosition.setBeginIndex(0);
680 fieldPosition.setEndIndex(0);
681
682 // Special case for NaN, sets the begin and end index to be the
683 // the string length of localized name of NaN.
684 if (uprv_isNaN(number))
685 {
686 if (fieldPosition.getField() == NumberFormat::kIntegerField)
687 fieldPosition.setBeginIndex(appendTo.length());
688
689 appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
690
691 if (fieldPosition.getField() == NumberFormat::kIntegerField)
692 fieldPosition.setEndIndex(appendTo.length());
693
694 addPadding(appendTo, fieldPosition, 0, 0);
695 return appendTo;
696 }
697
698 /* Detecting whether a double is negative is easy with the exception of
699 * the value -0.0. This is a double which has a zero mantissa (and
700 * exponent), but a negative sign bit. It is semantically distinct from
701 * a zero with a positive sign bit, and this distinction is important
702 * to certain kinds of computations. However, it's a little tricky to
703 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
704 * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
705 * -Infinity. Proper detection of -0.0 is needed to deal with the
706 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
707 */
708 UBool isNegative = uprv_isNegative(number);
709
710 // Do this BEFORE checking to see if value is infinite! Sets the
711 // begin and end index to be length of the string composed of
712 // localized name of Infinite and the positive/negative localized
713 // signs.
714
715 number *= fMultiplier;
716
717 // Apply rounding after multiplier
718 if (fRoundingIncrement != NULL) {
719 if (isNegative) // For rounding in the correct direction
720 number = -number;
721 number = fRoundingDouble
722 * round(number / fRoundingDouble, fRoundingMode, isNegative);
723 if (isNegative)
724 number = -number;
725 }
726
727 // Special case for INFINITE,
728 if (uprv_isInfinite(number))
729 {
730 int32_t prefixLen = appendAffix(appendTo, number, isNegative, TRUE);
731
732 if (fieldPosition.getField() == NumberFormat::kIntegerField)
733 fieldPosition.setBeginIndex(appendTo.length());
734
735 appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
736
737 if (fieldPosition.getField() == NumberFormat::kIntegerField)
738 fieldPosition.setEndIndex(appendTo.length());
739
740 int32_t suffixLen = appendAffix(appendTo, number, isNegative, FALSE);
741
742 addPadding(appendTo, fieldPosition, prefixLen, suffixLen);
743 return appendTo;
744 }
745
746 DigitList digits;
747
748 // This detects negativity too.
03115e54
A
749 if (fRoundingIncrement == NULL) {
750 // If we did not round in binary space, round in decimal space
751 digits.fRoundingMode = fRoundingMode;
752 }
374ca955
A
753 digits.set(number, precision(FALSE),
754 !fUseExponentialNotation && !areSignificantDigitsUsed());
b75a7d8f
A
755
756 return subformat(appendTo, fieldPosition, digits, FALSE);
757}
758
759/**
760 * Round a double value to the nearest integer according to the
761 * given mode.
762 * @param a the absolute value of the number to be rounded
763 * @param mode a BigDecimal rounding mode
764 * @param isNegative true if the number to be rounded is negative
765 * @return the absolute value of the rounded result
766 */
767double DecimalFormat::round(double a, ERoundingMode mode, UBool isNegative) {
768 switch (mode) {
769 case kRoundCeiling:
770 return isNegative ? uprv_floor(a) : uprv_ceil(a);
771 case kRoundFloor:
772 return isNegative ? uprv_ceil(a) : uprv_floor(a);
773 case kRoundDown:
774 return uprv_floor(a);
775 case kRoundUp:
776 return uprv_ceil(a);
777 case kRoundHalfEven:
778 {
779 double f = uprv_floor(a);
780 if ((a - f) != 0.5) {
781 return uprv_floor(a + 0.5);
782 }
783 double g = f / 2.0;
784 return (g == uprv_floor(g)) ? f : (f + 1.0);
785 }
786 case kRoundHalfDown:
787 return ((a - uprv_floor(a)) <= 0.5) ? uprv_floor(a) : uprv_ceil(a);
788 case kRoundHalfUp:
789 return ((a - uprv_floor(a)) < 0.5) ? uprv_floor(a) : uprv_ceil(a);
790 }
791 return 1.0;
792}
793
794UnicodeString&
795DecimalFormat::format( const Formattable& obj,
796 UnicodeString& appendTo,
797 FieldPosition& fieldPosition,
798 UErrorCode& status) const
799{
800 return NumberFormat::format(obj, appendTo, fieldPosition, status);
801}
802
803/**
804 * Return true if a grouping separator belongs at the given
805 * position, based on whether grouping is in use and the values of
806 * the primary and secondary grouping interval.
807 * @param pos the number of integer digits to the right of
808 * the current position. Zero indicates the position after the
809 * rightmost integer digit.
810 * @return true if a grouping character belongs at the current
811 * position.
812 */
813UBool DecimalFormat::isGroupingPosition(int32_t pos) const {
814 UBool result = FALSE;
815 if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) {
816 if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) {
817 result = ((pos - fGroupingSize) % fGroupingSize2) == 0;
818 } else {
819 result = pos % fGroupingSize == 0;
820 }
821 }
822 return result;
823}
824
825//------------------------------------------------------------------------------
826
827/**
828 * Complete the formatting of a finite number. On entry, the fDigitList must
829 * be filled in with the correct digits.
830 */
831UnicodeString&
832DecimalFormat::subformat(UnicodeString& appendTo,
833 FieldPosition& fieldPosition,
834 DigitList& digits,
835 UBool isInteger) const
836{
837 // Gets the localized zero Unicode character.
838 UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
839 int32_t zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
840 const UnicodeString *grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
841 const UnicodeString *decimal;
842 if(fIsCurrencyFormat) {
843 decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
844 } else {
845 decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
846 }
374ca955 847 UBool useSigDig = areSignificantDigitsUsed();
b75a7d8f
A
848 int32_t maxIntDig = getMaximumIntegerDigits();
849 int32_t minIntDig = getMinimumIntegerDigits();
850
851 /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
852 * format as zero. This allows sensible computations and preserves
853 * relations such as signum(1/x) = signum(x), where x is +Infinity or
854 * -Infinity. Prior to this fix, we always formatted zero values as if
855 * they were positive. Liu 7/6/98.
856 */
857 if (digits.isZero())
858 {
859 digits.fDecimalAt = digits.fCount = 0; // Normalize
860 }
861
862 // Appends the prefix.
863 double doubleValue = digits.getDouble();
864 int32_t prefixLen = appendAffix(appendTo, doubleValue, !digits.fIsPositive, TRUE);
865
866 if (fUseExponentialNotation)
867 {
868 // Record field information for caller.
869 if (fieldPosition.getField() == NumberFormat::kIntegerField)
870 {
871 fieldPosition.setBeginIndex(appendTo.length());
872 fieldPosition.setEndIndex(-1);
873 }
874 else if (fieldPosition.getField() == NumberFormat::kFractionField)
875 {
876 fieldPosition.setBeginIndex(-1);
877 }
878
374ca955
A
879 int32_t minFracDig = 0;
880 if (useSigDig) {
881 maxIntDig = minIntDig = 1;
882 minFracDig = getMinimumSignificantDigits() - 1;
883 } else {
884 minFracDig = getMinimumFractionDigits();
885 if (maxIntDig > kMaxScientificIntegerDigits) {
886 maxIntDig = 1;
887 if (maxIntDig < minIntDig) {
888 maxIntDig = minIntDig;
889 }
890 }
891 if (maxIntDig > minIntDig) {
892 minIntDig = 1;
893 }
894 }
895
b75a7d8f
A
896 // Minimum integer digits are handled in exponential format by
897 // adjusting the exponent. For example, 0.01234 with 3 minimum
898 // integer digits is "123.4E-4".
899
900 // Maximum integer digits are interpreted as indicating the
901 // repeating range. This is useful for engineering notation, in
902 // which the exponent is restricted to a multiple of 3. For
903 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
904 // If maximum integer digits are defined and are larger than
905 // minimum integer digits, then minimum integer digits are
906 // ignored.
907 int32_t exponent = digits.fDecimalAt;
908 if (maxIntDig > 1 && maxIntDig != minIntDig) {
909 // A exponent increment is defined; adjust to it.
910 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
911 : (exponent / maxIntDig) - 1;
912 exponent *= maxIntDig;
913 } else {
914 // No exponent increment is defined; use minimum integer digits.
915 // If none is specified, as in "#E0", generate 1 integer digit.
374ca955 916 exponent -= (minIntDig > 0 || minFracDig > 0)
b75a7d8f
A
917 ? minIntDig : 1;
918 }
919
920 // We now output a minimum number of digits, and more if there
921 // are more digits, up to the maximum number of digits. We
922 // place the decimal point after the "integer" digits, which
923 // are the first (decimalAt - exponent) digits.
374ca955 924 int32_t minimumDigits = minIntDig + minFracDig;
b75a7d8f
A
925 // The number of integer digits is handled specially if the number
926 // is zero, since then there may be no digits.
927 int32_t integerDigits = digits.isZero() ? minIntDig :
928 digits.fDecimalAt - exponent;
929 int32_t totalDigits = digits.fCount;
930 if (minimumDigits > totalDigits)
931 totalDigits = minimumDigits;
932 if (integerDigits > totalDigits)
933 totalDigits = integerDigits;
934
935 // totalDigits records total number of digits needs to be processed
936 int32_t i;
937 for (i=0; i<totalDigits; ++i)
938 {
939 if (i == integerDigits)
940 {
941 // Record field information for caller.
942 if (fieldPosition.getField() == NumberFormat::kIntegerField)
943 fieldPosition.setEndIndex(appendTo.length());
944
945 appendTo += *decimal;
946
947 // Record field information for caller.
948 if (fieldPosition.getField() == NumberFormat::kFractionField)
949 fieldPosition.setBeginIndex(appendTo.length());
950 }
951 // Restores the digit character or pads the buffer with zeros.
952 UChar32 c = (UChar32)((i < digits.fCount) ?
953 (digits.fDigits[i] + zeroDelta) :
954 zero);
955 appendTo += c;
956 }
957
958 // Record field information
959 if (fieldPosition.getField() == NumberFormat::kIntegerField)
960 {
961 if (fieldPosition.getEndIndex() < 0)
962 fieldPosition.setEndIndex(appendTo.length());
963 }
964 else if (fieldPosition.getField() == NumberFormat::kFractionField)
965 {
966 if (fieldPosition.getBeginIndex() < 0)
967 fieldPosition.setBeginIndex(appendTo.length());
968 fieldPosition.setEndIndex(appendTo.length());
969 }
970
971 // The exponent is output using the pattern-specified minimum
972 // exponent digits. There is no maximum limit to the exponent
973 // digits, since truncating the exponent would appendTo in an
974 // unacceptable inaccuracy.
975 appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
976
977 // For zero values, we force the exponent to zero. We
978 // must do this here, and not earlier, because the value
979 // is used to determine integer digit count above.
980 if (digits.isZero())
981 exponent = 0;
982
983 if (exponent < 0) {
984 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
985 } else if (fExponentSignAlwaysShown) {
986 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
987 }
988
989 DigitList expDigits;
990 expDigits.set(exponent);
374ca955
A
991 {
992 int expDig = fMinExponentDigits;
993 if (fUseExponentialNotation && expDig < 1) {
994 expDig = 1;
995 }
996 for (i=expDigits.fDecimalAt; i<expDig; ++i)
997 appendTo += (zero);
998 }
b75a7d8f
A
999 for (i=0; i<expDigits.fDecimalAt; ++i)
1000 {
1001 UChar32 c = (UChar32)((i < expDigits.fCount) ?
1002 (expDigits.fDigits[i] + zeroDelta) : zero);
1003 appendTo += c;
1004 }
1005 }
1006 else // Not using exponential notation
1007 {
1008 // Record field information for caller.
1009 if (fieldPosition.getField() == NumberFormat::kIntegerField)
1010 fieldPosition.setBeginIndex(appendTo.length());
1011
374ca955
A
1012 int32_t sigCount = 0;
1013 int32_t minSigDig = getMinimumSignificantDigits();
1014 int32_t maxSigDig = getMaximumSignificantDigits();
1015 if (!useSigDig) {
1016 minSigDig = 0;
1017 maxSigDig = INT32_MAX;
1018 }
1019
b75a7d8f
A
1020 // Output the integer portion. Here 'count' is the total
1021 // number of integer digits we will display, including both
1022 // leading zeros required to satisfy getMinimumIntegerDigits,
1023 // and actual digits present in the number.
374ca955
A
1024 int32_t count = useSigDig ?
1025 _max(1, digits.fDecimalAt) : minIntDig;
1026 if (digits.fDecimalAt > 0 && count < digits.fDecimalAt) {
b75a7d8f 1027 count = digits.fDecimalAt;
374ca955 1028 }
b75a7d8f
A
1029
1030 // Handle the case where getMaximumIntegerDigits() is smaller
1031 // than the real number of integer digits. If this is so, we
1032 // output the least significant max integer digits. For example,
1033 // the value 1997 printed with 2 max integer digits is just "97".
1034
374ca955
A
1035 int32_t digitIndex = 0; // Index into digitList.fDigits[]
1036 if (count > maxIntDig && maxIntDig >= 0) {
b75a7d8f
A
1037 count = maxIntDig;
1038 digitIndex = digits.fDecimalAt - count;
1039 }
1040
1041 int32_t sizeBeforeIntegerPart = appendTo.length();
1042
1043 int32_t i;
1044 for (i=count-1; i>=0; --i)
1045 {
374ca955
A
1046 if (i < digits.fDecimalAt && digitIndex < digits.fCount &&
1047 sigCount < maxSigDig) {
b75a7d8f
A
1048 // Output a real digit
1049 appendTo += ((UChar32)(digits.fDigits[digitIndex++] + zeroDelta));
374ca955 1050 ++sigCount;
b75a7d8f
A
1051 }
1052 else
1053 {
374ca955 1054 // Output a zero (leading or trailing)
b75a7d8f 1055 appendTo += (zero);
374ca955
A
1056 if (sigCount > 0) {
1057 ++sigCount;
1058 }
b75a7d8f
A
1059 }
1060
1061 // Output grouping separator if necessary.
1062 if (isGroupingPosition(i)) {
1063 appendTo.append(*grouping);
1064 }
1065 }
1066
1067 // Record field information for caller.
1068 if (fieldPosition.getField() == NumberFormat::kIntegerField)
1069 fieldPosition.setEndIndex(appendTo.length());
1070
1071 // Determine whether or not there are any printable fractional
1072 // digits. If we've used up the digits we know there aren't.
374ca955
A
1073 UBool fractionPresent = (!isInteger && digitIndex < digits.fCount) ||
1074 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
b75a7d8f
A
1075
1076 // If there is no fraction present, and we haven't printed any
1077 // integer digits, then print a zero. Otherwise we won't print
1078 // _any_ digits, and we won't be able to parse this string.
1079 if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart)
1080 appendTo += (zero);
1081
1082 // Output the decimal separator if we always do so.
1083 if (fDecimalSeparatorAlwaysShown || fractionPresent)
1084 appendTo += *decimal;
1085
1086 // Record field information for caller.
1087 if (fieldPosition.getField() == NumberFormat::kFractionField)
1088 fieldPosition.setBeginIndex(appendTo.length());
1089
374ca955
A
1090 count = useSigDig ? INT32_MAX : getMaximumFractionDigits();
1091 if (useSigDig && (sigCount == maxSigDig ||
1092 (sigCount >= minSigDig && digitIndex == digits.fCount))) {
1093 count = 0;
1094 }
1095
1096 for (i=0; i < count; ++i) {
1097 // Here is where we escape from the loop. We escape
1098 // if we've output the maximum fraction digits
1099 // (specified in the for expression above). We also
1100 // stop when we've output the minimum digits and
1101 // either: we have an integer, so there is no
1102 // fractional stuff to display, or we're out of
1103 // significant digits.
1104 if (!useSigDig && i >= getMinimumFractionDigits() &&
1105 (isInteger || digitIndex >= digits.fCount)) {
1106 break;
b75a7d8f 1107 }
b75a7d8f 1108
374ca955
A
1109 // Output leading fractional zeros. These are zeros
1110 // that come after the decimal but before any
1111 // significant digits. These are only output if
1112 // abs(number being formatted) < 1.0.
1113 if (-1-i > (digits.fDecimalAt-1)) {
b75a7d8f 1114 appendTo += zero;
374ca955
A
1115 continue;
1116 }
1117
1118 // Output a digit, if we have any precision left, or a
1119 // zero if we don't. We don't want to output noise digits.
1120 if (!isInteger && digitIndex < digits.fCount) {
1121 appendTo += ((UChar32)(digits.fDigits[digitIndex++] + zeroDelta));
1122 } else {
1123 appendTo += zero;
1124 }
1125
1126 // If we reach the maximum number of significant
1127 // digits, or if we output all the real digits and
1128 // reach the minimum, then we are done.
1129 ++sigCount;
1130 if (useSigDig &&
1131 (sigCount == maxSigDig ||
1132 (digitIndex == digits.fCount && sigCount >= minSigDig))) {
1133 break;
b75a7d8f
A
1134 }
1135 }
1136
1137 // Record field information for caller.
1138 if (fieldPosition.getField() == NumberFormat::kFractionField)
1139 fieldPosition.setEndIndex(appendTo.length());
1140 }
1141
1142 int32_t suffixLen = appendAffix(appendTo, doubleValue, !digits.fIsPositive, FALSE);
1143
1144 addPadding(appendTo, fieldPosition, prefixLen, suffixLen);
1145 return appendTo;
1146}
1147
1148/**
1149 * Inserts the character fPad as needed to expand result to fFormatWidth.
1150 * @param result the string to be padded
1151 */
1152void DecimalFormat::addPadding(UnicodeString& appendTo,
1153 FieldPosition& fieldPosition,
1154 int32_t prefixLen,
1155 int32_t suffixLen) const
1156{
1157 if (fFormatWidth > 0) {
1158 int32_t len = fFormatWidth - appendTo.length();
1159 if (len > 0) {
1160 UnicodeString padding;
1161 for (int32_t i=0; i<len; ++i) {
1162 padding += fPad;
1163 }
1164 switch (fPadPosition) {
1165 case kPadAfterPrefix:
1166 appendTo.insert(prefixLen, padding);
1167 break;
1168 case kPadBeforePrefix:
1169 appendTo.insert(0, padding);
1170 break;
1171 case kPadBeforeSuffix:
1172 appendTo.insert(appendTo.length() - suffixLen, padding);
1173 break;
1174 case kPadAfterSuffix:
1175 appendTo += padding;
1176 break;
1177 }
1178 if (fPadPosition == kPadBeforePrefix ||
1179 fPadPosition == kPadAfterPrefix) {
1180 fieldPosition.setBeginIndex(len + fieldPosition.getBeginIndex());
1181 fieldPosition.setEndIndex(len + fieldPosition.getEndIndex());
1182 }
1183 }
1184 }
1185}
1186
1187//------------------------------------------------------------------------------
1188
1189void
1190DecimalFormat::parse(const UnicodeString& text,
1191 Formattable& result,
1192 UErrorCode& status) const
1193{
1194 NumberFormat::parse(text, result, status);
1195}
1196
1197void
1198DecimalFormat::parse(const UnicodeString& text,
1199 Formattable& result,
374ca955
A
1200 ParsePosition& parsePosition) const {
1201 parse(text, result, parsePosition, FALSE);
1202}
1203
1204Formattable& DecimalFormat::parseCurrency(const UnicodeString& text,
1205 Formattable& result,
1206 ParsePosition& pos) const {
1207 parse(text, result, pos, TRUE);
1208 return result;
1209}
1210
1211/**
1212 * Parses the given text as either a number or a currency amount.
1213 * @param text the string to parse
1214 * @param result output parameter for the result
1215 * @param parsePosition input-output position; on input, the
1216 * position within text to match; must have 0 <= pos.getIndex() <
1217 * text.length(); on output, the position after the last matched
1218 * character. If the parse fails, the position in unchanged upon
1219 * output.
1220 * @param parseCurrency if true, a currency amount is parsed;
1221 * otherwise a Number is parsed
1222 */
1223void DecimalFormat::parse(const UnicodeString& text,
1224 Formattable& result,
1225 ParsePosition& parsePosition,
1226 UBool parseCurrency) const {
b75a7d8f
A
1227 int32_t backup;
1228 int32_t i = backup = parsePosition.getIndex();
1229
1230 // Handle NaN as a special case:
1231
1232 // Skip padding characters, if around prefix
1233 if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix ||
1234 fPadPosition == kPadAfterPrefix)) {
1235 i = skipPadding(text, i);
1236 }
1237 // If the text is composed of the representation of NaN, returns NaN.length
1238 const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1239 int32_t nanLen = (text.compare(i, nan->length(), *nan)
1240 ? 0 : nan->length());
1241 if (nanLen) {
1242 i += nanLen;
1243 if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix ||
1244 fPadPosition == kPadAfterSuffix)) {
1245 i = skipPadding(text, i);
1246 }
1247 parsePosition.setIndex(i);
1248 result.setDouble(uprv_getNaN());
1249 return;
1250 }
1251
1252 // NaN parse failed; start over
1253 i = backup;
1254
1255 // status is used to record whether a number is infinite.
1256 UBool status[fgStatusLength];
374ca955
A
1257 UChar curbuf[4];
1258 UChar* currency = parseCurrency ? curbuf : NULL;
b75a7d8f
A
1259 DigitList digits;
1260
374ca955 1261 if (!subparse(text, parsePosition, digits, status, currency)) {
b75a7d8f
A
1262 parsePosition.setIndex(backup);
1263 return;
1264 }
1265
1266 // Handle infinity
1267 if (status[fgStatusInfinite]) {
1268 double inf = uprv_getInfinity();
1269 result.setDouble(digits.fIsPositive ? inf : -inf);
b75a7d8f
A
1270 }
1271
374ca955
A
1272 else {
1273 // Do as much of the multiplier conversion as possible without
1274 // losing accuracy.
1275 int32_t mult = fMultiplier; // Don't modify this.multiplier
1276 while (mult % 10 == 0) {
1277 mult /= 10;
1278 --digits.fDecimalAt;
1279 }
1280
1281 // Handle integral values. We want to return the most
1282 // parsimonious type that will accommodate all of the result's
1283 // precision. We therefore only return a long if the result fits
1284 // entirely within a long (taking into account the multiplier) --
1285 // otherwise we fall through and return a double. When more
1286 // numeric types are supported by Formattable (e.g., 64-bit
1287 // integers, bignums) we will extend this logic to include them.
1288 if (digits.fitsIntoLong(isParseIntegerOnly())) {
1289 int32_t n = digits.getLong();
1290 if (n % mult == 0) {
1291 result.setLong(n / mult);
1292 }
1293 else { // else handle the remainder
1294 result.setDouble(((double)n) / mult);
1295 }
b75a7d8f 1296 }
374ca955
A
1297 else if (digits.fitsIntoInt64(isParseIntegerOnly())) {
1298 int64_t n = digits.getInt64();
1299 if (n % mult == 0) {
1300 result.setInt64(n / mult);
1301 }
1302 else { // else handle the remainder
1303 result.setDouble(((double)n) / mult);
1304 }
1305 }
1306 else {
1307 // Handle non-integral or very large values
1308 // Dividing by one is okay and not that costly.
1309 result.setDouble(digits.getDouble() / mult);
b75a7d8f
A
1310 }
1311 }
374ca955
A
1312
1313 if (parseCurrency) {
1314 UErrorCode ec = U_ZERO_ERROR;
1315 Formattable n(result);
1316 result.adoptObject(new CurrencyAmount(n, curbuf, ec));
1317 U_ASSERT(U_SUCCESS(ec)); // should always succeed
b75a7d8f
A
1318 }
1319}
1320
1321
1322/*
1323This is an old implimentation that was preparing for 64-bit numbers in ICU.
1324It is very slow, and 64-bit numbers are not ANSI-C compatible. This code
1325is here if we change our minds.
374ca955
A
1326
1327^^^ what is this referring to? remove? ^^^ [alan]
b75a7d8f 1328*/
374ca955 1329
b75a7d8f
A
1330/**
1331 * Parse the given text into a number. The text is parsed beginning at
1332 * parsePosition, until an unparseable character is seen.
374ca955 1333 * @param text the string to parse.
b75a7d8f 1334 * @param parsePosition The position at which to being parsing. Upon
374ca955
A
1335 * return, the first unparsed character.
1336 * @param digits the DigitList to set to the parsed value.
1337 * @param status output param containing boolean status flags indicating
b75a7d8f 1338 * whether the value was infinite and whether it was positive.
374ca955
A
1339 * @param currency return value for parsed currency, for generic
1340 * currency parsing mode, or NULL for normal parsing. In generic
1341 * currency parsing mode, any currency is parsed, not just the
1342 * currency that this formatter is set to.
b75a7d8f
A
1343 */
1344UBool DecimalFormat::subparse(const UnicodeString& text, ParsePosition& parsePosition,
374ca955
A
1345 DigitList& digits, UBool* status,
1346 UChar* currency) const
b75a7d8f
A
1347{
1348 int32_t position = parsePosition.getIndex();
1349 int32_t oldStart = position;
1350
1351 // Match padding before prefix
1352 if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) {
1353 position = skipPadding(text, position);
1354 }
1355
1356 // Match positive and negative prefixes; prefer longest match.
374ca955
A
1357 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, currency);
1358 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, currency);
b75a7d8f
A
1359 if (posMatch >= 0 && negMatch >= 0) {
1360 if (posMatch > negMatch) {
1361 negMatch = -1;
1362 } else if (negMatch > posMatch) {
1363 posMatch = -1;
1364 }
1365 }
1366 if (posMatch >= 0) {
1367 position += posMatch;
1368 } else if (negMatch >= 0) {
1369 position += negMatch;
1370 } else {
1371 parsePosition.setErrorIndex(position);
1372 return FALSE;
1373 }
1374
1375 // Match padding before prefix
1376 if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) {
1377 position = skipPadding(text, position);
1378 }
1379
1380 // process digits or Inf, find decimal position
1381 const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
1382 int32_t infLen = (text.compare(position, inf->length(), *inf)
1383 ? 0 : inf->length());
1384 position += infLen; // infLen is non-zero when it does equal to infinity
1385 status[fgStatusInfinite] = (UBool)infLen;
1386 if (!infLen)
1387 {
1388 // We now have a string of digits, possibly with grouping symbols,
1389 // and decimal points. We want to process these into a DigitList.
1390 // We don't want to put a bunch of leading zeros into the DigitList
1391 // though, so we keep track of the location of the decimal point,
1392 // put only significant digits into the DigitList, and adjust the
1393 // exponent as needed.
1394
1395 digits.fDecimalAt = digits.fCount = 0;
1396 UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
1397
1398 const UnicodeString *decimal;
1399 if(fIsCurrencyFormat) {
1400 decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1401 } else {
1402 decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1403 }
1404 const UnicodeString *grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
b75a7d8f
A
1405 UBool sawDecimal = FALSE;
1406 UBool sawDigit = FALSE;
1407 int32_t backup = -1;
1408 int32_t digit;
1409 int32_t textLength = text.length(); // One less pointer to follow
1410 int32_t groupingLen = grouping->length();
1411 int32_t decimalLen = decimal->length();
1412
1413 // We have to track digitCount ourselves, because digits.fCount will
1414 // pin when the maximum allowable digits is reached.
1415 int32_t digitCount = 0;
1416
1417 for (; position < textLength; )
1418 {
1419 UChar32 ch = text.char32At(position);
1420
1421 /* We recognize all digit ranges, not only the Latin digit range
1422 * '0'..'9'. We do so by using the Character.digit() method,
1423 * which converts a valid Unicode digit to the range 0..9.
1424 *
1425 * The character 'ch' may be a digit. If so, place its value
1426 * from 0 to 9 in 'digit'. First try using the locale digit,
1427 * which may or MAY NOT be a standard Unicode digit range. If
1428 * this fails, try using the standard Unicode digit ranges by
1429 * calling Character.digit(). If this also fails, digit will
1430 * have a value outside the range 0..9.
1431 */
1432 digit = ch - zero;
1433 if (digit < 0 || digit > 9)
1434 {
1435 digit = u_charDigitValue(ch);
1436 }
1437
1438 if (digit > 0 && digit <= 9)
1439 {
1440 // Cancel out backup setting (see grouping handler below)
1441 backup = -1;
1442
1443 sawDigit = TRUE;
1444 // output a regular non-zero digit.
1445 ++digitCount;
1446 digits.append((char)(digit + '0'));
1447 position += U16_LENGTH(ch);
1448 }
1449 else if (digit == 0)
1450 {
1451 // Cancel out backup setting (see grouping handler below)
1452 backup = -1;
1453 sawDigit = TRUE;
1454
1455 // Check for leading zeros
1456 if (digits.fCount != 0)
1457 {
1458 // output a regular zero digit.
1459 ++digitCount;
1460 digits.append((char)(digit + '0'));
1461 }
1462 else if (sawDecimal)
1463 {
1464 // If we have seen the decimal, but no significant digits yet,
1465 // then we account for leading zeros by decrementing the
1466 // digits.fDecimalAt into negative values.
1467 --digits.fDecimalAt;
1468 }
1469 // else ignore leading zeros in integer part of number.
1470 position += U16_LENGTH(ch);
1471 }
1472 else if (!text.compare(position, groupingLen, *grouping) && isGroupingUsed())
1473 {
1474 // Ignore grouping characters, if we are using them, but require
1475 // that they be followed by a digit. Otherwise we backup and
1476 // reprocess them.
1477 backup = position;
1478 position += groupingLen;
1479 }
1480 else if (!text.compare(position, decimalLen, *decimal) && !isParseIntegerOnly() && !sawDecimal)
1481 {
1482 // If we're only parsing integers, or if we ALREADY saw the
1483 // decimal, then don't parse this one.
1484
1485 digits.fDecimalAt = digitCount; // Not digits.fCount!
1486 sawDecimal = TRUE;
1487 position += decimalLen;
1488 }
1489 else {
1490 const UnicodeString *tmp;
1491 tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
1492 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit
1493 {
1494 // Parse sign, if present
1495 int32_t pos = position + tmp->length();
1496 DigitList exponentDigits;
1497
1498 if (pos < textLength)
1499 {
1500 tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1501 if (!text.compare(pos, tmp->length(), *tmp))
1502 {
1503 pos += tmp->length();
1504 }
1505 else {
1506 tmp = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1507 if (!text.compare(pos, tmp->length(), *tmp))
1508 {
1509 pos += tmp->length();
1510 exponentDigits.fIsPositive = FALSE;
1511 }
1512 }
1513 }
1514
1515 while (pos < textLength) {
1516 ch = text[(int32_t)pos];
1517 digit = ch - zero;
1518
1519 if (digit < 0 || digit > 9) {
1520 digit = u_charDigitValue(ch);
1521 }
1522 if (0 <= digit && digit <= 9) {
1523 ++pos;
1524 exponentDigits.append((char)(digit + '0'));
1525 } else {
1526 break;
1527 }
1528 }
1529
1530 if (exponentDigits.fCount > 0) {
1531 exponentDigits.fDecimalAt = exponentDigits.fCount;
1532 digits.fDecimalAt += exponentDigits.getLong();
1533 position = pos; // Advance past the exponent
1534 }
1535
1536 break; // Whether we fail or succeed, we exit this loop
1537 }
1538 else {
1539 break;
1540 }
1541 }
1542 }
1543
1544 if (backup != -1)
1545 {
1546 position = backup;
1547 }
1548
1549 // If there was no decimal point we have an integer
1550 if (!sawDecimal)
1551 {
1552 digits.fDecimalAt += digitCount; // Not digits.fCount!
1553 }
1554
1555 // If none of the text string was recognized. For example, parse
1556 // "x" with pattern "#0.00" (return index and error index both 0)
1557 // parse "$" with pattern "$#0.00". (return index 0 and error index
1558 // 1).
1559 if (!sawDigit && digitCount == 0) {
1560 parsePosition.setIndex(oldStart);
1561 parsePosition.setErrorIndex(oldStart);
1562 return FALSE;
1563 }
1564 }
1565
1566 // Match padding before suffix
1567 if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) {
1568 position = skipPadding(text, position);
1569 }
1570
1571 // Match positive and negative suffixes; prefer longest match.
1572 if (posMatch >= 0) {
374ca955 1573 posMatch = compareAffix(text, position, FALSE, FALSE, currency);
b75a7d8f
A
1574 }
1575 if (negMatch >= 0) {
374ca955 1576 negMatch = compareAffix(text, position, TRUE, FALSE, currency);
b75a7d8f
A
1577 }
1578 if (posMatch >= 0 && negMatch >= 0) {
1579 if (posMatch > negMatch) {
1580 negMatch = -1;
1581 } else if (negMatch > posMatch) {
1582 posMatch = -1;
1583 }
1584 }
1585
1586 // Fail if neither or both
1587 if ((posMatch >= 0) == (negMatch >= 0)) {
1588 parsePosition.setErrorIndex(position);
1589 return FALSE;
1590 }
1591
1592 position += (posMatch>=0 ? posMatch : negMatch);
1593
1594 // Match padding before suffix
1595 if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) {
1596 position = skipPadding(text, position);
1597 }
1598
1599 parsePosition.setIndex(position);
1600
1601 digits.fIsPositive = (posMatch >= 0);
1602
1603 if(parsePosition.getIndex() == oldStart)
1604 {
1605 parsePosition.setErrorIndex(position);
1606 return FALSE;
1607 }
1608 return TRUE;
1609}
1610
1611/**
1612 * Starting at position, advance past a run of pad characters, if any.
1613 * Return the index of the first character after position that is not a pad
1614 * character. Result is >= position.
1615 */
1616int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
1617 int32_t padLen = U16_LENGTH(fPad);
1618 while (position < text.length() &&
1619 text.char32At(position) == fPad) {
1620 position += padLen;
1621 }
1622 return position;
1623}
1624
1625/**
1626 * Return the length matched by the given affix, or -1 if none.
1627 * Runs of white space in the affix, match runs of white space in
1628 * the input. Pattern white space and input white space are
1629 * determined differently; see code.
1630 * @param text input text
1631 * @param pos offset into input at which to begin matching
1632 * @param isNegative
1633 * @param isPrefix
374ca955
A
1634 * @param currency return value for parsed currency, for generic
1635 * currency parsing mode, or null for normal parsing. In generic
1636 * currency parsing mode, any currency is parsed, not just the
1637 * currency that this formatter is set to.
b75a7d8f
A
1638 * @return length of input that matches, or -1 if match failure
1639 */
1640int32_t DecimalFormat::compareAffix(const UnicodeString& text,
1641 int32_t pos,
1642 UBool isNegative,
374ca955
A
1643 UBool isPrefix,
1644 UChar* currency) const {
1645 if (fCurrencyChoice != NULL || currency != NULL) {
b75a7d8f
A
1646 if (isPrefix) {
1647 return compareComplexAffix(isNegative ? *fNegPrefixPattern : *fPosPrefixPattern,
374ca955 1648 text, pos, currency);
b75a7d8f
A
1649 } else {
1650 return compareComplexAffix(isNegative ? *fNegSuffixPattern : *fPosSuffixPattern,
374ca955 1651 text, pos, currency);
b75a7d8f
A
1652 }
1653 }
1654
1655 if (isPrefix) {
1656 return compareSimpleAffix(isNegative ? fNegativePrefix : fPositivePrefix,
1657 text, pos);
1658 } else {
1659 return compareSimpleAffix(isNegative ? fNegativeSuffix : fPositiveSuffix,
1660 text, pos);
1661 }
1662}
1663
1664/**
1665 * Return the length matched by the given affix, or -1 if none.
1666 * Runs of white space in the affix, match runs of white space in
1667 * the input. Pattern white space and input white space are
1668 * determined differently; see code.
1669 * @param affix pattern string, taken as a literal
1670 * @param input input text
1671 * @param pos offset into input at which to begin matching
1672 * @return length of input that matches, or -1 if match failure
1673 */
1674int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
1675 const UnicodeString& input,
1676 int32_t pos) {
1677 int32_t start = pos;
1678 for (int32_t i=0; i<affix.length(); ) {
1679 UChar32 c = affix.char32At(i);
1680 int32_t len = U16_LENGTH(c);
1681 if (uprv_isRuleWhiteSpace(c)) {
1682 // We may have a pattern like: \u200F \u0020
1683 // and input text like: \u200F \u0020
1684 // Note that U+200F and U+0020 are RuleWhiteSpace but only
1685 // U+0020 is UWhiteSpace. So we have to first do a direct
1686 // match of the run of RULE whitespace in the pattern,
1687 // then match any extra characters.
1688 UBool literalMatch = FALSE;
1689 while (pos < input.length() &&
1690 input.char32At(pos) == c) {
1691 literalMatch = TRUE;
1692 i += len;
1693 pos += len;
1694 if (i == affix.length()) {
1695 break;
1696 }
1697 c = affix.char32At(i);
1698 len = U16_LENGTH(c);
1699 if (!uprv_isRuleWhiteSpace(c)) {
1700 break;
1701 }
1702 }
1703
1704 // Advance over run in pattern
1705 i = skipRuleWhiteSpace(affix, i);
1706
1707 // Advance over run in input text
1708 // Must see at least one white space char in input,
1709 // unless we've already matched some characters literally.
1710 int32_t s = pos;
1711 pos = skipUWhiteSpace(input, pos);
1712 if (pos == s && !literalMatch) {
1713 return -1;
1714 }
1715 } else {
1716 if (pos < input.length() &&
1717 input.char32At(pos) == c) {
1718 i += len;
1719 pos += len;
1720 } else {
1721 return -1;
1722 }
1723 }
1724 }
1725 return pos - start;
1726}
1727
1728/**
1729 * Skip over a run of zero or more isRuleWhiteSpace() characters at
1730 * pos in text.
1731 */
1732int32_t DecimalFormat::skipRuleWhiteSpace(const UnicodeString& text, int32_t pos) {
1733 while (pos < text.length()) {
1734 UChar32 c = text.char32At(pos);
1735 if (!uprv_isRuleWhiteSpace(c)) {
1736 break;
1737 }
1738 pos += U16_LENGTH(c);
1739 }
1740 return pos;
1741}
1742
1743/**
1744 * Skip over a run of zero or more isUWhiteSpace() characters at pos
1745 * in text.
1746 */
1747int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) {
1748 while (pos < text.length()) {
1749 UChar32 c = text.char32At(pos);
1750 if (!u_isUWhiteSpace(c)) {
1751 break;
1752 }
1753 pos += U16_LENGTH(c);
1754 }
1755 return pos;
1756}
1757
1758/**
1759 * Return the length matched by the given affix, or -1 if none.
1760 * @param affixPat pattern string
1761 * @param input input text
1762 * @param pos offset into input at which to begin matching
374ca955
A
1763 * @param currency return value for parsed currency, for generic
1764 * currency parsing mode, or null for normal parsing. In generic
1765 * currency parsing mode, any currency is parsed, not just the
1766 * currency that this formatter is set to.
b75a7d8f
A
1767 * @return length of input that matches, or -1 if match failure
1768 */
1769int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
1770 const UnicodeString& text,
374ca955
A
1771 int32_t pos,
1772 UChar* currency) const {
1773 U_ASSERT(currency != NULL ||
1774 (fCurrencyChoice != NULL && *getCurrency() != 0));
b75a7d8f
A
1775
1776 for (int32_t i=0; i<affixPat.length() && pos >= 0; ) {
1777 UChar32 c = affixPat.char32At(i);
1778 i += U16_LENGTH(c);
1779
1780 if (c == kQuote) {
1781 U_ASSERT(i <= affixPat.length());
1782 c = affixPat.char32At(i);
1783 i += U16_LENGTH(c);
1784
1785 const UnicodeString* affix = NULL;
1786
1787 switch (c) {
1788 case kCurrencySign: {
374ca955
A
1789 // If currency != null, then perform generic currency matching.
1790 // Otherwise, do currency choice parsing.
b75a7d8f
A
1791 UBool intl = i<affixPat.length() &&
1792 affixPat.char32At(i) == kCurrencySign;
374ca955
A
1793 // Parse generic currency -- anything for which we
1794 // have a display name, or any 3-letter ISO code.
1795 if (currency != NULL) {
1796 // Try to parse display name for our locale; first
1797 // determine our locale.
1798 UErrorCode ec = U_ZERO_ERROR;
1799 const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
1800 if (U_FAILURE(ec) || loc == NULL || *loc == 0) {
1801 // applyPattern has been called; use the symbols
1802 loc = fSymbols->getLocale().getName();
1803 ec = U_ZERO_ERROR;
1804 }
1805 // Delegate parse of display name => ISO code to Currency
b75a7d8f 1806 ParsePosition ppos(pos);
374ca955
A
1807 UChar curr[4];
1808 uprv_parseCurrency(loc, text, ppos, curr, ec);
1809
1810 // If parse succeeds, populate currency[0]
1811 if (U_SUCCESS(ec) && ppos.getIndex() != pos) {
1812 u_strcpy(currency, curr);
1813 pos = ppos.getIndex();
1814 } else {
1815 pos = -1;
1816 }
1817 } else {
1818 if (intl) {
1819 ++i;
1820 pos = match(text, pos, getCurrency());
1821 } else {
1822 ParsePosition ppos(pos);
1823 Formattable result;
1824 fCurrencyChoice->parse(text, result, ppos);
1825 pos = (ppos.getIndex() == pos) ? -1 : ppos.getIndex();
1826 }
b75a7d8f
A
1827 }
1828 continue;
1829 }
1830 case kPatternPercent:
1831 affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
1832 break;
1833 case kPatternPerMill:
1834 affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
1835 break;
1836 case kPatternPlus:
1837 affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1838 break;
1839 case kPatternMinus:
1840 affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1841 break;
1842 default:
1843 // fall through to affix!=0 test, which will fail
1844 break;
1845 }
1846
1847 if (affix != NULL) {
1848 pos = match(text, pos, *affix);
1849 continue;
1850 }
1851 }
1852
1853 pos = match(text, pos, c);
1854 if (uprv_isRuleWhiteSpace(c)) {
1855 i = skipRuleWhiteSpace(affixPat, i);
1856 }
1857 }
1858 return pos;
1859}
1860
1861/**
1862 * Match a single character at text[pos] and return the index of the
1863 * next character upon success. Return -1 on failure. If
1864 * isRuleWhiteSpace(ch) then match a run of white space in text.
1865 */
1866int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) {
1867 if (uprv_isRuleWhiteSpace(ch)) {
1868 // Advance over run of white space in input text
1869 // Must see at least one white space char in input
1870 int32_t s = pos;
1871 pos = skipUWhiteSpace(text, pos);
1872 if (pos == s) {
1873 return -1;
1874 }
1875 return pos;
1876 }
1877 return (pos >= 0 && text.char32At(pos) == ch) ?
1878 (pos + U16_LENGTH(ch)) : -1;
1879}
1880
1881/**
1882 * Match a string at text[pos] and return the index of the next
1883 * character upon success. Return -1 on failure. Match a run of
1884 * white space in str with a run of white space in text.
1885 */
1886int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) {
1887 for (int32_t i=0; i<str.length() && pos >= 0; ) {
1888 UChar32 ch = str.char32At(i);
1889 i += U16_LENGTH(ch);
1890 if (uprv_isRuleWhiteSpace(ch)) {
1891 i = skipRuleWhiteSpace(str, i);
1892 }
1893 pos = match(text, pos, ch);
1894 }
1895 return pos;
1896}
1897
1898//------------------------------------------------------------------------------
1899// Gets the pointer to the localized decimal format symbols
1900
1901const DecimalFormatSymbols*
1902DecimalFormat::getDecimalFormatSymbols() const
1903{
1904 return fSymbols;
1905}
1906
1907//------------------------------------------------------------------------------
1908// De-owning the current localized symbols and adopt the new symbols.
1909
1910void
1911DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
1912{
374ca955
A
1913 if (symbolsToAdopt == NULL) {
1914 return; // do not allow caller to set fSymbols to NULL
1915 }
1916
1917 UBool sameSymbols = FALSE;
1918 if (fSymbols != NULL) {
1919 sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
1920 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
1921 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
1922 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
b75a7d8f 1923 delete fSymbols;
374ca955 1924 }
b75a7d8f
A
1925
1926 fSymbols = symbolsToAdopt;
374ca955
A
1927 if (!sameSymbols) {
1928 // If the currency symbols are the same, there is no need to recalculate.
1929 setCurrencyForSymbols();
1930 }
b75a7d8f
A
1931 expandAffixes();
1932}
1933//------------------------------------------------------------------------------
1934// Setting the symbols is equlivalent to adopting a newly created localized
1935// symbols.
1936
1937void
1938DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
1939{
1940 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
1941}
1942
1943/**
1944 * Update the currency object to match the symbols. This method
1945 * is used only when the caller has passed in a symbols object
1946 * that may not be the default object for its locale.
1947 */
1948void
1949DecimalFormat::setCurrencyForSymbols() {
1950 /*Bug 4212072
1951 Update the affix strings accroding to symbols in order to keep
1952 the affix strings up to date.
1953 [Richard/GCL]
1954 */
1955
1956 // With the introduction of the Currency object, the currency
1957 // symbols in the DFS object are ignored. For backward
1958 // compatibility, we check any explicitly set DFS object. If it
1959 // is a default symbols object for its locale, we change the
1960 // currency object to one for that locale. If it is custom,
1961 // we set the currency to null.
1962 UErrorCode ec = U_ZERO_ERROR;
374ca955
A
1963 const UChar* c = NULL;
1964 const char* loc = fSymbols->getLocale().getName();
1965 UChar intlCurrencySymbol[4];
1966 ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec);
1967 UnicodeString currencySymbol;
1968
1969 uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec);
1970 if (U_SUCCESS(ec)
1971 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol
1972 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == intlCurrencySymbol)
1973 {
1974 // Trap an error in mapping locale to currency. If we can't
1975 // map, then don't fail and set the currency to "".
1976 c = intlCurrencySymbol;
b75a7d8f 1977 }
374ca955
A
1978 ec = U_ZERO_ERROR; // reset local error code!
1979 setCurrency(c, ec);
b75a7d8f
A
1980}
1981
1982
1983//------------------------------------------------------------------------------
1984// Gets the positive prefix of the number pattern.
1985
1986UnicodeString&
1987DecimalFormat::getPositivePrefix(UnicodeString& result) const
1988{
1989 result = fPositivePrefix;
1990 return result;
1991}
1992
1993//------------------------------------------------------------------------------
1994// Sets the positive prefix of the number pattern.
1995
1996void
1997DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
1998{
1999 fPositivePrefix = newValue;
2000 delete fPosPrefixPattern;
2001 fPosPrefixPattern = 0;
2002}
2003
2004//------------------------------------------------------------------------------
2005// Gets the negative prefix of the number pattern.
2006
2007UnicodeString&
2008DecimalFormat::getNegativePrefix(UnicodeString& result) const
2009{
2010 result = fNegativePrefix;
2011 return result;
2012}
2013
2014//------------------------------------------------------------------------------
2015// Gets the negative prefix of the number pattern.
2016
2017void
2018DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
2019{
2020 fNegativePrefix = newValue;
2021 delete fNegPrefixPattern;
2022 fNegPrefixPattern = 0;
2023}
2024
2025//------------------------------------------------------------------------------
2026// Gets the positive suffix of the number pattern.
2027
2028UnicodeString&
2029DecimalFormat::getPositiveSuffix(UnicodeString& result) const
2030{
2031 result = fPositiveSuffix;
2032 return result;
2033}
2034
2035//------------------------------------------------------------------------------
2036// Sets the positive suffix of the number pattern.
2037
2038void
2039DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
2040{
2041 fPositiveSuffix = newValue;
2042 delete fPosSuffixPattern;
2043 fPosSuffixPattern = 0;
2044}
2045
2046//------------------------------------------------------------------------------
2047// Gets the negative suffix of the number pattern.
2048
2049UnicodeString&
2050DecimalFormat::getNegativeSuffix(UnicodeString& result) const
2051{
2052 result = fNegativeSuffix;
2053 return result;
2054}
2055
2056//------------------------------------------------------------------------------
2057// Sets the negative suffix of the number pattern.
2058
2059void
2060DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
2061{
2062 fNegativeSuffix = newValue;
2063 delete fNegSuffixPattern;
2064 fNegSuffixPattern = 0;
2065}
2066
2067//------------------------------------------------------------------------------
2068// Gets the multiplier of the number pattern.
2069
2070int32_t DecimalFormat::getMultiplier() const
2071{
2072 return fMultiplier;
2073}
2074
2075//------------------------------------------------------------------------------
2076// Sets the multiplier of the number pattern.
2077void
2078DecimalFormat::setMultiplier(int32_t newValue)
2079{
2080 // This shouldn't be set to 0.
2081 // Due to compatibility with ICU4J we cannot set an error code and refuse 0.
2082 // So the rest of the code should ignore fMultiplier when it's 0. [grhoten]
2083 fMultiplier = newValue;
2084}
2085
2086/**
2087 * Get the rounding increment.
2088 * @return A positive rounding increment, or 0.0 if rounding
2089 * is not in effect.
2090 * @see #setRoundingIncrement
2091 * @see #getRoundingMode
2092 * @see #setRoundingMode
2093 */
374ca955 2094double DecimalFormat::getRoundingIncrement() const {
b75a7d8f
A
2095 return fRoundingDouble;
2096}
2097
2098/**
2099 * Set the rounding increment. This method also controls whether
2100 * rounding is enabled.
2101 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2102 * Negative increments are equivalent to 0.0.
2103 * @see #getRoundingIncrement
2104 * @see #getRoundingMode
2105 * @see #setRoundingMode
2106 */
2107void DecimalFormat::setRoundingIncrement(double newValue) {
2108 if (newValue > 0.0) {
2109 if (fRoundingIncrement == NULL) {
2110 fRoundingIncrement = new DigitList();
2111 }
2112 fRoundingIncrement->set((int32_t)newValue);
2113 fRoundingDouble = newValue;
2114 } else {
2115 delete fRoundingIncrement;
2116 fRoundingIncrement = NULL;
2117 fRoundingDouble = 0.0;
2118 }
2119}
2120
2121/**
2122 * Get the rounding mode.
2123 * @return A rounding mode
2124 * @see #setRoundingIncrement
2125 * @see #getRoundingIncrement
2126 * @see #setRoundingMode
2127 */
374ca955 2128DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
b75a7d8f
A
2129 return fRoundingMode;
2130}
2131
2132/**
2133 * Set the rounding mode. This has no effect unless the rounding
2134 * increment is greater than zero.
2135 * @param roundingMode A rounding mode
2136 * @see #setRoundingIncrement
2137 * @see #getRoundingIncrement
2138 * @see #getRoundingMode
2139 */
2140void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
2141 fRoundingMode = roundingMode;
2142}
2143
2144/**
2145 * Get the width to which the output of <code>format()</code> is padded.
2146 * @return the format width, or zero if no padding is in effect
2147 * @see #setFormatWidth
2148 * @see #getPadCharacter
2149 * @see #setPadCharacter
2150 * @see #getPadPosition
2151 * @see #setPadPosition
2152 */
374ca955 2153int32_t DecimalFormat::getFormatWidth() const {
b75a7d8f
A
2154 return fFormatWidth;
2155}
2156
2157/**
2158 * Set the width to which the output of <code>format()</code> is padded.
2159 * This method also controls whether padding is enabled.
2160 * @param width the width to which to pad the result of
2161 * <code>format()</code>, or zero to disable padding. A negative
2162 * width is equivalent to 0.
2163 * @see #getFormatWidth
2164 * @see #getPadCharacter
2165 * @see #setPadCharacter
2166 * @see #getPadPosition
2167 * @see #setPadPosition
2168 */
2169void DecimalFormat::setFormatWidth(int32_t width) {
2170 fFormatWidth = (width > 0) ? width : 0;
2171}
2172
374ca955 2173UnicodeString DecimalFormat::getPadCharacterString() const {
b75a7d8f
A
2174 return fPad;
2175}
2176
b75a7d8f
A
2177void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
2178 if (padChar.length() > 0) {
2179 fPad = padChar.char32At(0);
2180 }
2181 else {
2182 fPad = kDefaultPad;
2183 }
2184}
2185
2186/**
2187 * Get the position at which padding will take place. This is the location
2188 * at which padding will be inserted if the result of <code>format()</code>
2189 * is shorter than the format width.
2190 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2191 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2192 * <code>kPadAfterSuffix</code>.
2193 * @see #setFormatWidth
2194 * @see #getFormatWidth
2195 * @see #setPadCharacter
2196 * @see #getPadCharacter
2197 * @see #setPadPosition
2198 * @see #kPadBeforePrefix
2199 * @see #kPadAfterPrefix
2200 * @see #kPadBeforeSuffix
2201 * @see #kPadAfterSuffix
2202 */
374ca955 2203DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
b75a7d8f
A
2204 return fPadPosition;
2205}
2206
2207/**
2208 * <strong><font face=helvetica color=red>NEW</font></strong>
2209 * Set the position at which padding will take place. This is the location
2210 * at which padding will be inserted if the result of <code>format()</code>
2211 * is shorter than the format width. This has no effect unless padding is
2212 * enabled.
2213 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2214 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2215 * <code>kPadAfterSuffix</code>.
2216 * @see #setFormatWidth
2217 * @see #getFormatWidth
2218 * @see #setPadCharacter
2219 * @see #getPadCharacter
2220 * @see #getPadPosition
2221 * @see #kPadBeforePrefix
2222 * @see #kPadAfterPrefix
2223 * @see #kPadBeforeSuffix
2224 * @see #kPadAfterSuffix
2225 */
2226void DecimalFormat::setPadPosition(EPadPosition padPos) {
2227 fPadPosition = padPos;
2228}
2229
2230/**
2231 * Return whether or not scientific notation is used.
2232 * @return TRUE if this object formats and parses scientific notation
2233 * @see #setScientificNotation
2234 * @see #getMinimumExponentDigits
2235 * @see #setMinimumExponentDigits
2236 * @see #isExponentSignAlwaysShown
2237 * @see #setExponentSignAlwaysShown
2238 */
2239UBool DecimalFormat::isScientificNotation() {
2240 return fUseExponentialNotation;
2241}
2242
2243/**
2244 * Set whether or not scientific notation is used.
2245 * @param useScientific TRUE if this object formats and parses scientific
2246 * notation
2247 * @see #isScientificNotation
2248 * @see #getMinimumExponentDigits
2249 * @see #setMinimumExponentDigits
2250 * @see #isExponentSignAlwaysShown
2251 * @see #setExponentSignAlwaysShown
2252 */
2253void DecimalFormat::setScientificNotation(UBool useScientific) {
2254 fUseExponentialNotation = useScientific;
b75a7d8f
A
2255}
2256
2257/**
2258 * Return the minimum exponent digits that will be shown.
2259 * @return the minimum exponent digits that will be shown
2260 * @see #setScientificNotation
2261 * @see #isScientificNotation
2262 * @see #setMinimumExponentDigits
2263 * @see #isExponentSignAlwaysShown
2264 * @see #setExponentSignAlwaysShown
2265 */
374ca955 2266int8_t DecimalFormat::getMinimumExponentDigits() const {
b75a7d8f
A
2267 return fMinExponentDigits;
2268}
2269
2270/**
2271 * Set the minimum exponent digits that will be shown. This has no
2272 * effect unless scientific notation is in use.
2273 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2274 * that will be shown. Values less than 1 will be treated as 1.
2275 * @see #setScientificNotation
2276 * @see #isScientificNotation
2277 * @see #getMinimumExponentDigits
2278 * @see #isExponentSignAlwaysShown
2279 * @see #setExponentSignAlwaysShown
2280 */
2281void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
2282 fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
2283}
2284
2285/**
2286 * Return whether the exponent sign is always shown.
2287 * @return TRUE if the exponent is always prefixed with either the
2288 * localized minus sign or the localized plus sign, false if only negative
2289 * exponents are prefixed with the localized minus sign.
2290 * @see #setScientificNotation
2291 * @see #isScientificNotation
2292 * @see #setMinimumExponentDigits
2293 * @see #getMinimumExponentDigits
2294 * @see #setExponentSignAlwaysShown
2295 */
2296UBool DecimalFormat::isExponentSignAlwaysShown() {
2297 return fExponentSignAlwaysShown;
2298}
2299
2300/**
2301 * Set whether the exponent sign is always shown. This has no effect
2302 * unless scientific notation is in use.
2303 * @param expSignAlways TRUE if the exponent is always prefixed with either
2304 * the localized minus sign or the localized plus sign, false if only
2305 * negative exponents are prefixed with the localized minus sign.
2306 * @see #setScientificNotation
2307 * @see #isScientificNotation
2308 * @see #setMinimumExponentDigits
2309 * @see #getMinimumExponentDigits
2310 * @see #isExponentSignAlwaysShown
2311 */
2312void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
2313 fExponentSignAlwaysShown = expSignAlways;
2314}
2315
2316//------------------------------------------------------------------------------
2317// Gets the grouping size of the number pattern. For example, thousand or 10
2318// thousand groupings.
2319
2320int32_t
2321DecimalFormat::getGroupingSize() const
2322{
2323 return fGroupingSize;
2324}
2325
2326//------------------------------------------------------------------------------
2327// Gets the grouping size of the number pattern.
2328
2329void
2330DecimalFormat::setGroupingSize(int32_t newValue)
2331{
2332 fGroupingSize = newValue;
2333}
2334
2335//------------------------------------------------------------------------------
2336
2337int32_t
2338DecimalFormat::getSecondaryGroupingSize() const
2339{
2340 return fGroupingSize2;
2341}
2342
2343//------------------------------------------------------------------------------
2344
2345void
2346DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
2347{
2348 fGroupingSize2 = newValue;
2349}
2350
2351//------------------------------------------------------------------------------
2352// Checks if to show the decimal separator.
2353
2354UBool
2355DecimalFormat::isDecimalSeparatorAlwaysShown() const
2356{
2357 return fDecimalSeparatorAlwaysShown;
2358}
2359
2360//------------------------------------------------------------------------------
2361// Sets to always show the decimal separator.
2362
2363void
2364DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
2365{
2366 fDecimalSeparatorAlwaysShown = newValue;
2367}
2368
2369//------------------------------------------------------------------------------
2370// Emits the pattern of this DecimalFormat instance.
2371
2372UnicodeString&
2373DecimalFormat::toPattern(UnicodeString& result) const
2374{
2375 return toPattern(result, FALSE);
2376}
2377
2378//------------------------------------------------------------------------------
2379// Emits the localized pattern this DecimalFormat instance.
2380
2381UnicodeString&
2382DecimalFormat::toLocalizedPattern(UnicodeString& result) const
2383{
2384 return toPattern(result, TRUE);
2385}
2386
2387//------------------------------------------------------------------------------
2388/**
2389 * Expand the affix pattern strings into the expanded affix strings. If any
2390 * affix pattern string is null, do not expand it. This method should be
2391 * called any time the symbols or the affix patterns change in order to keep
2392 * the expanded affix strings up to date.
2393 */
2394void DecimalFormat::expandAffixes() {
2395 if (fPosPrefixPattern != 0) {
2396 expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, FALSE);
2397 }
2398 if (fPosSuffixPattern != 0) {
2399 expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, FALSE);
2400 }
2401 if (fNegPrefixPattern != 0) {
2402 expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, FALSE);
2403 }
2404 if (fNegSuffixPattern != 0) {
2405 expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, FALSE);
2406 }
2407#ifdef FMT_DEBUG
2408 UnicodeString s;
2409 s.append("[")
2410 .append(*fPosPrefixPattern).append("|").append(*fPosSuffixPattern)
2411 .append(";") .append(*fNegPrefixPattern).append("|").append(*fNegSuffixPattern)
2412 .append("]->[")
2413 .append(fPositivePrefix).append("|").append(fPositiveSuffix)
2414 .append(";") .append(fNegativePrefix).append("|").append(fNegativeSuffix)
2415 .append("]\n");
2416 debugout(s);
2417#endif
2418}
2419
2420/**
2421 * Expand an affix pattern into an affix string. All characters in the
2422 * pattern are literal unless prefixed by kQuote. The following characters
2423 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
2424 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
2425 * kCurrencySign + kCurrencySign), it is interpreted as an international
2426 * currency sign. Any other character after a kQuote represents itself.
2427 * kQuote must be followed by another character; kQuote may not occur by
2428 * itself at the end of the pattern.
2429 *
2430 * This method is used in two distinct ways. First, it is used to expand
2431 * the stored affix patterns into actual affixes. For this usage, doFormat
2432 * must be false. Second, it is used to expand the stored affix patterns
2433 * given a specific number (doFormat == true), for those rare cases in
2434 * which a currency format references a ChoiceFormat (e.g., en_IN display
2435 * name for INR). The number itself is taken from digitList.
2436 *
2437 * When used in the first way, this method has a side effect: It sets
2438 * currencyChoice to a ChoiceFormat object, if the currency's display name
2439 * in this locale is a ChoiceFormat pattern (very rare). It only does this
2440 * if currencyChoice is null to start with.
2441 *
2442 * @param pattern the non-null, fPossibly empty pattern
2443 * @param affix string to receive the expanded equivalent of pattern.
2444 * Previous contents are deleted.
2445 * @param doFormat if false, then the pattern will be expanded, and if a
2446 * currency symbol is encountered that expands to a ChoiceFormat, the
2447 * currencyChoice member variable will be initialized if it is null. If
2448 * doFormat is true, then it is assumed that the currencyChoice has been
2449 * created, and it will be used to format the value in digitList.
2450 */
2451void DecimalFormat::expandAffix(const UnicodeString& pattern,
2452 UnicodeString& affix,
2453 double number,
2454 UBool doFormat) const {
2455 affix.remove();
2456 for (int i=0; i<pattern.length(); ) {
2457 UChar32 c = pattern.char32At(i);
2458 i += U16_LENGTH(c);
2459 if (c == kQuote) {
2460 c = pattern.char32At(i);
2461 i += U16_LENGTH(c);
2462 switch (c) {
2463 case kCurrencySign: {
2464 // As of ICU 2.2 we use the currency object, and
2465 // ignore the currency symbols in the DFS, unless
2466 // we have a null currency object. This occurs if
2467 // resurrecting a pre-2.2 object or if the user
2468 // sets a custom DFS.
2469 UBool intl = i<pattern.length() &&
2470 pattern.char32At(i) == kCurrencySign;
2471 if (intl) {
2472 ++i;
2473 }
2474 const UChar* currencyUChars = getCurrency();
2475 if (currencyUChars[0] != 0) {
2476 UErrorCode ec = U_ZERO_ERROR;
2477 if(intl) {
2478 affix += currencyUChars;
2479 } else {
2480 int32_t len;
2481 UBool isChoiceFormat;
2482 const UChar* s = ucurr_getName(currencyUChars, fSymbols->getLocale().getName(),
2483 UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
2484 if (isChoiceFormat) {
2485 // Two modes here: If doFormat is false, we set up
2486 // currencyChoice. If doFormat is true, we use the
2487 // previously created currencyChoice to format the
2488 // value in digitList.
2489 if (!doFormat) {
2490 // If the currency is handled by a ChoiceFormat,
2491 // then we're not going to use the expanded
2492 // patterns. Instantiate the ChoiceFormat and
2493 // return.
2494 if (fCurrencyChoice == NULL) {
2495 // TODO Replace double-check with proper thread-safe code
2496 ChoiceFormat* fmt = new ChoiceFormat(s, ec);
2497 if (U_SUCCESS(ec)) {
2498 umtx_lock(NULL);
2499 if (fCurrencyChoice == NULL) {
2500 // Cast away const
2501 ((DecimalFormat*)this)->fCurrencyChoice = fmt;
2502 fmt = NULL;
2503 }
2504 umtx_unlock(NULL);
2505 delete fmt;
2506 }
2507 }
2508 // We could almost return null or "" here, since the
2509 // expanded affixes are almost not used at all
2510 // in this situation. However, one method --
2511 // toPattern() -- still does use the expanded
2512 // affixes, in order to set up a padding
2513 // pattern. We use the CURRENCY_SIGN as a
2514 // placeholder.
2515 affix.append(kCurrencySign);
2516 } else {
2517 if (fCurrencyChoice != NULL) {
2518 FieldPosition pos(0); // ignored
2519 if (number < 0) {
2520 number = -number;
2521 }
2522 fCurrencyChoice->format(number, affix, pos);
2523 } else {
2524 // We only arrive here if the currency choice
2525 // format in the locale data is INVALID.
2526 affix += currencyUChars;
2527 }
2528 }
2529 continue;
2530 }
2531 affix += UnicodeString(s, len);
2532 }
2533 } else {
2534 if(intl) {
2535 affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
2536 } else {
2537 affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
2538 }
2539 }
2540 break;
2541 }
2542 case kPatternPercent:
2543 affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2544 break;
2545 case kPatternPerMill:
2546 affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2547 break;
2548 case kPatternPlus:
2549 affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2550 break;
2551 case kPatternMinus:
2552 affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2553 break;
2554 default:
2555 affix.append(c);
2556 break;
2557 }
2558 }
2559 else {
2560 affix.append(c);
2561 }
2562 }
2563}
2564
2565/**
2566 * Append an affix to the given StringBuffer.
2567 * @param buf buffer to append to
2568 * @param isNegative
2569 * @param isPrefix
2570 */
2571int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
2572 UBool isNegative, UBool isPrefix) const {
2573 if (fCurrencyChoice != 0) {
2574 const UnicodeString* affixPat = 0;
2575 if (isPrefix) {
2576 affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern;
2577 } else {
2578 affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern;
2579 }
2580 UnicodeString affixBuf;
2581 expandAffix(*affixPat, affixBuf, number, TRUE);
2582 buf.append(affixBuf);
2583 return affixBuf.length();
2584 }
2585
2586 const UnicodeString* affix = NULL;
2587 if (isPrefix) {
2588 affix = isNegative ? &fNegativePrefix : &fPositivePrefix;
2589 } else {
2590 affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
2591 }
2592 buf.append(*affix);
2593 return affix->length();
2594}
2595
2596/**
2597 * Appends an affix pattern to the given StringBuffer, quoting special
2598 * characters as needed. Uses the internal affix pattern, if that exists,
2599 * or the literal affix, if the internal affix pattern is null. The
2600 * appended string will generate the same affix pattern (or literal affix)
2601 * when passed to toPattern().
2602 *
2603 * @param appendTo the affix string is appended to this
2604 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
2605 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
2606 * Ignored unless affixPattern is null. If affixPattern is null, then
2607 * expAffix is appended as a literal affix.
2608 * @param localized true if the appended pattern should contain localized
2609 * pattern characters; otherwise, non-localized pattern chars are appended
2610 */
2611void DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
2612 const UnicodeString* affixPattern,
2613 const UnicodeString& expAffix,
2614 UBool localized) const {
2615 if (affixPattern == 0) {
2616 appendAffixPattern(appendTo, expAffix, localized);
2617 } else {
2618 int i;
2619 for (int pos=0; pos<affixPattern->length(); pos=i) {
2620 i = affixPattern->indexOf(kQuote, pos);
2621 if (i < 0) {
2622 UnicodeString s;
2623 affixPattern->extractBetween(pos, affixPattern->length(), s);
2624 appendAffixPattern(appendTo, s, localized);
2625 break;
2626 }
2627 if (i > pos) {
2628 UnicodeString s;
2629 affixPattern->extractBetween(pos, i, s);
2630 appendAffixPattern(appendTo, s, localized);
2631 }
2632 UChar32 c = affixPattern->char32At(++i);
2633 ++i;
2634 if (c == kQuote) {
2635 appendTo.append(c).append(c);
2636 // Fall through and append another kQuote below
2637 } else if (c == kCurrencySign &&
2638 i<affixPattern->length() &&
2639 affixPattern->char32At(i) == kCurrencySign) {
2640 ++i;
2641 appendTo.append(c).append(c);
2642 } else if (localized) {
2643 switch (c) {
2644 case kPatternPercent:
2645 appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2646 break;
2647 case kPatternPerMill:
2648 appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2649 break;
2650 case kPatternPlus:
2651 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2652 break;
2653 case kPatternMinus:
2654 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2655 break;
2656 default:
2657 appendTo.append(c);
2658 }
2659 } else {
2660 appendTo.append(c);
2661 }
2662 }
2663 }
2664}
2665
2666/**
2667 * Append an affix to the given StringBuffer, using quotes if
2668 * there are special characters. Single quotes themselves must be
2669 * escaped in either case.
2670 */
2671void
2672DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
2673 const UnicodeString& affix,
2674 UBool localized) const {
2675 UBool needQuote;
2676 if(localized) {
2677 needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0
2678 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0
2679 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0
2680 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0
2681 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0
2682 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0
2683 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0
2684 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0
2685 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0
2686 || affix.indexOf(kCurrencySign) >= 0;
2687 }
2688 else {
2689 needQuote = affix.indexOf(kPatternZeroDigit) >= 0
2690 || affix.indexOf(kPatternGroupingSeparator) >= 0
2691 || affix.indexOf(kPatternDecimalSeparator) >= 0
2692 || affix.indexOf(kPatternPercent) >= 0
2693 || affix.indexOf(kPatternPerMill) >= 0
2694 || affix.indexOf(kPatternDigit) >= 0
2695 || affix.indexOf(kPatternSeparator) >= 0
2696 || affix.indexOf(kPatternExponent) >= 0
2697 || affix.indexOf(kPatternPlus) >= 0
2698 || affix.indexOf(kPatternMinus) >= 0
2699 || affix.indexOf(kCurrencySign) >= 0;
2700 }
2701 if (needQuote)
2702 appendTo += (UChar)0x0027 /*'\''*/;
2703 if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0)
2704 appendTo += affix;
2705 else {
2706 for (int32_t j = 0; j < affix.length(); ) {
2707 UChar32 c = affix.char32At(j);
2708 j += U16_LENGTH(c);
2709 appendTo += c;
2710 if (c == 0x0027 /*'\''*/)
2711 appendTo += c;
2712 }
2713 }
2714 if (needQuote)
2715 appendTo += (UChar)0x0027 /*'\''*/;
2716}
2717
2718//------------------------------------------------------------------------------
2719
2720/* Tell the VC++ compiler not to spew out the warnings about integral size conversion */
2721/*
2722#ifdef _WIN32
2723#pragma warning( disable : 4761 )
2724#endif
2725*/
2726
2727UnicodeString&
2728DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
2729{
2730 result.remove();
374ca955 2731 UChar32 zero, sigDigit = kPatternSignificantDigit;
b75a7d8f
A
2732 UnicodeString digit, group;
2733 int32_t i;
2734 int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits
2735 UnicodeString roundingDigits;
2736 int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1;
2737 UnicodeString padSpec;
374ca955 2738 UBool useSigDig = areSignificantDigitsUsed();
b75a7d8f
A
2739
2740 if (localized) {
2741 digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
2742 group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
2743 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
374ca955
A
2744 if (useSigDig) {
2745 sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
2746 }
b75a7d8f
A
2747 }
2748 else {
2749 digit.append((UChar)kPatternDigit);
2750 group.append((UChar)kPatternGroupingSeparator);
2751 zero = (UChar32)kPatternZeroDigit;
2752 }
2753 if (fFormatWidth > 0) {
2754 if (localized) {
2755 padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
2756 }
2757 else {
2758 padSpec.append((UChar)kPatternPadEscape);
2759 }
2760 padSpec.append(fPad);
2761 }
2762 if (fRoundingIncrement != NULL) {
2763 for(i=0; i<fRoundingIncrement->fCount; ++i) {
2764 roundingDigits.append((UChar)fRoundingIncrement->fDigits[i]);
2765 }
2766 roundingDecimalPos = fRoundingIncrement->fDecimalAt;
2767 }
2768 for (int32_t part=0; part<2; ++part) {
2769 if (padPos == kPadBeforePrefix) {
2770 result.append(padSpec);
2771 }
2772 appendAffixPattern(result,
2773 (part==0 ? fPosPrefixPattern : fNegPrefixPattern),
2774 (part==0 ? fPositivePrefix : fNegativePrefix),
2775 localized);
2776 if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) {
2777 result.append(padSpec);
2778 }
2779 int32_t sub0Start = result.length();
374ca955 2780 int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0;
b75a7d8f
A
2781 if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
2782 g += fGroupingSize2;
2783 }
374ca955
A
2784 int32_t maxDig = 0, minDig = 0, maxSigDig = 0;
2785 if (useSigDig) {
2786 minDig = getMinimumSignificantDigits();
2787 maxDig = maxSigDig = getMaximumSignificantDigits();
2788 } else {
2789 minDig = getMinimumIntegerDigits();
2790 maxDig = getMaximumIntegerDigits();
2791 }
2792 if (fUseExponentialNotation) {
2793 if (maxDig > kMaxScientificIntegerDigits) {
2794 maxDig = 1;
2795 }
2796 } else if (useSigDig) {
2797 maxDig = _max(maxDig, g+1);
2798 } else {
2799 maxDig = _max(_max(g, getMinimumIntegerDigits()),
2800 roundingDecimalPos) + 1;
2801 }
2802 for (i = maxDig; i > 0; --i) {
2803 if (!fUseExponentialNotation && i<maxDig &&
b75a7d8f
A
2804 isGroupingPosition(i)) {
2805 result.append(group);
2806 }
374ca955
A
2807 if (useSigDig) {
2808 // #@,@### (maxSigDig == 5, minSigDig == 2)
2809 // 65 4321 (1-based pos, count from the right)
2810 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
2811 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
2812 if (maxSigDig >= i && i > (maxSigDig - minDig)) {
2813 result.append(sigDigit);
2814 } else {
2815 result.append(digit);
2816 }
2817 } else {
2818 if (! roundingDigits.isEmpty()) {
2819 int32_t pos = roundingDecimalPos - i;
2820 if (pos >= 0 && pos < roundingDigits.length()) {
2821 result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
2822 continue;
2823 }
2824 }
2825 if (i<=minDig) {
2826 result.append(zero);
2827 } else {
2828 result.append(digit);
b75a7d8f 2829 }
b75a7d8f
A
2830 }
2831 }
374ca955
A
2832 if (!useSigDig) {
2833 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) {
2834 if (localized) {
2835 result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
2836 }
2837 else {
2838 result.append((UChar)kPatternDecimalSeparator);
2839 }
b75a7d8f 2840 }
374ca955
A
2841 int32_t pos = roundingDecimalPos;
2842 for (i = 0; i < getMaximumFractionDigits(); ++i) {
2843 if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) {
2844 if (pos < 0) {
2845 result.append(zero);
2846 }
2847 else {
2848 result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
2849 }
2850 ++pos;
2851 continue;
2852 }
2853 if (i<getMinimumFractionDigits()) {
b75a7d8f
A
2854 result.append(zero);
2855 }
2856 else {
374ca955 2857 result.append(digit);
b75a7d8f 2858 }
b75a7d8f
A
2859 }
2860 }
2861 if (fUseExponentialNotation) {
2862 if (localized) {
2863 result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
2864 }
2865 else {
2866 result.append((UChar)kPatternExponent);
2867 }
2868 if (fExponentSignAlwaysShown) {
2869 if (localized) {
2870 result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2871 }
2872 else {
2873 result.append((UChar)kPatternPlus);
2874 }
2875 }
2876 for (i=0; i<fMinExponentDigits; ++i) {
2877 result.append(zero);
2878 }
2879 }
2880 if (! padSpec.isEmpty() && !fUseExponentialNotation) {
2881 int32_t add = fFormatWidth - result.length() + sub0Start
2882 - ((part == 0)
2883 ? fPositivePrefix.length() + fPositiveSuffix.length()
2884 : fNegativePrefix.length() + fNegativeSuffix.length());
2885 while (add > 0) {
2886 result.insert(sub0Start, digit);
374ca955 2887 ++maxDig;
b75a7d8f
A
2888 --add;
2889 // Only add a grouping separator if we have at least
2890 // 2 additional characters to be added, so we don't
2891 // end up with ",###".
374ca955 2892 if (add>1 && isGroupingPosition(maxDig)) {
b75a7d8f
A
2893 result.insert(sub0Start, group);
2894 --add;
2895 }
2896 }
2897 }
2898 if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) {
2899 result.append(padSpec);
2900 }
2901 if (part == 0) {
2902 appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized);
2903 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
2904 result.append(padSpec);
2905 }
2906 UBool isDefault = FALSE;
2907 if ((fNegSuffixPattern == fPosSuffixPattern && // both null
2908 fNegativeSuffix == fPositiveSuffix)
2909 || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 &&
2910 *fNegSuffixPattern == *fPosSuffixPattern))
2911 {
2912 if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL)
2913 {
2914 int32_t length = fPosPrefixPattern->length();
2915 isDefault = fNegPrefixPattern->length() == (length+2) &&
2916 (*fNegPrefixPattern)[(int32_t)0] == kQuote &&
2917 (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus &&
2918 fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0;
2919 }
2920 if (!isDefault &&
2921 fNegPrefixPattern == NULL && fPosPrefixPattern == NULL)
2922 {
2923 int32_t length = fPositivePrefix.length();
2924 isDefault = fNegativePrefix.length() == (length+1) &&
2925 fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 &&
2926 fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0;
2927 }
2928 }
2929 if (isDefault) {
2930 break; // Don't output default negative subpattern
2931 } else {
2932 if (localized) {
2933 result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
2934 }
2935 else {
2936 result.append((UChar)kPatternSeparator);
2937 }
2938 }
2939 } else {
2940 appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized);
2941 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
2942 result.append(padSpec);
2943 }
2944 }
2945 }
2946
2947 return result;
2948}
2949
2950//------------------------------------------------------------------------------
2951
2952void
2953DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
2954{
2955 UParseError parseError;
2956 applyPattern(pattern, FALSE, parseError, status);
2957}
2958
2959//------------------------------------------------------------------------------
2960
2961void
2962DecimalFormat::applyPattern(const UnicodeString& pattern,
2963 UParseError& parseError,
2964 UErrorCode& status)
2965{
2966 applyPattern(pattern, FALSE, parseError, status);
2967}
2968//------------------------------------------------------------------------------
2969
2970void
2971DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
2972{
2973 UParseError parseError;
2974 applyPattern(pattern, TRUE,parseError,status);
2975}
2976
2977//------------------------------------------------------------------------------
2978
2979void
2980DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
2981 UParseError& parseError,
2982 UErrorCode& status)
2983{
2984 applyPattern(pattern, TRUE,parseError,status);
2985}
2986
2987//------------------------------------------------------------------------------
2988
2989void
2990DecimalFormat::applyPattern(const UnicodeString& pattern,
2991 UBool localized,
2992 UParseError& parseError,
2993 UErrorCode& status)
2994{
2995 if (U_FAILURE(status))
2996 {
2997 return;
2998 }
2999 // Clear error struct
3000 parseError.offset = -1;
3001 parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
3002
3003 // Set the significant pattern symbols
374ca955
A
3004 UChar32 zeroDigit = kPatternZeroDigit; // '0'
3005 UChar32 sigDigit = kPatternSignificantDigit; // '@'
b75a7d8f
A
3006 UnicodeString groupingSeparator ((UChar)kPatternGroupingSeparator);
3007 UnicodeString decimalSeparator ((UChar)kPatternDecimalSeparator);
3008 UnicodeString percent ((UChar)kPatternPercent);
3009 UnicodeString perMill ((UChar)kPatternPerMill);
374ca955 3010 UnicodeString digit ((UChar)kPatternDigit); // '#'
b75a7d8f
A
3011 UnicodeString separator ((UChar)kPatternSeparator);
3012 UnicodeString exponent ((UChar)kPatternExponent);
3013 UnicodeString plus ((UChar)kPatternPlus);
3014 UnicodeString minus ((UChar)kPatternMinus);
3015 UnicodeString padEscape ((UChar)kPatternPadEscape);
3016 // Substitute with the localized symbols if necessary
3017 if (localized) {
3018 zeroDigit = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
374ca955 3019 sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
b75a7d8f
A
3020 groupingSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
3021 decimalSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
3022 percent. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
3023 perMill. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
3024 digit. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
3025 separator. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
3026 exponent. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol));
3027 plus. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol));
3028 minus. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
3029 padEscape. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
3030 }
3031 UChar nineDigit = (UChar)(zeroDigit + 9);
3032 int32_t digitLen = digit.length();
3033 int32_t groupSepLen = groupingSeparator.length();
3034 int32_t decimalSepLen = decimalSeparator.length();
3035
3036 int32_t pos = 0;
3037 int32_t patLen = pattern.length();
3038 // Part 0 is the positive pattern. Part 1, if present, is the negative
3039 // pattern.
3040 for (int32_t part=0; part<2 && pos<patLen; ++part) {
3041 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
3042 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
3043 // between the prefix and suffix, and consists of pattern
3044 // characters. In the prefix and suffix, percent, perMill, and
3045 // currency symbols are recognized and translated.
3046 int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
3047
3048 // It's important that we don't change any fields of this object
3049 // prematurely. We set the following variables for the multiplier,
3050 // grouping, etc., and then only change the actual object fields if
3051 // everything parses correctly. This also lets us register
3052 // the data from part 0 and ignore the part 1, except for the
3053 // prefix and suffix.
3054 UnicodeString prefix;
3055 UnicodeString suffix;
3056 int32_t decimalPos = -1;
3057 int32_t multiplier = 1;
374ca955 3058 int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
b75a7d8f
A
3059 int8_t groupingCount = -1;
3060 int8_t groupingCount2 = -1;
3061 int32_t padPos = -1;
374ca955 3062 UChar32 padChar = 0;
b75a7d8f
A
3063 int32_t roundingPos = -1;
3064 DigitList roundingInc;
3065 int8_t expDigits = -1;
3066 UBool expSignAlways = FALSE;
3067 UBool isCurrency = FALSE;
3068
3069 // The affix is either the prefix or the suffix.
3070 UnicodeString* affix = &prefix;
3071
3072 int32_t start = pos;
3073 UBool isPartDone = FALSE;
3074 UChar32 ch;
3075
374ca955 3076 for (; !isPartDone && pos < patLen; ) {
b75a7d8f
A
3077 // Todo: account for surrogate pairs
3078 ch = pattern.char32At(pos);
3079 switch (subpart) {
3080 case 0: // Pattern proper subpart (between prefix & suffix)
3081 // Process the digits, decimal, and grouping characters. We
3082 // record five pieces of information. We expect the digits
3083 // to occur in the pattern ####00.00####, and we record the
3084 // number of left digits, zero (central) digits, and right
3085 // digits. The position of the last grouping character is
3086 // recorded (should be somewhere within the first two blocks
3087 // of characters), as is the position of the decimal point,
3088 // if any (should be in the zero digits). If there is no
3089 // decimal point, then there should be no right digits.
3090 if (pattern.compare(pos, digitLen, digit) == 0) {
374ca955 3091 if (zeroDigitCount > 0 || sigDigitCount > 0) {
b75a7d8f
A
3092 ++digitRightCount;
3093 } else {
3094 ++digitLeftCount;
3095 }
3096 if (groupingCount >= 0 && decimalPos < 0) {
3097 ++groupingCount;
3098 }
3099 pos += digitLen;
374ca955
A
3100 } else if ((ch >= zeroDigit && ch <= nineDigit) ||
3101 ch == sigDigit) {
b75a7d8f
A
3102 if (digitRightCount > 0) {
3103 // Unexpected '0'
3104 debug("Unexpected '0'")
3105 status = U_UNEXPECTED_TOKEN;
3106 syntaxError(pattern,pos,parseError);
3107 return;
3108 }
374ca955
A
3109 if (ch == sigDigit) {
3110 ++sigDigitCount;
3111 } else {
3112 ++zeroDigitCount;
3113 if (ch != zeroDigit && roundingPos < 0) {
3114 roundingPos = digitLeftCount + zeroDigitCount;
3115 }
3116 if (roundingPos >= 0) {
3117 roundingInc.append((char)(ch - zeroDigit + '0'));
3118 }
3119 }
b75a7d8f
A
3120 if (groupingCount >= 0 && decimalPos < 0) {
3121 ++groupingCount;
3122 }
374ca955 3123 pos += U16_LENGTH(ch);
b75a7d8f
A
3124 } else if (pattern.compare(pos, groupSepLen, groupingSeparator) == 0) {
3125 if (decimalPos >= 0) {
3126 // Grouping separator after decimal
3127 debug("Grouping separator after decimal")
3128 status = U_UNEXPECTED_TOKEN;
3129 syntaxError(pattern,pos,parseError);
3130 return;
3131 }
3132 groupingCount2 = groupingCount;
3133 groupingCount = 0;
3134 pos += groupSepLen;
3135 } else if (pattern.compare(pos, decimalSepLen, decimalSeparator) == 0) {
3136 if (decimalPos >= 0) {
3137 // Multiple decimal separators
3138 debug("Multiple decimal separators")
3139 status = U_MULTIPLE_DECIMAL_SEPARATORS;
3140 syntaxError(pattern,pos,parseError);
3141 return;
3142 }
3143 // Intentionally incorporate the digitRightCount,
3144 // even though it is illegal for this to be > 0
3145 // at this point. We check pattern syntax below.
3146 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
3147 pos += decimalSepLen;
3148 } else {
3149 if (pattern.compare(pos, exponent.length(), exponent) == 0) {
3150 if (expDigits >= 0) {
3151 // Multiple exponential symbols
3152 debug("Multiple exponential symbols")
3153 status = U_MULTIPLE_EXPONENTIAL_SYMBOLS;
3154 syntaxError(pattern,pos,parseError);
3155 return;
3156 }
3157 if (groupingCount >= 0) {
3158 // Grouping separator in exponential pattern
3159 debug("Grouping separator in exponential pattern")
3160 status = U_MALFORMED_EXPONENTIAL_PATTERN;
3161 syntaxError(pattern,pos,parseError);
3162 return;
3163 }
374ca955 3164 pos += exponent.length();
b75a7d8f 3165 // Check for positive prefix
374ca955
A
3166 if (pos < patLen
3167 && pattern.compare(pos, plus.length(), plus) == 0) {
b75a7d8f
A
3168 expSignAlways = TRUE;
3169 pos += plus.length();
3170 }
3171 // Use lookahead to parse out the exponential part of the
3172 // pattern, then jump into suffix subpart.
3173 expDigits = 0;
374ca955
A
3174 while (pos < patLen &&
3175 pattern.char32At(pos) == zeroDigit) {
b75a7d8f 3176 ++expDigits;
374ca955 3177 pos += U16_LENGTH(zeroDigit);
b75a7d8f
A
3178 }
3179
374ca955
A
3180 // 1. Require at least one mantissa pattern digit
3181 // 2. Disallow "#+ @" in mantissa
3182 // 3. Require at least one exponent pattern digit
3183 if (((digitLeftCount + zeroDigitCount) < 1 &&
3184 (sigDigitCount + digitRightCount) < 1) ||
3185 (sigDigitCount > 0 && digitLeftCount > 0) ||
b75a7d8f
A
3186 expDigits < 1) {
3187 // Malformed exponential pattern
3188 debug("Malformed exponential pattern")
3189 status = U_MALFORMED_EXPONENTIAL_PATTERN;
3190 syntaxError(pattern,pos,parseError);
3191 return;
3192 }
3193 }
3194 // Transition to suffix subpart
3195 subpart = 2; // suffix subpart
3196 affix = &suffix;
3197 sub0Limit = pos;
3198 continue;
3199 }
3200 break;
3201 case 1: // Prefix subpart
3202 case 2: // Suffix subpart
3203 // Process the prefix / suffix characters
3204 // Process unquoted characters seen in prefix or suffix
3205 // subpart.
374ca955
A
3206
3207 // Several syntax characters implicitly begins the
3208 // next subpart if we are in the prefix; otherwise
3209 // they are illegal if unquoted.
3210 if (!pattern.compare(pos, digitLen, digit) ||
3211 !pattern.compare(pos, groupSepLen, groupingSeparator) ||
3212 !pattern.compare(pos, decimalSepLen, decimalSeparator) ||
3213 (ch >= zeroDigit && ch <= nineDigit) ||
3214 ch == sigDigit) {
b75a7d8f
A
3215 if (subpart == 1) { // prefix subpart
3216 subpart = 0; // pattern proper subpart
3217 sub0Start = pos; // Reprocess this character
3218 continue;
374ca955
A
3219 } else {
3220 status = U_UNQUOTED_SPECIAL;
3221 syntaxError(pattern,pos,parseError);
3222 return;
b75a7d8f 3223 }
b75a7d8f 3224 } else if (ch == kCurrencySign) {
374ca955 3225 affix->append(kQuote); // Encode currency
b75a7d8f
A
3226 // Use lookahead to determine if the currency sign is
3227 // doubled or not.
374ca955
A
3228 U_ASSERT(U16_LENGTH(kCurrencySign) == 1);
3229 if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) {
b75a7d8f
A
3230 affix->append(kCurrencySign);
3231 ++pos; // Skip over the doubled character
3232 }
3233 isCurrency = TRUE;
3234 // Fall through to append(ch)
3235 } else if (ch == kQuote) {
3236 // A quote outside quotes indicates either the opening
3237 // quote or two quotes, which is a quote literal. That is,
3238 // we have the first quote in 'do' or o''clock.
374ca955 3239 U_ASSERT(U16_LENGTH(kQuote) == 1);
b75a7d8f
A
3240 ++pos;
3241 if (pos < pattern.length() && pattern[pos] == kQuote) {
3242 affix->append(kQuote); // Encode quote
b75a7d8f
A
3243 // Fall through to append(ch)
3244 } else {
3245 subpart += 2; // open quote
3246 continue;
3247 }
3248 } else if (pattern.compare(pos, separator.length(), separator) == 0) {
3249 // Don't allow separators in the prefix, and don't allow
3250 // separators in the second pattern (part == 1).
3251 if (subpart == 1 || part == 1) {
3252 // Unexpected separator
3253 debug("Unexpected separator")
3254 status = U_UNEXPECTED_TOKEN;
3255 syntaxError(pattern,pos,parseError);
3256 return;
3257 }
3258 sub2Limit = pos;
3259 isPartDone = TRUE; // Go to next part
3260 pos += separator.length();
3261 break;
3262 } else if (pattern.compare(pos, percent.length(), percent) == 0) {
3263 // Next handle characters which are appended directly.
3264 if (multiplier != 1) {
3265 // Too many percent/perMill characters
3266 debug("Too many percent characters")
3267 status = U_MULTIPLE_PERCENT_SYMBOLS;
3268 syntaxError(pattern,pos,parseError);
3269 return;
3270 }
3271 affix->append(kQuote); // Encode percent/perMill
374ca955 3272 affix->append(kPatternPercent); // Use unlocalized pattern char
b75a7d8f 3273 multiplier = 100;
b75a7d8f 3274 pos += percent.length();
374ca955 3275 break;
b75a7d8f
A
3276 } else if (pattern.compare(pos, perMill.length(), perMill) == 0) {
3277 // Next handle characters which are appended directly.
3278 if (multiplier != 1) {
3279 // Too many percent/perMill characters
3280 debug("Too many perMill characters")
3281 status = U_MULTIPLE_PERMILL_SYMBOLS;
3282 syntaxError(pattern,pos,parseError);
3283 return;
3284 }
3285 affix->append(kQuote); // Encode percent/perMill
374ca955 3286 affix->append(kPatternPerMill); // Use unlocalized pattern char
b75a7d8f 3287 multiplier = 1000;
b75a7d8f 3288 pos += perMill.length();
374ca955 3289 break;
b75a7d8f
A
3290 } else if (pattern.compare(pos, padEscape.length(), padEscape) == 0) {
3291 if (padPos >= 0 || // Multiple pad specifiers
3292 (pos+1) == pattern.length()) { // Nothing after padEscape
3293 debug("Multiple pad specifiers")
3294 status = U_MULTIPLE_PAD_SPECIFIERS;
3295 syntaxError(pattern,pos,parseError);
3296 return;
3297 }
3298 padPos = pos;
3299 pos += padEscape.length();
3300 padChar = pattern.char32At(pos);
3301 pos += U16_LENGTH(padChar);
374ca955 3302 break;
b75a7d8f
A
3303 } else if (pattern.compare(pos, minus.length(), minus) == 0) {
3304 affix->append(kQuote); // Encode minus
374ca955 3305 affix->append(kPatternMinus);
b75a7d8f 3306 pos += minus.length();
374ca955 3307 break;
b75a7d8f
A
3308 } else if (pattern.compare(pos, plus.length(), plus) == 0) {
3309 affix->append(kQuote); // Encode plus
374ca955 3310 affix->append(kPatternPlus);
b75a7d8f 3311 pos += plus.length();
374ca955 3312 break;
b75a7d8f
A
3313 }
3314 // Unquoted, non-special characters fall through to here, as
3315 // well as other code which needs to append something to the
3316 // affix.
3317 affix->append(ch);
374ca955 3318 pos += U16_LENGTH(ch);
b75a7d8f
A
3319 break;
3320 case 3: // Prefix subpart, in quote
3321 case 4: // Suffix subpart, in quote
3322 // A quote within quotes indicates either the closing
3323 // quote or two quotes, which is a quote literal. That is,
3324 // we have the second quote in 'do' or 'don''t'.
b75a7d8f 3325 if (ch == kQuote) {
374ca955 3326 ++pos;
b75a7d8f 3327 if (pos < pattern.length() && pattern[pos] == kQuote) {
b75a7d8f
A
3328 affix->append(kQuote); // Encode quote
3329 // Fall through to append(ch)
3330 } else {
3331 subpart -= 2; // close quote
3332 continue;
3333 }
3334 }
3335 affix->append(ch);
374ca955 3336 pos += U16_LENGTH(ch);
b75a7d8f
A
3337 break;
3338 }
3339 }
3340
3341 if (sub0Limit == 0) {
3342 sub0Limit = pattern.length();
3343 }
3344
3345 if (sub2Limit == 0) {
3346 sub2Limit = pattern.length();
3347 }
3348
3349 /* Handle patterns with no '0' pattern character. These patterns
3350 * are legal, but must be recodified to make sense. "##.###" ->
3351 * "#0.###". ".###" -> ".0##".
3352 *
3353 * We allow patterns of the form "####" to produce a zeroDigitCount
3354 * of zero (got that?); although this seems like it might make it
3355 * possible for format() to produce empty strings, format() checks
3356 * for this condition and outputs a zero digit in this situation.
3357 * Having a zeroDigitCount of zero yields a minimum integer digits
3358 * of zero, which allows proper round-trip patterns. We don't want
3359 * "#" to become "#0" when toPattern() is called (even though that's
3360 * what it really is, semantically).
3361 */
374ca955
A
3362 if (zeroDigitCount == 0 && sigDigitCount == 0 &&
3363 digitLeftCount > 0 && decimalPos >= 0) {
b75a7d8f
A
3364 // Handle "###.###" and "###." and ".###"
3365 int n = decimalPos;
3366 if (n == 0)
3367 ++n; // Handle ".###"
3368 digitRightCount = digitLeftCount - n;
3369 digitLeftCount = n - 1;
3370 zeroDigitCount = 1;
3371 }
3372
3373 // Do syntax checking on the digits, decimal points, and quotes.
374ca955 3374 if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
b75a7d8f 3375 (decimalPos >= 0 &&
374ca955
A
3376 (sigDigitCount > 0 ||
3377 decimalPos < digitLeftCount ||
b75a7d8f
A
3378 decimalPos > (digitLeftCount + zeroDigitCount))) ||
3379 groupingCount == 0 || groupingCount2 == 0 ||
374ca955 3380 (sigDigitCount > 0 && zeroDigitCount > 0) ||
b75a7d8f
A
3381 subpart > 2)
3382 { // subpart > 2 == unmatched quote
3383 debug("Syntax error")
3384 status = U_PATTERN_SYNTAX_ERROR;
3385 syntaxError(pattern,pos,parseError);
3386 return;
3387 }
3388
3389 // Make sure pad is at legal position before or after affix.
3390 if (padPos >= 0) {
3391 if (padPos == start) {
3392 padPos = kPadBeforePrefix;
3393 } else if (padPos+2 == sub0Start) {
3394 padPos = kPadAfterPrefix;
3395 } else if (padPos == sub0Limit) {
3396 padPos = kPadBeforeSuffix;
3397 } else if (padPos+2 == sub2Limit) {
3398 padPos = kPadAfterSuffix;
3399 } else {
3400 // Illegal pad position
3401 debug("Illegal pad position")
3402 status = U_ILLEGAL_PAD_POSITION;
3403 syntaxError(pattern,pos,parseError);
3404 return;
3405 }
3406 }
3407
3408 if (part == 0) {
3409 delete fPosPrefixPattern;
3410 delete fPosSuffixPattern;
3411 delete fNegPrefixPattern;
3412 delete fNegSuffixPattern;
3413 fPosPrefixPattern = new UnicodeString(prefix);
3414 /* test for NULL */
3415 if (fPosPrefixPattern == 0) {
3416 status = U_MEMORY_ALLOCATION_ERROR;
3417 return;
3418 }
3419 fPosSuffixPattern = new UnicodeString(suffix);
3420 /* test for NULL */
3421 if (fPosSuffixPattern == 0) {
3422 status = U_MEMORY_ALLOCATION_ERROR;
3423 delete fPosPrefixPattern;
3424 return;
3425 }
3426 fNegPrefixPattern = 0;
3427 fNegSuffixPattern = 0;
3428
3429 fUseExponentialNotation = (expDigits >= 0);
3430 if (fUseExponentialNotation) {
3431 fMinExponentDigits = expDigits;
3432 }
3433 fExponentSignAlwaysShown = expSignAlways;
3434 fIsCurrencyFormat = isCurrency;
374ca955 3435 int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
b75a7d8f
A
3436 // The effectiveDecimalPos is the position the decimal is at or
3437 // would be at if there is no decimal. Note that if
3438 // decimalPos<0, then digitTotalCount == digitLeftCount +
3439 // zeroDigitCount.
374ca955
A
3440 int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
3441 UBool isSigDig = (sigDigitCount > 0);
3442 setSignificantDigitsUsed(isSigDig);
3443 if (isSigDig) {
3444 setMinimumSignificantDigits(sigDigitCount);
3445 setMaximumSignificantDigits(sigDigitCount + digitRightCount);
3446 } else {
3447 int32_t minInt = effectiveDecimalPos - digitLeftCount;
3448 setMinimumIntegerDigits(minInt);
3449 setMaximumIntegerDigits(fUseExponentialNotation
b75a7d8f
A
3450 ? digitLeftCount + getMinimumIntegerDigits()
3451 : kDoubleIntegerDigits);
374ca955 3452 setMaximumFractionDigits(decimalPos >= 0
b75a7d8f 3453 ? (digitTotalCount - decimalPos) : 0);
374ca955 3454 setMinimumFractionDigits(decimalPos >= 0
b75a7d8f 3455 ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
374ca955 3456 }
b75a7d8f
A
3457 setGroupingUsed(groupingCount > 0);
3458 fGroupingSize = (groupingCount > 0) ? groupingCount : 0;
3459 fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
3460 ? groupingCount2 : 0;
3461 fMultiplier = multiplier;
3462 setDecimalSeparatorAlwaysShown(decimalPos == 0
3463 || decimalPos == digitTotalCount);
3464 if (padPos >= 0) {
3465 fPadPosition = (EPadPosition) padPos;
3466 // To compute the format width, first set up sub0Limit -
3467 // sub0Start. Add in prefix/suffix length later.
3468
3469 // fFormatWidth = prefix.length() + suffix.length() +
3470 // sub0Limit - sub0Start;
3471 fFormatWidth = sub0Limit - sub0Start;
3472 fPad = padChar;
3473 } else {
3474 fFormatWidth = 0;
3475 }
3476 if (roundingPos >= 0) {
3477 roundingInc.fDecimalAt = effectiveDecimalPos - roundingPos;
3478 if (fRoundingIncrement != NULL) {
3479 *fRoundingIncrement = roundingInc;
3480 } else {
3481 fRoundingIncrement = new DigitList(roundingInc);
3482 /* test for NULL */
3483 if (fRoundingIncrement == 0) {
3484 status = U_MEMORY_ALLOCATION_ERROR;
3485 delete fPosPrefixPattern;
3486 delete fPosSuffixPattern;
3487 return;
3488 }
3489 }
3490 fRoundingDouble = fRoundingIncrement->getDouble();
3491 fRoundingMode = kRoundHalfEven;
3492 } else {
3493 setRoundingIncrement(0.0);
3494 }
3495 } else {
3496 fNegPrefixPattern = new UnicodeString(prefix);
3497 /* test for NULL */
3498 if (fNegPrefixPattern == 0) {
3499 status = U_MEMORY_ALLOCATION_ERROR;
3500 return;
3501 }
3502 fNegSuffixPattern = new UnicodeString(suffix);
3503 /* test for NULL */
3504 if (fNegSuffixPattern == 0) {
3505 delete fNegPrefixPattern;
3506 status = U_MEMORY_ALLOCATION_ERROR;
3507 return;
3508 }
3509 }
3510 }
3511
3512 if (pattern.length() == 0) {
3513 delete fNegPrefixPattern;
3514 delete fNegSuffixPattern;
3515 fNegPrefixPattern = NULL;
3516 fNegSuffixPattern = NULL;
3517 if (fPosPrefixPattern != NULL) {
3518 fPosPrefixPattern->remove();
3519 } else {
3520 fPosPrefixPattern = new UnicodeString();
3521 /* test for NULL */
3522 if (fPosPrefixPattern == 0) {
3523 status = U_MEMORY_ALLOCATION_ERROR;
3524 return;
3525 }
3526 }
3527 if (fPosSuffixPattern != NULL) {
3528 fPosSuffixPattern->remove();
3529 } else {
3530 fPosSuffixPattern = new UnicodeString();
3531 /* test for NULL */
3532 if (fPosSuffixPattern == 0) {
3533 delete fPosPrefixPattern;
3534 status = U_MEMORY_ALLOCATION_ERROR;
3535 return;
3536 }
3537 }
3538
3539 setMinimumIntegerDigits(0);
3540 setMaximumIntegerDigits(kDoubleIntegerDigits);
3541 setMinimumFractionDigits(0);
3542 setMaximumFractionDigits(kDoubleFractionDigits);
3543
3544 fUseExponentialNotation = FALSE;
3545 fIsCurrencyFormat = FALSE;
3546 setGroupingUsed(FALSE);
3547 fGroupingSize = 0;
3548 fGroupingSize2 = 0;
3549 fMultiplier = 1;
3550 setDecimalSeparatorAlwaysShown(FALSE);
3551 fFormatWidth = 0;
3552 setRoundingIncrement(0.0);
3553 }
3554
3555 // If there was no negative pattern, or if the negative pattern is
3556 // identical to the positive pattern, then prepend the minus sign to the
3557 // positive pattern to form the negative pattern.
3558 if (fNegPrefixPattern == NULL ||
3559 (*fNegPrefixPattern == *fPosPrefixPattern
3560 && *fNegSuffixPattern == *fPosSuffixPattern)) {
3561 _copy_us_ptr(&fNegSuffixPattern, fPosSuffixPattern);
3562 if (fNegPrefixPattern == NULL) {
3563 fNegPrefixPattern = new UnicodeString();
3564 /* test for NULL */
3565 if (fNegPrefixPattern == 0) {
3566 status = U_MEMORY_ALLOCATION_ERROR;
3567 return;
3568 }
3569 } else {
3570 fNegPrefixPattern->remove();
3571 }
3572 fNegPrefixPattern->append(kQuote).append(kPatternMinus)
3573 .append(*fPosPrefixPattern);
3574 }
3575#ifdef FMT_DEBUG
3576 UnicodeString s;
3577 s.append("\"").append(pattern).append("\"->");
3578 debugout(s);
3579#endif
3580 expandAffixes();
3581 if (fFormatWidth > 0) {
3582 // Finish computing format width (see above)
3583 fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length();
3584 }
3585}
3586
3587/**
3588 * Sets the maximum number of digits allowed in the integer portion of a
3589 * number. This override limits the integer digit count to 309.
3590 * @see NumberFormat#setMaximumIntegerDigits
3591 */
3592void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
374ca955 3593 NumberFormat::setMaximumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
b75a7d8f
A
3594}
3595
3596/**
3597 * Sets the minimum number of digits allowed in the integer portion of a
3598 * number. This override limits the integer digit count to 309.
3599 * @see NumberFormat#setMinimumIntegerDigits
3600 */
3601void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
374ca955 3602 NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
b75a7d8f
A
3603}
3604
3605/**
3606 * Sets the maximum number of digits allowed in the fraction portion of a
3607 * number. This override limits the fraction digit count to 340.
3608 * @see NumberFormat#setMaximumFractionDigits
3609 */
3610void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
374ca955 3611 NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits));
b75a7d8f
A
3612}
3613
3614/**
3615 * Sets the minimum number of digits allowed in the fraction portion of a
3616 * number. This override limits the fraction digit count to 340.
3617 * @see NumberFormat#setMinimumFractionDigits
3618 */
3619void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
374ca955 3620 NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits));
b75a7d8f
A
3621}
3622
374ca955
A
3623int32_t DecimalFormat::getMinimumSignificantDigits() const {
3624 return fMinSignificantDigits;
3625}
3626
3627int32_t DecimalFormat::getMaximumSignificantDigits() const {
3628 return fMaxSignificantDigits;
3629}
3630
3631void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
3632 if (min < 1) {
3633 min = 1;
3634 }
3635 // pin max sig dig to >= min
3636 int32_t max = _max(fMaxSignificantDigits, min);
3637 fMinSignificantDigits = min;
3638 fMaxSignificantDigits = max;
3639}
3640
3641void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
3642 if (max < 1) {
3643 max = 1;
3644 }
3645 // pin min sig dig to 1..max
3646 U_ASSERT(fMinSignificantDigits >= 1);
3647 int32_t min = _min(fMinSignificantDigits, max);
3648 fMinSignificantDigits = min;
3649 fMaxSignificantDigits = max;
3650}
3651
3652UBool DecimalFormat::areSignificantDigitsUsed() const {
3653 return fUseSignificantDigits;
3654}
3655
3656void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
3657 fUseSignificantDigits = useSignificantDigits;
3658}
3659
3660void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
b75a7d8f
A
3661 // If we are a currency format, then modify our affixes to
3662 // encode the currency symbol for the given currency in our
3663 // locale, and adjust the decimal digits and rounding for the
3664 // given currency.
3665
374ca955
A
3666 // Note: The code is ordered so that this object is *not changed*
3667 // until we are sure we are going to succeed.
3668
3669 // NULL or empty currency is *legal* and indicates no currency.
3670 UBool isCurr = (theCurrency && *theCurrency);
3671
3672 double rounding = 0.0;
3673 int32_t frac = 0;
3674 if (fIsCurrencyFormat && isCurr) {
3675 rounding = ucurr_getRoundingIncrement(theCurrency, &ec);
3676 frac = ucurr_getDefaultFractionDigits(theCurrency, &ec);
3677 }
3678
3679 NumberFormat::setCurrency(theCurrency, ec);
3680 if (U_FAILURE(ec)) return;
b75a7d8f
A
3681
3682 if (fIsCurrencyFormat) {
374ca955
A
3683 // NULL or empty currency is *legal* and indicates no currency.
3684 if (isCurr) {
3685 setRoundingIncrement(rounding);
3686 setMinimumFractionDigits(frac);
3687 setMaximumFractionDigits(frac);
b75a7d8f 3688 }
b75a7d8f
A
3689 expandAffixes();
3690 }
3691}
3692
374ca955
A
3693// Deprecated variant with no UErrorCode parameter
3694void DecimalFormat::setCurrency(const UChar* theCurrency) {
3695 UErrorCode ec = U_ZERO_ERROR;
3696 setCurrency(theCurrency, ec);
3697}
3698
3699void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& /*ec*/) const {
3700 const UChar* c = getCurrency();
3701 if (*c == 0) {
3702 const UnicodeString &intl =
3703 fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
3704 c = intl.getBuffer(); // ok for intl to go out of scope
3705 }
3706 u_strncpy(result, c, 3);
3707 result[3] = 0;
3708}
3709
3710/**
3711 * Return the number of fraction digits to display, or the total
3712 * number of digits for significant digit formats and exponential
3713 * formats.
3714 */
3715int32_t
3716DecimalFormat::precision(UBool isIntegral) const {
3717 if (areSignificantDigitsUsed()) {
3718 return getMaximumSignificantDigits();
3719 } else if (fUseExponentialNotation) {
3720 return getMinimumIntegerDigits() + getMaximumFractionDigits();
3721 } else {
3722 return isIntegral ? 0 : getMaximumFractionDigits();
3723 }
3724}
3725
b75a7d8f
A
3726U_NAMESPACE_END
3727
3728#endif /* #if !UCONFIG_NO_FORMATTING */
3729
3730//eof