LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - decimfmt.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1312 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 140 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13