1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2015, International Business Machines Corporation and *
6 * others. All Rights Reserved. *
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 02/19/97 aliu Converted from java.
15 * 03/20/97 clhuang Implemented with new APIs.
16 * 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it.
17 * 04/3/97 aliu Rewrote parsing and formatting completely, and
18 * cleaned up and debugged. Actually works now.
19 * Implemented NAN and INF handling, for both parsing
20 * and formatting. Extensive testing & debugging.
21 * 04/10/97 aliu Modified to compile on AIX.
22 * 04/16/97 aliu Rewrote to use DigitList, which has been resurrected.
23 * Changed DigitCount to int per code review.
24 * 07/09/97 helena Made ParsePosition into a class.
25 * 08/26/97 aliu Extensive changes to applyPattern; completely
26 * rewritten from the Java.
27 * 09/09/97 aliu Ported over support for exponential formats.
28 * 07/20/98 stephen JDK 1.2 sync up.
29 * Various instances of '0' replaced with 'NULL'
30 * Check for grouping size in subFormat()
31 * Brought subParse() in line with Java 1.2
32 * Added method appendAffix()
33 * 08/24/1998 srl Removed Mutex calls. This is not a thread safe class!
34 * 02/22/99 stephen Removed character literals for EBCDIC safety
35 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
36 * 06/28/99 stephen Fixed bugs in toPattern().
37 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
39 ********************************************************************************
42 #include "unicode/utypes.h"
44 #if !UCONFIG_NO_FORMATTING
46 #include "unicode/uniset.h"
47 #include "unicode/currpinf.h"
48 #include "unicode/plurrule.h"
49 #include "unicode/utf16.h"
50 #include "unicode/numsys.h"
51 #include "unicode/localpointer.h"
55 #include "patternprops.h"
60 #include "plurrule_impl.h"
61 #include "decimalformatpattern.h"
62 #include "fmtableimp.h"
63 #include "decimfmtimpl.h"
64 #include "visibledigits.h"
67 * On certain platforms, round is a macro defined in math.h
68 * This undefine is to avoid conflict between the macro and
69 * the function defined below.
80 static void _debugout(const char *f, int l, const UnicodeString& s) {
82 s.extract((int32_t) 0, s.length(), buf, "utf-8");
83 printf("%s:%d: %s\n", f,l, buf);
85 #define debugout(x) _debugout(__FILE__,__LINE__,x)
86 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
87 static const UnicodeString dbg_null("<NULL>","");
88 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
95 /* For currency parsing purose,
96 * Need to remember all prefix patterns and suffix patterns of
97 * every currency format pattern,
98 * including the pattern of default currecny style
99 * and plural currency style. And the patterns are set through applyPattern.
101 struct AffixPatternsForCurrency : public UMemory {
102 // negative prefix pattern
103 UnicodeString negPrefixPatternForCurrency;
104 // negative suffix pattern
105 UnicodeString negSuffixPatternForCurrency;
106 // positive prefix pattern
107 UnicodeString posPrefixPatternForCurrency;
108 // positive suffix pattern
109 UnicodeString posSuffixPatternForCurrency;
112 AffixPatternsForCurrency(const UnicodeString& negPrefix,
113 const UnicodeString& negSuffix,
114 const UnicodeString& posPrefix,
115 const UnicodeString& posSuffix,
117 negPrefixPatternForCurrency = negPrefix;
118 negSuffixPatternForCurrency = negSuffix;
119 posPrefixPatternForCurrency = posPrefix;
120 posSuffixPatternForCurrency = posSuffix;
125 debugout( UnicodeString("AffixPatternsForCurrency( -=\"") +
126 negPrefixPatternForCurrency + (UnicodeString)"\"/\"" +
127 negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" +
128 posPrefixPatternForCurrency + (UnicodeString)"\"/\"" +
129 posSuffixPatternForCurrency + (UnicodeString)"\" )");
134 /* affix for currency formatting when the currency sign in the pattern
135 * equals to 3, such as the pattern contains 3 currency sign or
136 * the formatter style is currency plural format style.
138 struct AffixesForCurrency : public UMemory {
140 UnicodeString negPrefixForCurrency;
142 UnicodeString negSuffixForCurrency;
144 UnicodeString posPrefixForCurrency;
146 UnicodeString posSuffixForCurrency;
150 AffixesForCurrency(const UnicodeString& negPrefix,
151 const UnicodeString& negSuffix,
152 const UnicodeString& posPrefix,
153 const UnicodeString& posSuffix) {
154 negPrefixForCurrency = negPrefix;
155 negSuffixForCurrency = negSuffix;
156 posPrefixForCurrency = posPrefix;
157 posSuffixForCurrency = posSuffix;
161 debugout( UnicodeString("AffixesForCurrency( -=\"") +
162 negPrefixForCurrency + (UnicodeString)"\"/\"" +
163 negSuffixForCurrency + (UnicodeString)"\" +=\"" +
164 posPrefixForCurrency + (UnicodeString)"\"/\"" +
165 posSuffixForCurrency + (UnicodeString)"\" )");
175 static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2);
179 U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
180 const AffixPatternsForCurrency* affix_1 =
181 (AffixPatternsForCurrency*)val1.pointer;
182 const AffixPatternsForCurrency* affix_2 =
183 (AffixPatternsForCurrency*)val2.pointer;
184 return affix_1->negPrefixPatternForCurrency ==
185 affix_2->negPrefixPatternForCurrency &&
186 affix_1->negSuffixPatternForCurrency ==
187 affix_2->negSuffixPatternForCurrency &&
188 affix_1->posPrefixPatternForCurrency ==
189 affix_2->posPrefixPatternForCurrency &&
190 affix_1->posSuffixPatternForCurrency ==
191 affix_2->posSuffixPatternForCurrency &&
192 affix_1->patternType == affix_2->patternType;
200 // *****************************************************************************
201 // class DecimalFormat
202 // *****************************************************************************
204 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
206 // Constants for characters used in programmatic (unlocalized) patterns.
207 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
208 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
209 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
210 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
211 #define kPatternPerMill ((UChar)0x2030)
212 #define kPatternPercent ((UChar)0x0025) /*'%'*/
213 #define kPatternDigit ((UChar)0x0023) /*'#'*/
214 #define kPatternSeparator ((UChar)0x003B) /*';'*/
215 #define kPatternExponent ((UChar)0x0045) /*'E'*/
216 #define kPatternPlus ((UChar)0x002B) /*'+'*/
217 #define kPatternMinus ((UChar)0x002D) /*'-'*/
218 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
219 #define kQuote ((UChar)0x0027) /*'\''*/
221 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
222 * is used in patterns and substitued with either the currency symbol,
223 * or if it is doubled, with the international currency symbol. If the
224 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
225 * replaced with the monetary decimal separator.
227 #define kCurrencySign ((UChar)0x00A4)
228 #define kDefaultPad ((UChar)0x0020) /* */
230 const int32_t DecimalFormat::kDoubleIntegerDigits = 309;
231 const int32_t DecimalFormat::kDoubleFractionDigits = 340;
233 const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
236 * These are the tags we expect to see in normal resource bundle files associated
239 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used
240 static const char fgNumberElements[]="NumberElements";
241 static const char fgLatn[]="latn";
242 static const char fgPatterns[]="patterns";
243 static const char fgDecimalFormat[]="decimalFormat";
244 static const char fgCurrencyFormat[]="currencyFormat";
246 inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
247 inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
249 //------------------------------------------------------------------------------
250 // Constructs a DecimalFormat instance in the default locale.
252 DecimalFormat::DecimalFormat(UErrorCode& status) {
254 UParseError parseError;
255 construct(status, parseError);
258 //------------------------------------------------------------------------------
259 // Constructs a DecimalFormat instance with the specified number format
260 // pattern in the default locale.
262 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
263 UErrorCode& status) {
265 UParseError parseError;
266 construct(status, parseError, &pattern);
269 //------------------------------------------------------------------------------
270 // Constructs a DecimalFormat instance with the specified number format
271 // pattern and the number format symbols in the default locale. The
272 // created instance owns the symbols.
274 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
275 DecimalFormatSymbols* symbolsToAdopt,
276 UErrorCode& status) {
278 UParseError parseError;
279 if (symbolsToAdopt == NULL)
280 status = U_ILLEGAL_ARGUMENT_ERROR;
281 construct(status, parseError, &pattern, symbolsToAdopt);
284 DecimalFormat::DecimalFormat( const UnicodeString& pattern,
285 DecimalFormatSymbols* symbolsToAdopt,
286 UParseError& parseErr,
287 UErrorCode& status) {
289 if (symbolsToAdopt == NULL)
290 status = U_ILLEGAL_ARGUMENT_ERROR;
291 construct(status,parseErr, &pattern, symbolsToAdopt);
294 //------------------------------------------------------------------------------
295 // Constructs a DecimalFormat instance with the specified number format
296 // pattern and the number format symbols in the default locale. The
297 // created instance owns the clone of the symbols.
299 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
300 const DecimalFormatSymbols& symbols,
301 UErrorCode& status) {
303 UParseError parseError;
304 construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
307 //------------------------------------------------------------------------------
308 // Constructs a DecimalFormat instance with the specified number format
309 // pattern, the number format symbols, and the number format style.
310 // The created instance owns the clone of the symbols.
312 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
313 DecimalFormatSymbols* symbolsToAdopt,
314 UNumberFormatStyle style,
315 UErrorCode& status) {
318 UParseError parseError;
319 construct(status, parseError, &pattern, symbolsToAdopt);
322 //-----------------------------------------------------------------------------
323 // Common DecimalFormat initialization.
324 // Put all fields of an uninitialized object into a known state.
325 // Common code, shared by all constructors.
326 // Can not fail. Leave the object in good enough shape that the destructor
327 // or assignment operator can run successfully.
329 DecimalFormat::init() {
331 fStyle = UNUM_DECIMAL;
332 fAffixPatternsForCurrency = NULL;
333 fCurrencyPluralInfo = NULL;
334 #if UCONFIG_HAVE_PARSEALLINPUT
335 fParseAllInput = UNUM_MAYBE;
342 //------------------------------------------------------------------------------
343 // Constructs a DecimalFormat instance with the specified number format
344 // pattern and the number format symbols in the desired locale. The
345 // created instance owns the symbols.
348 DecimalFormat::construct(UErrorCode& status,
349 UParseError& parseErr,
350 const UnicodeString* pattern,
351 DecimalFormatSymbols* symbolsToAdopt)
353 LocalPointer<DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
354 if (U_FAILURE(status))
357 if (adoptedSymbols.isNull())
359 adoptedSymbols.adoptInstead(
360 new DecimalFormatSymbols(Locale::getDefault(), status));
361 if (adoptedSymbols.isNull() && U_SUCCESS(status)) {
362 status = U_MEMORY_ALLOCATION_ERROR;
364 if (U_FAILURE(status)) {
368 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
369 if (U_FAILURE(status)) {
374 // Uses the default locale's number format pattern if there isn't
378 UErrorCode nsStatus = U_ZERO_ERROR;
379 LocalPointer<NumberingSystem> ns(
380 NumberingSystem::createInstance(nsStatus));
381 if (U_FAILURE(nsStatus)) {
387 UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status);
389 UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status);
390 resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status);
391 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
392 const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
393 if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) {
394 status = U_ZERO_ERROR;
395 resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status);
396 resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status);
397 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
398 resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
400 str.setTo(TRUE, resStr, len);
402 ures_close(resource);
406 fImpl = new DecimalFormatImpl(this, *pattern, adoptedSymbols.getAlias(), parseErr, status);
408 adoptedSymbols.orphan();
409 } else if (U_SUCCESS(status)) {
410 status = U_MEMORY_ALLOCATION_ERROR;
412 if (U_FAILURE(status)) {
416 if (U_FAILURE(status))
421 const UnicodeString* patternUsed;
422 UnicodeString currencyPluralPatternForOther;
424 if (fStyle == UNUM_CURRENCY_PLURAL) {
425 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
426 if (U_FAILURE(status)) {
430 // the pattern used in format is not fixed until formatting,
431 // in which, the number is known and
432 // will be used to pick the right pattern based on plural count.
433 // Here, set the pattern as the pattern of plural count == "other".
434 // For most locale, the patterns are probably the same for all
435 // plural count. If not, the right pattern need to be re-applied
437 fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther);
438 // TODO(refactor): Revisit, we are setting the pattern twice.
439 fImpl->applyPatternFavorCurrencyPrecision(
440 currencyPluralPatternForOther, status);
441 patternUsed = ¤cyPluralPatternForOther;
444 patternUsed = pattern;
447 if (patternUsed->indexOf(kCurrencySign) != -1) {
448 // initialize for currency, not only for plural format,
449 // but also for mix parsing
450 handleCurrencySignInPattern(status);
455 DecimalFormat::handleCurrencySignInPattern(UErrorCode& status) {
456 // initialize for currency, not only for plural format,
457 // but also for mix parsing
458 if (U_FAILURE(status)) {
461 if (fCurrencyPluralInfo == NULL) {
462 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
463 if (U_FAILURE(status)) {
467 // need it for mix parsing
468 if (fAffixPatternsForCurrency == NULL) {
469 setupCurrencyAffixPatterns(status);
474 applyPatternWithNoSideEffects(
475 const UnicodeString& pattern,
476 UParseError& parseError,
477 UnicodeString &negPrefix,
478 UnicodeString &negSuffix,
479 UnicodeString &posPrefix,
480 UnicodeString &posSuffix,
481 UErrorCode& status) {
482 if (U_FAILURE(status))
486 DecimalFormatPatternParser patternParser;
487 DecimalFormatPattern out;
488 patternParser.applyPatternWithoutExpandAffix(
493 if (U_FAILURE(status)) {
496 negPrefix = out.fNegPrefixPattern;
497 negSuffix = out.fNegSuffixPattern;
498 posPrefix = out.fPosPrefixPattern;
499 posSuffix = out.fPosSuffixPattern;
503 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
504 if (U_FAILURE(status)) {
507 UParseError parseErr;
508 fAffixPatternsForCurrency = initHashForAffixPattern(status);
509 if (U_FAILURE(status)) {
513 NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLocale(),status);
514 if (U_FAILURE(status)) {
518 // Save the default currency patterns of this locale.
519 // Here, chose onlyApplyPatternWithoutExpandAffix without
520 // expanding the affix patterns into affixes.
521 UnicodeString currencyPattern;
522 UErrorCode error = U_ZERO_ERROR;
524 UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().getName(), &error);
525 UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error);
526 resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error);
527 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
529 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error);
530 if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) {
531 error = U_ZERO_ERROR;
532 resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error);
533 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
534 patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error);
536 ures_close(numElements);
537 ures_close(resource);
540 if (U_SUCCESS(error)) {
541 UnicodeString negPrefix;
542 UnicodeString negSuffix;
543 UnicodeString posPrefix;
544 UnicodeString posSuffix;
545 applyPatternWithNoSideEffects(UnicodeString(patResStr, patLen),
547 negPrefix, negSuffix, posPrefix, posSuffix, status);
548 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
554 fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status);
557 // save the unique currency plural patterns of this locale.
558 Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern;
559 const UHashElement* element = NULL;
560 int32_t pos = UHASH_FIRST;
561 Hashtable pluralPatternSet;
562 while ((element = pluralPtn->nextElement(pos)) != NULL) {
563 const UHashTok valueTok = element->value;
564 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
565 const UHashTok keyTok = element->key;
566 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
567 if (pluralPatternSet.geti(*value) != 1) {
568 UnicodeString negPrefix;
569 UnicodeString negSuffix;
570 UnicodeString posPrefix;
571 UnicodeString posSuffix;
572 pluralPatternSet.puti(*value, 1, status);
573 applyPatternWithNoSideEffects(
575 negPrefix, negSuffix, posPrefix, posSuffix, status);
576 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
582 fAffixPatternsForCurrency->put(*key, affixPtn, status);
588 //------------------------------------------------------------------------------
590 DecimalFormat::~DecimalFormat()
592 deleteHashForAffixPattern();
593 delete fCurrencyPluralInfo;
597 //------------------------------------------------------------------------------
600 DecimalFormat::DecimalFormat(const DecimalFormat &source) :
601 NumberFormat(source) {
606 //------------------------------------------------------------------------------
607 // assignment operator
610 static void _clone_ptr(T** pdest, const T* source) {
612 if (source == NULL) {
615 *pdest = static_cast<T*>(source->clone());
620 DecimalFormat::operator=(const DecimalFormat& rhs)
623 UErrorCode status = U_ZERO_ERROR;
624 NumberFormat::operator=(rhs);
626 fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status);
628 fImpl->assign(*rhs.fImpl, status);
630 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
632 _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo);
633 deleteHashForAffixPattern();
634 if (rhs.fAffixPatternsForCurrency) {
635 UErrorCode status = U_ZERO_ERROR;
636 fAffixPatternsForCurrency = initHashForAffixPattern(status);
637 copyHashForAffixPattern(rhs.fAffixPatternsForCurrency,
638 fAffixPatternsForCurrency, status);
645 //------------------------------------------------------------------------------
648 DecimalFormat::operator==(const Format& that) const
653 // NumberFormat::operator== guarantees this cast is safe
654 const DecimalFormat* other = (DecimalFormat*)&that;
657 NumberFormat::operator==(that) &&
658 fBoolFlags.getAll() == other->fBoolFlags.getAll() &&
659 *fImpl == *other->fImpl);
663 //------------------------------------------------------------------------------
666 DecimalFormat::clone() const
668 return new DecimalFormat(*this);
673 DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const {
674 VisibleDigitsWithExponent digits;
675 initVisibleDigitsWithExponent(number, digits, status);
676 if (U_FAILURE(status)) {
677 return FixedDecimal();
679 return FixedDecimal(digits.getMantissa());
682 VisibleDigitsWithExponent &
683 DecimalFormat::initVisibleDigitsWithExponent(
685 VisibleDigitsWithExponent &digits,
686 UErrorCode &status) const {
687 return fImpl->initVisibleDigitsWithExponent(number, digits, status);
691 DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const {
692 VisibleDigitsWithExponent digits;
693 initVisibleDigitsWithExponent(number, digits, status);
694 if (U_FAILURE(status)) {
695 return FixedDecimal();
697 return FixedDecimal(digits.getMantissa());
700 VisibleDigitsWithExponent &
701 DecimalFormat::initVisibleDigitsWithExponent(
702 const Formattable &number,
703 VisibleDigitsWithExponent &digits,
704 UErrorCode &status) const {
705 if (U_FAILURE(status)) {
708 if (!number.isNumeric()) {
709 status = U_ILLEGAL_ARGUMENT_ERROR;
713 DigitList *dl = number.getDigitList();
715 DigitList dlCopy(*dl);
716 return fImpl->initVisibleDigitsWithExponent(
717 dlCopy, digits, status);
720 Formattable::Type type = number.getType();
721 if (type == Formattable::kDouble || type == Formattable::kLong) {
722 return fImpl->initVisibleDigitsWithExponent(
723 number.getDouble(status), digits, status);
725 return fImpl->initVisibleDigitsWithExponent(
726 number.getInt64(), digits, status);
730 // Create a fixed decimal from a DigitList.
731 // The digit list may be modified.
732 // Internal function only.
734 DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const {
735 VisibleDigitsWithExponent digits;
736 initVisibleDigitsWithExponent(number, digits, status);
737 if (U_FAILURE(status)) {
738 return FixedDecimal();
740 return FixedDecimal(digits.getMantissa());
743 VisibleDigitsWithExponent &
744 DecimalFormat::initVisibleDigitsWithExponent(
746 VisibleDigitsWithExponent &digits,
747 UErrorCode &status) const {
748 return fImpl->initVisibleDigitsWithExponent(
749 number, digits, status);
753 //------------------------------------------------------------------------------
756 DecimalFormat::format(int32_t number,
757 UnicodeString& appendTo,
758 FieldPosition& fieldPosition) const
760 UErrorCode status = U_ZERO_ERROR;
761 return fImpl->format(number, appendTo, fieldPosition, status);
765 DecimalFormat::format(int32_t number,
766 UnicodeString& appendTo,
767 FieldPosition& fieldPosition,
768 UErrorCode& status) const
770 return fImpl->format(number, appendTo, fieldPosition, status);
774 DecimalFormat::format(int32_t number,
775 UnicodeString& appendTo,
776 FieldPositionIterator* posIter,
777 UErrorCode& status) const
779 return fImpl->format(number, appendTo, posIter, status);
783 //------------------------------------------------------------------------------
786 DecimalFormat::format(int64_t number,
787 UnicodeString& appendTo,
788 FieldPosition& fieldPosition) const
790 UErrorCode status = U_ZERO_ERROR; /* ignored */
791 return fImpl->format(number, appendTo, fieldPosition, status);
795 DecimalFormat::format(int64_t number,
796 UnicodeString& appendTo,
797 FieldPosition& fieldPosition,
798 UErrorCode& status) const
800 return fImpl->format(number, appendTo, fieldPosition, status);
804 DecimalFormat::format(int64_t number,
805 UnicodeString& appendTo,
806 FieldPositionIterator* posIter,
807 UErrorCode& status) const
809 return fImpl->format(number, appendTo, posIter, status);
812 //------------------------------------------------------------------------------
815 DecimalFormat::format( double number,
816 UnicodeString& appendTo,
817 FieldPosition& fieldPosition) const
819 UErrorCode status = U_ZERO_ERROR; /* ignored */
820 return fImpl->format(number, appendTo, fieldPosition, status);
824 DecimalFormat::format( double number,
825 UnicodeString& appendTo,
826 FieldPosition& fieldPosition,
827 UErrorCode& status) const
829 return fImpl->format(number, appendTo, fieldPosition, status);
833 DecimalFormat::format( double number,
834 UnicodeString& appendTo,
835 FieldPositionIterator* posIter,
836 UErrorCode& status) const
838 return fImpl->format(number, appendTo, posIter, status);
841 //------------------------------------------------------------------------------
845 DecimalFormat::format(StringPiece number,
846 UnicodeString &toAppendTo,
847 FieldPositionIterator *posIter,
848 UErrorCode &status) const
850 return fImpl->format(number, toAppendTo, posIter, status);
855 DecimalFormat::format(const DigitList &number,
856 UnicodeString &appendTo,
857 FieldPositionIterator *posIter,
858 UErrorCode &status) const {
859 return fImpl->format(number, appendTo, posIter, status);
864 DecimalFormat::format(const DigitList &number,
865 UnicodeString& appendTo,
867 UErrorCode &status) const {
868 return fImpl->format(number, appendTo, pos, status);
872 DecimalFormat::format(const VisibleDigitsWithExponent &number,
873 UnicodeString &appendTo,
874 FieldPositionIterator *posIter,
875 UErrorCode &status) const {
876 return fImpl->format(number, appendTo, posIter, status);
881 DecimalFormat::format(const VisibleDigitsWithExponent &number,
882 UnicodeString& appendTo,
884 UErrorCode &status) const {
885 return fImpl->format(number, appendTo, pos, status);
889 DecimalFormat::_round(const DigitList& number, DigitList& adjustedNum, UBool& isNegative, UErrorCode& status) const {
890 adjustedNum = number;
891 fImpl->round(adjustedNum, status);
892 isNegative = !adjustedNum.isPositive();
897 DecimalFormat::parse(const UnicodeString& text,
899 ParsePosition& parsePosition) const {
900 parse(text, result, parsePosition, NULL);
903 CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
904 ParsePosition& pos) const {
905 Formattable parseResult;
906 int32_t start = pos.getIndex();
907 UChar curbuf[4] = {};
908 parse(text, parseResult, pos, curbuf);
909 if (pos.getIndex() != start) {
910 UErrorCode ec = U_ZERO_ERROR;
911 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec), ec);
913 pos.setIndex(start); // indicate failure
915 return currAmt.orphan();
922 * Parses the given text as a number, optionally providing a currency amount.
923 * @param text the string to parse
924 * @param result output parameter for the numeric result.
925 * @param parsePosition input-output position; on input, the
926 * position within text to match; must have 0 <= pos.getIndex() <
927 * text.length(); on output, the position after the last matched
928 * character. If the parse fails, the position in unchanged upon
930 * @param currency if non-NULL, it should point to a 4-UChar buffer.
931 * In this case the text is parsed as a currency format, and the
932 * ISO 4217 code for the parsed currency is put into the buffer.
933 * Otherwise the text is parsed as a non-currency format.
935 void DecimalFormat::parse(const UnicodeString& text,
937 ParsePosition& parsePosition,
938 UChar* currency) const {
939 int32_t startIdx, backup;
940 int32_t i = startIdx = backup = parsePosition.getIndex();
942 // clear any old contents in the result. In particular, clears any DigitList
943 // that it may be holding.
945 if (currency != NULL) {
946 for (int32_t ci=0; ci<4; ci++) {
951 // Handle NaN as a special case:
952 int32_t formatWidth = fImpl->getOldFormatWidth();
954 // Skip padding characters, if around prefix
955 if (formatWidth > 0 && (
956 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix ||
957 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix)) {
958 i = skipPadding(text, i);
962 // skip any leading whitespace
963 i = backup = skipUWhiteSpace(text, i);
966 // If the text is composed of the representation of NaN, returns NaN.length
967 const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
968 int32_t nanLen = (text.compare(i, nan->length(), *nan)
969 ? 0 : nan->length());
972 if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix)) {
973 i = skipPadding(text, i);
975 parsePosition.setIndex(i);
976 result.setDouble(uprv_getNaN());
980 // NaN parse failed; start over
982 parsePosition.setIndex(i);
984 // status is used to record whether a number is infinite.
985 UBool status[fgStatusLength];
987 DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
988 if (digits == NULL) {
989 return; // no way to report error from here.
992 if (fImpl->fMonetary) {
993 if (!parseForCurrency(text, parsePosition, *digits,
999 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
1000 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
1001 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
1002 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
1003 FALSE, UCURR_SYMBOL_NAME,
1004 parsePosition, *digits, status, currency)) {
1005 debug("!subparse(...) - rewind");
1006 parsePosition.setIndex(startIdx);
1012 if (status[fgStatusInfinite]) {
1013 double inf = uprv_getInfinity();
1014 result.setDouble(digits->isPositive() ? inf : -inf);
1015 // TODO: set the dl to infinity, and let it fall into the code below.
1020 if (!fImpl->fMultiplier.isZero()) {
1021 UErrorCode ec = U_ZERO_ERROR;
1022 digits->div(fImpl->fMultiplier, ec);
1025 if (fImpl->fScale != 0) {
1027 ten.set((int32_t)10);
1028 if (fImpl->fScale > 0) {
1029 for (int32_t i = fImpl->fScale; i > 0; i--) {
1030 UErrorCode ec = U_ZERO_ERROR;
1031 digits->div(ten,ec);
1034 for (int32_t i = fImpl->fScale; i < 0; i++) {
1035 UErrorCode ec = U_ZERO_ERROR;
1036 digits->mult(ten,ec);
1041 // Negative zero special case:
1042 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1043 // if not parsing integerOnly, leave as -0, which a double can represent.
1044 if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) {
1045 digits->setPositive(TRUE);
1047 result.adoptDigitList(digits);
1054 DecimalFormat::parseForCurrency(const UnicodeString& text,
1055 ParsePosition& parsePosition,
1058 UChar* currency) const {
1059 UnicodeString positivePrefix;
1060 UnicodeString positiveSuffix;
1061 UnicodeString negativePrefix;
1062 UnicodeString negativeSuffix;
1063 fImpl->fPositivePrefixPattern.toString(positivePrefix);
1064 fImpl->fPositiveSuffixPattern.toString(positiveSuffix);
1065 fImpl->fNegativePrefixPattern.toString(negativePrefix);
1066 fImpl->fNegativeSuffixPattern.toString(negativeSuffix);
1068 int origPos = parsePosition.getIndex();
1069 int maxPosIndex = origPos;
1070 int maxErrorPos = -1;
1071 // First, parse against current pattern.
1072 // Since current pattern could be set by applyPattern(),
1073 // it could be an arbitrary pattern, and it may not be the one
1074 // defined in current locale.
1075 UBool tmpStatus[fgStatusLength];
1076 ParsePosition tmpPos(origPos);
1077 DigitList tmpDigitList;
1079 if (fStyle == UNUM_CURRENCY_PLURAL) {
1080 found = subparse(text,
1081 &negativePrefix, &negativeSuffix,
1082 &positivePrefix, &positiveSuffix,
1083 TRUE, UCURR_LONG_NAME,
1084 tmpPos, tmpDigitList, tmpStatus, currency);
1086 found = subparse(text,
1087 &negativePrefix, &negativeSuffix,
1088 &positivePrefix, &positiveSuffix,
1089 TRUE, UCURR_SYMBOL_NAME,
1090 tmpPos, tmpDigitList, tmpStatus, currency);
1093 if (tmpPos.getIndex() > maxPosIndex) {
1094 maxPosIndex = tmpPos.getIndex();
1095 for (int32_t i = 0; i < fgStatusLength; ++i) {
1096 status[i] = tmpStatus[i];
1098 digits = tmpDigitList;
1101 maxErrorPos = tmpPos.getErrorIndex();
1103 // Then, parse against affix patterns.
1104 // Those are currency patterns and currency plural patterns.
1105 int32_t pos = UHASH_FIRST;
1106 const UHashElement* element = NULL;
1107 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
1108 const UHashTok valueTok = element->value;
1109 const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer;
1110 UBool tmpStatus[fgStatusLength];
1111 ParsePosition tmpPos(origPos);
1112 DigitList tmpDigitList;
1115 debug("trying affix for currency..");
1119 UBool result = subparse(text,
1120 &affixPtn->negPrefixPatternForCurrency,
1121 &affixPtn->negSuffixPatternForCurrency,
1122 &affixPtn->posPrefixPatternForCurrency,
1123 &affixPtn->posSuffixPatternForCurrency,
1124 TRUE, affixPtn->patternType,
1125 tmpPos, tmpDigitList, tmpStatus, currency);
1128 if (tmpPos.getIndex() > maxPosIndex) {
1129 maxPosIndex = tmpPos.getIndex();
1130 for (int32_t i = 0; i < fgStatusLength; ++i) {
1131 status[i] = tmpStatus[i];
1133 digits = tmpDigitList;
1136 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
1137 tmpPos.getErrorIndex() : maxErrorPos;
1140 // Finally, parse against simple affix to find the match.
1141 // For example, in TestMonster suite,
1142 // if the to-be-parsed text is "-\u00A40,00".
1143 // complexAffixCompare will not find match,
1144 // since there is no ISO code matches "\u00A4",
1145 // and the parse stops at "\u00A4".
1146 // We will just use simple affix comparison (look for exact match)
1149 // TODO: We should parse against simple affix first when
1150 // output currency is not requested. After the complex currency
1151 // parsing implementation was introduced, the default currency
1152 // instance parsing slowed down because of the new code flow.
1153 // I filed #10312 - Yoshito
1154 UBool tmpStatus_2[fgStatusLength];
1155 ParsePosition tmpPos_2(origPos);
1156 DigitList tmpDigitList_2;
1158 // Disable complex currency parsing and try it again.
1159 UBool result = subparse(text,
1160 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
1161 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
1162 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
1163 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
1164 FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME,
1165 tmpPos_2, tmpDigitList_2, tmpStatus_2,
1168 if (tmpPos_2.getIndex() > maxPosIndex) {
1169 maxPosIndex = tmpPos_2.getIndex();
1170 for (int32_t i = 0; i < fgStatusLength; ++i) {
1171 status[i] = tmpStatus_2[i];
1173 digits = tmpDigitList_2;
1177 maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ?
1178 tmpPos_2.getErrorIndex() : maxErrorPos;
1182 //parsePosition.setIndex(origPos);
1183 parsePosition.setErrorIndex(maxErrorPos);
1185 parsePosition.setIndex(maxPosIndex);
1186 parsePosition.setErrorIndex(-1);
1193 * Parse the given text into a number. The text is parsed beginning at
1194 * parsePosition, until an unparseable character is seen.
1195 * @param text the string to parse.
1196 * @param negPrefix negative prefix.
1197 * @param negSuffix negative suffix.
1198 * @param posPrefix positive prefix.
1199 * @param posSuffix positive suffix.
1200 * @param complexCurrencyParsing whether it is complex currency parsing or not.
1201 * @param type the currency type to parse against, LONG_NAME only or not.
1202 * @param parsePosition The position at which to being parsing. Upon
1203 * return, the first unparsed character.
1204 * @param digits the DigitList to set to the parsed value.
1205 * @param status output param containing boolean status flags indicating
1206 * whether the value was infinite and whether it was positive.
1207 * @param currency return value for parsed currency, for generic
1208 * currency parsing mode, or NULL for normal parsing. In generic
1209 * currency parsing mode, any currency is parsed, not just the
1210 * currency that this formatter is set to.
1212 UBool DecimalFormat::subparse(const UnicodeString& text,
1213 const UnicodeString* negPrefix,
1214 const UnicodeString* negSuffix,
1215 const UnicodeString* posPrefix,
1216 const UnicodeString* posSuffix,
1217 UBool complexCurrencyParsing,
1219 ParsePosition& parsePosition,
1220 DigitList& digits, UBool* status,
1221 UChar* currency) const
1223 // The parsing process builds up the number as char string, in the neutral format that
1224 // will be acceptable to the decNumber library, then at the end passes that string
1225 // off for conversion to a decNumber.
1226 UErrorCode err = U_ZERO_ERROR;
1227 CharString parsedNum;
1230 int32_t position = parsePosition.getIndex();
1231 int32_t oldStart = position;
1232 int32_t textLength = text.length(); // One less pointer to follow
1233 UBool strictParse = !isLenient();
1234 UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
1235 const UnicodeString *groupingString = &fImpl->getConstSymbol(
1237 DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
1238 UChar32 groupingChar = groupingString->char32At(0);
1239 int32_t groupingStringLength = groupingString->length();
1240 int32_t groupingCharLength = U16_LENGTH(groupingChar);
1241 UBool groupingUsed = isGroupingUsed();
1244 UnicodeString s(dbgbuf,0,300);;
1245 s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " );
1246 #define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeString(" ")); } else { s.append(UnicodeString(#x "=NULL ")); }
1254 UBool fastParseOk = false; /* TRUE iff fast parse is OK */
1255 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
1256 if((fImpl->isParseFastpath()) && !fImpl->fMonetary &&
1259 (posPrefix==NULL||posPrefix->isEmpty()) &&
1260 (posSuffix==NULL||posSuffix->isEmpty()) &&
1261 // (negPrefix==NULL||negPrefix->isEmpty()) &&
1262 // (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
1263 TRUE) { // optimized path
1265 int l=text.length();
1267 UChar32 ch = text.char32At(j);
1268 const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1269 UChar32 decimalChar = 0;
1270 UBool intOnly = FALSE;
1271 UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0;
1273 int32_t decimalCount = decimalString->countChar32(0,3);
1274 if(isParseIntegerOnly()) {
1275 decimalChar = 0; // not allowed
1276 intOnly = TRUE; // Don't look for decimals.
1277 } else if(decimalCount==1) {
1278 decimalChar = decimalString->char32At(0); // Look for this decimal
1279 } else if(decimalCount==0) {
1280 decimalChar=0; // NO decimal set
1282 j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation.
1286 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
1287 decimalChar, groupingChar, ch,
1289 (strictParse)?'y':'n');
1291 if(ch==0x002D) { // '-'
1292 j=l+1;//=break - negative number.
1295 parsedNum.append('-',err);
1297 if(j<l) ch = text.char32At(j);
1300 parsedNum.append('+',err);
1303 int32_t digit = ch - zero;
1304 if(digit >=0 && digit <= 9) {
1305 parsedNum.append((char)(digit + '0'), err);
1306 if((digitCount>0) || digit!=0 || j==(l-1)) {
1309 } else if(ch == 0) { // break out
1312 } else if(ch == decimalChar) {
1313 parsedNum.append((char)('.'), err);
1314 decimalChar=0; // no more decimals.
1315 // fastParseHadDecimal=TRUE;
1316 } else if(ch == lookForGroup) {
1317 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
1318 } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) {
1319 // parsing integer only and can fall through
1321 digitCount=-1; // fail - fall through to slow parse
1325 ch = text.char32At(j); // for next
1328 ((j==l)||intOnly) // end OR only parsing integer
1329 && (digitCount>0)) { // and have at least one digit
1330 fastParseOk=true; // Fast parse OK!
1334 /* for testing, try it the slow way. also */
1338 parsePosition.setIndex(position=j);
1339 status[fgStatusInfinite]=false;
1342 // was not OK. reset, retry
1344 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount);
1350 printf("Could not fastpath parse. ");
1351 printf("text.length()=%d ", text.length());
1352 printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
1358 UnicodeString formatPattern;
1359 toPattern(formatPattern);
1362 #if UCONFIG_HAVE_PARSEALLINPUT
1363 && fParseAllInput!=UNUM_YES
1367 int32_t formatWidth = fImpl->getOldFormatWidth();
1368 // Match padding before prefix
1369 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
1370 position = skipPadding(text, position);
1373 // Match positive and negative prefixes; prefer longest match.
1374 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, complexCurrencyParsing, type, currency);
1375 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, complexCurrencyParsing, type, currency);
1376 if (posMatch >= 0 && negMatch >= 0) {
1377 if (posMatch > negMatch) {
1379 } else if (negMatch > posMatch) {
1383 if (posMatch >= 0) {
1384 position += posMatch;
1385 parsedNum.append('+', err);
1386 } else if (negMatch >= 0) {
1387 position += negMatch;
1388 parsedNum.append('-', err);
1389 } else if (strictParse){
1390 parsePosition.setErrorIndex(position);
1393 // Temporary set positive. This might be changed after checking suffix
1394 parsedNum.append('+', err);
1397 // Match padding before prefix
1398 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
1399 position = skipPadding(text, position);
1402 if (! strictParse) {
1403 position = skipUWhiteSpace(text, position);
1406 // process digits or Inf, find decimal position
1407 const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
1408 int32_t infLen = (text.compare(position, inf->length(), *inf)
1409 ? 0 : inf->length());
1410 position += infLen; // infLen is non-zero when it does equal to infinity
1411 status[fgStatusInfinite] = infLen != 0;
1414 parsedNum.append("Infinity", err);
1416 // We now have a string of digits, possibly with grouping symbols,
1417 // and decimal points. We want to process these into a DigitList.
1418 // We don't want to put a bunch of leading zeros into the DigitList
1419 // though, so we keep track of the location of the decimal point,
1420 // put only significant digits into the DigitList, and adjust the
1421 // exponent as needed.
1424 UBool strictFail = FALSE; // did we exit with a strict parse failure?
1425 int32_t lastGroup = -1; // where did we last see a grouping separator?
1426 int32_t digitStart = position;
1427 int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping.fGrouping : fImpl->fEffGrouping.fGrouping2;
1429 const UnicodeString *decimalString;
1430 if (fImpl->fMonetary) {
1431 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1433 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1435 UChar32 decimalChar = decimalString->char32At(0);
1436 int32_t decimalStringLength = decimalString->length();
1437 int32_t decimalCharLength = U16_LENGTH(decimalChar);
1439 UBool sawDecimal = FALSE;
1440 UChar32 sawDecimalChar = 0xFFFF;
1441 UBool sawGrouping = FALSE;
1442 UChar32 sawGroupingChar = 0xFFFF;
1443 UBool sawDigit = FALSE;
1444 int32_t backup = -1;
1447 // equivalent grouping and decimal support
1448 const UnicodeSet *decimalSet = NULL;
1449 const UnicodeSet *groupingSet = NULL;
1451 if (decimalCharLength == decimalStringLength) {
1452 decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse);
1455 if (groupingCharLength == groupingStringLength) {
1457 groupingSet = fStaticSets->fStrictDefaultGroupingSeparators;
1459 groupingSet = fStaticSets->fDefaultGroupingSeparators;
1463 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
1464 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
1465 // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
1467 // We have to track digitCount ourselves, because digits.fCount will
1468 // pin when the maximum allowable digits is reached.
1469 int32_t digitCount = 0;
1470 int32_t integerDigitCount = 0;
1472 for (; position < textLength; )
1474 UChar32 ch = text.char32At(position);
1476 /* We recognize all digit ranges, not only the Latin digit range
1477 * '0'..'9'. We do so by using the Character.digit() method,
1478 * which converts a valid Unicode digit to the range 0..9.
1480 * The character 'ch' may be a digit. If so, place its value
1481 * from 0 to 9 in 'digit'. First try using the locale digit,
1482 * which may or MAY NOT be a standard Unicode digit range. If
1483 * this fails, try using the standard Unicode digit ranges by
1484 * calling Character.digit(). If this also fails, digit will
1485 * have a value outside the range 0..9.
1488 if (digit < 0 || digit > 9)
1490 digit = u_charDigitValue(ch);
1493 // As a last resort, look through the localized digits if the zero digit
1494 // is not a "standard" Unicode digit.
1495 if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) {
1497 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) {
1500 for (digit = 1 ; digit < 10 ; digit++ ) {
1501 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
1507 if (digit >= 0 && digit <= 9)
1509 if (strictParse && backup != -1) {
1510 // comma followed by digit, so group before comma is a
1511 // secondary group. If there was a group separator
1512 // before that, the group must == the secondary group
1513 // length, else it can be <= the the secondary group
1515 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
1516 (lastGroup == -1 && position - digitStart - 1 > gs2)) {
1524 // Cancel out backup setting (see grouping handler below)
1528 // Note: this will append leading zeros
1529 parsedNum.append((char)(digit + '0'), err);
1531 // count any digit that's not a leading zero
1532 if (digit > 0 || digitCount > 0 || sawDecimal) {
1535 // count any integer digit that's not a leading zero
1537 integerDigitCount += 1;
1541 position += U16_LENGTH(ch);
1543 else if (groupingStringLength > 0 &&
1544 matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet,
1545 decimalChar, decimalSet,
1546 ch) && groupingUsed)
1553 if ((!sawDigit || backup != -1)) {
1554 // leading group, or two group separators in a row
1560 // Ignore grouping characters, if we are using them, but require
1561 // that they be followed by a digit. Otherwise we backup and
1564 position += groupingStringLength;
1566 // Once we see a grouping character, we only accept that grouping character from then on.
1569 else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch))
1573 (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1)) {
1579 // If we're only parsing integers, or if we ALREADY saw the
1580 // decimal, then don't parse this one.
1581 if (isParseIntegerOnly() || sawDecimal) {
1585 parsedNum.append('.', err);
1586 position += decimalStringLength;
1588 // Once we see a decimal character, we only accept that decimal character from then on.
1590 // decimalSet is considered to consist of (ch,ch)
1594 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless..
1595 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
1596 const UnicodeString *tmp;
1597 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
1599 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit
1601 // Parse sign, if present
1602 int32_t pos = position + tmp->length();
1603 char exponentSign = '+';
1605 if (pos < textLength)
1607 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1608 if (!text.compare(pos, tmp->length(), *tmp))
1610 pos += tmp->length();
1613 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1614 if (!text.compare(pos, tmp->length(), *tmp))
1617 pos += tmp->length();
1622 UBool sawExponentDigit = FALSE;
1623 while (pos < textLength) {
1624 ch = text[(int32_t)pos];
1627 if (digit < 0 || digit > 9) {
1628 digit = u_charDigitValue(ch);
1630 if (0 <= digit && digit <= 9) {
1631 if (!sawExponentDigit) {
1632 parsedNum.append('E', err);
1633 parsedNum.append(exponentSign, err);
1634 sawExponentDigit = TRUE;
1637 parsedNum.append((char)(digit + '0'), err);
1643 if (sawExponentDigit) {
1644 position = pos; // Advance past the exponent
1647 break; // Whether we fail or succeed, we exit this loop
1651 } else { // not parsing exponent
1657 // if we didn't see a decimal and it is required, check to see if the pattern had one
1658 if(!sawDecimal && isDecimalPatternMatchRequired())
1660 if(formatPattern.indexOf(kPatternDecimalSeparator) != -1)
1662 parsePosition.setIndex(oldStart);
1663 parsePosition.setErrorIndex(position);
1664 debug("decimal point match required fail!");
1674 if (strictParse && !sawDecimal) {
1675 if (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1) {
1681 // only set with strictParse and a grouping separator error
1683 parsePosition.setIndex(oldStart);
1684 parsePosition.setErrorIndex(position);
1685 debug("strictFail!");
1689 // If there was no decimal point we have an integer
1691 // If none of the text string was recognized. For example, parse
1692 // "x" with pattern "#0.00" (return index and error index both 0)
1693 // parse "$" with pattern "$#0.00". (return index 0 and error index
1695 if (!sawDigit && digitCount == 0) {
1697 debug("none of text rec");
1698 printf("position=%d\n",position);
1700 parsePosition.setIndex(oldStart);
1701 parsePosition.setErrorIndex(oldStart);
1706 // Match padding before suffix
1707 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
1708 position = skipPadding(text, position);
1711 int32_t posSuffixMatch = -1, negSuffixMatch = -1;
1713 // Match positive and negative suffixes; prefer longest match.
1714 if (posMatch >= 0 || (!strictParse && negMatch < 0)) {
1715 posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency);
1717 if (negMatch >= 0) {
1718 negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency);
1720 if (posSuffixMatch >= 0 && negSuffixMatch >= 0) {
1721 if (posSuffixMatch > negSuffixMatch) {
1722 negSuffixMatch = -1;
1723 } else if (negSuffixMatch > posSuffixMatch) {
1724 posSuffixMatch = -1;
1728 // Fail if neither or both
1729 if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) {
1730 parsePosition.setErrorIndex(position);
1731 debug("neither or both");
1735 position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0));
1737 // Match padding before suffix
1738 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
1739 position = skipPadding(text, position);
1742 parsePosition.setIndex(position);
1744 parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-';
1746 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err));
1748 } /* end SLOW parse */
1749 if(parsePosition.getIndex() == oldStart)
1752 printf(" PP didnt move, err\n");
1754 parsePosition.setErrorIndex(position);
1757 #if UCONFIG_HAVE_PARSEALLINPUT
1758 else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength)
1761 printf(" PP didnt consume all (UNUM_YES), err\n");
1763 parsePosition.setErrorIndex(position);
1767 // uint32_t bits = (fastParseOk?kFastpathOk:0) |
1768 // (fastParseHadDecimal?0:kNoDecimal);
1769 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
1770 digits.set(parsedNum.toStringPiece(),
1775 if (U_FAILURE(err)) {
1777 printf(" err setting %s\n", u_errorName(err));
1779 parsePosition.setErrorIndex(position);
1783 // check if we missed a required decimal point
1784 if(fastParseOk && isDecimalPatternMatchRequired())
1786 if(formatPattern.indexOf(kPatternDecimalSeparator) != -1)
1788 parsePosition.setIndex(oldStart);
1789 parsePosition.setErrorIndex(position);
1790 debug("decimal point match required fail!");
1800 * Starting at position, advance past a run of pad characters, if any.
1801 * Return the index of the first character after position that is not a pad
1802 * character. Result is >= position.
1804 int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
1805 int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar);
1806 while (position < text.length() &&
1807 text.char32At(position) == fImpl->fAffixes.fPadChar) {
1814 * Return the length matched by the given affix, or -1 if none.
1815 * Runs of white space in the affix, match runs of white space in
1816 * the input. Pattern white space and input white space are
1817 * determined differently; see code.
1818 * @param text input text
1819 * @param pos offset into input at which to begin matching
1822 * @param affixPat affix pattern used for currency affix comparison.
1823 * @param complexCurrencyParsing whether it is currency parsing or not
1824 * @param type the currency type to parse against, LONG_NAME only or not.
1825 * @param currency return value for parsed currency, for generic
1826 * currency parsing mode, or null for normal parsing. In generic
1827 * currency parsing mode, any currency is parsed, not just the
1828 * currency that this formatter is set to.
1829 * @return length of input that matches, or -1 if match failure
1831 int32_t DecimalFormat::compareAffix(const UnicodeString& text,
1835 const UnicodeString* affixPat,
1836 UBool complexCurrencyParsing,
1838 UChar* currency) const
1840 const UnicodeString *patternToCompare;
1841 if (currency != NULL ||
1842 (fImpl->fMonetary && complexCurrencyParsing)) {
1844 if (affixPat != NULL) {
1845 return compareComplexAffix(*affixPat, text, pos, type, currency);
1851 patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString();
1854 patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString();
1859 patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString();
1862 patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString();
1865 return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
1868 UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const {
1872 U_ASSERT(fStaticSets != NULL); // should already be loaded
1873 const UnicodeSet *minusSigns = fStaticSets->fMinusSigns;
1874 const UnicodeSet *plusSigns = fStaticSets->fPlusSigns;
1875 return (minusSigns->contains(lhs) && minusSigns->contains(rhs)) ||
1876 (plusSigns->contains(lhs) && plusSigns->contains(rhs));
1879 // check for LRM 0x200E, RLM 0x200F, ALM 0x061C
1880 #define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C)
1882 #define TRIM_BUFLEN 32
1883 UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix) {
1884 UChar trimBuf[TRIM_BUFLEN];
1885 int32_t affixLen = affix.length();
1886 int32_t affixPos, trimLen = 0;
1888 for (affixPos = 0; affixPos < affixLen; affixPos++) {
1889 UChar c = affix.charAt(affixPos);
1890 if (!IS_BIDI_MARK(c)) {
1891 if (trimLen < TRIM_BUFLEN) {
1892 trimBuf[trimLen++] = c;
1899 return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix);
1903 * Return the length matched by the given affix, or -1 if none.
1904 * Runs of white space in the affix, match runs of white space in
1905 * the input. Pattern white space and input white space are
1906 * determined differently; see code.
1907 * @param affix pattern string, taken as a literal
1908 * @param input input text
1909 * @param pos offset into input at which to begin matching
1910 * @return length of input that matches, or -1 if match failure
1912 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
1913 const UnicodeString& input,
1915 UBool lenient) const {
1916 int32_t start = pos;
1917 UnicodeString trimmedAffix;
1918 // For more efficiency we should keep lazily-created trimmed affixes around in
1919 // instance variables instead of trimming each time they are used (the next step)
1920 trimMarksFromAffix(affix, trimmedAffix);
1921 UChar32 affixChar = trimmedAffix.char32At(0);
1922 int32_t affixLength = trimmedAffix.length();
1923 int32_t inputLength = input.length();
1924 int32_t affixCharLength = U16_LENGTH(affixChar);
1925 UnicodeSet *affixSet;
1926 UErrorCode status = U_ZERO_ERROR;
1928 U_ASSERT(fStaticSets != NULL); // should already be loaded
1930 if (U_FAILURE(status)) {
1934 affixSet = fStaticSets->fStrictDashEquivalents;
1936 // If the trimmedAffix is exactly one character long and that character
1937 // is in the dash set and the very next input character is also
1938 // in the dash set, return a match.
1939 if (affixCharLength == affixLength && affixSet->contains(affixChar)) {
1940 UChar32 ic = input.char32At(pos);
1941 if (affixSet->contains(ic)) {
1942 pos += U16_LENGTH(ic);
1943 pos = skipBidiMarks(input, pos); // skip any trailing bidi marks
1948 for (int32_t i = 0; i < affixLength; ) {
1949 UChar32 c = trimmedAffix.char32At(i);
1950 int32_t len = U16_LENGTH(c);
1951 if (PatternProps::isWhiteSpace(c)) {
1952 // We may have a pattern like: \u200F \u0020
1953 // and input text like: \u200F \u0020
1954 // Note that U+200F and U+0020 are Pattern_White_Space but only
1955 // U+0020 is UWhiteSpace. So we have to first do a direct
1956 // match of the run of Pattern_White_Space in the pattern,
1957 // then match any extra characters.
1958 UBool literalMatch = FALSE;
1959 while (pos < inputLength) {
1960 UChar32 ic = input.char32At(pos);
1962 literalMatch = TRUE;
1965 if (i == affixLength) {
1968 c = trimmedAffix.char32At(i);
1969 len = U16_LENGTH(c);
1970 if (!PatternProps::isWhiteSpace(c)) {
1973 } else if (IS_BIDI_MARK(ic)) {
1974 pos ++; // just skip over this input text
1980 // Advance over run in pattern
1981 i = skipPatternWhiteSpace(trimmedAffix, i);
1983 // Advance over run in input text
1984 // Must see at least one white space char in input,
1985 // unless we've already matched some characters literally.
1987 pos = skipUWhiteSpace(input, pos);
1988 if (pos == s && !literalMatch) {
1992 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
1993 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
1994 // is also in the trimmedAffix.
1995 i = skipUWhiteSpace(trimmedAffix, i);
1997 UBool match = FALSE;
1998 while (pos < inputLength) {
1999 UChar32 ic = input.char32At(pos);
2000 if (!match && ic == c) {
2004 } else if (IS_BIDI_MARK(ic)) {
2005 pos++; // just skip over this input text
2016 UBool match = FALSE;
2018 affixSet = fStaticSets->fDashEquivalents;
2020 if (affixCharLength == affixLength && affixSet->contains(affixChar)) {
2021 pos = skipUWhiteSpaceAndMarks(input, pos);
2022 UChar32 ic = input.char32At(pos);
2024 if (affixSet->contains(ic)) {
2025 pos += U16_LENGTH(ic);
2026 pos = skipBidiMarks(input, pos);
2031 for (int32_t i = 0; i < affixLength; )
2033 //i = skipRuleWhiteSpace(trimmedAffix, i);
2034 i = skipUWhiteSpace(trimmedAffix, i);
2035 pos = skipUWhiteSpaceAndMarks(input, pos);
2037 if (i >= affixLength || pos >= inputLength) {
2041 UChar32 c = trimmedAffix.char32At(i);
2042 UChar32 ic = input.char32At(pos);
2044 if (!equalWithSignCompatibility(ic, c)) {
2050 pos += U16_LENGTH(ic);
2051 pos = skipBidiMarks(input, pos);
2054 if (affixLength > 0 && ! match) {
2062 * Skip over a run of zero or more Pattern_White_Space characters at
2065 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) {
2066 const UChar* s = text.getBuffer();
2067 return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s);
2071 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2074 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) {
2075 while (pos < text.length()) {
2076 UChar32 c = text.char32At(pos);
2077 if (!u_isUWhiteSpace(c)) {
2080 pos += U16_LENGTH(c);
2086 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos
2089 int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos) {
2090 while (pos < text.length()) {
2091 UChar32 c = text.char32At(pos);
2092 if (!u_isUWhiteSpace(c) && !IS_BIDI_MARK(c)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM
2095 pos += U16_LENGTH(c);
2101 * Skip over a run of zero or more bidi marks at pos in text.
2103 int32_t DecimalFormat::skipBidiMarks(const UnicodeString& text, int32_t pos) {
2104 while (pos < text.length()) {
2105 UChar c = text.charAt(pos);
2106 if (!IS_BIDI_MARK(c)) {
2115 * Return the length matched by the given affix, or -1 if none.
2116 * @param affixPat pattern string
2117 * @param input input text
2118 * @param pos offset into input at which to begin matching
2119 * @param type the currency type to parse against, LONG_NAME only or not.
2120 * @param currency return value for parsed currency, for generic
2121 * currency parsing mode, or null for normal parsing. In generic
2122 * currency parsing mode, any currency is parsed, not just the
2123 * currency that this formatter is set to.
2124 * @return length of input that matches, or -1 if match failure
2126 int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
2127 const UnicodeString& text,
2130 UChar* currency) const
2132 int32_t start = pos;
2133 U_ASSERT(currency != NULL || fImpl->fMonetary);
2136 i<affixPat.length() && pos >= 0; ) {
2137 UChar32 c = affixPat.char32At(i);
2141 U_ASSERT(i <= affixPat.length());
2142 c = affixPat.char32At(i);
2145 const UnicodeString* affix = NULL;
2148 case kCurrencySign: {
2149 // since the currency names in choice format is saved
2150 // the same way as other currency names,
2151 // do not need to do currency choice parsing here.
2152 // the general currency parsing parse against all names,
2153 // including names in choice format.
2154 UBool intl = i<affixPat.length() &&
2155 affixPat.char32At(i) == kCurrencySign;
2159 UBool plural = i<affixPat.length() &&
2160 affixPat.char32At(i) == kCurrencySign;
2165 // Parse generic currency -- anything for which we
2166 // have a display name, or any 3-letter ISO code.
2167 // Try to parse display name for our locale; first
2168 // determine our locale.
2169 const char* loc = fCurrencyPluralInfo->getLocale().getName();
2170 ParsePosition ppos(pos);
2172 UErrorCode ec = U_ZERO_ERROR;
2173 // Delegate parse of display name => ISO code to Currency
2174 uprv_parseCurrency(loc, text, ppos, type, curr, ec);
2176 // If parse succeeds, populate currency[0]
2177 if (U_SUCCESS(ec) && ppos.getIndex() != pos) {
2179 u_strcpy(currency, curr);
2181 // The formatter is currency-style but the client has not requested
2182 // the value of the parsed currency. In this case, if that value does
2183 // not match the formatter's current value, then the parse fails.
2184 UChar effectiveCurr[4];
2185 getEffectiveCurrency(effectiveCurr, ec);
2186 if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) {
2191 pos = ppos.getIndex();
2192 } else if (!isLenient()){
2197 case kPatternPercent:
2198 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2200 case kPatternPerMill:
2201 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2204 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2207 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2210 // fall through to affix!=0 test, which will fail
2214 if (affix != NULL) {
2215 pos = match(text, pos, *affix);
2220 pos = match(text, pos, c);
2221 if (PatternProps::isWhiteSpace(c)) {
2222 i = skipPatternWhiteSpace(affixPat, i);
2229 * Match a single character at text[pos] and return the index of the
2230 * next character upon success. Return -1 on failure. If
2231 * ch is a Pattern_White_Space then match a run of white space in text.
2233 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) {
2234 if (PatternProps::isWhiteSpace(ch)) {
2235 // Advance over run of white space in input text
2236 // Must see at least one white space char in input
2238 pos = skipPatternWhiteSpace(text, pos);
2244 return (pos >= 0 && text.char32At(pos) == ch) ?
2245 (pos + U16_LENGTH(ch)) : -1;
2249 * Match a string at text[pos] and return the index of the next
2250 * character upon success. Return -1 on failure. Match a run of
2251 * white space in str with a run of white space in text.
2253 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) {
2254 for (int32_t i=0; i<str.length() && pos >= 0; ) {
2255 UChar32 ch = str.char32At(i);
2256 i += U16_LENGTH(ch);
2257 if (PatternProps::isWhiteSpace(ch)) {
2258 i = skipPatternWhiteSpace(str, i);
2260 pos = match(text, pos, ch);
2265 UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol,
2266 UnicodeSet *sset, UChar32 schar)
2269 return sset->contains(schar);
2272 return text.compare(position, length, symbol) == 0;
2275 UBool DecimalFormat::matchDecimal(UChar32 symbolChar,
2276 UBool sawDecimal, UChar32 sawDecimalChar,
2277 const UnicodeSet *sset, UChar32 schar) {
2279 return schar==sawDecimalChar;
2280 } else if(schar==symbolChar) {
2282 } else if(sset!=NULL) {
2283 return sset->contains(schar);
2289 UBool DecimalFormat::matchGrouping(UChar32 groupingChar,
2290 UBool sawGrouping, UChar32 sawGroupingChar,
2291 const UnicodeSet *sset,
2292 UChar32 /*decimalChar*/, const UnicodeSet *decimalSet,
2295 return schar==sawGroupingChar; // previously found
2296 } else if(schar==groupingChar) {
2297 return TRUE; // char from symbols
2298 } else if(sset!=NULL) {
2299 return sset->contains(schar) && // in groupingSet but...
2300 ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet
2308 //------------------------------------------------------------------------------
2309 // Gets the pointer to the localized decimal format symbols
2311 const DecimalFormatSymbols*
2312 DecimalFormat::getDecimalFormatSymbols() const
2314 return &fImpl->getDecimalFormatSymbols();
2317 //------------------------------------------------------------------------------
2318 // De-owning the current localized symbols and adopt the new symbols.
2321 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
2323 if (symbolsToAdopt == NULL) {
2324 return; // do not allow caller to set fSymbols to NULL
2326 fImpl->adoptDecimalFormatSymbols(symbolsToAdopt);
2328 //------------------------------------------------------------------------------
2329 // Setting the symbols is equlivalent to adopting a newly created localized
2333 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
2335 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
2339 const CurrencyPluralInfo*
2340 DecimalFormat::getCurrencyPluralInfo(void) const
2342 return fCurrencyPluralInfo;
2347 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt)
2349 if (toAdopt != NULL) {
2350 delete fCurrencyPluralInfo;
2351 fCurrencyPluralInfo = toAdopt;
2352 // re-set currency affix patterns and currency affixes.
2353 if (fImpl->fMonetary) {
2354 UErrorCode status = U_ZERO_ERROR;
2355 if (fAffixPatternsForCurrency) {
2356 deleteHashForAffixPattern();
2358 setupCurrencyAffixPatterns(status);
2364 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
2366 adoptCurrencyPluralInfo(info.clone());
2370 //------------------------------------------------------------------------------
2371 // Gets the positive prefix of the number pattern.
2374 DecimalFormat::getPositivePrefix(UnicodeString& result) const
2376 return fImpl->getPositivePrefix(result);
2379 //------------------------------------------------------------------------------
2380 // Sets the positive prefix of the number pattern.
2383 DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
2385 fImpl->setPositivePrefix(newValue);
2388 //------------------------------------------------------------------------------
2389 // Gets the negative prefix of the number pattern.
2392 DecimalFormat::getNegativePrefix(UnicodeString& result) const
2394 return fImpl->getNegativePrefix(result);
2397 //------------------------------------------------------------------------------
2398 // Gets the negative prefix of the number pattern.
2401 DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
2403 fImpl->setNegativePrefix(newValue);
2406 //------------------------------------------------------------------------------
2407 // Gets the positive suffix of the number pattern.
2410 DecimalFormat::getPositiveSuffix(UnicodeString& result) const
2412 return fImpl->getPositiveSuffix(result);
2415 //------------------------------------------------------------------------------
2416 // Sets the positive suffix of the number pattern.
2419 DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
2421 fImpl->setPositiveSuffix(newValue);
2424 //------------------------------------------------------------------------------
2425 // Gets the negative suffix of the number pattern.
2428 DecimalFormat::getNegativeSuffix(UnicodeString& result) const
2430 return fImpl->getNegativeSuffix(result);
2433 //------------------------------------------------------------------------------
2434 // Sets the negative suffix of the number pattern.
2437 DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
2439 fImpl->setNegativeSuffix(newValue);
2442 //------------------------------------------------------------------------------
2443 // Gets the multiplier of the number pattern.
2444 // Multipliers are stored as decimal numbers (DigitLists) because that
2445 // is the most convenient for muliplying or dividing the numbers to be formatted.
2446 // A NULL multiplier implies one, and the scaling operations are skipped.
2449 DecimalFormat::getMultiplier() const
2451 return fImpl->getMultiplier();
2454 //------------------------------------------------------------------------------
2455 // Sets the multiplier of the number pattern.
2457 DecimalFormat::setMultiplier(int32_t newValue)
2459 fImpl->setMultiplier(newValue);
2463 * Get the rounding increment.
2464 * @return A positive rounding increment, or 0.0 if rounding
2466 * @see #setRoundingIncrement
2467 * @see #getRoundingMode
2468 * @see #setRoundingMode
2470 double DecimalFormat::getRoundingIncrement() const {
2471 return fImpl->getRoundingIncrement();
2475 * Set the rounding increment. This method also controls whether
2476 * rounding is enabled.
2477 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2478 * Negative increments are equivalent to 0.0.
2479 * @see #getRoundingIncrement
2480 * @see #getRoundingMode
2481 * @see #setRoundingMode
2483 void DecimalFormat::setRoundingIncrement(double newValue) {
2484 fImpl->setRoundingIncrement(newValue);
2488 * Get the rounding mode.
2489 * @return A rounding mode
2490 * @see #setRoundingIncrement
2491 * @see #getRoundingIncrement
2492 * @see #setRoundingMode
2494 DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
2495 return fImpl->getRoundingMode();
2499 * Set the rounding mode. This has no effect unless the rounding
2500 * increment is greater than zero.
2501 * @param roundingMode A rounding mode
2502 * @see #setRoundingIncrement
2503 * @see #getRoundingIncrement
2504 * @see #getRoundingMode
2506 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
2507 fImpl->setRoundingMode(roundingMode);
2511 * Get the width to which the output of <code>format()</code> is padded.
2512 * @return the format width, or zero if no padding is in effect
2513 * @see #setFormatWidth
2514 * @see #getPadCharacter
2515 * @see #setPadCharacter
2516 * @see #getPadPosition
2517 * @see #setPadPosition
2519 int32_t DecimalFormat::getFormatWidth() const {
2520 return fImpl->getFormatWidth();
2524 * Set the width to which the output of <code>format()</code> is padded.
2525 * This method also controls whether padding is enabled.
2526 * @param width the width to which to pad the result of
2527 * <code>format()</code>, or zero to disable padding. A negative
2528 * width is equivalent to 0.
2529 * @see #getFormatWidth
2530 * @see #getPadCharacter
2531 * @see #setPadCharacter
2532 * @see #getPadPosition
2533 * @see #setPadPosition
2535 void DecimalFormat::setFormatWidth(int32_t width) {
2536 int32_t formatWidth = (width > 0) ? width : 0;
2537 fImpl->setFormatWidth(formatWidth);
2540 UnicodeString DecimalFormat::getPadCharacterString() const {
2541 return UnicodeString(fImpl->getPadCharacter());
2544 void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
2546 if (padChar.length() > 0) {
2547 pad = padChar.char32At(0);
2552 fImpl->setPadCharacter(pad);
2555 static DecimalFormat::EPadPosition fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos) {
2557 case DigitAffixesAndPadding::kPadBeforePrefix:
2558 return DecimalFormat::kPadBeforePrefix;
2559 case DigitAffixesAndPadding::kPadAfterPrefix:
2560 return DecimalFormat::kPadAfterPrefix;
2561 case DigitAffixesAndPadding::kPadBeforeSuffix:
2562 return DecimalFormat::kPadBeforeSuffix;
2563 case DigitAffixesAndPadding::kPadAfterSuffix:
2564 return DecimalFormat::kPadAfterSuffix;
2569 return DecimalFormat::kPadBeforePrefix;
2573 * Get the position at which padding will take place. This is the location
2574 * at which padding will be inserted if the result of <code>format()</code>
2575 * is shorter than the format width.
2576 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2577 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2578 * <code>kPadAfterSuffix</code>.
2579 * @see #setFormatWidth
2580 * @see #getFormatWidth
2581 * @see #setPadCharacter
2582 * @see #getPadCharacter
2583 * @see #setPadPosition
2584 * @see #kPadBeforePrefix
2585 * @see #kPadAfterPrefix
2586 * @see #kPadBeforeSuffix
2587 * @see #kPadAfterSuffix
2589 DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
2590 return fromPadPosition(fImpl->getPadPosition());
2593 static DigitAffixesAndPadding::EPadPosition toPadPosition(DecimalFormat::EPadPosition padPos) {
2595 case DecimalFormat::kPadBeforePrefix:
2596 return DigitAffixesAndPadding::kPadBeforePrefix;
2597 case DecimalFormat::kPadAfterPrefix:
2598 return DigitAffixesAndPadding::kPadAfterPrefix;
2599 case DecimalFormat::kPadBeforeSuffix:
2600 return DigitAffixesAndPadding::kPadBeforeSuffix;
2601 case DecimalFormat::kPadAfterSuffix:
2602 return DigitAffixesAndPadding::kPadAfterSuffix;
2607 return DigitAffixesAndPadding::kPadBeforePrefix;
2611 * <strong><font face=helvetica color=red>NEW</font></strong>
2612 * Set the position at which padding will take place. This is the location
2613 * at which padding will be inserted if the result of <code>format()</code>
2614 * is shorter than the format width. This has no effect unless padding is
2616 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2617 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2618 * <code>kPadAfterSuffix</code>.
2619 * @see #setFormatWidth
2620 * @see #getFormatWidth
2621 * @see #setPadCharacter
2622 * @see #getPadCharacter
2623 * @see #getPadPosition
2624 * @see #kPadBeforePrefix
2625 * @see #kPadAfterPrefix
2626 * @see #kPadBeforeSuffix
2627 * @see #kPadAfterSuffix
2629 void DecimalFormat::setPadPosition(EPadPosition padPos) {
2630 fImpl->setPadPosition(toPadPosition(padPos));
2634 * Return whether or not scientific notation is used.
2635 * @return TRUE if this object formats and parses scientific notation
2636 * @see #setScientificNotation
2637 * @see #getMinimumExponentDigits
2638 * @see #setMinimumExponentDigits
2639 * @see #isExponentSignAlwaysShown
2640 * @see #setExponentSignAlwaysShown
2642 UBool DecimalFormat::isScientificNotation() const {
2643 return fImpl->isScientificNotation();
2647 * Set whether or not scientific notation is used.
2648 * @param useScientific TRUE if this object formats and parses scientific
2650 * @see #isScientificNotation
2651 * @see #getMinimumExponentDigits
2652 * @see #setMinimumExponentDigits
2653 * @see #isExponentSignAlwaysShown
2654 * @see #setExponentSignAlwaysShown
2656 void DecimalFormat::setScientificNotation(UBool useScientific) {
2657 fImpl->setScientificNotation(useScientific);
2661 * Return the minimum exponent digits that will be shown.
2662 * @return the minimum exponent digits that will be shown
2663 * @see #setScientificNotation
2664 * @see #isScientificNotation
2665 * @see #setMinimumExponentDigits
2666 * @see #isExponentSignAlwaysShown
2667 * @see #setExponentSignAlwaysShown
2669 int8_t DecimalFormat::getMinimumExponentDigits() const {
2670 return fImpl->getMinimumExponentDigits();
2674 * Set the minimum exponent digits that will be shown. This has no
2675 * effect unless scientific notation is in use.
2676 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2677 * that will be shown. Values less than 1 will be treated as 1.
2678 * @see #setScientificNotation
2679 * @see #isScientificNotation
2680 * @see #getMinimumExponentDigits
2681 * @see #isExponentSignAlwaysShown
2682 * @see #setExponentSignAlwaysShown
2684 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
2685 int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
2686 fImpl->setMinimumExponentDigits(minExponentDigits);
2690 * Return whether the exponent sign is always shown.
2691 * @return TRUE if the exponent is always prefixed with either the
2692 * localized minus sign or the localized plus sign, false if only negative
2693 * exponents are prefixed with the localized minus sign.
2694 * @see #setScientificNotation
2695 * @see #isScientificNotation
2696 * @see #setMinimumExponentDigits
2697 * @see #getMinimumExponentDigits
2698 * @see #setExponentSignAlwaysShown
2700 UBool DecimalFormat::isExponentSignAlwaysShown() const {
2701 return fImpl->isExponentSignAlwaysShown();
2705 * Set whether the exponent sign is always shown. This has no effect
2706 * unless scientific notation is in use.
2707 * @param expSignAlways TRUE if the exponent is always prefixed with either
2708 * the localized minus sign or the localized plus sign, false if only
2709 * negative exponents are prefixed with the localized minus sign.
2710 * @see #setScientificNotation
2711 * @see #isScientificNotation
2712 * @see #setMinimumExponentDigits
2713 * @see #getMinimumExponentDigits
2714 * @see #isExponentSignAlwaysShown
2716 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
2717 fImpl->setExponentSignAlwaysShown(expSignAlways);
2720 //------------------------------------------------------------------------------
2721 // Gets the grouping size of the number pattern. For example, thousand or 10
2722 // thousand groupings.
2725 DecimalFormat::getGroupingSize() const
2727 return fImpl->getGroupingSize();
2730 //------------------------------------------------------------------------------
2731 // Gets the grouping size of the number pattern.
2734 DecimalFormat::setGroupingSize(int32_t newValue)
2736 fImpl->setGroupingSize(newValue);
2739 //------------------------------------------------------------------------------
2742 DecimalFormat::getSecondaryGroupingSize() const
2744 return fImpl->getSecondaryGroupingSize();
2747 //------------------------------------------------------------------------------
2750 DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
2752 fImpl->setSecondaryGroupingSize(newValue);
2755 //------------------------------------------------------------------------------
2758 DecimalFormat::getMinimumGroupingDigits() const
2760 return fImpl->getMinimumGroupingDigits();
2763 //------------------------------------------------------------------------------
2766 DecimalFormat::setMinimumGroupingDigits(int32_t newValue)
2768 fImpl->setMinimumGroupingDigits(newValue);
2771 //------------------------------------------------------------------------------
2772 // Checks if to show the decimal separator.
2775 DecimalFormat::isDecimalSeparatorAlwaysShown() const
2777 return fImpl->isDecimalSeparatorAlwaysShown();
2780 //------------------------------------------------------------------------------
2781 // Sets to always show the decimal separator.
2784 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
2786 fImpl->setDecimalSeparatorAlwaysShown(newValue);
2789 //------------------------------------------------------------------------------
2790 // Checks if decimal point pattern match is required
2792 DecimalFormat::isDecimalPatternMatchRequired(void) const
2794 return fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED);
2797 //------------------------------------------------------------------------------
2798 // Checks if decimal point pattern match is required
2801 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue)
2803 fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue);
2807 //------------------------------------------------------------------------------
2808 // Emits the pattern of this DecimalFormat instance.
2811 DecimalFormat::toPattern(UnicodeString& result) const
2813 return fImpl->toPattern(result);
2816 //------------------------------------------------------------------------------
2817 // Emits the localized pattern this DecimalFormat instance.
2820 DecimalFormat::toLocalizedPattern(UnicodeString& result) const
2822 // toLocalizedPattern is deprecated, so we just make it the same as
2824 return fImpl->toPattern(result);
2827 //------------------------------------------------------------------------------
2830 DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
2832 if (pattern.indexOf(kCurrencySign) != -1) {
2833 handleCurrencySignInPattern(status);
2835 fImpl->applyPattern(pattern, status);
2838 //------------------------------------------------------------------------------
2841 DecimalFormat::applyPattern(const UnicodeString& pattern,
2842 UParseError& parseError,
2845 if (pattern.indexOf(kCurrencySign) != -1) {
2846 handleCurrencySignInPattern(status);
2848 fImpl->applyPattern(pattern, parseError, status);
2850 //------------------------------------------------------------------------------
2853 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
2855 if (pattern.indexOf(kCurrencySign) != -1) {
2856 handleCurrencySignInPattern(status);
2858 fImpl->applyLocalizedPattern(pattern, status);
2861 //------------------------------------------------------------------------------
2864 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
2865 UParseError& parseError,
2868 if (pattern.indexOf(kCurrencySign) != -1) {
2869 handleCurrencySignInPattern(status);
2871 fImpl->applyLocalizedPattern(pattern, parseError, status);
2874 //------------------------------------------------------------------------------
2877 * Sets the maximum number of digits allowed in the integer portion of a
2879 * @see NumberFormat#setMaximumIntegerDigits
2881 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
2882 newValue = _min(newValue, gDefaultMaxIntegerDigits);
2883 NumberFormat::setMaximumIntegerDigits(newValue);
2884 fImpl->updatePrecision();
2888 * Sets the minimum number of digits allowed in the integer portion of a
2889 * number. This override limits the integer digit count to 309.
2890 * @see NumberFormat#setMinimumIntegerDigits
2892 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
2893 newValue = _min(newValue, kDoubleIntegerDigits);
2894 NumberFormat::setMinimumIntegerDigits(newValue);
2895 fImpl->updatePrecision();
2899 * Sets the maximum number of digits allowed in the fraction portion of a
2900 * number. This override limits the fraction digit count to 340.
2901 * @see NumberFormat#setMaximumFractionDigits
2903 void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
2904 newValue = _min(newValue, kDoubleFractionDigits);
2905 NumberFormat::setMaximumFractionDigits(newValue);
2906 fImpl->updatePrecision();
2910 * Sets the minimum number of digits allowed in the fraction portion of a
2911 * number. This override limits the fraction digit count to 340.
2912 * @see NumberFormat#setMinimumFractionDigits
2914 void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
2915 newValue = _min(newValue, kDoubleFractionDigits);
2916 NumberFormat::setMinimumFractionDigits(newValue);
2917 fImpl->updatePrecision();
2920 int32_t DecimalFormat::getMinimumSignificantDigits() const {
2921 return fImpl->getMinimumSignificantDigits();
2924 int32_t DecimalFormat::getMaximumSignificantDigits() const {
2925 return fImpl->getMaximumSignificantDigits();
2928 void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
2932 // pin max sig dig to >= min
2933 int32_t max = _max(fImpl->fMaxSigDigits, min);
2934 fImpl->setMinMaxSignificantDigits(min, max);
2937 void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
2941 // pin min sig dig to 1..max
2942 U_ASSERT(fImpl->fMinSigDigits >= 1);
2943 int32_t min = _min(fImpl->fMinSigDigits, max);
2944 fImpl->setMinMaxSignificantDigits(min, max);
2947 UBool DecimalFormat::areSignificantDigitsUsed() const {
2948 return fImpl->areSignificantDigitsUsed();
2951 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
2952 fImpl->setSignificantDigitsUsed(useSignificantDigits);
2955 void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
2956 // set the currency before compute affixes to get the right currency names
2957 NumberFormat::setCurrency(theCurrency, ec);
2958 fImpl->updateCurrency(ec);
2961 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){
2962 fImpl->setCurrencyUsage(newContext, *ec);
2965 UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
2966 return fImpl->getCurrencyUsage();
2969 // Deprecated variant with no UErrorCode parameter
2970 void DecimalFormat::setCurrency(const UChar* theCurrency) {
2971 UErrorCode ec = U_ZERO_ERROR;
2972 setCurrency(theCurrency, ec);
2975 void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
2976 if (fImpl->fSymbols == NULL) {
2977 ec = U_MEMORY_ALLOCATION_ERROR;
2981 const UChar* c = getCurrency();
2983 const UnicodeString &intl =
2984 fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
2985 c = intl.getBuffer(); // ok for intl to go out of scope
2987 u_strncpy(result, c, 3);
2992 DecimalFormat::initHashForAffixPattern(UErrorCode& status) {
2993 if ( U_FAILURE(status) ) {
2997 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
2998 status = U_MEMORY_ALLOCATION_ERROR;
3001 if ( U_FAILURE(status) ) {
3005 hTable->setValueComparator(decimfmtAffixPatternValueComparator);
3010 DecimalFormat::deleteHashForAffixPattern()
3012 if ( fAffixPatternsForCurrency == NULL ) {
3015 int32_t pos = UHASH_FIRST;
3016 const UHashElement* element = NULL;
3017 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
3018 const UHashTok valueTok = element->value;
3019 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer;
3022 delete fAffixPatternsForCurrency;
3023 fAffixPatternsForCurrency = NULL;
3028 DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
3030 UErrorCode& status) {
3031 if ( U_FAILURE(status) ) {
3034 int32_t pos = UHASH_FIRST;
3035 const UHashElement* element = NULL;
3037 while ( (element = source->nextElement(pos)) != NULL ) {
3038 const UHashTok keyTok = element->key;
3039 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
3040 const UHashTok valueTok = element->value;
3041 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer;
3042 AffixPatternsForCurrency* copy = new AffixPatternsForCurrency(
3043 value->negPrefixPatternForCurrency,
3044 value->negSuffixPatternForCurrency,
3045 value->posPrefixPatternForCurrency,
3046 value->posSuffixPatternForCurrency,
3047 value->patternType);
3048 target->put(UnicodeString(*key), copy, status);
3049 if ( U_FAILURE(status) ) {
3057 DecimalFormat::setGroupingUsed(UBool newValue) {
3058 NumberFormat::setGroupingUsed(newValue);
3059 fImpl->updateGrouping();
3063 DecimalFormat::setParseIntegerOnly(UBool newValue) {
3064 NumberFormat::setParseIntegerOnly(newValue);
3068 DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {
3069 NumberFormat::setContext(value, status);
3072 DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
3074 UErrorCode &status) {
3075 if(U_FAILURE(status)) return *this;
3078 case UNUM_LENIENT_PARSE:
3079 setLenient(newValue!=0);
3082 case UNUM_PARSE_INT_ONLY:
3083 setParseIntegerOnly(newValue!=0);
3086 case UNUM_GROUPING_USED:
3087 setGroupingUsed(newValue!=0);
3090 case UNUM_DECIMAL_ALWAYS_SHOWN:
3091 setDecimalSeparatorAlwaysShown(newValue!=0);
3094 case UNUM_MAX_INTEGER_DIGITS:
3095 setMaximumIntegerDigits(newValue);
3098 case UNUM_MIN_INTEGER_DIGITS:
3099 setMinimumIntegerDigits(newValue);
3102 case UNUM_INTEGER_DIGITS:
3103 setMinimumIntegerDigits(newValue);
3104 setMaximumIntegerDigits(newValue);
3107 case UNUM_MAX_FRACTION_DIGITS:
3108 setMaximumFractionDigits(newValue);
3111 case UNUM_MIN_FRACTION_DIGITS:
3112 setMinimumFractionDigits(newValue);
3115 case UNUM_FRACTION_DIGITS:
3116 setMinimumFractionDigits(newValue);
3117 setMaximumFractionDigits(newValue);
3120 case UNUM_SIGNIFICANT_DIGITS_USED:
3121 setSignificantDigitsUsed(newValue!=0);
3124 case UNUM_MAX_SIGNIFICANT_DIGITS:
3125 setMaximumSignificantDigits(newValue);
3128 case UNUM_MIN_SIGNIFICANT_DIGITS:
3129 setMinimumSignificantDigits(newValue);
3132 case UNUM_MULTIPLIER:
3133 setMultiplier(newValue);
3136 case UNUM_GROUPING_SIZE:
3137 setGroupingSize(newValue);
3140 case UNUM_ROUNDING_MODE:
3141 setRoundingMode((DecimalFormat::ERoundingMode)newValue);
3144 case UNUM_FORMAT_WIDTH:
3145 setFormatWidth(newValue);
3148 case UNUM_PADDING_POSITION:
3149 /** The position at which padding will take place. */
3150 setPadPosition((DecimalFormat::EPadPosition)newValue);
3153 case UNUM_SECONDARY_GROUPING_SIZE:
3154 setSecondaryGroupingSize(newValue);
3157 #if UCONFIG_HAVE_PARSEALLINPUT
3158 case UNUM_PARSE_ALL_INPUT:
3159 setParseAllInput((UNumberFormatAttributeValue)newValue);
3163 /* These are stored in fBoolFlags */
3164 case UNUM_PARSE_NO_EXPONENT:
3165 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
3166 case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
3167 if(!fBoolFlags.isValidValue(newValue)) {
3168 status = U_ILLEGAL_ARGUMENT_ERROR;
3170 if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) {
3171 fImpl->setFailIfMoreThanMaxDigits((UBool) newValue);
3173 fBoolFlags.set(attr, newValue);
3178 fImpl->setScale(newValue);
3181 case UNUM_CURRENCY_USAGE:
3182 setCurrencyUsage((UCurrencyUsage)newValue, &status);
3185 case UNUM_MINIMUM_GROUPING_DIGITS:
3186 setMinimumGroupingDigits(newValue);
3190 status = U_UNSUPPORTED_ERROR;
3196 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
3197 UErrorCode &status ) const {
3198 if(U_FAILURE(status)) return -1;
3200 case UNUM_LENIENT_PARSE:
3203 case UNUM_PARSE_INT_ONLY:
3204 return isParseIntegerOnly();
3206 case UNUM_GROUPING_USED:
3207 return isGroupingUsed();
3209 case UNUM_DECIMAL_ALWAYS_SHOWN:
3210 return isDecimalSeparatorAlwaysShown();
3212 case UNUM_MAX_INTEGER_DIGITS:
3213 return getMaximumIntegerDigits();
3215 case UNUM_MIN_INTEGER_DIGITS:
3216 return getMinimumIntegerDigits();
3218 case UNUM_INTEGER_DIGITS:
3219 // TBD: what should this return?
3220 return getMinimumIntegerDigits();
3222 case UNUM_MAX_FRACTION_DIGITS:
3223 return getMaximumFractionDigits();
3225 case UNUM_MIN_FRACTION_DIGITS:
3226 return getMinimumFractionDigits();
3228 case UNUM_FRACTION_DIGITS:
3229 // TBD: what should this return?
3230 return getMinimumFractionDigits();
3232 case UNUM_SIGNIFICANT_DIGITS_USED:
3233 return areSignificantDigitsUsed();
3235 case UNUM_MAX_SIGNIFICANT_DIGITS:
3236 return getMaximumSignificantDigits();
3238 case UNUM_MIN_SIGNIFICANT_DIGITS:
3239 return getMinimumSignificantDigits();
3241 case UNUM_MULTIPLIER:
3242 return getMultiplier();
3244 case UNUM_GROUPING_SIZE:
3245 return getGroupingSize();
3247 case UNUM_ROUNDING_MODE:
3248 return getRoundingMode();
3250 case UNUM_FORMAT_WIDTH:
3251 return getFormatWidth();
3253 case UNUM_PADDING_POSITION:
3254 return getPadPosition();
3256 case UNUM_SECONDARY_GROUPING_SIZE:
3257 return getSecondaryGroupingSize();
3259 /* These are stored in fBoolFlags */
3260 case UNUM_PARSE_NO_EXPONENT:
3261 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
3262 case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
3263 return fBoolFlags.get(attr);
3266 return fImpl->fScale;
3268 case UNUM_CURRENCY_USAGE:
3269 return fImpl->getCurrencyUsage();
3271 case UNUM_MINIMUM_GROUPING_DIGITS:
3272 return getMinimumGroupingDigits();
3275 status = U_UNSUPPORTED_ERROR;
3279 return -1; /* undefined */
3282 #if UCONFIG_HAVE_PARSEALLINPUT
3283 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
3284 fParseAllInput = value;
3290 #endif /* #if !UCONFIG_NO_FORMATTING */