1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4*******************************************************************************
5* Copyright (C) 1997-2015, International Business Machines Corporation and    *
6* others. All Rights Reserved.                                                *
7*******************************************************************************
8*
9* File DECIMFMT.CPP
10*
11* Modification History:
12*
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,
38*                             fPadPosition
39********************************************************************************
40*/
41
42#include "unicode/utypes.h"
43
44#if !UCONFIG_NO_FORMATTING
45
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"
52#include "unicode/ustring.h"
53#include "uresimp.h"
54#include "ucurrimp.h"
55#include "charstr.h"
56#include "patternprops.h"
57#include "cstring.h"
58#include "uassert.h"
59#include "hash.h"
60#include "decfmtst.h"
61#include "plurrule_impl.h"
62#include "decimalformatpattern.h"
63#include "fmtableimp.h"
64#include "decimfmtimpl.h"
65#include "visibledigits.h"
66
67/*
68 * On certain platforms, round is a macro defined in math.h
69 * This undefine is to avoid conflict between the macro and
70 * the function defined below.
71 */
72#ifdef round
73#undef round
74#endif
75
76
77U_NAMESPACE_BEGIN
78
79#ifdef FMT_DEBUG
80#include <stdio.h>
81static void _debugout(const char *f, int l, const UnicodeString& s) {
82    char buf[2000];
83    s.extract((int32_t) 0, s.length(), buf, "utf-8");
84    printf("%s:%d: %s\n", f,l, buf);
85}
86#define debugout(x) _debugout(__FILE__,__LINE__,x)
87#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
88static const UnicodeString dbg_null("<NULL>","");
89#define DEREFSTR(x)   ((x!=NULL)?(*x):(dbg_null))
90#else
91#define debugout(x)
92#define debug(x)
93#endif
94
95
96/* For currency parsing purose,
97 * Need to remember all prefix patterns and suffix patterns of
98 * every currency format pattern,
99 * including the pattern of default currecny style
100 * and plural currency style. And the patterns are set through applyPattern.
101 */
102struct AffixPatternsForCurrency : public UMemory {
103	// negative prefix pattern
104	UnicodeString negPrefixPatternForCurrency;
105	// negative suffix pattern
106	UnicodeString negSuffixPatternForCurrency;
107	// positive prefix pattern
108	UnicodeString posPrefixPatternForCurrency;
109	// positive suffix pattern
110	UnicodeString posSuffixPatternForCurrency;
111	int8_t patternType;
112
113	AffixPatternsForCurrency(const UnicodeString& negPrefix,
114							 const UnicodeString& negSuffix,
115							 const UnicodeString& posPrefix,
116							 const UnicodeString& posSuffix,
117							 int8_t type) {
118		negPrefixPatternForCurrency = negPrefix;
119		negSuffixPatternForCurrency = negSuffix;
120		posPrefixPatternForCurrency = posPrefix;
121		posSuffixPatternForCurrency = posSuffix;
122		patternType = type;
123	}
124#ifdef FMT_DEBUG
125  void dump() const  {
126    debugout( UnicodeString("AffixPatternsForCurrency( -=\"") +
127              negPrefixPatternForCurrency + (UnicodeString)"\"/\"" +
128              negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" +
129              posPrefixPatternForCurrency + (UnicodeString)"\"/\"" +
130              posSuffixPatternForCurrency + (UnicodeString)"\" )");
131  }
132#endif
133};
134
135/* affix for currency formatting when the currency sign in the pattern
136 * equals to 3, such as the pattern contains 3 currency sign or
137 * the formatter style is currency plural format style.
138 */
139struct AffixesForCurrency : public UMemory {
140	// negative prefix
141	UnicodeString negPrefixForCurrency;
142	// negative suffix
143	UnicodeString negSuffixForCurrency;
144	// positive prefix
145	UnicodeString posPrefixForCurrency;
146	// positive suffix
147	UnicodeString posSuffixForCurrency;
148
149	int32_t formatWidth;
150
151	AffixesForCurrency(const UnicodeString& negPrefix,
152					   const UnicodeString& negSuffix,
153					   const UnicodeString& posPrefix,
154					   const UnicodeString& posSuffix) {
155		negPrefixForCurrency = negPrefix;
156		negSuffixForCurrency = negSuffix;
157		posPrefixForCurrency = posPrefix;
158		posSuffixForCurrency = posSuffix;
159	}
160#ifdef FMT_DEBUG
161  void dump() const {
162    debugout( UnicodeString("AffixesForCurrency( -=\"") +
163              negPrefixForCurrency + (UnicodeString)"\"/\"" +
164              negSuffixForCurrency + (UnicodeString)"\" +=\"" +
165              posPrefixForCurrency + (UnicodeString)"\"/\"" +
166              posSuffixForCurrency + (UnicodeString)"\" )");
167  }
168#endif
169};
170
171U_CDECL_BEGIN
172
173/**
174 * @internal ICU 4.2
175 */
176static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2);
177
178
179static UBool
180U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
181    const AffixPatternsForCurrency* affix_1 =
182        (AffixPatternsForCurrency*)val1.pointer;
183    const AffixPatternsForCurrency* affix_2 =
184        (AffixPatternsForCurrency*)val2.pointer;
185    return affix_1->negPrefixPatternForCurrency ==
186           affix_2->negPrefixPatternForCurrency &&
187           affix_1->negSuffixPatternForCurrency ==
188           affix_2->negSuffixPatternForCurrency &&
189           affix_1->posPrefixPatternForCurrency ==
190           affix_2->posPrefixPatternForCurrency &&
191           affix_1->posSuffixPatternForCurrency ==
192           affix_2->posSuffixPatternForCurrency &&
193           affix_1->patternType == affix_2->patternType;
194}
195
196U_CDECL_END
197
198
199
200
201// *****************************************************************************
202// class DecimalFormat
203// *****************************************************************************
204
205UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
206
207// Constants for characters used in programmatic (unlocalized) patterns.
208#define kPatternZeroDigit            ((UChar)0x0030) /*'0'*/
209#define kPatternSignificantDigit     ((UChar)0x0040) /*'@'*/
210#define kPatternGroupingSeparator    ((UChar)0x002C) /*','*/
211#define kPatternDecimalSeparator     ((UChar)0x002E) /*'.'*/
212#define kPatternPerMill              ((UChar)0x2030)
213#define kPatternPercent              ((UChar)0x0025) /*'%'*/
214#define kPatternDigit                ((UChar)0x0023) /*'#'*/
215#define kPatternSeparator            ((UChar)0x003B) /*';'*/
216#define kPatternExponent             ((UChar)0x0045) /*'E'*/
217#define kPatternPlus                 ((UChar)0x002B) /*'+'*/
218#define kPatternMinus                ((UChar)0x002D) /*'-'*/
219#define kPatternPadEscape            ((UChar)0x002A) /*'*'*/
220#define kQuote                       ((UChar)0x0027) /*'\''*/
221/**
222 * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
223 * is used in patterns and substitued with either the currency symbol,
224 * or if it is doubled, with the international currency symbol.  If the
225 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
226 * replaced with the monetary decimal separator.
227 */
228#define kCurrencySign                ((UChar)0x00A4)
229#define kDefaultPad                  ((UChar)0x0020) /* */
230
231const int32_t DecimalFormat::kDoubleIntegerDigits  = 309;
232const int32_t DecimalFormat::kDoubleFractionDigits = 340;
233
234const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
235
236/**
237 * These are the tags we expect to see in normal resource bundle files associated
238 * with a locale.
239 */
240const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used
241static const char fgNumberElements[]="NumberElements";
242static const char fgLatn[]="latn";
243static const char fgPatterns[]="patterns";
244static const char fgDecimalFormat[]="decimalFormat";
245static const char fgCurrencyFormat[]="currencyFormat";
246
247inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
248inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
249
250//------------------------------------------------------------------------------
251// Constructs a DecimalFormat instance in the default locale.
252
253DecimalFormat::DecimalFormat(UErrorCode& status) {
254    init();
255    UParseError parseError;
256    construct(status, parseError);
257}
258
259//------------------------------------------------------------------------------
260// Constructs a DecimalFormat instance with the specified number format
261// pattern in the default locale.
262
263DecimalFormat::DecimalFormat(const UnicodeString& pattern,
264                             UErrorCode& status) {
265    init();
266    UParseError parseError;
267    construct(status, parseError, &pattern);
268}
269
270//------------------------------------------------------------------------------
271// Constructs a DecimalFormat instance with the specified number format
272// pattern and the number format symbols in the default locale.  The
273// created instance owns the symbols.
274
275DecimalFormat::DecimalFormat(const UnicodeString& pattern,
276                             DecimalFormatSymbols* symbolsToAdopt,
277                             UErrorCode& status) {
278    init();
279    UParseError parseError;
280    if (symbolsToAdopt == NULL)
281        status = U_ILLEGAL_ARGUMENT_ERROR;
282    construct(status, parseError, &pattern, symbolsToAdopt);
283}
284
285DecimalFormat::DecimalFormat(  const UnicodeString& pattern,
286                    DecimalFormatSymbols* symbolsToAdopt,
287                    UParseError& parseErr,
288                    UErrorCode& status) {
289    init();
290    if (symbolsToAdopt == NULL)
291        status = U_ILLEGAL_ARGUMENT_ERROR;
292    construct(status,parseErr, &pattern, symbolsToAdopt);
293}
294
295//------------------------------------------------------------------------------
296// Constructs a DecimalFormat instance with the specified number format
297// pattern and the number format symbols in the default locale.  The
298// created instance owns the clone of the symbols.
299
300DecimalFormat::DecimalFormat(const UnicodeString& pattern,
301                             const DecimalFormatSymbols& symbols,
302                             UErrorCode& status) {
303    init();
304    UParseError parseError;
305    construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
306}
307
308//------------------------------------------------------------------------------
309// Constructs a DecimalFormat instance with the specified number format
310// pattern, the number format symbols, and the number format style.
311// The created instance owns the clone of the symbols.
312
313DecimalFormat::DecimalFormat(const UnicodeString& pattern,
314                             DecimalFormatSymbols* symbolsToAdopt,
315                             UNumberFormatStyle style,
316                             UErrorCode& status) {
317    init();
318    fStyle = style;
319    UParseError parseError;
320    construct(status, parseError, &pattern, symbolsToAdopt);
321}
322
323//-----------------------------------------------------------------------------
324// Common DecimalFormat initialization.
325//    Put all fields of an uninitialized object into a known state.
326//    Common code, shared by all constructors.
327//    Can not fail. Leave the object in good enough shape that the destructor
328//    or assignment operator can run successfully.
329void
330DecimalFormat::init() {
331    fBoolFlags.clear();
332    fStyle = UNUM_DECIMAL;
333    fAffixPatternsForCurrency = NULL;
334    fCurrencyPluralInfo = NULL;
335#if UCONFIG_HAVE_PARSEALLINPUT
336    fParseAllInput = UNUM_MAYBE;
337#endif
338
339    fStaticSets = NULL;
340    fImpl = NULL;
341}
342
343//------------------------------------------------------------------------------
344// Constructs a DecimalFormat instance with the specified number format
345// pattern and the number format symbols in the desired locale.  The
346// created instance owns the symbols.
347
348void
349DecimalFormat::construct(UErrorCode&            status,
350                         UParseError&           parseErr,
351                         const UnicodeString*   pattern,
352                         DecimalFormatSymbols*  symbolsToAdopt)
353{
354    LocalPointer<DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
355    if (U_FAILURE(status))
356        return;
357
358    if (adoptedSymbols.isNull())
359    {
360        adoptedSymbols.adoptInstead(
361                new DecimalFormatSymbols(Locale::getDefault(), status));
362        if (adoptedSymbols.isNull() && U_SUCCESS(status)) {
363            status = U_MEMORY_ALLOCATION_ERROR;
364        }
365        if (U_FAILURE(status)) {
366            return;
367        }
368    }
369    fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
370    if (U_FAILURE(status)) {
371        return;
372    }
373
374    UnicodeString str;
375    // Uses the default locale's number format pattern if there isn't
376    // one specified.
377    if (pattern == NULL)
378    {
379        UErrorCode nsStatus = U_ZERO_ERROR;
380        LocalPointer<NumberingSystem> ns(
381                NumberingSystem::createInstance(nsStatus));
382        if (U_FAILURE(nsStatus)) {
383            status = nsStatus;
384            return;
385        }
386
387        int32_t len = 0;
388        UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status);
389
390        UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status);
391        resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status);
392        resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
393        const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
394        if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) {
395            status = U_ZERO_ERROR;
396            resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status);
397            resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status);
398            resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
399            resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
400        }
401        str.setTo(TRUE, resStr, len);
402        pattern = &str;
403        ures_close(resource);
404        ures_close(top);
405    }
406
407    fImpl = new DecimalFormatImpl(this, *pattern, adoptedSymbols.getAlias(), parseErr, status);
408    if (fImpl) {
409        adoptedSymbols.orphan();
410    } else if (U_SUCCESS(status)) {
411        status = U_MEMORY_ALLOCATION_ERROR;
412    }
413    if (U_FAILURE(status)) {
414        return;
415    }
416
417    if (U_FAILURE(status))
418    {
419        return;
420    }
421
422    const UnicodeString* patternUsed;
423    UnicodeString currencyPluralPatternForOther;
424    // apply pattern
425    if (fStyle == UNUM_CURRENCY_PLURAL) {
426        fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
427        if (U_FAILURE(status)) {
428            return;
429        }
430
431        // the pattern used in format is not fixed until formatting,
432        // in which, the number is known and
433        // will be used to pick the right pattern based on plural count.
434        // Here, set the pattern as the pattern of plural count == "other".
435        // For most locale, the patterns are probably the same for all
436        // plural count. If not, the right pattern need to be re-applied
437        // during format.
438        fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther);
439        // TODO(refactor): Revisit, we are setting the pattern twice.
440        fImpl->applyPatternFavorCurrencyPrecision(
441                currencyPluralPatternForOther, status);
442        patternUsed = &currencyPluralPatternForOther;
443
444    } else {
445        patternUsed = pattern;
446    }
447
448    if (patternUsed->indexOf(kCurrencySign) != -1) {
449        // initialize for currency, not only for plural format,
450        // but also for mix parsing
451        handleCurrencySignInPattern(status);
452    }
453}
454
455void
456DecimalFormat::handleCurrencySignInPattern(UErrorCode& status) {
457    // initialize for currency, not only for plural format,
458    // but also for mix parsing
459    if (U_FAILURE(status)) {
460        return;
461    }
462    if (fCurrencyPluralInfo == NULL) {
463       fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
464       if (U_FAILURE(status)) {
465           return;
466       }
467    }
468    // need it for mix parsing
469    if (fAffixPatternsForCurrency == NULL) {
470        setupCurrencyAffixPatterns(status);
471    }
472}
473
474static void
475applyPatternWithNoSideEffects(
476        const UnicodeString& pattern,
477        UParseError& parseError,
478        UnicodeString &negPrefix,
479        UnicodeString &negSuffix,
480        UnicodeString &posPrefix,
481        UnicodeString &posSuffix,
482        UErrorCode& status) {
483        if (U_FAILURE(status))
484    {
485        return;
486    }
487    DecimalFormatPatternParser patternParser;
488    DecimalFormatPattern out;
489    patternParser.applyPatternWithoutExpandAffix(
490        pattern,
491        out,
492        parseError,
493        status);
494    if (U_FAILURE(status)) {
495      return;
496    }
497    negPrefix = out.fNegPrefixPattern;
498    negSuffix = out.fNegSuffixPattern;
499    posPrefix = out.fPosPrefixPattern;
500    posSuffix = out.fPosSuffixPattern;
501}
502
503void
504DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
505    if (U_FAILURE(status)) {
506        return;
507    }
508    UParseError parseErr;
509    fAffixPatternsForCurrency = initHashForAffixPattern(status);
510    if (U_FAILURE(status)) {
511        return;
512    }
513
514    NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLocale(),status);
515    if (U_FAILURE(status)) {
516        return;
517    }
518
519    // Save the default currency patterns of this locale.
520    // Here, chose onlyApplyPatternWithoutExpandAffix without
521    // expanding the affix patterns into affixes.
522    UnicodeString currencyPattern;
523    UErrorCode error = U_ZERO_ERROR;
524
525    UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().getName(), &error);
526    UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error);
527    resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error);
528    resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
529    int32_t patLen = 0;
530    const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat,  &patLen, &error);
531    if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) {
532        error = U_ZERO_ERROR;
533        resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error);
534        resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
535        patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat,  &patLen, &error);
536    }
537    ures_close(numElements);
538    ures_close(resource);
539    delete ns;
540
541    if (U_SUCCESS(error)) {
542        UnicodeString negPrefix;
543        UnicodeString negSuffix;
544        UnicodeString posPrefix;
545        UnicodeString posSuffix;
546        applyPatternWithNoSideEffects(UnicodeString(patResStr, patLen),
547                                       parseErr,
548                negPrefix, negSuffix, posPrefix, posSuffix,  status);
549        AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
550                                                    negPrefix,
551                                                    negSuffix,
552                                                    posPrefix,
553                                                    posSuffix,
554                                                    UCURR_SYMBOL_NAME);
555        fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status);
556    }
557
558    // save the unique currency plural patterns of this locale.
559    Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern;
560    const UHashElement* element = NULL;
561    int32_t pos = UHASH_FIRST;
562    Hashtable pluralPatternSet;
563    while ((element = pluralPtn->nextElement(pos)) != NULL) {
564        const UHashTok valueTok = element->value;
565        const UnicodeString* value = (UnicodeString*)valueTok.pointer;
566        const UHashTok keyTok = element->key;
567        const UnicodeString* key = (UnicodeString*)keyTok.pointer;
568        if (pluralPatternSet.geti(*value) != 1) {
569            UnicodeString negPrefix;
570            UnicodeString negSuffix;
571            UnicodeString posPrefix;
572            UnicodeString posSuffix;
573            pluralPatternSet.puti(*value, 1, status);
574            applyPatternWithNoSideEffects(
575                    *value, parseErr,
576                    negPrefix, negSuffix, posPrefix, posSuffix, status);
577            AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
578                                                    negPrefix,
579                                                    negSuffix,
580                                                    posPrefix,
581                                                    posSuffix,
582                                                    UCURR_LONG_NAME);
583            fAffixPatternsForCurrency->put(*key, affixPtn, status);
584        }
585    }
586}
587
588
589//------------------------------------------------------------------------------
590
591DecimalFormat::~DecimalFormat()
592{
593    deleteHashForAffixPattern();
594    delete fCurrencyPluralInfo;
595    delete fImpl;
596}
597
598//------------------------------------------------------------------------------
599// copy constructor
600
601DecimalFormat::DecimalFormat(const DecimalFormat &source) :
602    NumberFormat(source) {
603    init();
604    *this = source;
605}
606
607//------------------------------------------------------------------------------
608// assignment operator
609
610template <class T>
611static void _clone_ptr(T** pdest, const T* source) {
612    delete *pdest;
613    if (source == NULL) {
614        *pdest = NULL;
615    } else {
616        *pdest = static_cast<T*>(source->clone());
617    }
618}
619
620DecimalFormat&
621DecimalFormat::operator=(const DecimalFormat& rhs)
622{
623    if(this != &rhs) {
624        UErrorCode status = U_ZERO_ERROR;
625        NumberFormat::operator=(rhs);
626        if (fImpl == NULL) {
627            fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status);
628        } else {
629            fImpl->assign(*rhs.fImpl, status);
630        }
631        fStaticSets     = DecimalFormatStaticSets::getStaticSets(status);
632        fStyle = rhs.fStyle;
633        _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo);
634        deleteHashForAffixPattern();
635        if (rhs.fAffixPatternsForCurrency) {
636            UErrorCode status = U_ZERO_ERROR;
637            fAffixPatternsForCurrency = initHashForAffixPattern(status);
638            copyHashForAffixPattern(rhs.fAffixPatternsForCurrency,
639                                    fAffixPatternsForCurrency, status);
640        }
641    }
642
643    return *this;
644}
645
646//------------------------------------------------------------------------------
647
648UBool
649DecimalFormat::operator==(const Format& that) const
650{
651    if (this == &that)
652        return TRUE;
653
654    // NumberFormat::operator== guarantees this cast is safe
655    const DecimalFormat* other = (DecimalFormat*)&that;
656
657    return (
658        NumberFormat::operator==(that) &&
659        fBoolFlags.getAll() == other->fBoolFlags.getAll() &&
660        *fImpl == *other->fImpl);
661
662}
663
664//------------------------------------------------------------------------------
665
666Format*
667DecimalFormat::clone() const
668{
669    return new DecimalFormat(*this);
670}
671
672
673FixedDecimal
674DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const {
675    VisibleDigitsWithExponent digits;
676    initVisibleDigitsWithExponent(number, digits, status);
677    if (U_FAILURE(status)) {
678        return FixedDecimal();
679    }
680    return FixedDecimal(digits.getMantissa());
681}
682
683VisibleDigitsWithExponent &
684DecimalFormat::initVisibleDigitsWithExponent(
685        double number,
686        VisibleDigitsWithExponent &digits,
687        UErrorCode &status) const {
688    return fImpl->initVisibleDigitsWithExponent(number, digits, status);
689}
690
691FixedDecimal
692DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const {
693    VisibleDigitsWithExponent digits;
694    initVisibleDigitsWithExponent(number, digits, status);
695    if (U_FAILURE(status)) {
696        return FixedDecimal();
697    }
698    return FixedDecimal(digits.getMantissa());
699}
700
701VisibleDigitsWithExponent &
702DecimalFormat::initVisibleDigitsWithExponent(
703        const Formattable &number,
704        VisibleDigitsWithExponent &digits,
705        UErrorCode &status) const {
706    if (U_FAILURE(status)) {
707        return digits;
708    }
709    if (!number.isNumeric()) {
710        status = U_ILLEGAL_ARGUMENT_ERROR;
711        return digits;
712    }
713
714    DigitList *dl = number.getDigitList();
715    if (dl != NULL) {
716        DigitList dlCopy(*dl);
717        return fImpl->initVisibleDigitsWithExponent(
718                dlCopy, digits, status);
719    }
720
721    Formattable::Type type = number.getType();
722    if (type == Formattable::kDouble || type == Formattable::kLong) {
723        return fImpl->initVisibleDigitsWithExponent(
724                number.getDouble(status), digits, status);
725    }
726    return fImpl->initVisibleDigitsWithExponent(
727            number.getInt64(), digits, status);
728}
729
730
731// Create a fixed decimal from a DigitList.
732//    The digit list may be modified.
733//    Internal function only.
734FixedDecimal
735DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const {
736    VisibleDigitsWithExponent digits;
737    initVisibleDigitsWithExponent(number, digits, status);
738    if (U_FAILURE(status)) {
739        return FixedDecimal();
740    }
741    return FixedDecimal(digits.getMantissa());
742}
743
744VisibleDigitsWithExponent &
745DecimalFormat::initVisibleDigitsWithExponent(
746        DigitList &number,
747        VisibleDigitsWithExponent &digits,
748        UErrorCode &status) const {
749    return fImpl->initVisibleDigitsWithExponent(
750            number, digits, status);
751}
752
753
754//------------------------------------------------------------------------------
755
756UnicodeString&
757DecimalFormat::format(int32_t number,
758                      UnicodeString& appendTo,
759                      FieldPosition& fieldPosition) const
760{
761    UErrorCode status = U_ZERO_ERROR;
762    return fImpl->format(number, appendTo, fieldPosition, status);
763}
764
765UnicodeString&
766DecimalFormat::format(int32_t number,
767                      UnicodeString& appendTo,
768                      FieldPosition& fieldPosition,
769                      UErrorCode& status) const
770{
771    return fImpl->format(number, appendTo, fieldPosition, status);
772}
773
774UnicodeString&
775DecimalFormat::format(int32_t number,
776                      UnicodeString& appendTo,
777                      FieldPositionIterator* posIter,
778                      UErrorCode& status) const
779{
780    return fImpl->format(number, appendTo, posIter, status);
781}
782
783
784//------------------------------------------------------------------------------
785
786UnicodeString&
787DecimalFormat::format(int64_t number,
788                      UnicodeString& appendTo,
789                      FieldPosition& fieldPosition) const
790{
791    UErrorCode status = U_ZERO_ERROR; /* ignored */
792    return fImpl->format(number, appendTo, fieldPosition, status);
793}
794
795UnicodeString&
796DecimalFormat::format(int64_t number,
797                      UnicodeString& appendTo,
798                      FieldPosition& fieldPosition,
799                      UErrorCode& status) const
800{
801    return fImpl->format(number, appendTo, fieldPosition, status);
802}
803
804UnicodeString&
805DecimalFormat::format(int64_t number,
806                      UnicodeString& appendTo,
807                      FieldPositionIterator* posIter,
808                      UErrorCode& status) const
809{
810    return fImpl->format(number, appendTo, posIter, status);
811}
812
813//------------------------------------------------------------------------------
814
815UnicodeString&
816DecimalFormat::format(  double number,
817                        UnicodeString& appendTo,
818                        FieldPosition& fieldPosition) const
819{
820    UErrorCode status = U_ZERO_ERROR; /* ignored */
821    return fImpl->format(number, appendTo, fieldPosition, status);
822}
823
824UnicodeString&
825DecimalFormat::format(  double number,
826                        UnicodeString& appendTo,
827                        FieldPosition& fieldPosition,
828                        UErrorCode& status) const
829{
830    return fImpl->format(number, appendTo, fieldPosition, status);
831}
832
833UnicodeString&
834DecimalFormat::format(  double number,
835                        UnicodeString& appendTo,
836                        FieldPositionIterator* posIter,
837                        UErrorCode& status) const
838{
839    return fImpl->format(number, appendTo, posIter, status);
840}
841
842//------------------------------------------------------------------------------
843
844
845UnicodeString&
846DecimalFormat::format(StringPiece number,
847                      UnicodeString &toAppendTo,
848                      FieldPositionIterator *posIter,
849                      UErrorCode &status) const
850{
851  return fImpl->format(number, toAppendTo, posIter, status);
852}
853
854
855UnicodeString&
856DecimalFormat::format(const DigitList &number,
857                      UnicodeString &appendTo,
858                      FieldPositionIterator *posIter,
859                      UErrorCode &status) const {
860    return fImpl->format(number, appendTo, posIter, status);
861}
862
863
864UnicodeString&
865DecimalFormat::format(const DigitList &number,
866                     UnicodeString& appendTo,
867                     FieldPosition& pos,
868                     UErrorCode &status) const {
869    return fImpl->format(number, appendTo, pos, status);
870}
871
872UnicodeString&
873DecimalFormat::format(const VisibleDigitsWithExponent &number,
874                      UnicodeString &appendTo,
875                      FieldPositionIterator *posIter,
876                      UErrorCode &status) const {
877    return fImpl->format(number, appendTo, posIter, status);
878}
879
880
881UnicodeString&
882DecimalFormat::format(const VisibleDigitsWithExponent &number,
883                     UnicodeString& appendTo,
884                     FieldPosition& pos,
885                     UErrorCode &status) const {
886    return fImpl->format(number, appendTo, pos, status);
887}
888
889DigitList&
890DecimalFormat::_round(const DigitList& number, DigitList& adjustedNum, UBool& isNegative, UErrorCode& status) const {
891    adjustedNum = number;
892    fImpl->round(adjustedNum, status);
893    isNegative = !adjustedNum.isPositive();
894    return adjustedNum;
895}
896
897void
898DecimalFormat::parse(const UnicodeString& text,
899                     Formattable& result,
900                     ParsePosition& parsePosition) const {
901    parse(text, result, parsePosition, NULL);
902}
903
904CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
905                                             ParsePosition& pos) const {
906    Formattable parseResult;
907    int32_t start = pos.getIndex();
908    UChar curbuf[4] = {};
909    parse(text, parseResult, pos, curbuf);
910    if (pos.getIndex() != start) {
911        UErrorCode ec = U_ZERO_ERROR;
912        LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec), ec);
913        if (U_FAILURE(ec)) {
914            pos.setIndex(start); // indicate failure
915        } else {
916            return currAmt.orphan();
917        }
918    }
919    return NULL;
920}
921
922/**
923 * Parses the given text as a number, optionally providing a currency amount.
924 * @param text the string to parse
925 * @param result output parameter for the numeric result.
926 * @param parsePosition input-output position; on input, the
927 * position within text to match; must have 0 <= pos.getIndex() <
928 * text.length(); on output, the position after the last matched
929 * character. If the parse fails, the position in unchanged upon
930 * output.
931 * @param currency if non-NULL, it should point to a 4-UChar buffer.
932 * In this case the text is parsed as a currency format, and the
933 * ISO 4217 code for the parsed currency is put into the buffer.
934 * Otherwise the text is parsed as a non-currency format.
935 */
936void DecimalFormat::parse(const UnicodeString& text,
937                          Formattable& result,
938                          ParsePosition& parsePosition,
939                          UChar* currency) const {
940    int32_t startIdx, backup;
941    int32_t i = startIdx = backup = parsePosition.getIndex();
942
943    // clear any old contents in the result.  In particular, clears any DigitList
944    //   that it may be holding.
945    result.setLong(0);
946    if (currency != NULL) {
947        for (int32_t ci=0; ci<4; ci++) {
948            currency[ci] = 0;
949        }
950    }
951
952    // Handle NaN as a special case:
953    int32_t formatWidth = fImpl->getOldFormatWidth();
954
955    // Skip padding characters, if around prefix
956    if (formatWidth > 0 && (
957            fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix ||
958            fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix)) {
959        i = skipPadding(text, i);
960    }
961
962    if (isLenient()) {
963        // skip any leading whitespace
964        i = backup = skipUWhiteSpace(text, i);
965    }
966
967    // If the text is composed of the representation of NaN, returns NaN.length
968    const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
969    int32_t nanLen = (text.compare(i, nan->length(), *nan)
970                      ? 0 : nan->length());
971    if (nanLen) {
972        i += nanLen;
973        if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix)) {
974            i = skipPadding(text, i);
975        }
976        parsePosition.setIndex(i);
977        result.setDouble(uprv_getNaN());
978        return;
979    }
980
981    // NaN parse failed; start over
982    i = backup;
983    parsePosition.setIndex(i);
984
985    // status is used to record whether a number is infinite.
986    UBool status[fgStatusLength];
987
988    DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
989    if (digits == NULL) {
990        return;    // no way to report error from here.
991    }
992
993    if (fImpl->fMonetary) {
994        if (!parseForCurrency(text, parsePosition, *digits,
995                              status, currency)) {
996          return;
997        }
998    } else {
999        if (!subparse(text,
1000                      &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
1001                      &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
1002                      &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
1003                      &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
1004                      FALSE, UCURR_SYMBOL_NAME,
1005                      parsePosition, *digits, status, currency)) {
1006            debug("!subparse(...) - rewind");
1007            parsePosition.setIndex(startIdx);
1008            return;
1009        }
1010    }
1011
1012    // Handle infinity
1013    if (status[fgStatusInfinite]) {
1014        double inf = uprv_getInfinity();
1015        result.setDouble(digits->isPositive() ? inf : -inf);
1016        // TODO:  set the dl to infinity, and let it fall into the code below.
1017    }
1018
1019    else {
1020
1021        if (!fImpl->fMultiplier.isZero()) {
1022            UErrorCode ec = U_ZERO_ERROR;
1023            digits->div(fImpl->fMultiplier, ec);
1024        }
1025
1026        if (fImpl->fScale != 0) {
1027            DigitList ten;
1028            ten.set((int32_t)10);
1029            if (fImpl->fScale > 0) {
1030                for (int32_t i = fImpl->fScale; i > 0; i--) {
1031                    UErrorCode ec = U_ZERO_ERROR;
1032                    digits->div(ten,ec);
1033                }
1034            } else {
1035                for (int32_t i = fImpl->fScale; i < 0; i++) {
1036                    UErrorCode ec = U_ZERO_ERROR;
1037                    digits->mult(ten,ec);
1038                }
1039            }
1040        }
1041
1042        // Negative zero special case:
1043        //    if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1044        //    if not parsing integerOnly, leave as -0, which a double can represent.
1045        if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) {
1046            digits->setPositive(TRUE);
1047        }
1048        result.adoptDigitList(digits);
1049    }
1050}
1051
1052
1053
1054UBool
1055DecimalFormat::parseForCurrency(const UnicodeString& text,
1056                                ParsePosition& parsePosition,
1057                                DigitList& digits,
1058                                UBool* status,
1059                                UChar* currency) const {
1060    UnicodeString positivePrefix;
1061    UnicodeString positiveSuffix;
1062    UnicodeString negativePrefix;
1063    UnicodeString negativeSuffix;
1064    fImpl->fPositivePrefixPattern.toString(positivePrefix);
1065    fImpl->fPositiveSuffixPattern.toString(positiveSuffix);
1066    fImpl->fNegativePrefixPattern.toString(negativePrefix);
1067    fImpl->fNegativeSuffixPattern.toString(negativeSuffix);
1068
1069    int origPos = parsePosition.getIndex();
1070    int maxPosIndex = origPos;
1071    int maxErrorPos = -1;
1072    // First, parse against current pattern.
1073    // Since current pattern could be set by applyPattern(),
1074    // it could be an arbitrary pattern, and it may not be the one
1075    // defined in current locale.
1076    UBool tmpStatus[fgStatusLength];
1077    ParsePosition tmpPos(origPos);
1078    DigitList tmpDigitList;
1079    UBool found;
1080    if (fStyle == UNUM_CURRENCY_PLURAL) {
1081        found = subparse(text,
1082                         &negativePrefix, &negativeSuffix,
1083                         &positivePrefix, &positiveSuffix,
1084                         TRUE, UCURR_LONG_NAME,
1085                         tmpPos, tmpDigitList, tmpStatus, currency);
1086    } else {
1087        found = subparse(text,
1088                         &negativePrefix, &negativeSuffix,
1089                         &positivePrefix, &positiveSuffix,
1090                         TRUE, UCURR_SYMBOL_NAME,
1091                         tmpPos, tmpDigitList, tmpStatus, currency);
1092    }
1093    if (found) {
1094        if (tmpPos.getIndex() > maxPosIndex) {
1095            maxPosIndex = tmpPos.getIndex();
1096            for (int32_t i = 0; i < fgStatusLength; ++i) {
1097                status[i] = tmpStatus[i];
1098            }
1099            digits = tmpDigitList;
1100        }
1101    } else {
1102        maxErrorPos = tmpPos.getErrorIndex();
1103    }
1104    // Then, parse against affix patterns.
1105    // Those are currency patterns and currency plural patterns.
1106    int32_t pos = UHASH_FIRST;
1107    const UHashElement* element = NULL;
1108    while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
1109        const UHashTok valueTok = element->value;
1110        const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer;
1111        UBool tmpStatus[fgStatusLength];
1112        ParsePosition tmpPos(origPos);
1113        DigitList tmpDigitList;
1114
1115#ifdef FMT_DEBUG
1116        debug("trying affix for currency..");
1117        affixPtn->dump();
1118#endif
1119
1120        UBool result = subparse(text,
1121                                &affixPtn->negPrefixPatternForCurrency,
1122                                &affixPtn->negSuffixPatternForCurrency,
1123                                &affixPtn->posPrefixPatternForCurrency,
1124                                &affixPtn->posSuffixPatternForCurrency,
1125                                TRUE, affixPtn->patternType,
1126                                tmpPos, tmpDigitList, tmpStatus, currency);
1127        if (result) {
1128            found = true;
1129            if (tmpPos.getIndex() > maxPosIndex) {
1130                maxPosIndex = tmpPos.getIndex();
1131                for (int32_t i = 0; i < fgStatusLength; ++i) {
1132                    status[i] = tmpStatus[i];
1133                }
1134                digits = tmpDigitList;
1135            }
1136        } else {
1137            maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
1138                          tmpPos.getErrorIndex() : maxErrorPos;
1139        }
1140    }
1141    // Finally, parse against simple affix to find the match.
1142    // For example, in TestMonster suite,
1143    // if the to-be-parsed text is "-\u00A40,00".
1144    // complexAffixCompare will not find match,
1145    // since there is no ISO code matches "\u00A4",
1146    // and the parse stops at "\u00A4".
1147    // We will just use simple affix comparison (look for exact match)
1148    // to pass it.
1149    //
1150    // TODO: We should parse against simple affix first when
1151    // output currency is not requested. After the complex currency
1152    // parsing implementation was introduced, the default currency
1153    // instance parsing slowed down because of the new code flow.
1154    // I filed #10312 - Yoshito
1155    UBool tmpStatus_2[fgStatusLength];
1156    ParsePosition tmpPos_2(origPos);
1157    DigitList tmpDigitList_2;
1158
1159    // Disable complex currency parsing and try it again.
1160    UBool result = subparse(text,
1161                            &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
1162                            &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
1163                            &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
1164                            &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
1165                            FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME,
1166                            tmpPos_2, tmpDigitList_2, tmpStatus_2,
1167                            currency);
1168    if (result) {
1169        if (tmpPos_2.getIndex() > maxPosIndex) {
1170            maxPosIndex = tmpPos_2.getIndex();
1171            for (int32_t i = 0; i < fgStatusLength; ++i) {
1172                status[i] = tmpStatus_2[i];
1173            }
1174            digits = tmpDigitList_2;
1175        }
1176        found = true;
1177    } else {
1178            maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ?
1179                          tmpPos_2.getErrorIndex() : maxErrorPos;
1180    }
1181
1182    if (!found) {
1183        //parsePosition.setIndex(origPos);
1184        parsePosition.setErrorIndex(maxErrorPos);
1185    } else {
1186        parsePosition.setIndex(maxPosIndex);
1187        parsePosition.setErrorIndex(-1);
1188    }
1189    return found;
1190}
1191
1192
1193/**
1194 * Parse the given text into a number.  The text is parsed beginning at
1195 * parsePosition, until an unparseable character is seen.
1196 * @param text the string to parse.
1197 * @param negPrefix negative prefix.
1198 * @param negSuffix negative suffix.
1199 * @param posPrefix positive prefix.
1200 * @param posSuffix positive suffix.
1201 * @param complexCurrencyParsing whether it is complex currency parsing or not.
1202 * @param type the currency type to parse against, LONG_NAME only or not.
1203 * @param parsePosition The position at which to being parsing.  Upon
1204 * return, the first unparsed character.
1205 * @param digits the DigitList to set to the parsed value.
1206 * @param status output param containing boolean status flags indicating
1207 * whether the value was infinite and whether it was positive.
1208 * @param currency return value for parsed currency, for generic
1209 * currency parsing mode, or NULL for normal parsing. In generic
1210 * currency parsing mode, any currency is parsed, not just the
1211 * currency that this formatter is set to.
1212 */
1213UBool DecimalFormat::subparse(const UnicodeString& text,
1214                              const UnicodeString* negPrefix,
1215                              const UnicodeString* negSuffix,
1216                              const UnicodeString* posPrefix,
1217                              const UnicodeString* posSuffix,
1218                              UBool complexCurrencyParsing,
1219                              int8_t type,
1220                              ParsePosition& parsePosition,
1221                              DigitList& digits, UBool* status,
1222                              UChar* currency) const
1223{
1224    //  The parsing process builds up the number as char string, in the neutral format that
1225    //  will be acceptable to the decNumber library, then at the end passes that string
1226    //  off for conversion to a decNumber.
1227    UErrorCode err = U_ZERO_ERROR;
1228    CharString parsedNum;
1229    digits.setToZero();
1230
1231    int32_t position = parsePosition.getIndex();
1232    int32_t oldStart = position;
1233    int32_t textLength = text.length(); // One less pointer to follow
1234    UBool strictParse = !isLenient();
1235    UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
1236    const UnicodeString *groupingString = &fImpl->getConstSymbol(
1237            !fImpl->fMonetary ?
1238            DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
1239    UChar32 groupingChar = groupingString->char32At(0);
1240    int32_t groupingStringLength = groupingString->length();
1241    int32_t groupingCharLength   = U16_LENGTH(groupingChar);
1242    UBool   groupingUsed = isGroupingUsed();
1243#ifdef FMT_DEBUG
1244    UChar dbgbuf[300];
1245    UnicodeString s(dbgbuf,0,300);;
1246    s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " );
1247#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 ")); }
1248    DBGAPPD(negPrefix);
1249    DBGAPPD(negSuffix);
1250    DBGAPPD(posPrefix);
1251    DBGAPPD(posSuffix);
1252    debugout(s);
1253#endif
1254
1255    UBool fastParseOk = false; /* TRUE iff fast parse is OK */
1256    // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
1257    if((fImpl->isParseFastpath()) && !fImpl->fMonetary &&
1258       text.length()>0 &&
1259       text.length()<32 &&
1260       (posPrefix==NULL||posPrefix->isEmpty()) &&
1261       (posSuffix==NULL||posSuffix->isEmpty()) &&
1262       //            (negPrefix==NULL||negPrefix->isEmpty()) &&
1263       //            (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
1264       TRUE) {  // optimized path
1265      int j=position;
1266      int l=text.length();
1267      int digitCount=0;
1268      UChar32 ch = text.char32At(j);
1269      const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1270      UChar32 decimalChar = 0;
1271      UBool intOnly = FALSE;
1272      UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0;
1273
1274      int32_t decimalCount = decimalString->countChar32(0,3);
1275      if(isParseIntegerOnly()) {
1276        decimalChar = 0; // not allowed
1277        intOnly = TRUE; // Don't look for decimals.
1278      } else if(decimalCount==1) {
1279        decimalChar = decimalString->char32At(0); // Look for this decimal
1280      } else if(decimalCount==0) {
1281        decimalChar=0; // NO decimal set
1282      } else {
1283        j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation.
1284      }
1285
1286#ifdef FMT_DEBUG
1287      printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
1288        decimalChar, groupingChar, ch,
1289        (intOnly)?'y':'n',
1290        (strictParse)?'y':'n');
1291#endif
1292      if(ch==0x002D) { // '-'
1293        j=l+1;//=break - negative number.
1294
1295        /*
1296          parsedNum.append('-',err);
1297          j+=U16_LENGTH(ch);
1298          if(j<l) ch = text.char32At(j);
1299        */
1300      } else {
1301        parsedNum.append('+',err);
1302      }
1303      while(j<l) {
1304        int32_t digit = ch - zero;
1305        if(digit >=0 && digit <= 9) {
1306          parsedNum.append((char)(digit + '0'), err);
1307          if((digitCount>0) || digit!=0 || j==(l-1)) {
1308            digitCount++;
1309          }
1310        } else if(ch == 0) { // break out
1311          digitCount=-1;
1312          break;
1313        } else if(ch == decimalChar) {
1314          parsedNum.append((char)('.'), err);
1315          decimalChar=0; // no more decimals.
1316          // fastParseHadDecimal=TRUE;
1317        } else if(ch == lookForGroup) {
1318          // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
1319        } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) {
1320          // parsing integer only and can fall through
1321        } else {
1322          digitCount=-1; // fail - fall through to slow parse
1323          break;
1324        }
1325        j+=U16_LENGTH(ch);
1326        ch = text.char32At(j); // for next
1327      }
1328      if(
1329         ((j==l)||intOnly) // end OR only parsing integer
1330         && (digitCount>0)) { // and have at least one digit
1331        fastParseOk=true; // Fast parse OK!
1332
1333#ifdef SKIP_OPT
1334        debug("SKIP_OPT");
1335        /* for testing, try it the slow way. also */
1336        fastParseOk=false;
1337        parsedNum.clear();
1338#else
1339        parsePosition.setIndex(position=j);
1340        status[fgStatusInfinite]=false;
1341#endif
1342      } else {
1343        // was not OK. reset, retry
1344#ifdef FMT_DEBUG
1345        printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount);
1346#endif
1347        parsedNum.clear();
1348      }
1349    } else {
1350#ifdef FMT_DEBUG
1351      printf("Could not fastpath parse. ");
1352      printf("text.length()=%d ", text.length());
1353      printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
1354
1355      printf("\n");
1356#endif
1357    }
1358
1359  UnicodeString formatPattern;
1360  toPattern(formatPattern);
1361
1362  if(!fastParseOk
1363#if UCONFIG_HAVE_PARSEALLINPUT
1364     && fParseAllInput!=UNUM_YES
1365#endif
1366     )
1367  {
1368    int32_t formatWidth = fImpl->getOldFormatWidth();
1369    // Match padding before prefix
1370    if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
1371        position = skipPadding(text, position);
1372    }
1373
1374    // Match positive and negative prefixes; prefer longest match.
1375    int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, complexCurrencyParsing, type, currency);
1376    int32_t negMatch = compareAffix(text, position, TRUE,  TRUE, negPrefix, complexCurrencyParsing, type, currency);
1377    if (posMatch >= 0 && negMatch >= 0) {
1378        if (posMatch > negMatch) {
1379            negMatch = -1;
1380        } else if (negMatch > posMatch) {
1381            posMatch = -1;
1382        }
1383    }
1384    if (posMatch >= 0) {
1385        position += posMatch;
1386        parsedNum.append('+', err);
1387    } else if (negMatch >= 0) {
1388        position += negMatch;
1389        parsedNum.append('-', err);
1390    } else if (strictParse){
1391        parsePosition.setErrorIndex(position);
1392        return FALSE;
1393    } else {
1394        // Temporary set positive. This might be changed after checking suffix
1395        parsedNum.append('+', err);
1396    }
1397
1398    // Match padding before prefix
1399    if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
1400        position = skipPadding(text, position);
1401    }
1402
1403    if (! strictParse) {
1404        position = skipUWhiteSpace(text, position);
1405    }
1406
1407    // process digits or Inf, find decimal position
1408    const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
1409    int32_t infLen = (text.compare(position, inf->length(), *inf)
1410        ? 0 : inf->length());
1411    position += infLen; // infLen is non-zero when it does equal to infinity
1412    status[fgStatusInfinite] = infLen != 0;
1413
1414    if (infLen != 0) {
1415        parsedNum.append("Infinity", err);
1416    } else {
1417        // We now have a string of digits, possibly with grouping symbols,
1418        // and decimal points.  We want to process these into a DigitList.
1419        // We don't want to put a bunch of leading zeros into the DigitList
1420        // though, so we keep track of the location of the decimal point,
1421        // put only significant digits into the DigitList, and adjust the
1422        // exponent as needed.
1423
1424
1425        UBool strictFail = FALSE; // did we exit with a strict parse failure?
1426        int32_t lastGroup = -1; // after which digit index did we last see a grouping separator?
1427        int32_t currGroup = -1; // for temporary storage the digit index of the current grouping separator
1428        int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping.fGrouping : fImpl->fEffGrouping.fGrouping2;
1429
1430        const UnicodeString *decimalString;
1431        if (fImpl->fMonetary) {
1432            decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1433        } else {
1434            decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1435        }
1436        UChar32 decimalChar = decimalString->char32At(0);
1437        int32_t decimalStringLength = decimalString->length();
1438        int32_t decimalCharLength   = U16_LENGTH(decimalChar);
1439
1440        UBool sawDecimal = FALSE;
1441        UChar32 sawDecimalChar = 0xFFFF;
1442        UBool sawGrouping = FALSE;
1443        UChar32 sawGroupingChar = 0xFFFF;
1444        UBool sawDigit = FALSE;
1445        int32_t backup = -1;
1446        int32_t digit;
1447
1448        // equivalent grouping and decimal support
1449        const UnicodeSet *decimalSet = NULL;
1450        const UnicodeSet *groupingSet = NULL;
1451
1452        if (decimalCharLength == decimalStringLength) {
1453            decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse);
1454        }
1455
1456        if (groupingCharLength == groupingStringLength) {
1457            if (strictParse) {
1458                groupingSet = fStaticSets->fStrictDefaultGroupingSeparators;
1459            } else {
1460                groupingSet = fStaticSets->fDefaultGroupingSeparators;
1461            }
1462        }
1463
1464        // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
1465        // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
1466        // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
1467
1468        // We have to track digitCount ourselves, because digits.fCount will
1469        // pin when the maximum allowable digits is reached.
1470        int32_t digitCount = 0;
1471        int32_t integerDigitCount = 0;
1472
1473        for (; position < textLength; )
1474        {
1475            UChar32 ch = text.char32At(position);
1476
1477            /* We recognize all digit ranges, not only the Latin digit range
1478             * '0'..'9'.  We do so by using the Character.digit() method,
1479             * which converts a valid Unicode digit to the range 0..9.
1480             *
1481             * The character 'ch' may be a digit.  If so, place its value
1482             * from 0 to 9 in 'digit'.  First try using the locale digit,
1483             * which may or MAY NOT be a standard Unicode digit range.  If
1484             * this fails, try using the standard Unicode digit ranges by
1485             * calling Character.digit().  If this also fails, digit will
1486             * have a value outside the range 0..9.
1487             */
1488            digit = ch - zero;
1489            if (digit < 0 || digit > 9)
1490            {
1491                digit = u_charDigitValue(ch);
1492            }
1493
1494            // As a last resort, look through the localized digits if the zero digit
1495            // is not a "standard" Unicode digit.
1496            if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) {
1497                digit = 0;
1498                if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) {
1499                    break;
1500                }
1501                for (digit = 1 ; digit < 10 ; digit++ ) {
1502                    if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
1503                        break;
1504                    }
1505                }
1506            }
1507
1508            if (digit >= 0 && digit <= 9)
1509            {
1510                if (strictParse && backup != -1) {
1511                    // comma followed by digit, so group before comma is a
1512                    // secondary group.  If there was a group separator
1513                    // before that, the group must == the secondary group
1514                    // length, else it can be <= the the secondary group
1515                    // length.
1516                    if ((lastGroup != -1 && currGroup - lastGroup != gs2) ||
1517                        (lastGroup == -1 && digitCount - 1 > gs2)) {
1518                        strictFail = TRUE;
1519                        break;
1520                    }
1521
1522                    lastGroup = currGroup;
1523                }
1524
1525                // Cancel out backup setting (see grouping handler below)
1526                currGroup = -1;
1527                backup = -1;
1528                sawDigit = TRUE;
1529
1530                // Note: this will append leading zeros
1531                parsedNum.append((char)(digit + '0'), err);
1532
1533                // count any digit that's not a leading zero
1534                if (digit > 0 || digitCount > 0 || sawDecimal) {
1535                    digitCount += 1;
1536
1537                    // count any integer digit that's not a leading zero
1538                    if (! sawDecimal) {
1539                        integerDigitCount += 1;
1540                    }
1541                }
1542
1543                position += U16_LENGTH(ch);
1544            }
1545            else if (groupingStringLength > 0 &&
1546                matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet,
1547                            decimalChar, decimalSet,
1548                            ch) && groupingUsed)
1549            {
1550                if (sawDecimal) {
1551                    break;
1552                }
1553
1554                if (strictParse) {
1555                    if ((!sawDigit || backup != -1)) {
1556                        // leading group, or two group separators in a row
1557                        strictFail = TRUE;
1558                        break;
1559                    }
1560                }
1561
1562                // Ignore grouping characters, if we are using them, but require
1563                // that they be followed by a digit.  Otherwise we backup and
1564                // reprocess them.
1565                currGroup = digitCount;
1566                backup = position;
1567                position += groupingStringLength;
1568                sawGrouping=TRUE;
1569                // Once we see a grouping character, we only accept that grouping character from then on.
1570                sawGroupingChar=ch;
1571            }
1572            else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch))
1573            {
1574                if (strictParse) {
1575                    if (backup != -1 ||
1576                        (lastGroup != -1 && digitCount - lastGroup != fImpl->fEffGrouping.fGrouping)) {
1577                        strictFail = TRUE;
1578                        break;
1579                    }
1580                }
1581
1582                // If we're only parsing integers, or if we ALREADY saw the
1583                // decimal, then don't parse this one.
1584                if (isParseIntegerOnly() || sawDecimal) {
1585                    break;
1586                }
1587
1588                parsedNum.append('.', err);
1589                position += decimalStringLength;
1590                sawDecimal = TRUE;
1591                // Once we see a decimal character, we only accept that decimal character from then on.
1592                sawDecimalChar=ch;
1593                // decimalSet is considered to consist of (ch,ch)
1594            }
1595            else {
1596
1597                if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless..
1598                   isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
1599                    const UnicodeString *tmp;
1600                    tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
1601                    // TODO: CASE
1602                    if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT))    // error code is set below if !sawDigit
1603                    {
1604                        // Parse sign, if present
1605                        int32_t pos = position + tmp->length();
1606                        char exponentSign = '+';
1607
1608                        if (pos < textLength)
1609                        {
1610                            tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1611                            if (!text.compare(pos, tmp->length(), *tmp))
1612                            {
1613                                pos += tmp->length();
1614                            }
1615                            else {
1616                                tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1617                                if (!text.compare(pos, tmp->length(), *tmp))
1618                                {
1619                                    exponentSign = '-';
1620                                    pos += tmp->length();
1621                                }
1622                            }
1623                        }
1624
1625                        UBool sawExponentDigit = FALSE;
1626                        while (pos < textLength) {
1627                            ch = text.char32At(pos);
1628                            digit = ch - zero;
1629
1630                            if (digit < 0 || digit > 9) {
1631                                digit = u_charDigitValue(ch);
1632                            }
1633                            if (0 <= digit && digit <= 9) {
1634                                if (!sawExponentDigit) {
1635                                    parsedNum.append('E', err);
1636                                    parsedNum.append(exponentSign, err);
1637                                    sawExponentDigit = TRUE;
1638                                }
1639                                pos += U16_LENGTH(ch);
1640                                parsedNum.append((char)(digit + '0'), err);
1641                            } else {
1642                                break;
1643                            }
1644                        }
1645
1646                        if (sawExponentDigit) {
1647                            position = pos; // Advance past the exponent
1648                        }
1649
1650                        break; // Whether we fail or succeed, we exit this loop
1651                    } else {
1652                        break;
1653                    }
1654                } else { // not parsing exponent
1655                    break;
1656              }
1657            }
1658        }
1659
1660        // if we didn't see a decimal and it is required, check to see if the pattern had one
1661        if(!sawDecimal && isDecimalPatternMatchRequired())
1662        {
1663            if(formatPattern.indexOf(kPatternDecimalSeparator) != -1)
1664            {
1665                parsePosition.setIndex(oldStart);
1666                parsePosition.setErrorIndex(position);
1667                debug("decimal point match required fail!");
1668                return FALSE;
1669            }
1670        }
1671
1672        if (backup != -1)
1673        {
1674            position = backup;
1675        }
1676
1677        if (strictParse && !sawDecimal) {
1678            if (lastGroup != -1 && digitCount - lastGroup != fImpl->fEffGrouping.fGrouping) {
1679                strictFail = TRUE;
1680            }
1681        }
1682
1683        if (strictFail) {
1684            // only set with strictParse and a grouping separator error
1685
1686            parsePosition.setIndex(oldStart);
1687            parsePosition.setErrorIndex(position);
1688            debug("strictFail!");
1689            return FALSE;
1690        }
1691
1692        // If there was no decimal point we have an integer
1693
1694        // If none of the text string was recognized.  For example, parse
1695        // "x" with pattern "#0.00" (return index and error index both 0)
1696        // parse "$" with pattern "$#0.00". (return index 0 and error index
1697        // 1).
1698        if (!sawDigit && digitCount == 0) {
1699#ifdef FMT_DEBUG
1700            debug("none of text rec");
1701            printf("position=%d\n",position);
1702#endif
1703            parsePosition.setIndex(oldStart);
1704            parsePosition.setErrorIndex(oldStart);
1705            return FALSE;
1706        }
1707    }
1708
1709    // Match padding before suffix
1710    if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
1711        position = skipPadding(text, position);
1712    }
1713
1714    int32_t posSuffixMatch = -1, negSuffixMatch = -1;
1715
1716    // Match positive and negative suffixes; prefer longest match.
1717    if (posMatch >= 0 || (!strictParse && negMatch < 0)) {
1718        posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency);
1719    }
1720    if (negMatch >= 0) {
1721        negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency);
1722    }
1723    if (posSuffixMatch >= 0 && negSuffixMatch >= 0) {
1724        if (posSuffixMatch > negSuffixMatch) {
1725            negSuffixMatch = -1;
1726        } else if (negSuffixMatch > posSuffixMatch) {
1727            posSuffixMatch = -1;
1728        }
1729    }
1730
1731    // Fail if neither or both
1732    if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) {
1733        parsePosition.setErrorIndex(position);
1734        debug("neither or both");
1735        return FALSE;
1736    }
1737
1738    position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0));
1739
1740    // Match padding before suffix
1741    if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
1742        position = skipPadding(text, position);
1743    }
1744
1745    parsePosition.setIndex(position);
1746
1747    parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-';
1748#ifdef FMT_DEBUG
1749printf("PP -> %d, SLOW = [%s]!    pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err));
1750#endif
1751  } /* end SLOW parse */
1752  if(parsePosition.getIndex() == oldStart)
1753    {
1754#ifdef FMT_DEBUG
1755      printf(" PP didnt move, err\n");
1756#endif
1757        parsePosition.setErrorIndex(position);
1758        return FALSE;
1759    }
1760#if UCONFIG_HAVE_PARSEALLINPUT
1761  else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength)
1762    {
1763#ifdef FMT_DEBUG
1764      printf(" PP didnt consume all (UNUM_YES), err\n");
1765#endif
1766        parsePosition.setErrorIndex(position);
1767        return FALSE;
1768    }
1769#endif
1770    // uint32_t bits = (fastParseOk?kFastpathOk:0) |
1771    //   (fastParseHadDecimal?0:kNoDecimal);
1772    //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
1773    digits.set(parsedNum.toStringPiece(),
1774               err,
1775               0//bits
1776               );
1777
1778    if (U_FAILURE(err)) {
1779#ifdef FMT_DEBUG
1780      printf(" err setting %s\n", u_errorName(err));
1781#endif
1782        parsePosition.setErrorIndex(position);
1783        return FALSE;
1784    }
1785
1786    // check if we missed a required decimal point
1787    if(fastParseOk && isDecimalPatternMatchRequired())
1788    {
1789        if(formatPattern.indexOf(kPatternDecimalSeparator) != -1)
1790        {
1791            parsePosition.setIndex(oldStart);
1792            parsePosition.setErrorIndex(position);
1793            debug("decimal point match required fail!");
1794            return FALSE;
1795        }
1796    }
1797
1798
1799    return TRUE;
1800}
1801
1802/**
1803 * Starting at position, advance past a run of pad characters, if any.
1804 * Return the index of the first character after position that is not a pad
1805 * character.  Result is >= position.
1806 */
1807int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
1808    int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar);
1809    while (position < text.length() &&
1810           text.char32At(position) == fImpl->fAffixes.fPadChar) {
1811        position += padLen;
1812    }
1813    return position;
1814}
1815
1816/**
1817 * Return the length matched by the given affix, or -1 if none.
1818 * Runs of white space in the affix, match runs of white space in
1819 * the input.  Pattern white space and input white space are
1820 * determined differently; see code.
1821 * @param text input text
1822 * @param pos offset into input at which to begin matching
1823 * @param isNegative
1824 * @param isPrefix
1825 * @param affixPat affix pattern used for currency affix comparison.
1826 * @param complexCurrencyParsing whether it is currency parsing or not
1827 * @param type the currency type to parse against, LONG_NAME only or not.
1828 * @param currency return value for parsed currency, for generic
1829 * currency parsing mode, or null for normal parsing. In generic
1830 * currency parsing mode, any currency is parsed, not just the
1831 * currency that this formatter is set to.
1832 * @return length of input that matches, or -1 if match failure
1833 */
1834int32_t DecimalFormat::compareAffix(const UnicodeString& text,
1835                                    int32_t pos,
1836                                    UBool isNegative,
1837                                    UBool isPrefix,
1838                                    const UnicodeString* affixPat,
1839                                    UBool complexCurrencyParsing,
1840                                    int8_t type,
1841                                    UChar* currency) const
1842{
1843    const UnicodeString *patternToCompare;
1844    if (currency != NULL ||
1845        (fImpl->fMonetary && complexCurrencyParsing)) {
1846
1847        if (affixPat != NULL) {
1848            return compareComplexAffix(*affixPat, text, pos, type, currency);
1849        }
1850    }
1851
1852    if (isNegative) {
1853        if (isPrefix) {
1854            patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString();
1855        }
1856        else {
1857            patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString();
1858        }
1859    }
1860    else {
1861        if (isPrefix) {
1862            patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString();
1863        }
1864        else {
1865            patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString();
1866        }
1867    }
1868    return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
1869}
1870
1871UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const {
1872    if (lhs == rhs) {
1873        return TRUE;
1874    }
1875    U_ASSERT(fStaticSets != NULL); // should already be loaded
1876    const UnicodeSet *minusSigns = fStaticSets->fMinusSigns;
1877    const UnicodeSet *plusSigns = fStaticSets->fPlusSigns;
1878    return (minusSigns->contains(lhs) && minusSigns->contains(rhs)) ||
1879        (plusSigns->contains(lhs) && plusSigns->contains(rhs));
1880}
1881
1882// check for LRM 0x200E, RLM 0x200F, ALM 0x061C
1883#define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C)
1884
1885#define TRIM_BUFLEN 32
1886UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix) {
1887    UChar trimBuf[TRIM_BUFLEN];
1888    int32_t affixLen = affix.length();
1889    int32_t affixPos, trimLen = 0;
1890
1891    for (affixPos = 0; affixPos < affixLen; affixPos++) {
1892        UChar c = affix.charAt(affixPos);
1893        if (!IS_BIDI_MARK(c)) {
1894            if (trimLen < TRIM_BUFLEN) {
1895                trimBuf[trimLen++] = c;
1896            } else {
1897                trimLen = 0;
1898                break;
1899            }
1900        }
1901    }
1902    return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix);
1903}
1904
1905/**
1906 * Return the length matched by the given affix, or -1 if none.
1907 * Runs of white space in the affix, match runs of white space in
1908 * the input.  Pattern white space and input white space are
1909 * determined differently; see code.
1910 * @param affix pattern string, taken as a literal
1911 * @param input input text
1912 * @param pos offset into input at which to begin matching
1913 * @return length of input that matches, or -1 if match failure
1914 */
1915int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
1916                                          const UnicodeString& input,
1917                                          int32_t pos,
1918                                          UBool lenient) const {
1919    int32_t start = pos;
1920    UnicodeString trimmedAffix;
1921    // For more efficiency we should keep lazily-created trimmed affixes around in
1922    // instance variables instead of trimming each time they are used (the next step)
1923    trimMarksFromAffix(affix, trimmedAffix);
1924    UChar32 affixChar = trimmedAffix.char32At(0);
1925    int32_t affixLength = trimmedAffix.length();
1926    int32_t inputLength = input.length();
1927    int32_t affixCharLength = U16_LENGTH(affixChar);
1928    UnicodeSet *affixSet;
1929    UErrorCode status = U_ZERO_ERROR;
1930
1931    U_ASSERT(fStaticSets != NULL); // should already be loaded
1932
1933    if (U_FAILURE(status)) {
1934        return -1;
1935    }
1936    if (!lenient) {
1937        affixSet = fStaticSets->fStrictDashEquivalents;
1938
1939        // If the trimmedAffix is exactly one character long and that character
1940        // is in the dash set and the very next input character is also
1941        // in the dash set, return a match.
1942        if (affixCharLength == affixLength && affixSet->contains(affixChar))  {
1943            UChar32 ic = input.char32At(pos);
1944            if (affixSet->contains(ic)) {
1945                pos += U16_LENGTH(ic);
1946                pos = skipBidiMarks(input, pos); // skip any trailing bidi marks
1947                return pos - start;
1948            }
1949        }
1950
1951        for (int32_t i = 0; i < affixLength; ) {
1952            UChar32 c = trimmedAffix.char32At(i);
1953            int32_t len = U16_LENGTH(c);
1954            if (PatternProps::isWhiteSpace(c)) {
1955                // We may have a pattern like: \u200F \u0020
1956                //        and input text like: \u200F \u0020
1957                // Note that U+200F and U+0020 are Pattern_White_Space but only
1958                // U+0020 is UWhiteSpace.  So we have to first do a direct
1959                // match of the run of Pattern_White_Space in the pattern,
1960                // then match any extra characters.
1961                UBool literalMatch = FALSE;
1962                while (pos < inputLength) {
1963                    UChar32 ic = input.char32At(pos);
1964                    if (ic == c) {
1965                        literalMatch = TRUE;
1966                        i += len;
1967                        pos += len;
1968                        if (i == affixLength) {
1969                            break;
1970                        }
1971                        c = trimmedAffix.char32At(i);
1972                        len = U16_LENGTH(c);
1973                        if (!PatternProps::isWhiteSpace(c)) {
1974                            break;
1975                        }
1976                    } else if (IS_BIDI_MARK(ic)) {
1977                        pos ++; // just skip over this input text
1978                    } else {
1979                        break;
1980                    }
1981                }
1982
1983                // Advance over run in pattern
1984                i = skipPatternWhiteSpace(trimmedAffix, i);
1985
1986                // Advance over run in input text
1987                // Must see at least one white space char in input,
1988                // unless we've already matched some characters literally.
1989                int32_t s = pos;
1990                pos = skipUWhiteSpace(input, pos);
1991                if (pos == s && !literalMatch) {
1992                    return -1;
1993                }
1994
1995                // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
1996                // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
1997                // is also in the trimmedAffix.
1998                i = skipUWhiteSpace(trimmedAffix, i);
1999            } else {
2000                UBool match = FALSE;
2001                while (pos < inputLength) {
2002                    UChar32 ic = input.char32At(pos);
2003                    if (!match && ic == c) {
2004                        i += len;
2005                        pos += len;
2006                        match = TRUE;
2007                    } else if (IS_BIDI_MARK(ic)) {
2008                        pos++; // just skip over this input text
2009                    } else {
2010                        break;
2011                    }
2012                }
2013                if (!match) {
2014                    return -1;
2015                }
2016            }
2017        }
2018    } else {
2019        UBool match = FALSE;
2020
2021        affixSet = fStaticSets->fDashEquivalents;
2022
2023        if (affixCharLength == affixLength && affixSet->contains(affixChar))  {
2024            pos = skipUWhiteSpaceAndMarks(input, pos);
2025            UChar32 ic = input.char32At(pos);
2026
2027            if (affixSet->contains(ic)) {
2028                pos += U16_LENGTH(ic);
2029                pos = skipBidiMarks(input, pos);
2030                return pos - start;
2031            }
2032        }
2033
2034        for (int32_t i = 0; i < affixLength; )
2035        {
2036            //i = skipRuleWhiteSpace(trimmedAffix, i);
2037            i = skipUWhiteSpace(trimmedAffix, i);
2038            pos = skipUWhiteSpaceAndMarks(input, pos);
2039
2040            if (i >= affixLength || pos >= inputLength) {
2041                break;
2042            }
2043
2044            UChar32 c = trimmedAffix.char32At(i);
2045            UChar32 ic = input.char32At(pos);
2046
2047            if (!equalWithSignCompatibility(ic, c)) {
2048                return -1;
2049            }
2050
2051            match = TRUE;
2052            i += U16_LENGTH(c);
2053            pos += U16_LENGTH(ic);
2054            pos = skipBidiMarks(input, pos);
2055        }
2056
2057        if (affixLength > 0 && ! match) {
2058            return -1;
2059        }
2060    }
2061    return pos - start;
2062}
2063
2064/**
2065 * Skip over a run of zero or more Pattern_White_Space characters at
2066 * pos in text.
2067 */
2068int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) {
2069    const UChar* s = text.getBuffer();
2070    return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s);
2071}
2072
2073/**
2074 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2075 * in text.
2076 */
2077int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) {
2078    while (pos < text.length()) {
2079        UChar32 c = text.char32At(pos);
2080        if (!u_isUWhiteSpace(c)) {
2081            break;
2082        }
2083        pos += U16_LENGTH(c);
2084    }
2085    return pos;
2086}
2087
2088/**
2089 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos
2090 * in text.
2091 */
2092int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos) {
2093    while (pos < text.length()) {
2094        UChar32 c = text.char32At(pos);
2095        if (!u_isUWhiteSpace(c) && !IS_BIDI_MARK(c)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM
2096            break;
2097        }
2098        pos += U16_LENGTH(c);
2099    }
2100    return pos;
2101}
2102
2103/**
2104 * Skip over a run of zero or more bidi marks at pos in text.
2105 */
2106int32_t DecimalFormat::skipBidiMarks(const UnicodeString& text, int32_t pos) {
2107    while (pos < text.length()) {
2108        UChar c = text.charAt(pos);
2109        if (!IS_BIDI_MARK(c)) {
2110            break;
2111        }
2112        pos++;
2113    }
2114    return pos;
2115}
2116
2117/**
2118 * Return the length matched by the given affix, or -1 if none.
2119 * @param affixPat pattern string
2120 * @param input input text
2121 * @param pos offset into input at which to begin matching
2122 * @param type the currency type to parse against, LONG_NAME only or not.
2123 * @param currency return value for parsed currency, for generic
2124 * currency parsing mode, or null for normal parsing. In generic
2125 * currency parsing mode, any currency is parsed, not just the
2126 * currency that this formatter is set to.
2127 * @return length of input that matches, or -1 if match failure
2128 */
2129int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
2130                                           const UnicodeString& text,
2131                                           int32_t pos,
2132                                           int8_t type,
2133                                           UChar* currency) const
2134{
2135    int32_t start = pos;
2136    U_ASSERT(currency != NULL || fImpl->fMonetary);
2137
2138    for (int32_t i=0;
2139         i<affixPat.length() && pos >= 0; ) {
2140        UChar32 c = affixPat.char32At(i);
2141        i += U16_LENGTH(c);
2142
2143        if (c == kQuote) {
2144            U_ASSERT(i <= affixPat.length());
2145            c = affixPat.char32At(i);
2146            i += U16_LENGTH(c);
2147
2148            const UnicodeString* affix = NULL;
2149
2150            switch (c) {
2151            case kCurrencySign: {
2152                // since the currency names in choice format is saved
2153                // the same way as other currency names,
2154                // do not need to do currency choice parsing here.
2155                // the general currency parsing parse against all names,
2156                // including names in choice format.
2157                UBool intl = i<affixPat.length() &&
2158                    affixPat.char32At(i) == kCurrencySign;
2159                if (intl) {
2160                    ++i;
2161                }
2162                UBool plural = i<affixPat.length() &&
2163                    affixPat.char32At(i) == kCurrencySign;
2164                if (plural) {
2165                    ++i;
2166                    intl = FALSE;
2167                }
2168                // Parse generic currency -- anything for which we
2169                // have a display name, or any 3-letter ISO code.
2170                // Try to parse display name for our locale; first
2171                // determine our locale.
2172                const char* loc = fCurrencyPluralInfo->getLocale().getName();
2173                ParsePosition ppos(pos);
2174                UChar curr[4];
2175                UErrorCode ec = U_ZERO_ERROR;
2176                // Delegate parse of display name => ISO code to Currency
2177                uprv_parseCurrency(loc, text, ppos, type, curr, ec);
2178
2179                // If parse succeeds, populate currency[0]
2180                if (U_SUCCESS(ec) && ppos.getIndex() != pos) {
2181                    if (currency) {
2182                        u_strcpy(currency, curr);
2183                    } else {
2184                        // The formatter is currency-style but the client has not requested
2185                        // the value of the parsed currency. In this case, if that value does
2186                        // not match the formatter's current value, then the parse fails.
2187                        UChar effectiveCurr[4];
2188                        getEffectiveCurrency(effectiveCurr, ec);
2189                        if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) {
2190                            pos = -1;
2191                            continue;
2192                        }
2193                    }
2194                    pos = ppos.getIndex();
2195                } else if (!isLenient()){
2196                    pos = -1;
2197                }
2198                continue;
2199            }
2200            case kPatternPercent:
2201                affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2202                break;
2203            case kPatternPerMill:
2204                affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2205                break;
2206            case kPatternPlus:
2207                affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2208                break;
2209            case kPatternMinus:
2210                affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2211                break;
2212            default:
2213                // fall through to affix!=0 test, which will fail
2214                break;
2215            }
2216
2217            if (affix != NULL) {
2218                pos = match(text, pos, *affix);
2219                continue;
2220            }
2221        }
2222
2223        pos = match(text, pos, c);
2224        if (PatternProps::isWhiteSpace(c)) {
2225            i = skipPatternWhiteSpace(affixPat, i);
2226        }
2227    }
2228    return pos - start;
2229}
2230
2231/**
2232 * Match a single character at text[pos] and return the index of the
2233 * next character upon success.  Return -1 on failure.  If
2234 * ch is a Pattern_White_Space then match a run of white space in text.
2235 */
2236int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) {
2237    if (PatternProps::isWhiteSpace(ch)) {
2238        // Advance over run of white space in input text
2239        // Must see at least one white space char in input
2240        int32_t s = pos;
2241        pos = skipPatternWhiteSpace(text, pos);
2242        if (pos == s) {
2243            return -1;
2244        }
2245        return pos;
2246    }
2247    return (pos >= 0 && text.char32At(pos) == ch) ?
2248        (pos + U16_LENGTH(ch)) : -1;
2249}
2250
2251/**
2252 * Match a string at text[pos] and return the index of the next
2253 * character upon success.  Return -1 on failure.  Match a run of
2254 * white space in str with a run of white space in text.
2255 */
2256int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) {
2257    for (int32_t i=0; i<str.length() && pos >= 0; ) {
2258        UChar32 ch = str.char32At(i);
2259        i += U16_LENGTH(ch);
2260        if (PatternProps::isWhiteSpace(ch)) {
2261            i = skipPatternWhiteSpace(str, i);
2262        }
2263        pos = match(text, pos, ch);
2264    }
2265    return pos;
2266}
2267
2268UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol,
2269                         UnicodeSet *sset, UChar32 schar)
2270{
2271    if (sset != NULL) {
2272        return sset->contains(schar);
2273    }
2274
2275    return text.compare(position, length, symbol) == 0;
2276}
2277
2278UBool DecimalFormat::matchDecimal(UChar32 symbolChar,
2279                            UBool sawDecimal,  UChar32 sawDecimalChar,
2280                             const UnicodeSet *sset, UChar32 schar) {
2281   if(sawDecimal) {
2282       return schar==sawDecimalChar;
2283   } else if(schar==symbolChar) {
2284       return TRUE;
2285   } else if(sset!=NULL) {
2286        return sset->contains(schar);
2287   } else {
2288       return FALSE;
2289   }
2290}
2291
2292UBool DecimalFormat::matchGrouping(UChar32 groupingChar,
2293                            UBool sawGrouping, UChar32 sawGroupingChar,
2294                             const UnicodeSet *sset,
2295                             UChar32 /*decimalChar*/, const UnicodeSet *decimalSet,
2296                             UChar32 schar) {
2297    if(sawGrouping) {
2298        return schar==sawGroupingChar;  // previously found
2299    } else if(schar==groupingChar) {
2300        return TRUE; // char from symbols
2301    } else if(sset!=NULL) {
2302        return sset->contains(schar) &&  // in groupingSet but...
2303           ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet
2304    } else {
2305        return FALSE;
2306    }
2307}
2308
2309
2310
2311//------------------------------------------------------------------------------
2312// Gets the pointer to the localized decimal format symbols
2313
2314const DecimalFormatSymbols*
2315DecimalFormat::getDecimalFormatSymbols() const
2316{
2317    return &fImpl->getDecimalFormatSymbols();
2318}
2319
2320//------------------------------------------------------------------------------
2321// De-owning the current localized symbols and adopt the new symbols.
2322
2323void
2324DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
2325{
2326    if (symbolsToAdopt == NULL) {
2327        return; // do not allow caller to set fSymbols to NULL
2328    }
2329    fImpl->adoptDecimalFormatSymbols(symbolsToAdopt);
2330}
2331//------------------------------------------------------------------------------
2332// Setting the symbols is equlivalent to adopting a newly created localized
2333// symbols.
2334
2335void
2336DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
2337{
2338    adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
2339}
2340
2341
2342const CurrencyPluralInfo*
2343DecimalFormat::getCurrencyPluralInfo(void) const
2344{
2345    return fCurrencyPluralInfo;
2346}
2347
2348
2349void
2350DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt)
2351{
2352    if (toAdopt != NULL) {
2353        delete fCurrencyPluralInfo;
2354        fCurrencyPluralInfo = toAdopt;
2355        // re-set currency affix patterns and currency affixes.
2356        if (fImpl->fMonetary) {
2357            UErrorCode status = U_ZERO_ERROR;
2358            if (fAffixPatternsForCurrency) {
2359                deleteHashForAffixPattern();
2360            }
2361            setupCurrencyAffixPatterns(status);
2362        }
2363    }
2364}
2365
2366void
2367DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
2368{
2369    adoptCurrencyPluralInfo(info.clone());
2370}
2371
2372
2373//------------------------------------------------------------------------------
2374// Gets the positive prefix of the number pattern.
2375
2376UnicodeString&
2377DecimalFormat::getPositivePrefix(UnicodeString& result) const
2378{
2379    return fImpl->getPositivePrefix(result);
2380}
2381
2382//------------------------------------------------------------------------------
2383// Sets the positive prefix of the number pattern.
2384
2385void
2386DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
2387{
2388    fImpl->setPositivePrefix(newValue);
2389}
2390
2391//------------------------------------------------------------------------------
2392// Gets the negative prefix  of the number pattern.
2393
2394UnicodeString&
2395DecimalFormat::getNegativePrefix(UnicodeString& result) const
2396{
2397    return fImpl->getNegativePrefix(result);
2398}
2399
2400//------------------------------------------------------------------------------
2401// Gets the negative prefix  of the number pattern.
2402
2403void
2404DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
2405{
2406    fImpl->setNegativePrefix(newValue);
2407}
2408
2409//------------------------------------------------------------------------------
2410// Gets the positive suffix of the number pattern.
2411
2412UnicodeString&
2413DecimalFormat::getPositiveSuffix(UnicodeString& result) const
2414{
2415    return fImpl->getPositiveSuffix(result);
2416}
2417
2418//------------------------------------------------------------------------------
2419// Sets the positive suffix of the number pattern.
2420
2421void
2422DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
2423{
2424    fImpl->setPositiveSuffix(newValue);
2425}
2426
2427//------------------------------------------------------------------------------
2428// Gets the negative suffix of the number pattern.
2429
2430UnicodeString&
2431DecimalFormat::getNegativeSuffix(UnicodeString& result) const
2432{
2433    return fImpl->getNegativeSuffix(result);
2434}
2435
2436//------------------------------------------------------------------------------
2437// Sets the negative suffix of the number pattern.
2438
2439void
2440DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
2441{
2442    fImpl->setNegativeSuffix(newValue);
2443}
2444
2445//------------------------------------------------------------------------------
2446// Gets the multiplier of the number pattern.
2447//   Multipliers are stored as decimal numbers (DigitLists) because that
2448//      is the most convenient for muliplying or dividing the numbers to be formatted.
2449//   A NULL multiplier implies one, and the scaling operations are skipped.
2450
2451int32_t
2452DecimalFormat::getMultiplier() const
2453{
2454    return fImpl->getMultiplier();
2455}
2456
2457//------------------------------------------------------------------------------
2458// Sets the multiplier of the number pattern.
2459void
2460DecimalFormat::setMultiplier(int32_t newValue)
2461{
2462    fImpl->setMultiplier(newValue);
2463}
2464
2465/**
2466 * Get the rounding increment.
2467 * @return A positive rounding increment, or 0.0 if rounding
2468 * is not in effect.
2469 * @see #setRoundingIncrement
2470 * @see #getRoundingMode
2471 * @see #setRoundingMode
2472 */
2473double DecimalFormat::getRoundingIncrement() const {
2474    return fImpl->getRoundingIncrement();
2475}
2476
2477/**
2478 * Set the rounding increment.  This method also controls whether
2479 * rounding is enabled.
2480 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2481 * Negative increments are equivalent to 0.0.
2482 * @see #getRoundingIncrement
2483 * @see #getRoundingMode
2484 * @see #setRoundingMode
2485 */
2486void DecimalFormat::setRoundingIncrement(double newValue) {
2487    fImpl->setRoundingIncrement(newValue);
2488}
2489
2490/**
2491 * Get the rounding mode.
2492 * @return A rounding mode
2493 * @see #setRoundingIncrement
2494 * @see #getRoundingIncrement
2495 * @see #setRoundingMode
2496 */
2497DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
2498    return fImpl->getRoundingMode();
2499}
2500
2501/**
2502 * Set the rounding mode.  This has no effect unless the rounding
2503 * increment is greater than zero.
2504 * @param roundingMode A rounding mode
2505 * @see #setRoundingIncrement
2506 * @see #getRoundingIncrement
2507 * @see #getRoundingMode
2508 */
2509void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
2510    fImpl->setRoundingMode(roundingMode);
2511}
2512
2513/**
2514 * Get the width to which the output of <code>format()</code> is padded.
2515 * @return the format width, or zero if no padding is in effect
2516 * @see #setFormatWidth
2517 * @see #getPadCharacter
2518 * @see #setPadCharacter
2519 * @see #getPadPosition
2520 * @see #setPadPosition
2521 */
2522int32_t DecimalFormat::getFormatWidth() const {
2523    return fImpl->getFormatWidth();
2524}
2525
2526/**
2527 * Set the width to which the output of <code>format()</code> is padded.
2528 * This method also controls whether padding is enabled.
2529 * @param width the width to which to pad the result of
2530 * <code>format()</code>, or zero to disable padding.  A negative
2531 * width is equivalent to 0.
2532 * @see #getFormatWidth
2533 * @see #getPadCharacter
2534 * @see #setPadCharacter
2535 * @see #getPadPosition
2536 * @see #setPadPosition
2537 */
2538void DecimalFormat::setFormatWidth(int32_t width) {
2539    int32_t formatWidth = (width > 0) ? width : 0;
2540    fImpl->setFormatWidth(formatWidth);
2541}
2542
2543UnicodeString DecimalFormat::getPadCharacterString() const {
2544    return UnicodeString(fImpl->getPadCharacter());
2545}
2546
2547void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
2548    UChar32 pad;
2549    if (padChar.length() > 0) {
2550        pad = padChar.char32At(0);
2551    }
2552    else {
2553        pad = kDefaultPad;
2554    }
2555    fImpl->setPadCharacter(pad);
2556}
2557
2558static DecimalFormat::EPadPosition fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos) {
2559    switch (padPos) {
2560    case DigitAffixesAndPadding::kPadBeforePrefix:
2561        return DecimalFormat::kPadBeforePrefix;
2562    case DigitAffixesAndPadding::kPadAfterPrefix:
2563        return DecimalFormat::kPadAfterPrefix;
2564    case DigitAffixesAndPadding::kPadBeforeSuffix:
2565        return DecimalFormat::kPadBeforeSuffix;
2566    case DigitAffixesAndPadding::kPadAfterSuffix:
2567        return DecimalFormat::kPadAfterSuffix;
2568    default:
2569        U_ASSERT(FALSE);
2570        break;
2571    }
2572    return DecimalFormat::kPadBeforePrefix;
2573}
2574
2575/**
2576 * Get the position at which padding will take place.  This is the location
2577 * at which padding will be inserted if the result of <code>format()</code>
2578 * is shorter than the format width.
2579 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2580 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2581 * <code>kPadAfterSuffix</code>.
2582 * @see #setFormatWidth
2583 * @see #getFormatWidth
2584 * @see #setPadCharacter
2585 * @see #getPadCharacter
2586 * @see #setPadPosition
2587 * @see #kPadBeforePrefix
2588 * @see #kPadAfterPrefix
2589 * @see #kPadBeforeSuffix
2590 * @see #kPadAfterSuffix
2591 */
2592DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
2593    return fromPadPosition(fImpl->getPadPosition());
2594}
2595
2596static DigitAffixesAndPadding::EPadPosition toPadPosition(DecimalFormat::EPadPosition padPos) {
2597    switch (padPos) {
2598    case DecimalFormat::kPadBeforePrefix:
2599        return DigitAffixesAndPadding::kPadBeforePrefix;
2600    case DecimalFormat::kPadAfterPrefix:
2601        return DigitAffixesAndPadding::kPadAfterPrefix;
2602    case DecimalFormat::kPadBeforeSuffix:
2603        return DigitAffixesAndPadding::kPadBeforeSuffix;
2604    case DecimalFormat::kPadAfterSuffix:
2605        return DigitAffixesAndPadding::kPadAfterSuffix;
2606    default:
2607        U_ASSERT(FALSE);
2608        break;
2609    }
2610    return DigitAffixesAndPadding::kPadBeforePrefix;
2611}
2612
2613/**
2614 * <strong><font face=helvetica color=red>NEW</font></strong>
2615 * Set the position at which padding will take place.  This is the location
2616 * at which padding will be inserted if the result of <code>format()</code>
2617 * is shorter than the format width.  This has no effect unless padding is
2618 * enabled.
2619 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2620 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2621 * <code>kPadAfterSuffix</code>.
2622 * @see #setFormatWidth
2623 * @see #getFormatWidth
2624 * @see #setPadCharacter
2625 * @see #getPadCharacter
2626 * @see #getPadPosition
2627 * @see #kPadBeforePrefix
2628 * @see #kPadAfterPrefix
2629 * @see #kPadBeforeSuffix
2630 * @see #kPadAfterSuffix
2631 */
2632void DecimalFormat::setPadPosition(EPadPosition padPos) {
2633    fImpl->setPadPosition(toPadPosition(padPos));
2634}
2635
2636/**
2637 * Return whether or not scientific notation is used.
2638 * @return TRUE if this object formats and parses scientific notation
2639 * @see #setScientificNotation
2640 * @see #getMinimumExponentDigits
2641 * @see #setMinimumExponentDigits
2642 * @see #isExponentSignAlwaysShown
2643 * @see #setExponentSignAlwaysShown
2644 */
2645UBool DecimalFormat::isScientificNotation() const {
2646    return fImpl->isScientificNotation();
2647}
2648
2649/**
2650 * Set whether or not scientific notation is used.
2651 * @param useScientific TRUE if this object formats and parses scientific
2652 * notation
2653 * @see #isScientificNotation
2654 * @see #getMinimumExponentDigits
2655 * @see #setMinimumExponentDigits
2656 * @see #isExponentSignAlwaysShown
2657 * @see #setExponentSignAlwaysShown
2658 */
2659void DecimalFormat::setScientificNotation(UBool useScientific) {
2660    fImpl->setScientificNotation(useScientific);
2661}
2662
2663/**
2664 * Return the minimum exponent digits that will be shown.
2665 * @return the minimum exponent digits that will be shown
2666 * @see #setScientificNotation
2667 * @see #isScientificNotation
2668 * @see #setMinimumExponentDigits
2669 * @see #isExponentSignAlwaysShown
2670 * @see #setExponentSignAlwaysShown
2671 */
2672int8_t DecimalFormat::getMinimumExponentDigits() const {
2673    return fImpl->getMinimumExponentDigits();
2674}
2675
2676/**
2677 * Set the minimum exponent digits that will be shown.  This has no
2678 * effect unless scientific notation is in use.
2679 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2680 * that will be shown.  Values less than 1 will be treated as 1.
2681 * @see #setScientificNotation
2682 * @see #isScientificNotation
2683 * @see #getMinimumExponentDigits
2684 * @see #isExponentSignAlwaysShown
2685 * @see #setExponentSignAlwaysShown
2686 */
2687void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
2688    int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
2689    fImpl->setMinimumExponentDigits(minExponentDigits);
2690}
2691
2692/**
2693 * Return whether the exponent sign is always shown.
2694 * @return TRUE if the exponent is always prefixed with either the
2695 * localized minus sign or the localized plus sign, false if only negative
2696 * exponents are prefixed with the localized minus sign.
2697 * @see #setScientificNotation
2698 * @see #isScientificNotation
2699 * @see #setMinimumExponentDigits
2700 * @see #getMinimumExponentDigits
2701 * @see #setExponentSignAlwaysShown
2702 */
2703UBool DecimalFormat::isExponentSignAlwaysShown() const {
2704    return fImpl->isExponentSignAlwaysShown();
2705}
2706
2707/**
2708 * Set whether the exponent sign is always shown.  This has no effect
2709 * unless scientific notation is in use.
2710 * @param expSignAlways TRUE if the exponent is always prefixed with either
2711 * the localized minus sign or the localized plus sign, false if only
2712 * negative exponents are prefixed with the localized minus sign.
2713 * @see #setScientificNotation
2714 * @see #isScientificNotation
2715 * @see #setMinimumExponentDigits
2716 * @see #getMinimumExponentDigits
2717 * @see #isExponentSignAlwaysShown
2718 */
2719void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
2720    fImpl->setExponentSignAlwaysShown(expSignAlways);
2721}
2722
2723//------------------------------------------------------------------------------
2724// Gets the grouping size of the number pattern.  For example, thousand or 10
2725// thousand groupings.
2726
2727int32_t
2728DecimalFormat::getGroupingSize() const
2729{
2730    return fImpl->getGroupingSize();
2731}
2732
2733//------------------------------------------------------------------------------
2734// Gets the grouping size of the number pattern.
2735
2736void
2737DecimalFormat::setGroupingSize(int32_t newValue)
2738{
2739    fImpl->setGroupingSize(newValue);
2740}
2741
2742//------------------------------------------------------------------------------
2743
2744int32_t
2745DecimalFormat::getSecondaryGroupingSize() const
2746{
2747    return fImpl->getSecondaryGroupingSize();
2748}
2749
2750//------------------------------------------------------------------------------
2751
2752void
2753DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
2754{
2755    fImpl->setSecondaryGroupingSize(newValue);
2756}
2757
2758//------------------------------------------------------------------------------
2759
2760int32_t
2761DecimalFormat::getMinimumGroupingDigits() const
2762{
2763    return fImpl->getMinimumGroupingDigits();
2764}
2765
2766//------------------------------------------------------------------------------
2767
2768void
2769DecimalFormat::setMinimumGroupingDigits(int32_t newValue)
2770{
2771    fImpl->setMinimumGroupingDigits(newValue);
2772}
2773
2774//------------------------------------------------------------------------------
2775// Checks if to show the decimal separator.
2776
2777UBool
2778DecimalFormat::isDecimalSeparatorAlwaysShown() const
2779{
2780    return fImpl->isDecimalSeparatorAlwaysShown();
2781}
2782
2783//------------------------------------------------------------------------------
2784// Sets to always show the decimal separator.
2785
2786void
2787DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
2788{
2789    fImpl->setDecimalSeparatorAlwaysShown(newValue);
2790}
2791
2792//------------------------------------------------------------------------------
2793// Checks if decimal point pattern match is required
2794UBool
2795DecimalFormat::isDecimalPatternMatchRequired(void) const
2796{
2797    return static_cast<UBool>(fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED));
2798}
2799
2800//------------------------------------------------------------------------------
2801// Checks if decimal point pattern match is required
2802
2803void
2804DecimalFormat::setDecimalPatternMatchRequired(UBool newValue)
2805{
2806    fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue);
2807}
2808
2809
2810//------------------------------------------------------------------------------
2811// Emits the pattern of this DecimalFormat instance.
2812
2813UnicodeString&
2814DecimalFormat::toPattern(UnicodeString& result) const
2815{
2816    return fImpl->toPattern(result);
2817}
2818
2819//------------------------------------------------------------------------------
2820// Emits the localized pattern this DecimalFormat instance.
2821
2822UnicodeString&
2823DecimalFormat::toLocalizedPattern(UnicodeString& result) const
2824{
2825    // toLocalizedPattern is deprecated, so we just make it the same as
2826    // toPattern.
2827    return fImpl->toPattern(result);
2828}
2829
2830//------------------------------------------------------------------------------
2831
2832void
2833DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
2834{
2835    if (pattern.indexOf(kCurrencySign) != -1) {
2836        handleCurrencySignInPattern(status);
2837    }
2838    fImpl->applyPattern(pattern, status);
2839}
2840
2841//------------------------------------------------------------------------------
2842
2843void
2844DecimalFormat::applyPattern(const UnicodeString& pattern,
2845                            UParseError& parseError,
2846                            UErrorCode& status)
2847{
2848    if (pattern.indexOf(kCurrencySign) != -1) {
2849        handleCurrencySignInPattern(status);
2850    }
2851    fImpl->applyPattern(pattern, parseError, status);
2852}
2853//------------------------------------------------------------------------------
2854
2855void
2856DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
2857{
2858    if (pattern.indexOf(kCurrencySign) != -1) {
2859        handleCurrencySignInPattern(status);
2860    }
2861    fImpl->applyLocalizedPattern(pattern, status);
2862}
2863
2864//------------------------------------------------------------------------------
2865
2866void
2867DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
2868                                     UParseError& parseError,
2869                                     UErrorCode& status)
2870{
2871    if (pattern.indexOf(kCurrencySign) != -1) {
2872        handleCurrencySignInPattern(status);
2873    }
2874    fImpl->applyLocalizedPattern(pattern, parseError, status);
2875}
2876
2877//------------------------------------------------------------------------------
2878
2879/**
2880 * Sets the maximum number of digits allowed in the integer portion of a
2881 * number.
2882 * @see NumberFormat#setMaximumIntegerDigits
2883 */
2884void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
2885    newValue = _min(newValue, gDefaultMaxIntegerDigits);
2886    NumberFormat::setMaximumIntegerDigits(newValue);
2887    fImpl->updatePrecision();
2888}
2889
2890/**
2891 * Sets the minimum number of digits allowed in the integer portion of a
2892 * number. This override limits the integer digit count to 309.
2893 * @see NumberFormat#setMinimumIntegerDigits
2894 */
2895void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
2896    newValue = _min(newValue, kDoubleIntegerDigits);
2897    NumberFormat::setMinimumIntegerDigits(newValue);
2898    fImpl->updatePrecision();
2899}
2900
2901/**
2902 * Sets the maximum number of digits allowed in the fraction portion of a
2903 * number. This override limits the fraction digit count to 340.
2904 * @see NumberFormat#setMaximumFractionDigits
2905 */
2906void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
2907    newValue = _min(newValue, kDoubleFractionDigits);
2908    NumberFormat::setMaximumFractionDigits(newValue);
2909    fImpl->updatePrecision();
2910}
2911
2912/**
2913 * Sets the minimum number of digits allowed in the fraction portion of a
2914 * number. This override limits the fraction digit count to 340.
2915 * @see NumberFormat#setMinimumFractionDigits
2916 */
2917void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
2918    newValue = _min(newValue, kDoubleFractionDigits);
2919    NumberFormat::setMinimumFractionDigits(newValue);
2920    fImpl->updatePrecision();
2921}
2922
2923int32_t DecimalFormat::getMinimumSignificantDigits() const {
2924    return fImpl->getMinimumSignificantDigits();
2925}
2926
2927int32_t DecimalFormat::getMaximumSignificantDigits() const {
2928    return fImpl->getMaximumSignificantDigits();
2929}
2930
2931void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
2932    if (min < 1) {
2933        min = 1;
2934    }
2935    // pin max sig dig to >= min
2936    int32_t max = _max(fImpl->fMaxSigDigits, min);
2937    fImpl->setMinMaxSignificantDigits(min, max);
2938}
2939
2940void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
2941    if (max < 1) {
2942        max = 1;
2943    }
2944    // pin min sig dig to 1..max
2945    U_ASSERT(fImpl->fMinSigDigits >= 1);
2946    int32_t min = _min(fImpl->fMinSigDigits, max);
2947    fImpl->setMinMaxSignificantDigits(min, max);
2948}
2949
2950UBool DecimalFormat::areSignificantDigitsUsed() const {
2951    return fImpl->areSignificantDigitsUsed();
2952}
2953
2954void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
2955    fImpl->setSignificantDigitsUsed(useSignificantDigits);
2956}
2957
2958void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
2959    // set the currency before compute affixes to get the right currency names
2960    NumberFormat::setCurrency(theCurrency, ec);
2961    fImpl->updateCurrency(ec);
2962}
2963
2964void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){
2965    fImpl->setCurrencyUsage(newContext, *ec);
2966}
2967
2968UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
2969    return fImpl->getCurrencyUsage();
2970}
2971
2972// Deprecated variant with no UErrorCode parameter
2973void DecimalFormat::setCurrency(const UChar* theCurrency) {
2974    UErrorCode ec = U_ZERO_ERROR;
2975    setCurrency(theCurrency, ec);
2976}
2977
2978void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
2979    if (fImpl->fSymbols == NULL) {
2980        ec = U_MEMORY_ALLOCATION_ERROR;
2981        return;
2982    }
2983    ec = U_ZERO_ERROR;
2984    const UChar* c = getCurrency();
2985    if (*c == 0) {
2986        const UnicodeString &intl =
2987            fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
2988        c = intl.getBuffer(); // ok for intl to go out of scope
2989    }
2990    u_strncpy(result, c, 3);
2991    result[3] = 0;
2992}
2993
2994Hashtable*
2995DecimalFormat::initHashForAffixPattern(UErrorCode& status) {
2996    if ( U_FAILURE(status) ) {
2997        return NULL;
2998    }
2999    Hashtable* hTable;
3000    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
3001        status = U_MEMORY_ALLOCATION_ERROR;
3002        return NULL;
3003    }
3004    if ( U_FAILURE(status) ) {
3005        delete hTable;
3006        return NULL;
3007    }
3008    hTable->setValueComparator(decimfmtAffixPatternValueComparator);
3009    return hTable;
3010}
3011
3012void
3013DecimalFormat::deleteHashForAffixPattern()
3014{
3015    if ( fAffixPatternsForCurrency == NULL ) {
3016        return;
3017    }
3018    int32_t pos = UHASH_FIRST;
3019    const UHashElement* element = NULL;
3020    while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
3021        const UHashTok valueTok = element->value;
3022        const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer;
3023        delete value;
3024    }
3025    delete fAffixPatternsForCurrency;
3026    fAffixPatternsForCurrency = NULL;
3027}
3028
3029
3030void
3031DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
3032                                       Hashtable* target,
3033                                       UErrorCode& status) {
3034    if ( U_FAILURE(status) ) {
3035        return;
3036    }
3037    int32_t pos = UHASH_FIRST;
3038    const UHashElement* element = NULL;
3039    if ( source ) {
3040        while ( (element = source->nextElement(pos)) != NULL ) {
3041            const UHashTok keyTok = element->key;
3042            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
3043            const UHashTok valueTok = element->value;
3044            const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer;
3045            AffixPatternsForCurrency* copy = new AffixPatternsForCurrency(
3046                value->negPrefixPatternForCurrency,
3047                value->negSuffixPatternForCurrency,
3048                value->posPrefixPatternForCurrency,
3049                value->posSuffixPatternForCurrency,
3050                value->patternType);
3051            target->put(UnicodeString(*key), copy, status);
3052            if ( U_FAILURE(status) ) {
3053                return;
3054            }
3055        }
3056    }
3057}
3058
3059void
3060DecimalFormat::setGroupingUsed(UBool newValue) {
3061  NumberFormat::setGroupingUsed(newValue);
3062  fImpl->updateGrouping();
3063}
3064
3065void
3066DecimalFormat::setParseIntegerOnly(UBool newValue) {
3067  NumberFormat::setParseIntegerOnly(newValue);
3068}
3069
3070void
3071DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {
3072  NumberFormat::setContext(value, status);
3073}
3074
3075DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
3076                                            int32_t newValue,
3077                                            UErrorCode &status) {
3078  if(U_FAILURE(status)) return *this;
3079
3080  switch(attr) {
3081  case UNUM_LENIENT_PARSE:
3082    setLenient(newValue!=0);
3083    break;
3084
3085    case UNUM_PARSE_INT_ONLY:
3086      setParseIntegerOnly(newValue!=0);
3087      break;
3088
3089    case UNUM_GROUPING_USED:
3090      setGroupingUsed(newValue!=0);
3091      break;
3092
3093    case UNUM_DECIMAL_ALWAYS_SHOWN:
3094      setDecimalSeparatorAlwaysShown(newValue!=0);
3095        break;
3096
3097    case UNUM_MAX_INTEGER_DIGITS:
3098      setMaximumIntegerDigits(newValue);
3099        break;
3100
3101    case UNUM_MIN_INTEGER_DIGITS:
3102      setMinimumIntegerDigits(newValue);
3103        break;
3104
3105    case UNUM_INTEGER_DIGITS:
3106      setMinimumIntegerDigits(newValue);
3107      setMaximumIntegerDigits(newValue);
3108        break;
3109
3110    case UNUM_MAX_FRACTION_DIGITS:
3111      setMaximumFractionDigits(newValue);
3112        break;
3113
3114    case UNUM_MIN_FRACTION_DIGITS:
3115      setMinimumFractionDigits(newValue);
3116        break;
3117
3118    case UNUM_FRACTION_DIGITS:
3119      setMinimumFractionDigits(newValue);
3120      setMaximumFractionDigits(newValue);
3121      break;
3122
3123    case UNUM_SIGNIFICANT_DIGITS_USED:
3124      setSignificantDigitsUsed(newValue!=0);
3125        break;
3126
3127    case UNUM_MAX_SIGNIFICANT_DIGITS:
3128      setMaximumSignificantDigits(newValue);
3129        break;
3130
3131    case UNUM_MIN_SIGNIFICANT_DIGITS:
3132      setMinimumSignificantDigits(newValue);
3133        break;
3134
3135    case UNUM_MULTIPLIER:
3136      setMultiplier(newValue);
3137       break;
3138
3139    case UNUM_GROUPING_SIZE:
3140      setGroupingSize(newValue);
3141        break;
3142
3143    case UNUM_ROUNDING_MODE:
3144      setRoundingMode((DecimalFormat::ERoundingMode)newValue);
3145        break;
3146
3147    case UNUM_FORMAT_WIDTH:
3148      setFormatWidth(newValue);
3149        break;
3150
3151    case UNUM_PADDING_POSITION:
3152        /** The position at which padding will take place. */
3153      setPadPosition((DecimalFormat::EPadPosition)newValue);
3154        break;
3155
3156    case UNUM_SECONDARY_GROUPING_SIZE:
3157      setSecondaryGroupingSize(newValue);
3158        break;
3159
3160#if UCONFIG_HAVE_PARSEALLINPUT
3161    case UNUM_PARSE_ALL_INPUT:
3162      setParseAllInput((UNumberFormatAttributeValue)newValue);
3163        break;
3164#endif
3165
3166    /* These are stored in fBoolFlags */
3167    case UNUM_PARSE_NO_EXPONENT:
3168    case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
3169    case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
3170      if(!fBoolFlags.isValidValue(newValue)) {
3171          status = U_ILLEGAL_ARGUMENT_ERROR;
3172      } else {
3173          if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) {
3174              fImpl->setFailIfMoreThanMaxDigits((UBool) newValue);
3175          }
3176          fBoolFlags.set(attr, newValue);
3177      }
3178      break;
3179
3180    case UNUM_SCALE:
3181        fImpl->setScale(newValue);
3182        break;
3183
3184    case UNUM_CURRENCY_USAGE:
3185        setCurrencyUsage((UCurrencyUsage)newValue, &status);
3186        break;
3187
3188    case UNUM_MINIMUM_GROUPING_DIGITS:
3189        setMinimumGroupingDigits(newValue);
3190        break;
3191
3192    default:
3193      status = U_UNSUPPORTED_ERROR;
3194      break;
3195  }
3196  return *this;
3197}
3198
3199int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
3200                                     UErrorCode &status ) const {
3201  if(U_FAILURE(status)) return -1;
3202  switch(attr) {
3203    case UNUM_LENIENT_PARSE:
3204        return isLenient();
3205
3206    case UNUM_PARSE_INT_ONLY:
3207        return isParseIntegerOnly();
3208
3209    case UNUM_GROUPING_USED:
3210        return isGroupingUsed();
3211
3212    case UNUM_DECIMAL_ALWAYS_SHOWN:
3213        return isDecimalSeparatorAlwaysShown();
3214
3215    case UNUM_MAX_INTEGER_DIGITS:
3216        return getMaximumIntegerDigits();
3217
3218    case UNUM_MIN_INTEGER_DIGITS:
3219        return getMinimumIntegerDigits();
3220
3221    case UNUM_INTEGER_DIGITS:
3222        // TBD: what should this return?
3223        return getMinimumIntegerDigits();
3224
3225    case UNUM_MAX_FRACTION_DIGITS:
3226        return getMaximumFractionDigits();
3227
3228    case UNUM_MIN_FRACTION_DIGITS:
3229        return getMinimumFractionDigits();
3230
3231    case UNUM_FRACTION_DIGITS:
3232        // TBD: what should this return?
3233        return getMinimumFractionDigits();
3234
3235    case UNUM_SIGNIFICANT_DIGITS_USED:
3236        return areSignificantDigitsUsed();
3237
3238    case UNUM_MAX_SIGNIFICANT_DIGITS:
3239        return getMaximumSignificantDigits();
3240
3241    case UNUM_MIN_SIGNIFICANT_DIGITS:
3242        return getMinimumSignificantDigits();
3243
3244    case UNUM_MULTIPLIER:
3245        return getMultiplier();
3246
3247    case UNUM_GROUPING_SIZE:
3248        return getGroupingSize();
3249
3250    case UNUM_ROUNDING_MODE:
3251        return getRoundingMode();
3252
3253    case UNUM_FORMAT_WIDTH:
3254        return getFormatWidth();
3255
3256    case UNUM_PADDING_POSITION:
3257        return getPadPosition();
3258
3259    case UNUM_SECONDARY_GROUPING_SIZE:
3260        return getSecondaryGroupingSize();
3261
3262    /* These are stored in fBoolFlags */
3263    case UNUM_PARSE_NO_EXPONENT:
3264    case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
3265    case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
3266      return fBoolFlags.get(attr);
3267
3268    case UNUM_SCALE:
3269        return fImpl->fScale;
3270
3271    case UNUM_CURRENCY_USAGE:
3272        return fImpl->getCurrencyUsage();
3273
3274    case UNUM_MINIMUM_GROUPING_DIGITS:
3275        return getMinimumGroupingDigits();
3276
3277    default:
3278        status = U_UNSUPPORTED_ERROR;
3279        break;
3280  }
3281
3282  return -1; /* undefined */
3283}
3284
3285#if UCONFIG_HAVE_PARSEALLINPUT
3286void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
3287  fParseAllInput = value;
3288}
3289#endif
3290
3291U_NAMESPACE_END
3292
3293#endif /* #if !UCONFIG_NO_FORMATTING */
3294
3295//eof
3296