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