1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/decimfmt.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,5990 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 1997-2013, International Business Machines Corporation and * 1.7 +* others. All Rights Reserved. * 1.8 +******************************************************************************* 1.9 +* 1.10 +* File DECIMFMT.CPP 1.11 +* 1.12 +* Modification History: 1.13 +* 1.14 +* Date Name Description 1.15 +* 02/19/97 aliu Converted from java. 1.16 +* 03/20/97 clhuang Implemented with new APIs. 1.17 +* 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it. 1.18 +* 04/3/97 aliu Rewrote parsing and formatting completely, and 1.19 +* cleaned up and debugged. Actually works now. 1.20 +* Implemented NAN and INF handling, for both parsing 1.21 +* and formatting. Extensive testing & debugging. 1.22 +* 04/10/97 aliu Modified to compile on AIX. 1.23 +* 04/16/97 aliu Rewrote to use DigitList, which has been resurrected. 1.24 +* Changed DigitCount to int per code review. 1.25 +* 07/09/97 helena Made ParsePosition into a class. 1.26 +* 08/26/97 aliu Extensive changes to applyPattern; completely 1.27 +* rewritten from the Java. 1.28 +* 09/09/97 aliu Ported over support for exponential formats. 1.29 +* 07/20/98 stephen JDK 1.2 sync up. 1.30 +* Various instances of '0' replaced with 'NULL' 1.31 +* Check for grouping size in subFormat() 1.32 +* Brought subParse() in line with Java 1.2 1.33 +* Added method appendAffix() 1.34 +* 08/24/1998 srl Removed Mutex calls. This is not a thread safe class! 1.35 +* 02/22/99 stephen Removed character literals for EBCDIC safety 1.36 +* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes 1.37 +* 06/28/99 stephen Fixed bugs in toPattern(). 1.38 +* 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad, 1.39 +* fPadPosition 1.40 +******************************************************************************** 1.41 +*/ 1.42 + 1.43 +#include "unicode/utypes.h" 1.44 + 1.45 +#if !UCONFIG_NO_FORMATTING 1.46 + 1.47 +#include "fphdlimp.h" 1.48 +#include "unicode/decimfmt.h" 1.49 +#include "unicode/choicfmt.h" 1.50 +#include "unicode/ucurr.h" 1.51 +#include "unicode/ustring.h" 1.52 +#include "unicode/dcfmtsym.h" 1.53 +#include "unicode/ures.h" 1.54 +#include "unicode/uchar.h" 1.55 +#include "unicode/uniset.h" 1.56 +#include "unicode/curramt.h" 1.57 +#include "unicode/currpinf.h" 1.58 +#include "unicode/plurrule.h" 1.59 +#include "unicode/utf16.h" 1.60 +#include "unicode/numsys.h" 1.61 +#include "unicode/localpointer.h" 1.62 +#include "uresimp.h" 1.63 +#include "ucurrimp.h" 1.64 +#include "charstr.h" 1.65 +#include "cmemory.h" 1.66 +#include "patternprops.h" 1.67 +#include "digitlst.h" 1.68 +#include "cstring.h" 1.69 +#include "umutex.h" 1.70 +#include "uassert.h" 1.71 +#include "putilimp.h" 1.72 +#include <math.h> 1.73 +#include "hash.h" 1.74 +#include "decfmtst.h" 1.75 +#include "dcfmtimp.h" 1.76 +#include "plurrule_impl.h" 1.77 + 1.78 +/* 1.79 + * On certain platforms, round is a macro defined in math.h 1.80 + * This undefine is to avoid conflict between the macro and 1.81 + * the function defined below. 1.82 + */ 1.83 +#ifdef round 1.84 +#undef round 1.85 +#endif 1.86 + 1.87 + 1.88 +U_NAMESPACE_BEGIN 1.89 + 1.90 +#ifdef FMT_DEBUG 1.91 +#include <stdio.h> 1.92 +static void _debugout(const char *f, int l, const UnicodeString& s) { 1.93 + char buf[2000]; 1.94 + s.extract((int32_t) 0, s.length(), buf, "utf-8"); 1.95 + printf("%s:%d: %s\n", f,l, buf); 1.96 +} 1.97 +#define debugout(x) _debugout(__FILE__,__LINE__,x) 1.98 +#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); 1.99 +static const UnicodeString dbg_null("<NULL>",""); 1.100 +#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) 1.101 +#else 1.102 +#define debugout(x) 1.103 +#define debug(x) 1.104 +#endif 1.105 + 1.106 + 1.107 + 1.108 +/* == Fastpath calculation. == 1.109 + */ 1.110 +#if UCONFIG_FORMAT_FASTPATHS_49 1.111 +inline DecimalFormatInternal& internalData(uint8_t *reserved) { 1.112 + return *reinterpret_cast<DecimalFormatInternal*>(reserved); 1.113 +} 1.114 +inline const DecimalFormatInternal& internalData(const uint8_t *reserved) { 1.115 + return *reinterpret_cast<const DecimalFormatInternal*>(reserved); 1.116 +} 1.117 +#else 1.118 +#endif 1.119 + 1.120 +/* For currency parsing purose, 1.121 + * Need to remember all prefix patterns and suffix patterns of 1.122 + * every currency format pattern, 1.123 + * including the pattern of default currecny style 1.124 + * and plural currency style. And the patterns are set through applyPattern. 1.125 + */ 1.126 +struct AffixPatternsForCurrency : public UMemory { 1.127 + // negative prefix pattern 1.128 + UnicodeString negPrefixPatternForCurrency; 1.129 + // negative suffix pattern 1.130 + UnicodeString negSuffixPatternForCurrency; 1.131 + // positive prefix pattern 1.132 + UnicodeString posPrefixPatternForCurrency; 1.133 + // positive suffix pattern 1.134 + UnicodeString posSuffixPatternForCurrency; 1.135 + int8_t patternType; 1.136 + 1.137 + AffixPatternsForCurrency(const UnicodeString& negPrefix, 1.138 + const UnicodeString& negSuffix, 1.139 + const UnicodeString& posPrefix, 1.140 + const UnicodeString& posSuffix, 1.141 + int8_t type) { 1.142 + negPrefixPatternForCurrency = negPrefix; 1.143 + negSuffixPatternForCurrency = negSuffix; 1.144 + posPrefixPatternForCurrency = posPrefix; 1.145 + posSuffixPatternForCurrency = posSuffix; 1.146 + patternType = type; 1.147 + } 1.148 +#ifdef FMT_DEBUG 1.149 + void dump() const { 1.150 + debugout( UnicodeString("AffixPatternsForCurrency( -=\"") + 1.151 + negPrefixPatternForCurrency + (UnicodeString)"\"/\"" + 1.152 + negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" + 1.153 + posPrefixPatternForCurrency + (UnicodeString)"\"/\"" + 1.154 + posSuffixPatternForCurrency + (UnicodeString)"\" )"); 1.155 + } 1.156 +#endif 1.157 +}; 1.158 + 1.159 +/* affix for currency formatting when the currency sign in the pattern 1.160 + * equals to 3, such as the pattern contains 3 currency sign or 1.161 + * the formatter style is currency plural format style. 1.162 + */ 1.163 +struct AffixesForCurrency : public UMemory { 1.164 + // negative prefix 1.165 + UnicodeString negPrefixForCurrency; 1.166 + // negative suffix 1.167 + UnicodeString negSuffixForCurrency; 1.168 + // positive prefix 1.169 + UnicodeString posPrefixForCurrency; 1.170 + // positive suffix 1.171 + UnicodeString posSuffixForCurrency; 1.172 + 1.173 + int32_t formatWidth; 1.174 + 1.175 + AffixesForCurrency(const UnicodeString& negPrefix, 1.176 + const UnicodeString& negSuffix, 1.177 + const UnicodeString& posPrefix, 1.178 + const UnicodeString& posSuffix) { 1.179 + negPrefixForCurrency = negPrefix; 1.180 + negSuffixForCurrency = negSuffix; 1.181 + posPrefixForCurrency = posPrefix; 1.182 + posSuffixForCurrency = posSuffix; 1.183 + } 1.184 +#ifdef FMT_DEBUG 1.185 + void dump() const { 1.186 + debugout( UnicodeString("AffixesForCurrency( -=\"") + 1.187 + negPrefixForCurrency + (UnicodeString)"\"/\"" + 1.188 + negSuffixForCurrency + (UnicodeString)"\" +=\"" + 1.189 + posPrefixForCurrency + (UnicodeString)"\"/\"" + 1.190 + posSuffixForCurrency + (UnicodeString)"\" )"); 1.191 + } 1.192 +#endif 1.193 +}; 1.194 + 1.195 +U_CDECL_BEGIN 1.196 + 1.197 +/** 1.198 + * @internal ICU 4.2 1.199 + */ 1.200 +static UBool U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2); 1.201 + 1.202 +/** 1.203 + * @internal ICU 4.2 1.204 + */ 1.205 +static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2); 1.206 + 1.207 + 1.208 +static UBool 1.209 +U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2) { 1.210 + const AffixesForCurrency* affix_1 = 1.211 + (AffixesForCurrency*)val1.pointer; 1.212 + const AffixesForCurrency* affix_2 = 1.213 + (AffixesForCurrency*)val2.pointer; 1.214 + return affix_1->negPrefixForCurrency == affix_2->negPrefixForCurrency && 1.215 + affix_1->negSuffixForCurrency == affix_2->negSuffixForCurrency && 1.216 + affix_1->posPrefixForCurrency == affix_2->posPrefixForCurrency && 1.217 + affix_1->posSuffixForCurrency == affix_2->posSuffixForCurrency; 1.218 +} 1.219 + 1.220 + 1.221 +static UBool 1.222 +U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) { 1.223 + const AffixPatternsForCurrency* affix_1 = 1.224 + (AffixPatternsForCurrency*)val1.pointer; 1.225 + const AffixPatternsForCurrency* affix_2 = 1.226 + (AffixPatternsForCurrency*)val2.pointer; 1.227 + return affix_1->negPrefixPatternForCurrency == 1.228 + affix_2->negPrefixPatternForCurrency && 1.229 + affix_1->negSuffixPatternForCurrency == 1.230 + affix_2->negSuffixPatternForCurrency && 1.231 + affix_1->posPrefixPatternForCurrency == 1.232 + affix_2->posPrefixPatternForCurrency && 1.233 + affix_1->posSuffixPatternForCurrency == 1.234 + affix_2->posSuffixPatternForCurrency && 1.235 + affix_1->patternType == affix_2->patternType; 1.236 +} 1.237 + 1.238 +U_CDECL_END 1.239 + 1.240 + 1.241 + 1.242 + 1.243 +// ***************************************************************************** 1.244 +// class DecimalFormat 1.245 +// ***************************************************************************** 1.246 + 1.247 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat) 1.248 + 1.249 +// Constants for characters used in programmatic (unlocalized) patterns. 1.250 +#define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ 1.251 +#define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ 1.252 +#define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ 1.253 +#define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ 1.254 +#define kPatternPerMill ((UChar)0x2030) 1.255 +#define kPatternPercent ((UChar)0x0025) /*'%'*/ 1.256 +#define kPatternDigit ((UChar)0x0023) /*'#'*/ 1.257 +#define kPatternSeparator ((UChar)0x003B) /*';'*/ 1.258 +#define kPatternExponent ((UChar)0x0045) /*'E'*/ 1.259 +#define kPatternPlus ((UChar)0x002B) /*'+'*/ 1.260 +#define kPatternMinus ((UChar)0x002D) /*'-'*/ 1.261 +#define kPatternPadEscape ((UChar)0x002A) /*'*'*/ 1.262 +#define kQuote ((UChar)0x0027) /*'\''*/ 1.263 +/** 1.264 + * The CURRENCY_SIGN is the standard Unicode symbol for currency. It 1.265 + * is used in patterns and substitued with either the currency symbol, 1.266 + * or if it is doubled, with the international currency symbol. If the 1.267 + * CURRENCY_SIGN is seen in a pattern, then the decimal separator is 1.268 + * replaced with the monetary decimal separator. 1.269 + */ 1.270 +#define kCurrencySign ((UChar)0x00A4) 1.271 +#define kDefaultPad ((UChar)0x0020) /* */ 1.272 + 1.273 +const int32_t DecimalFormat::kDoubleIntegerDigits = 309; 1.274 +const int32_t DecimalFormat::kDoubleFractionDigits = 340; 1.275 + 1.276 +const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8; 1.277 + 1.278 +/** 1.279 + * These are the tags we expect to see in normal resource bundle files associated 1.280 + * with a locale. 1.281 + */ 1.282 +const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used 1.283 +static const char fgNumberElements[]="NumberElements"; 1.284 +static const char fgLatn[]="latn"; 1.285 +static const char fgPatterns[]="patterns"; 1.286 +static const char fgDecimalFormat[]="decimalFormat"; 1.287 +static const char fgCurrencyFormat[]="currencyFormat"; 1.288 + 1.289 +static const UChar fgTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0}; 1.290 + 1.291 +inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; } 1.292 +inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; } 1.293 + 1.294 +//------------------------------------------------------------------------------ 1.295 +// Constructs a DecimalFormat instance in the default locale. 1.296 + 1.297 +DecimalFormat::DecimalFormat(UErrorCode& status) { 1.298 + init(); 1.299 + UParseError parseError; 1.300 + construct(status, parseError); 1.301 +} 1.302 + 1.303 +//------------------------------------------------------------------------------ 1.304 +// Constructs a DecimalFormat instance with the specified number format 1.305 +// pattern in the default locale. 1.306 + 1.307 +DecimalFormat::DecimalFormat(const UnicodeString& pattern, 1.308 + UErrorCode& status) { 1.309 + init(); 1.310 + UParseError parseError; 1.311 + construct(status, parseError, &pattern); 1.312 +} 1.313 + 1.314 +//------------------------------------------------------------------------------ 1.315 +// Constructs a DecimalFormat instance with the specified number format 1.316 +// pattern and the number format symbols in the default locale. The 1.317 +// created instance owns the symbols. 1.318 + 1.319 +DecimalFormat::DecimalFormat(const UnicodeString& pattern, 1.320 + DecimalFormatSymbols* symbolsToAdopt, 1.321 + UErrorCode& status) { 1.322 + init(); 1.323 + UParseError parseError; 1.324 + if (symbolsToAdopt == NULL) 1.325 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.326 + construct(status, parseError, &pattern, symbolsToAdopt); 1.327 +} 1.328 + 1.329 +DecimalFormat::DecimalFormat( const UnicodeString& pattern, 1.330 + DecimalFormatSymbols* symbolsToAdopt, 1.331 + UParseError& parseErr, 1.332 + UErrorCode& status) { 1.333 + init(); 1.334 + if (symbolsToAdopt == NULL) 1.335 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.336 + construct(status,parseErr, &pattern, symbolsToAdopt); 1.337 +} 1.338 + 1.339 +//------------------------------------------------------------------------------ 1.340 +// Constructs a DecimalFormat instance with the specified number format 1.341 +// pattern and the number format symbols in the default locale. The 1.342 +// created instance owns the clone of the symbols. 1.343 + 1.344 +DecimalFormat::DecimalFormat(const UnicodeString& pattern, 1.345 + const DecimalFormatSymbols& symbols, 1.346 + UErrorCode& status) { 1.347 + init(); 1.348 + UParseError parseError; 1.349 + construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols)); 1.350 +} 1.351 + 1.352 +//------------------------------------------------------------------------------ 1.353 +// Constructs a DecimalFormat instance with the specified number format 1.354 +// pattern, the number format symbols, and the number format style. 1.355 +// The created instance owns the clone of the symbols. 1.356 + 1.357 +DecimalFormat::DecimalFormat(const UnicodeString& pattern, 1.358 + DecimalFormatSymbols* symbolsToAdopt, 1.359 + UNumberFormatStyle style, 1.360 + UErrorCode& status) { 1.361 + init(); 1.362 + fStyle = style; 1.363 + UParseError parseError; 1.364 + construct(status, parseError, &pattern, symbolsToAdopt); 1.365 +} 1.366 + 1.367 +//----------------------------------------------------------------------------- 1.368 +// Common DecimalFormat initialization. 1.369 +// Put all fields of an uninitialized object into a known state. 1.370 +// Common code, shared by all constructors. 1.371 +// Can not fail. Leave the object in good enough shape that the destructor 1.372 +// or assignment operator can run successfully. 1.373 +void 1.374 +DecimalFormat::init() { 1.375 + fPosPrefixPattern = 0; 1.376 + fPosSuffixPattern = 0; 1.377 + fNegPrefixPattern = 0; 1.378 + fNegSuffixPattern = 0; 1.379 + fCurrencyChoice = 0; 1.380 + fMultiplier = NULL; 1.381 + fScale = 0; 1.382 + fGroupingSize = 0; 1.383 + fGroupingSize2 = 0; 1.384 + fDecimalSeparatorAlwaysShown = FALSE; 1.385 + fSymbols = NULL; 1.386 + fUseSignificantDigits = FALSE; 1.387 + fMinSignificantDigits = 1; 1.388 + fMaxSignificantDigits = 6; 1.389 + fUseExponentialNotation = FALSE; 1.390 + fMinExponentDigits = 0; 1.391 + fExponentSignAlwaysShown = FALSE; 1.392 + fBoolFlags.clear(); 1.393 + fRoundingIncrement = 0; 1.394 + fRoundingMode = kRoundHalfEven; 1.395 + fPad = 0; 1.396 + fFormatWidth = 0; 1.397 + fPadPosition = kPadBeforePrefix; 1.398 + fStyle = UNUM_DECIMAL; 1.399 + fCurrencySignCount = fgCurrencySignCountZero; 1.400 + fAffixPatternsForCurrency = NULL; 1.401 + fAffixesForCurrency = NULL; 1.402 + fPluralAffixesForCurrency = NULL; 1.403 + fCurrencyPluralInfo = NULL; 1.404 +#if UCONFIG_HAVE_PARSEALLINPUT 1.405 + fParseAllInput = UNUM_MAYBE; 1.406 +#endif 1.407 + 1.408 +#if UCONFIG_FORMAT_FASTPATHS_49 1.409 + DecimalFormatInternal &data = internalData(fReserved); 1.410 + data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later. 1.411 + data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later. 1.412 +#endif 1.413 + fStaticSets = NULL; 1.414 +} 1.415 + 1.416 +//------------------------------------------------------------------------------ 1.417 +// Constructs a DecimalFormat instance with the specified number format 1.418 +// pattern and the number format symbols in the desired locale. The 1.419 +// created instance owns the symbols. 1.420 + 1.421 +void 1.422 +DecimalFormat::construct(UErrorCode& status, 1.423 + UParseError& parseErr, 1.424 + const UnicodeString* pattern, 1.425 + DecimalFormatSymbols* symbolsToAdopt) 1.426 +{ 1.427 + fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!! 1.428 + fRoundingIncrement = NULL; 1.429 + fRoundingMode = kRoundHalfEven; 1.430 + fPad = kPatternPadEscape; 1.431 + fPadPosition = kPadBeforePrefix; 1.432 + if (U_FAILURE(status)) 1.433 + return; 1.434 + 1.435 + fPosPrefixPattern = fPosSuffixPattern = NULL; 1.436 + fNegPrefixPattern = fNegSuffixPattern = NULL; 1.437 + setMultiplier(1); 1.438 + fGroupingSize = 3; 1.439 + fGroupingSize2 = 0; 1.440 + fDecimalSeparatorAlwaysShown = FALSE; 1.441 + fUseExponentialNotation = FALSE; 1.442 + fMinExponentDigits = 0; 1.443 + 1.444 + if (fSymbols == NULL) 1.445 + { 1.446 + fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status); 1.447 + if (fSymbols == 0) { 1.448 + status = U_MEMORY_ALLOCATION_ERROR; 1.449 + return; 1.450 + } 1.451 + } 1.452 + fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 1.453 + if (U_FAILURE(status)) { 1.454 + return; 1.455 + } 1.456 + UErrorCode nsStatus = U_ZERO_ERROR; 1.457 + NumberingSystem *ns = NumberingSystem::createInstance(nsStatus); 1.458 + if (U_FAILURE(nsStatus)) { 1.459 + status = nsStatus; 1.460 + return; 1.461 + } 1.462 + 1.463 + UnicodeString str; 1.464 + // Uses the default locale's number format pattern if there isn't 1.465 + // one specified. 1.466 + if (pattern == NULL) 1.467 + { 1.468 + int32_t len = 0; 1.469 + UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status); 1.470 + 1.471 + UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status); 1.472 + resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status); 1.473 + resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 1.474 + const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 1.475 + if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) { 1.476 + status = U_ZERO_ERROR; 1.477 + resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status); 1.478 + resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status); 1.479 + resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 1.480 + resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 1.481 + } 1.482 + str.setTo(TRUE, resStr, len); 1.483 + pattern = &str; 1.484 + ures_close(resource); 1.485 + ures_close(top); 1.486 + } 1.487 + 1.488 + delete ns; 1.489 + 1.490 + if (U_FAILURE(status)) 1.491 + { 1.492 + return; 1.493 + } 1.494 + 1.495 + if (pattern->indexOf((UChar)kCurrencySign) >= 0) { 1.496 + // If it looks like we are going to use a currency pattern 1.497 + // then do the time consuming lookup. 1.498 + setCurrencyForSymbols(); 1.499 + } else { 1.500 + setCurrencyInternally(NULL, status); 1.501 + } 1.502 + 1.503 + const UnicodeString* patternUsed; 1.504 + UnicodeString currencyPluralPatternForOther; 1.505 + // apply pattern 1.506 + if (fStyle == UNUM_CURRENCY_PLURAL) { 1.507 + fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status); 1.508 + if (U_FAILURE(status)) { 1.509 + return; 1.510 + } 1.511 + 1.512 + // the pattern used in format is not fixed until formatting, 1.513 + // in which, the number is known and 1.514 + // will be used to pick the right pattern based on plural count. 1.515 + // Here, set the pattern as the pattern of plural count == "other". 1.516 + // For most locale, the patterns are probably the same for all 1.517 + // plural count. If not, the right pattern need to be re-applied 1.518 + // during format. 1.519 + fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther); 1.520 + patternUsed = ¤cyPluralPatternForOther; 1.521 + // TODO: not needed? 1.522 + setCurrencyForSymbols(); 1.523 + 1.524 + } else { 1.525 + patternUsed = pattern; 1.526 + } 1.527 + 1.528 + if (patternUsed->indexOf(kCurrencySign) != -1) { 1.529 + // initialize for currency, not only for plural format, 1.530 + // but also for mix parsing 1.531 + if (fCurrencyPluralInfo == NULL) { 1.532 + fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status); 1.533 + if (U_FAILURE(status)) { 1.534 + return; 1.535 + } 1.536 + } 1.537 + // need it for mix parsing 1.538 + setupCurrencyAffixPatterns(status); 1.539 + // expanded affixes for plural names 1.540 + if (patternUsed->indexOf(fgTripleCurrencySign, 3, 0) != -1) { 1.541 + setupCurrencyAffixes(*patternUsed, TRUE, TRUE, status); 1.542 + } 1.543 + } 1.544 + 1.545 + applyPatternWithoutExpandAffix(*patternUsed,FALSE, parseErr, status); 1.546 + 1.547 + // expand affixes 1.548 + if (fCurrencySignCount != fgCurrencySignCountInPluralFormat) { 1.549 + expandAffixAdjustWidth(NULL); 1.550 + } 1.551 + 1.552 + // If it was a currency format, apply the appropriate rounding by 1.553 + // resetting the currency. NOTE: this copies fCurrency on top of itself. 1.554 + if (fCurrencySignCount != fgCurrencySignCountZero) { 1.555 + setCurrencyInternally(getCurrency(), status); 1.556 + } 1.557 +#if UCONFIG_FORMAT_FASTPATHS_49 1.558 + DecimalFormatInternal &data = internalData(fReserved); 1.559 + data.fFastFormatStatus = kFastpathNO; // allow it to be calculated 1.560 + data.fFastParseStatus = kFastpathNO; // allow it to be calculated 1.561 + handleChanged(); 1.562 +#endif 1.563 +} 1.564 + 1.565 + 1.566 +void 1.567 +DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) { 1.568 + if (U_FAILURE(status)) { 1.569 + return; 1.570 + } 1.571 + UParseError parseErr; 1.572 + fAffixPatternsForCurrency = initHashForAffixPattern(status); 1.573 + if (U_FAILURE(status)) { 1.574 + return; 1.575 + } 1.576 + 1.577 + NumberingSystem *ns = NumberingSystem::createInstance(fSymbols->getLocale(),status); 1.578 + if (U_FAILURE(status)) { 1.579 + return; 1.580 + } 1.581 + 1.582 + // Save the default currency patterns of this locale. 1.583 + // Here, chose onlyApplyPatternWithoutExpandAffix without 1.584 + // expanding the affix patterns into affixes. 1.585 + UnicodeString currencyPattern; 1.586 + UErrorCode error = U_ZERO_ERROR; 1.587 + 1.588 + UResourceBundle *resource = ures_open(NULL, fSymbols->getLocale().getName(), &error); 1.589 + UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error); 1.590 + resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error); 1.591 + resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); 1.592 + int32_t patLen = 0; 1.593 + const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 1.594 + if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) { 1.595 + error = U_ZERO_ERROR; 1.596 + resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error); 1.597 + resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); 1.598 + patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 1.599 + } 1.600 + ures_close(numElements); 1.601 + ures_close(resource); 1.602 + delete ns; 1.603 + 1.604 + if (U_SUCCESS(error)) { 1.605 + applyPatternWithoutExpandAffix(UnicodeString(patResStr, patLen), false, 1.606 + parseErr, status); 1.607 + AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 1.608 + *fNegPrefixPattern, 1.609 + *fNegSuffixPattern, 1.610 + *fPosPrefixPattern, 1.611 + *fPosSuffixPattern, 1.612 + UCURR_SYMBOL_NAME); 1.613 + fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status); 1.614 + } 1.615 + 1.616 + // save the unique currency plural patterns of this locale. 1.617 + Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern; 1.618 + const UHashElement* element = NULL; 1.619 + int32_t pos = -1; 1.620 + Hashtable pluralPatternSet; 1.621 + while ((element = pluralPtn->nextElement(pos)) != NULL) { 1.622 + const UHashTok valueTok = element->value; 1.623 + const UnicodeString* value = (UnicodeString*)valueTok.pointer; 1.624 + const UHashTok keyTok = element->key; 1.625 + const UnicodeString* key = (UnicodeString*)keyTok.pointer; 1.626 + if (pluralPatternSet.geti(*value) != 1) { 1.627 + pluralPatternSet.puti(*value, 1, status); 1.628 + applyPatternWithoutExpandAffix(*value, false, parseErr, status); 1.629 + AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 1.630 + *fNegPrefixPattern, 1.631 + *fNegSuffixPattern, 1.632 + *fPosPrefixPattern, 1.633 + *fPosSuffixPattern, 1.634 + UCURR_LONG_NAME); 1.635 + fAffixPatternsForCurrency->put(*key, affixPtn, status); 1.636 + } 1.637 + } 1.638 +} 1.639 + 1.640 + 1.641 +void 1.642 +DecimalFormat::setupCurrencyAffixes(const UnicodeString& pattern, 1.643 + UBool setupForCurrentPattern, 1.644 + UBool setupForPluralPattern, 1.645 + UErrorCode& status) { 1.646 + if (U_FAILURE(status)) { 1.647 + return; 1.648 + } 1.649 + UParseError parseErr; 1.650 + if (setupForCurrentPattern) { 1.651 + if (fAffixesForCurrency) { 1.652 + deleteHashForAffix(fAffixesForCurrency); 1.653 + } 1.654 + fAffixesForCurrency = initHashForAffix(status); 1.655 + if (U_SUCCESS(status)) { 1.656 + applyPatternWithoutExpandAffix(pattern, false, parseErr, status); 1.657 + const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules(); 1.658 + StringEnumeration* keywords = pluralRules->getKeywords(status); 1.659 + if (U_SUCCESS(status)) { 1.660 + const UnicodeString* pluralCount; 1.661 + while ((pluralCount = keywords->snext(status)) != NULL) { 1.662 + if ( U_SUCCESS(status) ) { 1.663 + expandAffixAdjustWidth(pluralCount); 1.664 + AffixesForCurrency* affix = new AffixesForCurrency( 1.665 + fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix); 1.666 + fAffixesForCurrency->put(*pluralCount, affix, status); 1.667 + } 1.668 + } 1.669 + } 1.670 + delete keywords; 1.671 + } 1.672 + } 1.673 + 1.674 + if (U_FAILURE(status)) { 1.675 + return; 1.676 + } 1.677 + 1.678 + if (setupForPluralPattern) { 1.679 + if (fPluralAffixesForCurrency) { 1.680 + deleteHashForAffix(fPluralAffixesForCurrency); 1.681 + } 1.682 + fPluralAffixesForCurrency = initHashForAffix(status); 1.683 + if (U_SUCCESS(status)) { 1.684 + const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules(); 1.685 + StringEnumeration* keywords = pluralRules->getKeywords(status); 1.686 + if (U_SUCCESS(status)) { 1.687 + const UnicodeString* pluralCount; 1.688 + while ((pluralCount = keywords->snext(status)) != NULL) { 1.689 + if ( U_SUCCESS(status) ) { 1.690 + UnicodeString ptn; 1.691 + fCurrencyPluralInfo->getCurrencyPluralPattern(*pluralCount, ptn); 1.692 + applyPatternInternally(*pluralCount, ptn, false, parseErr, status); 1.693 + AffixesForCurrency* affix = new AffixesForCurrency( 1.694 + fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix); 1.695 + fPluralAffixesForCurrency->put(*pluralCount, affix, status); 1.696 + } 1.697 + } 1.698 + } 1.699 + delete keywords; 1.700 + } 1.701 + } 1.702 +} 1.703 + 1.704 + 1.705 +//------------------------------------------------------------------------------ 1.706 + 1.707 +DecimalFormat::~DecimalFormat() 1.708 +{ 1.709 + delete fPosPrefixPattern; 1.710 + delete fPosSuffixPattern; 1.711 + delete fNegPrefixPattern; 1.712 + delete fNegSuffixPattern; 1.713 + delete fCurrencyChoice; 1.714 + delete fMultiplier; 1.715 + delete fSymbols; 1.716 + delete fRoundingIncrement; 1.717 + deleteHashForAffixPattern(); 1.718 + deleteHashForAffix(fAffixesForCurrency); 1.719 + deleteHashForAffix(fPluralAffixesForCurrency); 1.720 + delete fCurrencyPluralInfo; 1.721 +} 1.722 + 1.723 +//------------------------------------------------------------------------------ 1.724 +// copy constructor 1.725 + 1.726 +DecimalFormat::DecimalFormat(const DecimalFormat &source) : 1.727 + NumberFormat(source) { 1.728 + init(); 1.729 + *this = source; 1.730 +} 1.731 + 1.732 +//------------------------------------------------------------------------------ 1.733 +// assignment operator 1.734 + 1.735 +template <class T> 1.736 +static void _copy_ptr(T** pdest, const T* source) { 1.737 + if (source == NULL) { 1.738 + delete *pdest; 1.739 + *pdest = NULL; 1.740 + } else if (*pdest == NULL) { 1.741 + *pdest = new T(*source); 1.742 + } else { 1.743 + **pdest = *source; 1.744 + } 1.745 +} 1.746 + 1.747 +template <class T> 1.748 +static void _clone_ptr(T** pdest, const T* source) { 1.749 + delete *pdest; 1.750 + if (source == NULL) { 1.751 + *pdest = NULL; 1.752 + } else { 1.753 + *pdest = static_cast<T*>(source->clone()); 1.754 + } 1.755 +} 1.756 + 1.757 +DecimalFormat& 1.758 +DecimalFormat::operator=(const DecimalFormat& rhs) 1.759 +{ 1.760 + if(this != &rhs) { 1.761 + UErrorCode status = U_ZERO_ERROR; 1.762 + NumberFormat::operator=(rhs); 1.763 + fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 1.764 + fPositivePrefix = rhs.fPositivePrefix; 1.765 + fPositiveSuffix = rhs.fPositiveSuffix; 1.766 + fNegativePrefix = rhs.fNegativePrefix; 1.767 + fNegativeSuffix = rhs.fNegativeSuffix; 1.768 + _copy_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern); 1.769 + _copy_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern); 1.770 + _copy_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern); 1.771 + _copy_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern); 1.772 + _clone_ptr(&fCurrencyChoice, rhs.fCurrencyChoice); 1.773 + setRoundingIncrement(rhs.getRoundingIncrement()); 1.774 + fRoundingMode = rhs.fRoundingMode; 1.775 + setMultiplier(rhs.getMultiplier()); 1.776 + fGroupingSize = rhs.fGroupingSize; 1.777 + fGroupingSize2 = rhs.fGroupingSize2; 1.778 + fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown; 1.779 + _copy_ptr(&fSymbols, rhs.fSymbols); 1.780 + fUseExponentialNotation = rhs.fUseExponentialNotation; 1.781 + fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown; 1.782 + fBoolFlags = rhs.fBoolFlags; 1.783 + /*Bertrand A. D. Update 98.03.17*/ 1.784 + fCurrencySignCount = rhs.fCurrencySignCount; 1.785 + /*end of Update*/ 1.786 + fMinExponentDigits = rhs.fMinExponentDigits; 1.787 + 1.788 + /* sfb 990629 */ 1.789 + fFormatWidth = rhs.fFormatWidth; 1.790 + fPad = rhs.fPad; 1.791 + fPadPosition = rhs.fPadPosition; 1.792 + /* end sfb */ 1.793 + fMinSignificantDigits = rhs.fMinSignificantDigits; 1.794 + fMaxSignificantDigits = rhs.fMaxSignificantDigits; 1.795 + fUseSignificantDigits = rhs.fUseSignificantDigits; 1.796 + fFormatPattern = rhs.fFormatPattern; 1.797 + fStyle = rhs.fStyle; 1.798 + fCurrencySignCount = rhs.fCurrencySignCount; 1.799 + _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo); 1.800 + deleteHashForAffixPattern(); 1.801 + if (rhs.fAffixPatternsForCurrency) { 1.802 + UErrorCode status = U_ZERO_ERROR; 1.803 + fAffixPatternsForCurrency = initHashForAffixPattern(status); 1.804 + copyHashForAffixPattern(rhs.fAffixPatternsForCurrency, 1.805 + fAffixPatternsForCurrency, status); 1.806 + } 1.807 + deleteHashForAffix(fAffixesForCurrency); 1.808 + if (rhs.fAffixesForCurrency) { 1.809 + UErrorCode status = U_ZERO_ERROR; 1.810 + fAffixesForCurrency = initHashForAffixPattern(status); 1.811 + copyHashForAffix(rhs.fAffixesForCurrency, fAffixesForCurrency, status); 1.812 + } 1.813 + deleteHashForAffix(fPluralAffixesForCurrency); 1.814 + if (rhs.fPluralAffixesForCurrency) { 1.815 + UErrorCode status = U_ZERO_ERROR; 1.816 + fPluralAffixesForCurrency = initHashForAffixPattern(status); 1.817 + copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCurrency, status); 1.818 + } 1.819 + } 1.820 +#if UCONFIG_FORMAT_FASTPATHS_49 1.821 + handleChanged(); 1.822 +#endif 1.823 + return *this; 1.824 +} 1.825 + 1.826 +//------------------------------------------------------------------------------ 1.827 + 1.828 +UBool 1.829 +DecimalFormat::operator==(const Format& that) const 1.830 +{ 1.831 + if (this == &that) 1.832 + return TRUE; 1.833 + 1.834 + // NumberFormat::operator== guarantees this cast is safe 1.835 + const DecimalFormat* other = (DecimalFormat*)&that; 1.836 + 1.837 +#ifdef FMT_DEBUG 1.838 + // This code makes it easy to determine why two format objects that should 1.839 + // be equal aren't. 1.840 + UBool first = TRUE; 1.841 + if (!NumberFormat::operator==(that)) { 1.842 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.843 + debug("NumberFormat::!="); 1.844 + } else { 1.845 + if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null 1.846 + fPositivePrefix == other->fPositivePrefix) 1.847 + || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 && 1.848 + *fPosPrefixPattern == *other->fPosPrefixPattern))) { 1.849 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.850 + debug("Pos Prefix !="); 1.851 + } 1.852 + if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null 1.853 + fPositiveSuffix == other->fPositiveSuffix) 1.854 + || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 && 1.855 + *fPosSuffixPattern == *other->fPosSuffixPattern))) { 1.856 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.857 + debug("Pos Suffix !="); 1.858 + } 1.859 + if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null 1.860 + fNegativePrefix == other->fNegativePrefix) 1.861 + || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 && 1.862 + *fNegPrefixPattern == *other->fNegPrefixPattern))) { 1.863 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.864 + debug("Neg Prefix "); 1.865 + if (fNegPrefixPattern == NULL) { 1.866 + debug("NULL("); 1.867 + debugout(fNegativePrefix); 1.868 + debug(")"); 1.869 + } else { 1.870 + debugout(*fNegPrefixPattern); 1.871 + } 1.872 + debug(" != "); 1.873 + if (other->fNegPrefixPattern == NULL) { 1.874 + debug("NULL("); 1.875 + debugout(other->fNegativePrefix); 1.876 + debug(")"); 1.877 + } else { 1.878 + debugout(*other->fNegPrefixPattern); 1.879 + } 1.880 + } 1.881 + if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null 1.882 + fNegativeSuffix == other->fNegativeSuffix) 1.883 + || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 && 1.884 + *fNegSuffixPattern == *other->fNegSuffixPattern))) { 1.885 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.886 + debug("Neg Suffix "); 1.887 + if (fNegSuffixPattern == NULL) { 1.888 + debug("NULL("); 1.889 + debugout(fNegativeSuffix); 1.890 + debug(")"); 1.891 + } else { 1.892 + debugout(*fNegSuffixPattern); 1.893 + } 1.894 + debug(" != "); 1.895 + if (other->fNegSuffixPattern == NULL) { 1.896 + debug("NULL("); 1.897 + debugout(other->fNegativeSuffix); 1.898 + debug(")"); 1.899 + } else { 1.900 + debugout(*other->fNegSuffixPattern); 1.901 + } 1.902 + } 1.903 + if (!((fRoundingIncrement == other->fRoundingIncrement) // both null 1.904 + || (fRoundingIncrement != NULL && 1.905 + other->fRoundingIncrement != NULL && 1.906 + *fRoundingIncrement == *other->fRoundingIncrement))) { 1.907 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.908 + debug("Rounding Increment !="); 1.909 + } 1.910 + if (getMultiplier() != other->getMultiplier()) { 1.911 + if (first) { printf("[ "); first = FALSE; } 1.912 + printf("Multiplier %ld != %ld", getMultiplier(), other->getMultiplier()); 1.913 + } 1.914 + if (fGroupingSize != other->fGroupingSize) { 1.915 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.916 + printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize); 1.917 + } 1.918 + if (fGroupingSize2 != other->fGroupingSize2) { 1.919 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.920 + printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGroupingSize2); 1.921 + } 1.922 + if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) { 1.923 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.924 + printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown); 1.925 + } 1.926 + if (fUseExponentialNotation != other->fUseExponentialNotation) { 1.927 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.928 + debug("Use Exp !="); 1.929 + } 1.930 + if (!(!fUseExponentialNotation || 1.931 + fMinExponentDigits != other->fMinExponentDigits)) { 1.932 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.933 + debug("Exp Digits !="); 1.934 + } 1.935 + if (*fSymbols != *(other->fSymbols)) { 1.936 + if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1.937 + debug("Symbols !="); 1.938 + } 1.939 + // TODO Add debug stuff for significant digits here 1.940 + if (fUseSignificantDigits != other->fUseSignificantDigits) { 1.941 + debug("fUseSignificantDigits !="); 1.942 + } 1.943 + if (fUseSignificantDigits && 1.944 + fMinSignificantDigits != other->fMinSignificantDigits) { 1.945 + debug("fMinSignificantDigits !="); 1.946 + } 1.947 + if (fUseSignificantDigits && 1.948 + fMaxSignificantDigits != other->fMaxSignificantDigits) { 1.949 + debug("fMaxSignificantDigits !="); 1.950 + } 1.951 + 1.952 + if (!first) { printf(" ]"); } 1.953 + if (fCurrencySignCount != other->fCurrencySignCount) { 1.954 + debug("fCurrencySignCount !="); 1.955 + } 1.956 + if (fCurrencyPluralInfo == other->fCurrencyPluralInfo) { 1.957 + debug("fCurrencyPluralInfo == "); 1.958 + if (fCurrencyPluralInfo == NULL) { 1.959 + debug("fCurrencyPluralInfo == NULL"); 1.960 + } 1.961 + } 1.962 + if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL && 1.963 + *fCurrencyPluralInfo != *(other->fCurrencyPluralInfo)) { 1.964 + debug("fCurrencyPluralInfo !="); 1.965 + } 1.966 + if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo == NULL || 1.967 + fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo != NULL) { 1.968 + debug("fCurrencyPluralInfo one NULL, the other not"); 1.969 + } 1.970 + if (fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo == NULL) { 1.971 + debug("fCurrencyPluralInfo == "); 1.972 + } 1.973 + } 1.974 +#endif 1.975 + 1.976 + return (NumberFormat::operator==(that) && 1.977 + ((fCurrencySignCount == fgCurrencySignCountInPluralFormat) ? 1.978 + (fAffixPatternsForCurrency->equals(*other->fAffixPatternsForCurrency)) : 1.979 + (((fPosPrefixPattern == other->fPosPrefixPattern && // both null 1.980 + fPositivePrefix == other->fPositivePrefix) 1.981 + || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 && 1.982 + *fPosPrefixPattern == *other->fPosPrefixPattern)) && 1.983 + ((fPosSuffixPattern == other->fPosSuffixPattern && // both null 1.984 + fPositiveSuffix == other->fPositiveSuffix) 1.985 + || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 && 1.986 + *fPosSuffixPattern == *other->fPosSuffixPattern)) && 1.987 + ((fNegPrefixPattern == other->fNegPrefixPattern && // both null 1.988 + fNegativePrefix == other->fNegativePrefix) 1.989 + || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 && 1.990 + *fNegPrefixPattern == *other->fNegPrefixPattern)) && 1.991 + ((fNegSuffixPattern == other->fNegSuffixPattern && // both null 1.992 + fNegativeSuffix == other->fNegativeSuffix) 1.993 + || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 && 1.994 + *fNegSuffixPattern == *other->fNegSuffixPattern)))) && 1.995 + ((fRoundingIncrement == other->fRoundingIncrement) // both null 1.996 + || (fRoundingIncrement != NULL && 1.997 + other->fRoundingIncrement != NULL && 1.998 + *fRoundingIncrement == *other->fRoundingIncrement)) && 1.999 + getMultiplier() == other->getMultiplier() && 1.1000 + fGroupingSize == other->fGroupingSize && 1.1001 + fGroupingSize2 == other->fGroupingSize2 && 1.1002 + fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown && 1.1003 + fUseExponentialNotation == other->fUseExponentialNotation && 1.1004 + (!fUseExponentialNotation || 1.1005 + fMinExponentDigits == other->fMinExponentDigits) && 1.1006 + *fSymbols == *(other->fSymbols) && 1.1007 + fUseSignificantDigits == other->fUseSignificantDigits && 1.1008 + (!fUseSignificantDigits || 1.1009 + (fMinSignificantDigits == other->fMinSignificantDigits && 1.1010 + fMaxSignificantDigits == other->fMaxSignificantDigits)) && 1.1011 + fCurrencySignCount == other->fCurrencySignCount && 1.1012 + ((fCurrencyPluralInfo == other->fCurrencyPluralInfo && 1.1013 + fCurrencyPluralInfo == NULL) || 1.1014 + (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL && 1.1015 + *fCurrencyPluralInfo == *(other->fCurrencyPluralInfo)))); 1.1016 +} 1.1017 + 1.1018 +//------------------------------------------------------------------------------ 1.1019 + 1.1020 +Format* 1.1021 +DecimalFormat::clone() const 1.1022 +{ 1.1023 + return new DecimalFormat(*this); 1.1024 +} 1.1025 + 1.1026 + 1.1027 +FixedDecimal 1.1028 +DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const { 1.1029 + FixedDecimal result; 1.1030 + 1.1031 + if (U_FAILURE(status)) { 1.1032 + return result; 1.1033 + } 1.1034 + 1.1035 + if (uprv_isNaN(number) || uprv_isPositiveInfinity(fabs(number))) { 1.1036 + // For NaN and Infinity the state of the formatter is ignored. 1.1037 + result.init(number); 1.1038 + return result; 1.1039 + } 1.1040 + 1.1041 + if (fMultiplier == NULL && fScale == 0 && fRoundingIncrement == 0 && areSignificantDigitsUsed() == FALSE && 1.1042 + result.quickInit(number) && result.visibleDecimalDigitCount <= getMaximumFractionDigits()) { 1.1043 + // Fast Path. Construction of an exact FixedDecimal directly from the double, without passing 1.1044 + // through a DigitList, was successful, and the formatter is doing nothing tricky with rounding. 1.1045 + // printf("getFixedDecimal(%g): taking fast path.\n", number); 1.1046 + result.adjustForMinFractionDigits(getMinimumFractionDigits()); 1.1047 + } else { 1.1048 + // Slow path. Create a DigitList, and have this formatter round it according to the 1.1049 + // requirements of the format, and fill the fixedDecimal from that. 1.1050 + DigitList digits; 1.1051 + digits.set(number); 1.1052 + result = getFixedDecimal(digits, status); 1.1053 + } 1.1054 + return result; 1.1055 +} 1.1056 + 1.1057 +// MSVC optimizer bug? 1.1058 +// turn off optimization as it causes different behavior in the int64->double->int64 conversion 1.1059 +#if defined (_MSC_VER) 1.1060 +#pragma optimize ( "", off ) 1.1061 +#endif 1.1062 +FixedDecimal 1.1063 +DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const { 1.1064 + if (U_FAILURE(status)) { 1.1065 + return FixedDecimal(); 1.1066 + } 1.1067 + if (!number.isNumeric()) { 1.1068 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.1069 + return FixedDecimal(); 1.1070 + } 1.1071 + 1.1072 + DigitList *dl = number.getDigitList(); 1.1073 + if (dl != NULL) { 1.1074 + DigitList clonedDL(*dl); 1.1075 + return getFixedDecimal(clonedDL, status); 1.1076 + } 1.1077 + 1.1078 + Formattable::Type type = number.getType(); 1.1079 + if (type == Formattable::kDouble || type == Formattable::kLong) { 1.1080 + return getFixedDecimal(number.getDouble(status), status); 1.1081 + } 1.1082 + 1.1083 + if (type == Formattable::kInt64) { 1.1084 + // "volatile" here is a workaround to avoid optimization issues. 1.1085 + volatile double fdv = number.getDouble(status); 1.1086 + // Note: conversion of int64_t -> double rounds with some compilers to 1.1087 + // values beyond what can be represented as a 64 bit int. Subsequent 1.1088 + // testing or conversion with int64_t produces bad results. 1.1089 + // So filter the problematic values, route them to DigitList. 1.1090 + if (fdv != (double)U_INT64_MAX && fdv != (double)U_INT64_MIN && 1.1091 + number.getInt64() == (int64_t)fdv) { 1.1092 + return getFixedDecimal(number.getDouble(status), status); 1.1093 + } 1.1094 + } 1.1095 + 1.1096 + // The only case left is type==int64_t, with a value with more digits than a double can represent. 1.1097 + // Any formattable originating as a big decimal will have had a pre-existing digit list. 1.1098 + // Any originating as a double or int32 will have been handled as a double. 1.1099 + 1.1100 + U_ASSERT(type == Formattable::kInt64); 1.1101 + DigitList digits; 1.1102 + digits.set(number.getInt64()); 1.1103 + return getFixedDecimal(digits, status); 1.1104 +} 1.1105 +// end workaround MSVC optimizer bug 1.1106 +#if defined (_MSC_VER) 1.1107 +#pragma optimize ( "", on ) 1.1108 +#endif 1.1109 + 1.1110 + 1.1111 +// Create a fixed decimal from a DigitList. 1.1112 +// The digit list may be modified. 1.1113 +// Internal function only. 1.1114 +FixedDecimal 1.1115 +DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const { 1.1116 + // Round the number according to the requirements of this Format. 1.1117 + FixedDecimal result; 1.1118 + _round(number, number, result.isNegative, status); 1.1119 + 1.1120 + // The int64_t fields in FixedDecimal can easily overflow. 1.1121 + // In deciding what to discard in this event, consider that fixedDecimal 1.1122 + // is being used only with PluralRules, and those rules mostly look at least significant 1.1123 + // few digits of the integer part, and whether the fraction part is zero or not. 1.1124 + // 1.1125 + // So, in case of overflow when filling in the fields of the FixedDecimal object, 1.1126 + // for the integer part, discard the most significant digits. 1.1127 + // for the fraction part, discard the least significant digits, 1.1128 + // don't truncate the fraction value to zero. 1.1129 + // For simplicity, the int64_t fields are limited to 18 decimal digits, even 1.1130 + // though they could hold most (but not all) 19 digit values. 1.1131 + 1.1132 + // Integer Digits. 1.1133 + int32_t di = number.getDecimalAt()-18; // Take at most 18 digits. 1.1134 + if (di < 0) { 1.1135 + di = 0; 1.1136 + } 1.1137 + result.intValue = 0; 1.1138 + for (; di<number.getDecimalAt(); di++) { 1.1139 + result.intValue = result.intValue * 10 + (number.getDigit(di) & 0x0f); 1.1140 + } 1.1141 + if (result.intValue == 0 && number.getDecimalAt()-18 > 0) { 1.1142 + // The number is something like 100000000000000000000000. 1.1143 + // More than 18 digits integer digits, but the least significant 18 are all zero. 1.1144 + // We don't want to return zero as the int part, but want to keep zeros 1.1145 + // for several of the least significant digits. 1.1146 + result.intValue = 100000000000000000LL; 1.1147 + } 1.1148 + 1.1149 + // Fraction digits. 1.1150 + result.decimalDigits = result.decimalDigitsWithoutTrailingZeros = result.visibleDecimalDigitCount = 0; 1.1151 + for (di = number.getDecimalAt(); di < number.getCount(); di++) { 1.1152 + result.visibleDecimalDigitCount++; 1.1153 + if (result.decimalDigits < 100000000000000000LL) { 1.1154 + // 9223372036854775807 Largest 64 bit signed integer 1.1155 + int32_t digitVal = number.getDigit(di) & 0x0f; // getDigit() returns a char, '0'-'9'. 1.1156 + result.decimalDigits = result.decimalDigits * 10 + digitVal; 1.1157 + if (digitVal > 0) { 1.1158 + result.decimalDigitsWithoutTrailingZeros = result.decimalDigits; 1.1159 + } 1.1160 + } 1.1161 + } 1.1162 + 1.1163 + result.hasIntegerValue = (result.decimalDigits == 0); 1.1164 + 1.1165 + // Trailing fraction zeros. The format specification may require more trailing 1.1166 + // zeros than the numeric value. Add any such on now. 1.1167 + 1.1168 + int32_t minFractionDigits; 1.1169 + if (areSignificantDigitsUsed()) { 1.1170 + minFractionDigits = getMinimumSignificantDigits() - number.getDecimalAt(); 1.1171 + if (minFractionDigits < 0) { 1.1172 + minFractionDigits = 0; 1.1173 + } 1.1174 + } else { 1.1175 + minFractionDigits = getMinimumFractionDigits(); 1.1176 + } 1.1177 + result.adjustForMinFractionDigits(minFractionDigits); 1.1178 + 1.1179 + return result; 1.1180 +} 1.1181 + 1.1182 + 1.1183 +//------------------------------------------------------------------------------ 1.1184 + 1.1185 +UnicodeString& 1.1186 +DecimalFormat::format(int32_t number, 1.1187 + UnicodeString& appendTo, 1.1188 + FieldPosition& fieldPosition) const 1.1189 +{ 1.1190 + return format((int64_t)number, appendTo, fieldPosition); 1.1191 +} 1.1192 + 1.1193 +UnicodeString& 1.1194 +DecimalFormat::format(int32_t number, 1.1195 + UnicodeString& appendTo, 1.1196 + FieldPosition& fieldPosition, 1.1197 + UErrorCode& status) const 1.1198 +{ 1.1199 + return format((int64_t)number, appendTo, fieldPosition, status); 1.1200 +} 1.1201 + 1.1202 +UnicodeString& 1.1203 +DecimalFormat::format(int32_t number, 1.1204 + UnicodeString& appendTo, 1.1205 + FieldPositionIterator* posIter, 1.1206 + UErrorCode& status) const 1.1207 +{ 1.1208 + return format((int64_t)number, appendTo, posIter, status); 1.1209 +} 1.1210 + 1.1211 + 1.1212 +#if UCONFIG_FORMAT_FASTPATHS_49 1.1213 +void DecimalFormat::handleChanged() { 1.1214 + DecimalFormatInternal &data = internalData(fReserved); 1.1215 + 1.1216 + if(data.fFastFormatStatus == kFastpathUNKNOWN || data.fFastParseStatus == kFastpathUNKNOWN) { 1.1217 + return; // still constructing. Wait. 1.1218 + } 1.1219 + 1.1220 + data.fFastParseStatus = data.fFastFormatStatus = kFastpathNO; 1.1221 + 1.1222 +#if UCONFIG_HAVE_PARSEALLINPUT 1.1223 + if(fParseAllInput == UNUM_NO) { 1.1224 + debug("No Parse fastpath: fParseAllInput==UNUM_NO"); 1.1225 + } else 1.1226 +#endif 1.1227 + if (fFormatWidth!=0) { 1.1228 + debug("No Parse fastpath: fFormatWidth"); 1.1229 + } else if(fPositivePrefix.length()>0) { 1.1230 + debug("No Parse fastpath: positive prefix"); 1.1231 + } else if(fPositiveSuffix.length()>0) { 1.1232 + debug("No Parse fastpath: positive suffix"); 1.1233 + } else if(fNegativePrefix.length()>1 1.1234 + || ((fNegativePrefix.length()==1) && (fNegativePrefix.charAt(0)!=0x002D))) { 1.1235 + debug("No Parse fastpath: negative prefix that isn't '-'"); 1.1236 + } else if(fNegativeSuffix.length()>0) { 1.1237 + debug("No Parse fastpath: negative suffix"); 1.1238 + } else { 1.1239 + data.fFastParseStatus = kFastpathYES; 1.1240 + debug("parse fastpath: YES"); 1.1241 + } 1.1242 + 1.1243 + if (fGroupingSize!=0 && isGroupingUsed()) { 1.1244 + debug("No format fastpath: fGroupingSize!=0 and grouping is used"); 1.1245 +#ifdef FMT_DEBUG 1.1246 + printf("groupingsize=%d\n", fGroupingSize); 1.1247 +#endif 1.1248 + } else if(fGroupingSize2!=0 && isGroupingUsed()) { 1.1249 + debug("No format fastpath: fGroupingSize2!=0"); 1.1250 + } else if(fUseExponentialNotation) { 1.1251 + debug("No format fastpath: fUseExponentialNotation"); 1.1252 + } else if(fFormatWidth!=0) { 1.1253 + debug("No format fastpath: fFormatWidth!=0"); 1.1254 + } else if(fMinSignificantDigits!=1) { 1.1255 + debug("No format fastpath: fMinSignificantDigits!=1"); 1.1256 + } else if(fMultiplier!=NULL) { 1.1257 + debug("No format fastpath: fMultiplier!=NULL"); 1.1258 + } else if(fScale!=0) { 1.1259 + debug("No format fastpath: fScale!=0"); 1.1260 + } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)) { 1.1261 + debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)"); 1.1262 + } else if(fDecimalSeparatorAlwaysShown) { 1.1263 + debug("No format fastpath: fDecimalSeparatorAlwaysShown"); 1.1264 + } else if(getMinimumFractionDigits()>0) { 1.1265 + debug("No format fastpath: fMinFractionDigits>0"); 1.1266 + } else if(fCurrencySignCount != fgCurrencySignCountZero) { 1.1267 + debug("No format fastpath: fCurrencySignCount != fgCurrencySignCountZero"); 1.1268 + } else if(fRoundingIncrement!=0) { 1.1269 + debug("No format fastpath: fRoundingIncrement!=0"); 1.1270 + } else { 1.1271 + data.fFastFormatStatus = kFastpathYES; 1.1272 + debug("format:kFastpathYES!"); 1.1273 + } 1.1274 + 1.1275 + 1.1276 +} 1.1277 +#endif 1.1278 +//------------------------------------------------------------------------------ 1.1279 + 1.1280 +UnicodeString& 1.1281 +DecimalFormat::format(int64_t number, 1.1282 + UnicodeString& appendTo, 1.1283 + FieldPosition& fieldPosition) const 1.1284 +{ 1.1285 + UErrorCode status = U_ZERO_ERROR; /* ignored */ 1.1286 + FieldPositionOnlyHandler handler(fieldPosition); 1.1287 + return _format(number, appendTo, handler, status); 1.1288 +} 1.1289 + 1.1290 +UnicodeString& 1.1291 +DecimalFormat::format(int64_t number, 1.1292 + UnicodeString& appendTo, 1.1293 + FieldPosition& fieldPosition, 1.1294 + UErrorCode& status) const 1.1295 +{ 1.1296 + FieldPositionOnlyHandler handler(fieldPosition); 1.1297 + return _format(number, appendTo, handler, status); 1.1298 +} 1.1299 + 1.1300 +UnicodeString& 1.1301 +DecimalFormat::format(int64_t number, 1.1302 + UnicodeString& appendTo, 1.1303 + FieldPositionIterator* posIter, 1.1304 + UErrorCode& status) const 1.1305 +{ 1.1306 + FieldPositionIteratorHandler handler(posIter, status); 1.1307 + return _format(number, appendTo, handler, status); 1.1308 +} 1.1309 + 1.1310 +UnicodeString& 1.1311 +DecimalFormat::_format(int64_t number, 1.1312 + UnicodeString& appendTo, 1.1313 + FieldPositionHandler& handler, 1.1314 + UErrorCode &status) const 1.1315 +{ 1.1316 + // Bottleneck function for formatting int64_t 1.1317 + if (U_FAILURE(status)) { 1.1318 + return appendTo; 1.1319 + } 1.1320 + 1.1321 +#if UCONFIG_FORMAT_FASTPATHS_49 1.1322 + // const UnicodeString *posPrefix = fPosPrefixPattern; 1.1323 + // const UnicodeString *posSuffix = fPosSuffixPattern; 1.1324 + // const UnicodeString *negSuffix = fNegSuffixPattern; 1.1325 + 1.1326 + const DecimalFormatInternal &data = internalData(fReserved); 1.1327 + 1.1328 +#ifdef FMT_DEBUG 1.1329 + data.dump(); 1.1330 + printf("fastpath? [%d]\n", number); 1.1331 +#endif 1.1332 + 1.1333 + if( data.fFastFormatStatus==kFastpathYES) { 1.1334 + 1.1335 +#define kZero 0x0030 1.1336 + const int32_t MAX_IDX = MAX_DIGITS+2; 1.1337 + UChar outputStr[MAX_IDX]; 1.1338 + int32_t destIdx = MAX_IDX; 1.1339 + outputStr[--destIdx] = 0; // term 1.1340 + 1.1341 + int64_t n = number; 1.1342 + if (number < 1) { 1.1343 + // Negative numbers are slightly larger than positive 1.1344 + // output the first digit (or the leading zero) 1.1345 + outputStr[--destIdx] = (-(n % 10) + kZero); 1.1346 + n /= -10; 1.1347 + } 1.1348 + // get any remaining digits 1.1349 + while (n > 0) { 1.1350 + outputStr[--destIdx] = (n % 10) + kZero; 1.1351 + n /= 10; 1.1352 + } 1.1353 + 1.1354 + 1.1355 + // Slide the number to the start of the output str 1.1356 + U_ASSERT(destIdx >= 0); 1.1357 + int32_t length = MAX_IDX - destIdx -1; 1.1358 + /*int32_t prefixLen = */ appendAffix(appendTo, number, handler, number<0, TRUE); 1.1359 + int32_t maxIntDig = getMaximumIntegerDigits(); 1.1360 + int32_t destlength = length<=maxIntDig?length:maxIntDig; // dest length pinned to max int digits 1.1361 + 1.1362 + if(length>maxIntDig && fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) { 1.1363 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.1364 + } 1.1365 + 1.1366 + int32_t prependZero = getMinimumIntegerDigits() - destlength; 1.1367 + 1.1368 +#ifdef FMT_DEBUG 1.1369 + printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d skip=%d\n", prependZero, length, getMinimumIntegerDigits(), maxIntDig, destlength, length-destlength); 1.1370 +#endif 1.1371 + int32_t intBegin = appendTo.length(); 1.1372 + 1.1373 + while((prependZero--)>0) { 1.1374 + appendTo.append((UChar)0x0030); // '0' 1.1375 + } 1.1376 + 1.1377 + appendTo.append(outputStr+destIdx+ 1.1378 + (length-destlength), // skip any leading digits 1.1379 + destlength); 1.1380 + handler.addAttribute(kIntegerField, intBegin, appendTo.length()); 1.1381 + 1.1382 + /*int32_t suffixLen =*/ appendAffix(appendTo, number, handler, number<0, FALSE); 1.1383 + 1.1384 + //outputStr[length]=0; 1.1385 + 1.1386 +#ifdef FMT_DEBUG 1.1387 + printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr+destIdx, length, MAX_IDX, number); 1.1388 +#endif 1.1389 + 1.1390 +#undef kZero 1.1391 + 1.1392 + return appendTo; 1.1393 + } // end fastpath 1.1394 +#endif 1.1395 + 1.1396 + // Else the slow way - via DigitList 1.1397 + DigitList digits; 1.1398 + digits.set(number); 1.1399 + return _format(digits, appendTo, handler, status); 1.1400 +} 1.1401 + 1.1402 +//------------------------------------------------------------------------------ 1.1403 + 1.1404 +UnicodeString& 1.1405 +DecimalFormat::format( double number, 1.1406 + UnicodeString& appendTo, 1.1407 + FieldPosition& fieldPosition) const 1.1408 +{ 1.1409 + UErrorCode status = U_ZERO_ERROR; /* ignored */ 1.1410 + FieldPositionOnlyHandler handler(fieldPosition); 1.1411 + return _format(number, appendTo, handler, status); 1.1412 +} 1.1413 + 1.1414 +UnicodeString& 1.1415 +DecimalFormat::format( double number, 1.1416 + UnicodeString& appendTo, 1.1417 + FieldPosition& fieldPosition, 1.1418 + UErrorCode& status) const 1.1419 +{ 1.1420 + FieldPositionOnlyHandler handler(fieldPosition); 1.1421 + return _format(number, appendTo, handler, status); 1.1422 +} 1.1423 + 1.1424 +UnicodeString& 1.1425 +DecimalFormat::format( double number, 1.1426 + UnicodeString& appendTo, 1.1427 + FieldPositionIterator* posIter, 1.1428 + UErrorCode& status) const 1.1429 +{ 1.1430 + FieldPositionIteratorHandler handler(posIter, status); 1.1431 + return _format(number, appendTo, handler, status); 1.1432 +} 1.1433 + 1.1434 +UnicodeString& 1.1435 +DecimalFormat::_format( double number, 1.1436 + UnicodeString& appendTo, 1.1437 + FieldPositionHandler& handler, 1.1438 + UErrorCode &status) const 1.1439 +{ 1.1440 + if (U_FAILURE(status)) { 1.1441 + return appendTo; 1.1442 + } 1.1443 + // Special case for NaN, sets the begin and end index to be the 1.1444 + // the string length of localized name of NaN. 1.1445 + // TODO: let NaNs go through DigitList. 1.1446 + if (uprv_isNaN(number)) 1.1447 + { 1.1448 + int begin = appendTo.length(); 1.1449 + appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 1.1450 + 1.1451 + handler.addAttribute(kIntegerField, begin, appendTo.length()); 1.1452 + 1.1453 + addPadding(appendTo, handler, 0, 0); 1.1454 + return appendTo; 1.1455 + } 1.1456 + 1.1457 + DigitList digits; 1.1458 + digits.set(number); 1.1459 + _format(digits, appendTo, handler, status); 1.1460 + // No way to return status from here. 1.1461 + return appendTo; 1.1462 +} 1.1463 + 1.1464 +//------------------------------------------------------------------------------ 1.1465 + 1.1466 + 1.1467 +UnicodeString& 1.1468 +DecimalFormat::format(const StringPiece &number, 1.1469 + UnicodeString &toAppendTo, 1.1470 + FieldPositionIterator *posIter, 1.1471 + UErrorCode &status) const 1.1472 +{ 1.1473 +#if UCONFIG_FORMAT_FASTPATHS_49 1.1474 + // don't bother if the int64 path is not optimized 1.1475 + int32_t len = number.length(); 1.1476 + 1.1477 + if(len>0&&len<10) { /* 10 or more digits may not be an int64 */ 1.1478 + const char *data = number.data(); 1.1479 + int64_t num = 0; 1.1480 + UBool neg = FALSE; 1.1481 + UBool ok = TRUE; 1.1482 + 1.1483 + int32_t start = 0; 1.1484 + 1.1485 + if(data[start]=='+') { 1.1486 + start++; 1.1487 + } else if(data[start]=='-') { 1.1488 + neg=TRUE; 1.1489 + start++; 1.1490 + } 1.1491 + 1.1492 + int32_t place = 1; /* 1, 10, ... */ 1.1493 + for(int32_t i=len-1;i>=start;i--) { 1.1494 + if(data[i]>='0'&&data[i]<='9') { 1.1495 + num+=place*(int64_t)(data[i]-'0'); 1.1496 + } else { 1.1497 + ok=FALSE; 1.1498 + break; 1.1499 + } 1.1500 + place *= 10; 1.1501 + } 1.1502 + 1.1503 + if(ok) { 1.1504 + if(neg) { 1.1505 + num = -num;// add minus bit 1.1506 + } 1.1507 + // format as int64_t 1.1508 + return format(num, toAppendTo, posIter, status); 1.1509 + } 1.1510 + // else fall through 1.1511 + } 1.1512 +#endif 1.1513 + 1.1514 + DigitList dnum; 1.1515 + dnum.set(number, status); 1.1516 + if (U_FAILURE(status)) { 1.1517 + return toAppendTo; 1.1518 + } 1.1519 + FieldPositionIteratorHandler handler(posIter, status); 1.1520 + _format(dnum, toAppendTo, handler, status); 1.1521 + return toAppendTo; 1.1522 +} 1.1523 + 1.1524 + 1.1525 +UnicodeString& 1.1526 +DecimalFormat::format(const DigitList &number, 1.1527 + UnicodeString &appendTo, 1.1528 + FieldPositionIterator *posIter, 1.1529 + UErrorCode &status) const { 1.1530 + FieldPositionIteratorHandler handler(posIter, status); 1.1531 + _format(number, appendTo, handler, status); 1.1532 + return appendTo; 1.1533 +} 1.1534 + 1.1535 + 1.1536 + 1.1537 +UnicodeString& 1.1538 +DecimalFormat::format(const DigitList &number, 1.1539 + UnicodeString& appendTo, 1.1540 + FieldPosition& pos, 1.1541 + UErrorCode &status) const { 1.1542 + FieldPositionOnlyHandler handler(pos); 1.1543 + _format(number, appendTo, handler, status); 1.1544 + return appendTo; 1.1545 +} 1.1546 + 1.1547 +DigitList& 1.1548 +DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& isNegative, UErrorCode &status) const { 1.1549 + if (U_FAILURE(status)) { 1.1550 + return adjustedNum; 1.1551 + } 1.1552 + 1.1553 + // note: number and adjustedNum may refer to the same DigitList, in cases where a copy 1.1554 + // is not needed by the caller. 1.1555 + 1.1556 + adjustedNum = number; 1.1557 + isNegative = false; 1.1558 + if (number.isNaN()) { 1.1559 + return adjustedNum; 1.1560 + } 1.1561 + 1.1562 + // Do this BEFORE checking to see if value is infinite or negative! Sets the 1.1563 + // begin and end index to be length of the string composed of 1.1564 + // localized name of Infinite and the positive/negative localized 1.1565 + // signs. 1.1566 + 1.1567 + adjustedNum.setRoundingMode(fRoundingMode); 1.1568 + if (fMultiplier != NULL) { 1.1569 + adjustedNum.mult(*fMultiplier, status); 1.1570 + if (U_FAILURE(status)) { 1.1571 + return adjustedNum; 1.1572 + } 1.1573 + } 1.1574 + 1.1575 + if (fScale != 0) { 1.1576 + DigitList ten; 1.1577 + ten.set((int32_t)10); 1.1578 + if (fScale > 0) { 1.1579 + for (int32_t i = fScale ; i > 0 ; i--) { 1.1580 + adjustedNum.mult(ten, status); 1.1581 + if (U_FAILURE(status)) { 1.1582 + return adjustedNum; 1.1583 + } 1.1584 + } 1.1585 + } else { 1.1586 + for (int32_t i = fScale ; i < 0 ; i++) { 1.1587 + adjustedNum.div(ten, status); 1.1588 + if (U_FAILURE(status)) { 1.1589 + return adjustedNum; 1.1590 + } 1.1591 + } 1.1592 + } 1.1593 + } 1.1594 + 1.1595 + /* 1.1596 + * Note: sign is important for zero as well as non-zero numbers. 1.1597 + * Proper detection of -0.0 is needed to deal with the 1.1598 + * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98. 1.1599 + */ 1.1600 + isNegative = !adjustedNum.isPositive(); 1.1601 + 1.1602 + // Apply rounding after multiplier 1.1603 + 1.1604 + adjustedNum.fContext.status &= ~DEC_Inexact; 1.1605 + if (fRoundingIncrement != NULL) { 1.1606 + adjustedNum.div(*fRoundingIncrement, status); 1.1607 + adjustedNum.toIntegralValue(); 1.1608 + adjustedNum.mult(*fRoundingIncrement, status); 1.1609 + adjustedNum.trim(); 1.1610 + if (U_FAILURE(status)) { 1.1611 + return adjustedNum; 1.1612 + } 1.1613 + } 1.1614 + if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) { 1.1615 + status = U_FORMAT_INEXACT_ERROR; 1.1616 + return adjustedNum; 1.1617 + } 1.1618 + 1.1619 + if (adjustedNum.isInfinite()) { 1.1620 + return adjustedNum; 1.1621 + } 1.1622 + 1.1623 + if (fUseExponentialNotation || areSignificantDigitsUsed()) { 1.1624 + int32_t sigDigits = precision(); 1.1625 + if (sigDigits > 0) { 1.1626 + adjustedNum.round(sigDigits); 1.1627 + } 1.1628 + } else { 1.1629 + // Fixed point format. Round to a set number of fraction digits. 1.1630 + int32_t numFractionDigits = precision(); 1.1631 + adjustedNum.roundFixedPoint(numFractionDigits); 1.1632 + } 1.1633 + if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) { 1.1634 + status = U_FORMAT_INEXACT_ERROR; 1.1635 + return adjustedNum; 1.1636 + } 1.1637 + return adjustedNum; 1.1638 +} 1.1639 + 1.1640 +UnicodeString& 1.1641 +DecimalFormat::_format(const DigitList &number, 1.1642 + UnicodeString& appendTo, 1.1643 + FieldPositionHandler& handler, 1.1644 + UErrorCode &status) const 1.1645 +{ 1.1646 + if (U_FAILURE(status)) { 1.1647 + return appendTo; 1.1648 + } 1.1649 + 1.1650 + // Special case for NaN, sets the begin and end index to be the 1.1651 + // the string length of localized name of NaN. 1.1652 + if (number.isNaN()) 1.1653 + { 1.1654 + int begin = appendTo.length(); 1.1655 + appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 1.1656 + 1.1657 + handler.addAttribute(kIntegerField, begin, appendTo.length()); 1.1658 + 1.1659 + addPadding(appendTo, handler, 0, 0); 1.1660 + return appendTo; 1.1661 + } 1.1662 + 1.1663 + DigitList adjustedNum; 1.1664 + UBool isNegative; 1.1665 + _round(number, adjustedNum, isNegative, status); 1.1666 + if (U_FAILURE(status)) { 1.1667 + return appendTo; 1.1668 + } 1.1669 + 1.1670 + // Special case for INFINITE, 1.1671 + if (adjustedNum.isInfinite()) { 1.1672 + int32_t prefixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, TRUE); 1.1673 + 1.1674 + int begin = appendTo.length(); 1.1675 + appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol); 1.1676 + 1.1677 + handler.addAttribute(kIntegerField, begin, appendTo.length()); 1.1678 + 1.1679 + int32_t suffixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, FALSE); 1.1680 + 1.1681 + addPadding(appendTo, handler, prefixLen, suffixLen); 1.1682 + return appendTo; 1.1683 + } 1.1684 + return subformat(appendTo, handler, adjustedNum, FALSE, status); 1.1685 +} 1.1686 + 1.1687 +/** 1.1688 + * Return true if a grouping separator belongs at the given 1.1689 + * position, based on whether grouping is in use and the values of 1.1690 + * the primary and secondary grouping interval. 1.1691 + * @param pos the number of integer digits to the right of 1.1692 + * the current position. Zero indicates the position after the 1.1693 + * rightmost integer digit. 1.1694 + * @return true if a grouping character belongs at the current 1.1695 + * position. 1.1696 + */ 1.1697 +UBool DecimalFormat::isGroupingPosition(int32_t pos) const { 1.1698 + UBool result = FALSE; 1.1699 + if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) { 1.1700 + if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) { 1.1701 + result = ((pos - fGroupingSize) % fGroupingSize2) == 0; 1.1702 + } else { 1.1703 + result = pos % fGroupingSize == 0; 1.1704 + } 1.1705 + } 1.1706 + return result; 1.1707 +} 1.1708 + 1.1709 +//------------------------------------------------------------------------------ 1.1710 + 1.1711 +/** 1.1712 + * Complete the formatting of a finite number. On entry, the DigitList must 1.1713 + * be filled in with the correct digits. 1.1714 + */ 1.1715 +UnicodeString& 1.1716 +DecimalFormat::subformat(UnicodeString& appendTo, 1.1717 + FieldPositionHandler& handler, 1.1718 + DigitList& digits, 1.1719 + UBool isInteger, 1.1720 + UErrorCode& status) const 1.1721 +{ 1.1722 + // char zero = '0'; 1.1723 + // DigitList returns digits as '0' thru '9', so we will need to 1.1724 + // always need to subtract the character 0 to get the numeric value to use for indexing. 1.1725 + 1.1726 + UChar32 localizedDigits[10]; 1.1727 + localizedDigits[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 1.1728 + localizedDigits[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0); 1.1729 + localizedDigits[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0); 1.1730 + localizedDigits[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0); 1.1731 + localizedDigits[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0); 1.1732 + localizedDigits[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0); 1.1733 + localizedDigits[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0); 1.1734 + localizedDigits[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0); 1.1735 + localizedDigits[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0); 1.1736 + localizedDigits[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0); 1.1737 + 1.1738 + const UnicodeString *grouping ; 1.1739 + if(fCurrencySignCount == fgCurrencySignCountZero) { 1.1740 + grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); 1.1741 + }else{ 1.1742 + grouping = &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); 1.1743 + } 1.1744 + const UnicodeString *decimal; 1.1745 + if(fCurrencySignCount == fgCurrencySignCountZero) { 1.1746 + decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1.1747 + } else { 1.1748 + decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 1.1749 + } 1.1750 + UBool useSigDig = areSignificantDigitsUsed(); 1.1751 + int32_t maxIntDig = getMaximumIntegerDigits(); 1.1752 + int32_t minIntDig = getMinimumIntegerDigits(); 1.1753 + 1.1754 + // Appends the prefix. 1.1755 + double doubleValue = digits.getDouble(); 1.1756 + int32_t prefixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), TRUE); 1.1757 + 1.1758 + if (fUseExponentialNotation) 1.1759 + { 1.1760 + int currentLength = appendTo.length(); 1.1761 + int intBegin = currentLength; 1.1762 + int intEnd = -1; 1.1763 + int fracBegin = -1; 1.1764 + 1.1765 + int32_t minFracDig = 0; 1.1766 + if (useSigDig) { 1.1767 + maxIntDig = minIntDig = 1; 1.1768 + minFracDig = getMinimumSignificantDigits() - 1; 1.1769 + } else { 1.1770 + minFracDig = getMinimumFractionDigits(); 1.1771 + if (maxIntDig > kMaxScientificIntegerDigits) { 1.1772 + maxIntDig = 1; 1.1773 + if (maxIntDig < minIntDig) { 1.1774 + maxIntDig = minIntDig; 1.1775 + } 1.1776 + } 1.1777 + if (maxIntDig > minIntDig) { 1.1778 + minIntDig = 1; 1.1779 + } 1.1780 + } 1.1781 + 1.1782 + // Minimum integer digits are handled in exponential format by 1.1783 + // adjusting the exponent. For example, 0.01234 with 3 minimum 1.1784 + // integer digits is "123.4E-4". 1.1785 + 1.1786 + // Maximum integer digits are interpreted as indicating the 1.1787 + // repeating range. This is useful for engineering notation, in 1.1788 + // which the exponent is restricted to a multiple of 3. For 1.1789 + // example, 0.01234 with 3 maximum integer digits is "12.34e-3". 1.1790 + // If maximum integer digits are defined and are larger than 1.1791 + // minimum integer digits, then minimum integer digits are 1.1792 + // ignored. 1.1793 + digits.reduce(); // Removes trailing zero digits. 1.1794 + int32_t exponent = digits.getDecimalAt(); 1.1795 + if (maxIntDig > 1 && maxIntDig != minIntDig) { 1.1796 + // A exponent increment is defined; adjust to it. 1.1797 + exponent = (exponent > 0) ? (exponent - 1) / maxIntDig 1.1798 + : (exponent / maxIntDig) - 1; 1.1799 + exponent *= maxIntDig; 1.1800 + } else { 1.1801 + // No exponent increment is defined; use minimum integer digits. 1.1802 + // If none is specified, as in "#E0", generate 1 integer digit. 1.1803 + exponent -= (minIntDig > 0 || minFracDig > 0) 1.1804 + ? minIntDig : 1; 1.1805 + } 1.1806 + 1.1807 + // We now output a minimum number of digits, and more if there 1.1808 + // are more digits, up to the maximum number of digits. We 1.1809 + // place the decimal point after the "integer" digits, which 1.1810 + // are the first (decimalAt - exponent) digits. 1.1811 + int32_t minimumDigits = minIntDig + minFracDig; 1.1812 + // The number of integer digits is handled specially if the number 1.1813 + // is zero, since then there may be no digits. 1.1814 + int32_t integerDigits = digits.isZero() ? minIntDig : 1.1815 + digits.getDecimalAt() - exponent; 1.1816 + int32_t totalDigits = digits.getCount(); 1.1817 + if (minimumDigits > totalDigits) 1.1818 + totalDigits = minimumDigits; 1.1819 + if (integerDigits > totalDigits) 1.1820 + totalDigits = integerDigits; 1.1821 + 1.1822 + // totalDigits records total number of digits needs to be processed 1.1823 + int32_t i; 1.1824 + for (i=0; i<totalDigits; ++i) 1.1825 + { 1.1826 + if (i == integerDigits) 1.1827 + { 1.1828 + intEnd = appendTo.length(); 1.1829 + handler.addAttribute(kIntegerField, intBegin, intEnd); 1.1830 + 1.1831 + appendTo += *decimal; 1.1832 + 1.1833 + fracBegin = appendTo.length(); 1.1834 + handler.addAttribute(kDecimalSeparatorField, fracBegin - 1, fracBegin); 1.1835 + } 1.1836 + // Restores the digit character or pads the buffer with zeros. 1.1837 + UChar32 c = (UChar32)((i < digits.getCount()) ? 1.1838 + localizedDigits[digits.getDigitValue(i)] : 1.1839 + localizedDigits[0]); 1.1840 + appendTo += c; 1.1841 + } 1.1842 + 1.1843 + currentLength = appendTo.length(); 1.1844 + 1.1845 + if (intEnd < 0) { 1.1846 + handler.addAttribute(kIntegerField, intBegin, currentLength); 1.1847 + } 1.1848 + if (fracBegin > 0) { 1.1849 + handler.addAttribute(kFractionField, fracBegin, currentLength); 1.1850 + } 1.1851 + 1.1852 + // The exponent is output using the pattern-specified minimum 1.1853 + // exponent digits. There is no maximum limit to the exponent 1.1854 + // digits, since truncating the exponent would appendTo in an 1.1855 + // unacceptable inaccuracy. 1.1856 + appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 1.1857 + 1.1858 + handler.addAttribute(kExponentSymbolField, currentLength, appendTo.length()); 1.1859 + currentLength = appendTo.length(); 1.1860 + 1.1861 + // For zero values, we force the exponent to zero. We 1.1862 + // must do this here, and not earlier, because the value 1.1863 + // is used to determine integer digit count above. 1.1864 + if (digits.isZero()) 1.1865 + exponent = 0; 1.1866 + 1.1867 + if (exponent < 0) { 1.1868 + appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1.1869 + handler.addAttribute(kExponentSignField, currentLength, appendTo.length()); 1.1870 + } else if (fExponentSignAlwaysShown) { 1.1871 + appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1.1872 + handler.addAttribute(kExponentSignField, currentLength, appendTo.length()); 1.1873 + } 1.1874 + 1.1875 + currentLength = appendTo.length(); 1.1876 + 1.1877 + DigitList expDigits; 1.1878 + expDigits.set(exponent); 1.1879 + { 1.1880 + int expDig = fMinExponentDigits; 1.1881 + if (fUseExponentialNotation && expDig < 1) { 1.1882 + expDig = 1; 1.1883 + } 1.1884 + for (i=expDigits.getDecimalAt(); i<expDig; ++i) 1.1885 + appendTo += (localizedDigits[0]); 1.1886 + } 1.1887 + for (i=0; i<expDigits.getDecimalAt(); ++i) 1.1888 + { 1.1889 + UChar32 c = (UChar32)((i < expDigits.getCount()) ? 1.1890 + localizedDigits[expDigits.getDigitValue(i)] : 1.1891 + localizedDigits[0]); 1.1892 + appendTo += c; 1.1893 + } 1.1894 + 1.1895 + handler.addAttribute(kExponentField, currentLength, appendTo.length()); 1.1896 + } 1.1897 + else // Not using exponential notation 1.1898 + { 1.1899 + int currentLength = appendTo.length(); 1.1900 + int intBegin = currentLength; 1.1901 + 1.1902 + int32_t sigCount = 0; 1.1903 + int32_t minSigDig = getMinimumSignificantDigits(); 1.1904 + int32_t maxSigDig = getMaximumSignificantDigits(); 1.1905 + if (!useSigDig) { 1.1906 + minSigDig = 0; 1.1907 + maxSigDig = INT32_MAX; 1.1908 + } 1.1909 + 1.1910 + // Output the integer portion. Here 'count' is the total 1.1911 + // number of integer digits we will display, including both 1.1912 + // leading zeros required to satisfy getMinimumIntegerDigits, 1.1913 + // and actual digits present in the number. 1.1914 + int32_t count = useSigDig ? 1.1915 + _max(1, digits.getDecimalAt()) : minIntDig; 1.1916 + if (digits.getDecimalAt() > 0 && count < digits.getDecimalAt()) { 1.1917 + count = digits.getDecimalAt(); 1.1918 + } 1.1919 + 1.1920 + // Handle the case where getMaximumIntegerDigits() is smaller 1.1921 + // than the real number of integer digits. If this is so, we 1.1922 + // output the least significant max integer digits. For example, 1.1923 + // the value 1997 printed with 2 max integer digits is just "97". 1.1924 + 1.1925 + int32_t digitIndex = 0; // Index into digitList.fDigits[] 1.1926 + if (count > maxIntDig && maxIntDig >= 0) { 1.1927 + count = maxIntDig; 1.1928 + digitIndex = digits.getDecimalAt() - count; 1.1929 + if(fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) { 1.1930 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.1931 + } 1.1932 + } 1.1933 + 1.1934 + int32_t sizeBeforeIntegerPart = appendTo.length(); 1.1935 + 1.1936 + int32_t i; 1.1937 + for (i=count-1; i>=0; --i) 1.1938 + { 1.1939 + if (i < digits.getDecimalAt() && digitIndex < digits.getCount() && 1.1940 + sigCount < maxSigDig) { 1.1941 + // Output a real digit 1.1942 + appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)]; 1.1943 + ++sigCount; 1.1944 + } 1.1945 + else 1.1946 + { 1.1947 + // Output a zero (leading or trailing) 1.1948 + appendTo += localizedDigits[0]; 1.1949 + if (sigCount > 0) { 1.1950 + ++sigCount; 1.1951 + } 1.1952 + } 1.1953 + 1.1954 + // Output grouping separator if necessary. 1.1955 + if (isGroupingPosition(i)) { 1.1956 + currentLength = appendTo.length(); 1.1957 + appendTo.append(*grouping); 1.1958 + handler.addAttribute(kGroupingSeparatorField, currentLength, appendTo.length()); 1.1959 + } 1.1960 + } 1.1961 + 1.1962 + // This handles the special case of formatting 0. For zero only, we count the 1.1963 + // zero to the left of the decimal point as one signficant digit. Ordinarily we 1.1964 + // do not count any leading 0's as significant. If the number we are formatting 1.1965 + // is not zero, then either sigCount or digits.getCount() will be non-zero. 1.1966 + if (sigCount == 0 && digits.getCount() == 0) { 1.1967 + sigCount = 1; 1.1968 + } 1.1969 + 1.1970 + // TODO(dlf): this looks like it was a bug, we marked the int field as ending 1.1971 + // before the zero was generated. 1.1972 + // Record field information for caller. 1.1973 + // if (fieldPosition.getField() == NumberFormat::kIntegerField) 1.1974 + // fieldPosition.setEndIndex(appendTo.length()); 1.1975 + 1.1976 + // Determine whether or not there are any printable fractional 1.1977 + // digits. If we've used up the digits we know there aren't. 1.1978 + UBool fractionPresent = (!isInteger && digitIndex < digits.getCount()) || 1.1979 + (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0)); 1.1980 + 1.1981 + // If there is no fraction present, and we haven't printed any 1.1982 + // integer digits, then print a zero. Otherwise we won't print 1.1983 + // _any_ digits, and we won't be able to parse this string. 1.1984 + if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart) 1.1985 + appendTo += localizedDigits[0]; 1.1986 + 1.1987 + currentLength = appendTo.length(); 1.1988 + handler.addAttribute(kIntegerField, intBegin, currentLength); 1.1989 + 1.1990 + // Output the decimal separator if we always do so. 1.1991 + if (fDecimalSeparatorAlwaysShown || fractionPresent) { 1.1992 + appendTo += *decimal; 1.1993 + handler.addAttribute(kDecimalSeparatorField, currentLength, appendTo.length()); 1.1994 + currentLength = appendTo.length(); 1.1995 + } 1.1996 + 1.1997 + int fracBegin = currentLength; 1.1998 + 1.1999 + count = useSigDig ? INT32_MAX : getMaximumFractionDigits(); 1.2000 + if (useSigDig && (sigCount == maxSigDig || 1.2001 + (sigCount >= minSigDig && digitIndex == digits.getCount()))) { 1.2002 + count = 0; 1.2003 + } 1.2004 + 1.2005 + for (i=0; i < count; ++i) { 1.2006 + // Here is where we escape from the loop. We escape 1.2007 + // if we've output the maximum fraction digits 1.2008 + // (specified in the for expression above). We also 1.2009 + // stop when we've output the minimum digits and 1.2010 + // either: we have an integer, so there is no 1.2011 + // fractional stuff to display, or we're out of 1.2012 + // significant digits. 1.2013 + if (!useSigDig && i >= getMinimumFractionDigits() && 1.2014 + (isInteger || digitIndex >= digits.getCount())) { 1.2015 + break; 1.2016 + } 1.2017 + 1.2018 + // Output leading fractional zeros. These are zeros 1.2019 + // that come after the decimal but before any 1.2020 + // significant digits. These are only output if 1.2021 + // abs(number being formatted) < 1.0. 1.2022 + if (-1-i > (digits.getDecimalAt()-1)) { 1.2023 + appendTo += localizedDigits[0]; 1.2024 + continue; 1.2025 + } 1.2026 + 1.2027 + // Output a digit, if we have any precision left, or a 1.2028 + // zero if we don't. We don't want to output noise digits. 1.2029 + if (!isInteger && digitIndex < digits.getCount()) { 1.2030 + appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)]; 1.2031 + } else { 1.2032 + appendTo += localizedDigits[0]; 1.2033 + } 1.2034 + 1.2035 + // If we reach the maximum number of significant 1.2036 + // digits, or if we output all the real digits and 1.2037 + // reach the minimum, then we are done. 1.2038 + ++sigCount; 1.2039 + if (useSigDig && 1.2040 + (sigCount == maxSigDig || 1.2041 + (digitIndex == digits.getCount() && sigCount >= minSigDig))) { 1.2042 + break; 1.2043 + } 1.2044 + } 1.2045 + 1.2046 + handler.addAttribute(kFractionField, fracBegin, appendTo.length()); 1.2047 + } 1.2048 + 1.2049 + int32_t suffixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), FALSE); 1.2050 + 1.2051 + addPadding(appendTo, handler, prefixLen, suffixLen); 1.2052 + return appendTo; 1.2053 +} 1.2054 + 1.2055 +/** 1.2056 + * Inserts the character fPad as needed to expand result to fFormatWidth. 1.2057 + * @param result the string to be padded 1.2058 + */ 1.2059 +void DecimalFormat::addPadding(UnicodeString& appendTo, 1.2060 + FieldPositionHandler& handler, 1.2061 + int32_t prefixLen, 1.2062 + int32_t suffixLen) const 1.2063 +{ 1.2064 + if (fFormatWidth > 0) { 1.2065 + int32_t len = fFormatWidth - appendTo.length(); 1.2066 + if (len > 0) { 1.2067 + UnicodeString padding; 1.2068 + for (int32_t i=0; i<len; ++i) { 1.2069 + padding += fPad; 1.2070 + } 1.2071 + switch (fPadPosition) { 1.2072 + case kPadAfterPrefix: 1.2073 + appendTo.insert(prefixLen, padding); 1.2074 + break; 1.2075 + case kPadBeforePrefix: 1.2076 + appendTo.insert(0, padding); 1.2077 + break; 1.2078 + case kPadBeforeSuffix: 1.2079 + appendTo.insert(appendTo.length() - suffixLen, padding); 1.2080 + break; 1.2081 + case kPadAfterSuffix: 1.2082 + appendTo += padding; 1.2083 + break; 1.2084 + } 1.2085 + if (fPadPosition == kPadBeforePrefix || fPadPosition == kPadAfterPrefix) { 1.2086 + handler.shiftLast(len); 1.2087 + } 1.2088 + } 1.2089 + } 1.2090 +} 1.2091 + 1.2092 +//------------------------------------------------------------------------------ 1.2093 + 1.2094 +void 1.2095 +DecimalFormat::parse(const UnicodeString& text, 1.2096 + Formattable& result, 1.2097 + ParsePosition& parsePosition) const { 1.2098 + parse(text, result, parsePosition, NULL); 1.2099 +} 1.2100 + 1.2101 +CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, 1.2102 + ParsePosition& pos) const { 1.2103 + Formattable parseResult; 1.2104 + int32_t start = pos.getIndex(); 1.2105 + UChar curbuf[4] = {}; 1.2106 + parse(text, parseResult, pos, curbuf); 1.2107 + if (pos.getIndex() != start) { 1.2108 + UErrorCode ec = U_ZERO_ERROR; 1.2109 + LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec)); 1.2110 + if (U_FAILURE(ec)) { 1.2111 + pos.setIndex(start); // indicate failure 1.2112 + } else { 1.2113 + return currAmt.orphan(); 1.2114 + } 1.2115 + } 1.2116 + return NULL; 1.2117 +} 1.2118 + 1.2119 +/** 1.2120 + * Parses the given text as a number, optionally providing a currency amount. 1.2121 + * @param text the string to parse 1.2122 + * @param result output parameter for the numeric result. 1.2123 + * @param parsePosition input-output position; on input, the 1.2124 + * position within text to match; must have 0 <= pos.getIndex() < 1.2125 + * text.length(); on output, the position after the last matched 1.2126 + * character. If the parse fails, the position in unchanged upon 1.2127 + * output. 1.2128 + * @param currency if non-NULL, it should point to a 4-UChar buffer. 1.2129 + * In this case the text is parsed as a currency format, and the 1.2130 + * ISO 4217 code for the parsed currency is put into the buffer. 1.2131 + * Otherwise the text is parsed as a non-currency format. 1.2132 + */ 1.2133 +void DecimalFormat::parse(const UnicodeString& text, 1.2134 + Formattable& result, 1.2135 + ParsePosition& parsePosition, 1.2136 + UChar* currency) const { 1.2137 + int32_t startIdx, backup; 1.2138 + int32_t i = startIdx = backup = parsePosition.getIndex(); 1.2139 + 1.2140 + // clear any old contents in the result. In particular, clears any DigitList 1.2141 + // that it may be holding. 1.2142 + result.setLong(0); 1.2143 + if (currency != NULL) { 1.2144 + for (int32_t ci=0; ci<4; ci++) { 1.2145 + currency[ci] = 0; 1.2146 + } 1.2147 + } 1.2148 + 1.2149 + // Handle NaN as a special case: 1.2150 + 1.2151 + // Skip padding characters, if around prefix 1.2152 + if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix || 1.2153 + fPadPosition == kPadAfterPrefix)) { 1.2154 + i = skipPadding(text, i); 1.2155 + } 1.2156 + 1.2157 + if (isLenient()) { 1.2158 + // skip any leading whitespace 1.2159 + i = backup = skipUWhiteSpace(text, i); 1.2160 + } 1.2161 + 1.2162 + // If the text is composed of the representation of NaN, returns NaN.length 1.2163 + const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 1.2164 + int32_t nanLen = (text.compare(i, nan->length(), *nan) 1.2165 + ? 0 : nan->length()); 1.2166 + if (nanLen) { 1.2167 + i += nanLen; 1.2168 + if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix || 1.2169 + fPadPosition == kPadAfterSuffix)) { 1.2170 + i = skipPadding(text, i); 1.2171 + } 1.2172 + parsePosition.setIndex(i); 1.2173 + result.setDouble(uprv_getNaN()); 1.2174 + return; 1.2175 + } 1.2176 + 1.2177 + // NaN parse failed; start over 1.2178 + i = backup; 1.2179 + parsePosition.setIndex(i); 1.2180 + 1.2181 + // status is used to record whether a number is infinite. 1.2182 + UBool status[fgStatusLength]; 1.2183 + 1.2184 + DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer 1.2185 + if (digits == NULL) { 1.2186 + return; // no way to report error from here. 1.2187 + } 1.2188 + 1.2189 + if (fCurrencySignCount != fgCurrencySignCountZero) { 1.2190 + if (!parseForCurrency(text, parsePosition, *digits, 1.2191 + status, currency)) { 1.2192 + return; 1.2193 + } 1.2194 + } else { 1.2195 + if (!subparse(text, 1.2196 + fNegPrefixPattern, fNegSuffixPattern, 1.2197 + fPosPrefixPattern, fPosSuffixPattern, 1.2198 + FALSE, UCURR_SYMBOL_NAME, 1.2199 + parsePosition, *digits, status, currency)) { 1.2200 + debug("!subparse(...) - rewind"); 1.2201 + parsePosition.setIndex(startIdx); 1.2202 + return; 1.2203 + } 1.2204 + } 1.2205 + 1.2206 + // Handle infinity 1.2207 + if (status[fgStatusInfinite]) { 1.2208 + double inf = uprv_getInfinity(); 1.2209 + result.setDouble(digits->isPositive() ? inf : -inf); 1.2210 + // TODO: set the dl to infinity, and let it fall into the code below. 1.2211 + } 1.2212 + 1.2213 + else { 1.2214 + 1.2215 + if (fMultiplier != NULL) { 1.2216 + UErrorCode ec = U_ZERO_ERROR; 1.2217 + digits->div(*fMultiplier, ec); 1.2218 + } 1.2219 + 1.2220 + if (fScale != 0) { 1.2221 + DigitList ten; 1.2222 + ten.set((int32_t)10); 1.2223 + if (fScale > 0) { 1.2224 + for (int32_t i = fScale; i > 0; i--) { 1.2225 + UErrorCode ec = U_ZERO_ERROR; 1.2226 + digits->div(ten,ec); 1.2227 + } 1.2228 + } else { 1.2229 + for (int32_t i = fScale; i < 0; i++) { 1.2230 + UErrorCode ec = U_ZERO_ERROR; 1.2231 + digits->mult(ten,ec); 1.2232 + } 1.2233 + } 1.2234 + } 1.2235 + 1.2236 + // Negative zero special case: 1.2237 + // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable. 1.2238 + // if not parsing integerOnly, leave as -0, which a double can represent. 1.2239 + if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) { 1.2240 + digits->setPositive(TRUE); 1.2241 + } 1.2242 + result.adoptDigitList(digits); 1.2243 + } 1.2244 +} 1.2245 + 1.2246 + 1.2247 + 1.2248 +UBool 1.2249 +DecimalFormat::parseForCurrency(const UnicodeString& text, 1.2250 + ParsePosition& parsePosition, 1.2251 + DigitList& digits, 1.2252 + UBool* status, 1.2253 + UChar* currency) const { 1.2254 + int origPos = parsePosition.getIndex(); 1.2255 + int maxPosIndex = origPos; 1.2256 + int maxErrorPos = -1; 1.2257 + // First, parse against current pattern. 1.2258 + // Since current pattern could be set by applyPattern(), 1.2259 + // it could be an arbitrary pattern, and it may not be the one 1.2260 + // defined in current locale. 1.2261 + UBool tmpStatus[fgStatusLength]; 1.2262 + ParsePosition tmpPos(origPos); 1.2263 + DigitList tmpDigitList; 1.2264 + UBool found; 1.2265 + if (fStyle == UNUM_CURRENCY_PLURAL) { 1.2266 + found = subparse(text, 1.2267 + fNegPrefixPattern, fNegSuffixPattern, 1.2268 + fPosPrefixPattern, fPosSuffixPattern, 1.2269 + TRUE, UCURR_LONG_NAME, 1.2270 + tmpPos, tmpDigitList, tmpStatus, currency); 1.2271 + } else { 1.2272 + found = subparse(text, 1.2273 + fNegPrefixPattern, fNegSuffixPattern, 1.2274 + fPosPrefixPattern, fPosSuffixPattern, 1.2275 + TRUE, UCURR_SYMBOL_NAME, 1.2276 + tmpPos, tmpDigitList, tmpStatus, currency); 1.2277 + } 1.2278 + if (found) { 1.2279 + if (tmpPos.getIndex() > maxPosIndex) { 1.2280 + maxPosIndex = tmpPos.getIndex(); 1.2281 + for (int32_t i = 0; i < fgStatusLength; ++i) { 1.2282 + status[i] = tmpStatus[i]; 1.2283 + } 1.2284 + digits = tmpDigitList; 1.2285 + } 1.2286 + } else { 1.2287 + maxErrorPos = tmpPos.getErrorIndex(); 1.2288 + } 1.2289 + // Then, parse against affix patterns. 1.2290 + // Those are currency patterns and currency plural patterns. 1.2291 + int32_t pos = -1; 1.2292 + const UHashElement* element = NULL; 1.2293 + while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 1.2294 + const UHashTok valueTok = element->value; 1.2295 + const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer; 1.2296 + UBool tmpStatus[fgStatusLength]; 1.2297 + ParsePosition tmpPos(origPos); 1.2298 + DigitList tmpDigitList; 1.2299 + 1.2300 +#ifdef FMT_DEBUG 1.2301 + debug("trying affix for currency.."); 1.2302 + affixPtn->dump(); 1.2303 +#endif 1.2304 + 1.2305 + UBool result = subparse(text, 1.2306 + &affixPtn->negPrefixPatternForCurrency, 1.2307 + &affixPtn->negSuffixPatternForCurrency, 1.2308 + &affixPtn->posPrefixPatternForCurrency, 1.2309 + &affixPtn->posSuffixPatternForCurrency, 1.2310 + TRUE, affixPtn->patternType, 1.2311 + tmpPos, tmpDigitList, tmpStatus, currency); 1.2312 + if (result) { 1.2313 + found = true; 1.2314 + if (tmpPos.getIndex() > maxPosIndex) { 1.2315 + maxPosIndex = tmpPos.getIndex(); 1.2316 + for (int32_t i = 0; i < fgStatusLength; ++i) { 1.2317 + status[i] = tmpStatus[i]; 1.2318 + } 1.2319 + digits = tmpDigitList; 1.2320 + } 1.2321 + } else { 1.2322 + maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? 1.2323 + tmpPos.getErrorIndex() : maxErrorPos; 1.2324 + } 1.2325 + } 1.2326 + // Finally, parse against simple affix to find the match. 1.2327 + // For example, in TestMonster suite, 1.2328 + // if the to-be-parsed text is "-\u00A40,00". 1.2329 + // complexAffixCompare will not find match, 1.2330 + // since there is no ISO code matches "\u00A4", 1.2331 + // and the parse stops at "\u00A4". 1.2332 + // We will just use simple affix comparison (look for exact match) 1.2333 + // to pass it. 1.2334 + // 1.2335 + // TODO: We should parse against simple affix first when 1.2336 + // output currency is not requested. After the complex currency 1.2337 + // parsing implementation was introduced, the default currency 1.2338 + // instance parsing slowed down because of the new code flow. 1.2339 + // I filed #10312 - Yoshito 1.2340 + UBool tmpStatus_2[fgStatusLength]; 1.2341 + ParsePosition tmpPos_2(origPos); 1.2342 + DigitList tmpDigitList_2; 1.2343 + 1.2344 + // Disable complex currency parsing and try it again. 1.2345 + UBool result = subparse(text, 1.2346 + &fNegativePrefix, &fNegativeSuffix, 1.2347 + &fPositivePrefix, &fPositiveSuffix, 1.2348 + FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME, 1.2349 + tmpPos_2, tmpDigitList_2, tmpStatus_2, 1.2350 + currency); 1.2351 + if (result) { 1.2352 + if (tmpPos_2.getIndex() > maxPosIndex) { 1.2353 + maxPosIndex = tmpPos_2.getIndex(); 1.2354 + for (int32_t i = 0; i < fgStatusLength; ++i) { 1.2355 + status[i] = tmpStatus_2[i]; 1.2356 + } 1.2357 + digits = tmpDigitList_2; 1.2358 + } 1.2359 + found = true; 1.2360 + } else { 1.2361 + maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ? 1.2362 + tmpPos_2.getErrorIndex() : maxErrorPos; 1.2363 + } 1.2364 + 1.2365 + if (!found) { 1.2366 + //parsePosition.setIndex(origPos); 1.2367 + parsePosition.setErrorIndex(maxErrorPos); 1.2368 + } else { 1.2369 + parsePosition.setIndex(maxPosIndex); 1.2370 + parsePosition.setErrorIndex(-1); 1.2371 + } 1.2372 + return found; 1.2373 +} 1.2374 + 1.2375 + 1.2376 +/** 1.2377 + * Parse the given text into a number. The text is parsed beginning at 1.2378 + * parsePosition, until an unparseable character is seen. 1.2379 + * @param text the string to parse. 1.2380 + * @param negPrefix negative prefix. 1.2381 + * @param negSuffix negative suffix. 1.2382 + * @param posPrefix positive prefix. 1.2383 + * @param posSuffix positive suffix. 1.2384 + * @param complexCurrencyParsing whether it is complex currency parsing or not. 1.2385 + * @param type the currency type to parse against, LONG_NAME only or not. 1.2386 + * @param parsePosition The position at which to being parsing. Upon 1.2387 + * return, the first unparsed character. 1.2388 + * @param digits the DigitList to set to the parsed value. 1.2389 + * @param status output param containing boolean status flags indicating 1.2390 + * whether the value was infinite and whether it was positive. 1.2391 + * @param currency return value for parsed currency, for generic 1.2392 + * currency parsing mode, or NULL for normal parsing. In generic 1.2393 + * currency parsing mode, any currency is parsed, not just the 1.2394 + * currency that this formatter is set to. 1.2395 + */ 1.2396 +UBool DecimalFormat::subparse(const UnicodeString& text, 1.2397 + const UnicodeString* negPrefix, 1.2398 + const UnicodeString* negSuffix, 1.2399 + const UnicodeString* posPrefix, 1.2400 + const UnicodeString* posSuffix, 1.2401 + UBool complexCurrencyParsing, 1.2402 + int8_t type, 1.2403 + ParsePosition& parsePosition, 1.2404 + DigitList& digits, UBool* status, 1.2405 + UChar* currency) const 1.2406 +{ 1.2407 + // The parsing process builds up the number as char string, in the neutral format that 1.2408 + // will be acceptable to the decNumber library, then at the end passes that string 1.2409 + // off for conversion to a decNumber. 1.2410 + UErrorCode err = U_ZERO_ERROR; 1.2411 + CharString parsedNum; 1.2412 + digits.setToZero(); 1.2413 + 1.2414 + int32_t position = parsePosition.getIndex(); 1.2415 + int32_t oldStart = position; 1.2416 + int32_t textLength = text.length(); // One less pointer to follow 1.2417 + UBool strictParse = !isLenient(); 1.2418 + UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 1.2419 + const UnicodeString *groupingString = &getConstSymbol(fCurrencySignCount == fgCurrencySignCountZero ? 1.2420 + DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); 1.2421 + UChar32 groupingChar = groupingString->char32At(0); 1.2422 + int32_t groupingStringLength = groupingString->length(); 1.2423 + int32_t groupingCharLength = U16_LENGTH(groupingChar); 1.2424 + UBool groupingUsed = isGroupingUsed(); 1.2425 +#ifdef FMT_DEBUG 1.2426 + UChar dbgbuf[300]; 1.2427 + UnicodeString s(dbgbuf,0,300);; 1.2428 + s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " ); 1.2429 +#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 ")); } 1.2430 + DBGAPPD(negPrefix); 1.2431 + DBGAPPD(negSuffix); 1.2432 + DBGAPPD(posPrefix); 1.2433 + DBGAPPD(posSuffix); 1.2434 + debugout(s); 1.2435 + printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, (isParseIntegerOnly())?'Y':'N', text.length(), negPrefix!=NULL?negPrefix->length():-1); 1.2436 +#endif 1.2437 + 1.2438 + UBool fastParseOk = false; /* TRUE iff fast parse is OK */ 1.2439 + // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */ 1.2440 + const DecimalFormatInternal &data = internalData(fReserved); 1.2441 + if((data.fFastParseStatus==kFastpathYES) && 1.2442 + fCurrencySignCount == fgCurrencySignCountZero && 1.2443 + // (negPrefix!=NULL&&negPrefix->isEmpty()) || 1.2444 + text.length()>0 && 1.2445 + text.length()<32 && 1.2446 + (posPrefix==NULL||posPrefix->isEmpty()) && 1.2447 + (posSuffix==NULL||posSuffix->isEmpty()) && 1.2448 + // (negPrefix==NULL||negPrefix->isEmpty()) && 1.2449 + // (negSuffix==NULL||(negSuffix->isEmpty()) ) && 1.2450 + TRUE) { // optimized path 1.2451 + int j=position; 1.2452 + int l=text.length(); 1.2453 + int digitCount=0; 1.2454 + UChar32 ch = text.char32At(j); 1.2455 + const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1.2456 + UChar32 decimalChar = 0; 1.2457 + UBool intOnly = FALSE; 1.2458 + UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0; 1.2459 + 1.2460 + int32_t decimalCount = decimalString->countChar32(0,3); 1.2461 + if(isParseIntegerOnly()) { 1.2462 + decimalChar = 0; // not allowed 1.2463 + intOnly = TRUE; // Don't look for decimals. 1.2464 + } else if(decimalCount==1) { 1.2465 + decimalChar = decimalString->char32At(0); // Look for this decimal 1.2466 + } else if(decimalCount==0) { 1.2467 + decimalChar=0; // NO decimal set 1.2468 + } else { 1.2469 + j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation. 1.2470 + } 1.2471 + 1.2472 +#ifdef FMT_DEBUG 1.2473 + printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n", 1.2474 + decimalChar, groupingChar, ch, 1.2475 + (intOnly)?'y':'n', 1.2476 + (strictParse)?'y':'n'); 1.2477 +#endif 1.2478 + if(ch==0x002D) { // '-' 1.2479 + j=l+1;//=break - negative number. 1.2480 + 1.2481 + /* 1.2482 + parsedNum.append('-',err); 1.2483 + j+=U16_LENGTH(ch); 1.2484 + if(j<l) ch = text.char32At(j); 1.2485 + */ 1.2486 + } else { 1.2487 + parsedNum.append('+',err); 1.2488 + } 1.2489 + while(j<l) { 1.2490 + int32_t digit = ch - zero; 1.2491 + if(digit >=0 && digit <= 9) { 1.2492 + parsedNum.append((char)(digit + '0'), err); 1.2493 + if((digitCount>0) || digit!=0 || j==(l-1)) { 1.2494 + digitCount++; 1.2495 + } 1.2496 + } else if(ch == 0) { // break out 1.2497 + digitCount=-1; 1.2498 + break; 1.2499 + } else if(ch == decimalChar) { 1.2500 + parsedNum.append((char)('.'), err); 1.2501 + decimalChar=0; // no more decimals. 1.2502 + // fastParseHadDecimal=TRUE; 1.2503 + } else if(ch == lookForGroup) { 1.2504 + // ignore grouping char. No decimals, so it has to be an ignorable grouping sep 1.2505 + } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) { 1.2506 + // parsing integer only and can fall through 1.2507 + } else { 1.2508 + digitCount=-1; // fail - fall through to slow parse 1.2509 + break; 1.2510 + } 1.2511 + j+=U16_LENGTH(ch); 1.2512 + ch = text.char32At(j); // for next 1.2513 + } 1.2514 + if( 1.2515 + ((j==l)||intOnly) // end OR only parsing integer 1.2516 + && (digitCount>0)) { // and have at least one digit 1.2517 +#ifdef FMT_DEBUG 1.2518 + printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2); 1.2519 +#endif 1.2520 + fastParseOk=true; // Fast parse OK! 1.2521 + 1.2522 +#ifdef SKIP_OPT 1.2523 + debug("SKIP_OPT"); 1.2524 + /* for testing, try it the slow way. also */ 1.2525 + fastParseOk=false; 1.2526 + parsedNum.clear(); 1.2527 +#else 1.2528 + parsePosition.setIndex(position=j); 1.2529 + status[fgStatusInfinite]=false; 1.2530 +#endif 1.2531 + } else { 1.2532 + // was not OK. reset, retry 1.2533 +#ifdef FMT_DEBUG 1.2534 + printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount); 1.2535 +#endif 1.2536 + parsedNum.clear(); 1.2537 + } 1.2538 + } else { 1.2539 +#ifdef FMT_DEBUG 1.2540 + printf("Could not fastpath parse. "); 1.2541 + printf("fFormatWidth=%d ", fFormatWidth); 1.2542 + printf("text.length()=%d ", text.length()); 1.2543 + printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix); 1.2544 + 1.2545 + printf("\n"); 1.2546 +#endif 1.2547 + } 1.2548 + 1.2549 + if(!fastParseOk 1.2550 +#if UCONFIG_HAVE_PARSEALLINPUT 1.2551 + && fParseAllInput!=UNUM_YES 1.2552 +#endif 1.2553 + ) 1.2554 + { 1.2555 + // Match padding before prefix 1.2556 + if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) { 1.2557 + position = skipPadding(text, position); 1.2558 + } 1.2559 + 1.2560 + // Match positive and negative prefixes; prefer longest match. 1.2561 + int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, complexCurrencyParsing, type, currency); 1.2562 + int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, complexCurrencyParsing, type, currency); 1.2563 + if (posMatch >= 0 && negMatch >= 0) { 1.2564 + if (posMatch > negMatch) { 1.2565 + negMatch = -1; 1.2566 + } else if (negMatch > posMatch) { 1.2567 + posMatch = -1; 1.2568 + } 1.2569 + } 1.2570 + if (posMatch >= 0) { 1.2571 + position += posMatch; 1.2572 + parsedNum.append('+', err); 1.2573 + } else if (negMatch >= 0) { 1.2574 + position += negMatch; 1.2575 + parsedNum.append('-', err); 1.2576 + } else if (strictParse){ 1.2577 + parsePosition.setErrorIndex(position); 1.2578 + return FALSE; 1.2579 + } else { 1.2580 + // Temporary set positive. This might be changed after checking suffix 1.2581 + parsedNum.append('+', err); 1.2582 + } 1.2583 + 1.2584 + // Match padding before prefix 1.2585 + if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) { 1.2586 + position = skipPadding(text, position); 1.2587 + } 1.2588 + 1.2589 + if (! strictParse) { 1.2590 + position = skipUWhiteSpace(text, position); 1.2591 + } 1.2592 + 1.2593 + // process digits or Inf, find decimal position 1.2594 + const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol); 1.2595 + int32_t infLen = (text.compare(position, inf->length(), *inf) 1.2596 + ? 0 : inf->length()); 1.2597 + position += infLen; // infLen is non-zero when it does equal to infinity 1.2598 + status[fgStatusInfinite] = infLen != 0; 1.2599 + 1.2600 + if (infLen != 0) { 1.2601 + parsedNum.append("Infinity", err); 1.2602 + } else { 1.2603 + // We now have a string of digits, possibly with grouping symbols, 1.2604 + // and decimal points. We want to process these into a DigitList. 1.2605 + // We don't want to put a bunch of leading zeros into the DigitList 1.2606 + // though, so we keep track of the location of the decimal point, 1.2607 + // put only significant digits into the DigitList, and adjust the 1.2608 + // exponent as needed. 1.2609 + 1.2610 + 1.2611 + UBool strictFail = FALSE; // did we exit with a strict parse failure? 1.2612 + int32_t lastGroup = -1; // where did we last see a grouping separator? 1.2613 + int32_t digitStart = position; 1.2614 + int32_t gs2 = fGroupingSize2 == 0 ? fGroupingSize : fGroupingSize2; 1.2615 + 1.2616 + const UnicodeString *decimalString; 1.2617 + if (fCurrencySignCount != fgCurrencySignCountZero) { 1.2618 + decimalString = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 1.2619 + } else { 1.2620 + decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1.2621 + } 1.2622 + UChar32 decimalChar = decimalString->char32At(0); 1.2623 + int32_t decimalStringLength = decimalString->length(); 1.2624 + int32_t decimalCharLength = U16_LENGTH(decimalChar); 1.2625 + 1.2626 + UBool sawDecimal = FALSE; 1.2627 + UChar32 sawDecimalChar = 0xFFFF; 1.2628 + UBool sawGrouping = FALSE; 1.2629 + UChar32 sawGroupingChar = 0xFFFF; 1.2630 + UBool sawDigit = FALSE; 1.2631 + int32_t backup = -1; 1.2632 + int32_t digit; 1.2633 + 1.2634 + // equivalent grouping and decimal support 1.2635 + const UnicodeSet *decimalSet = NULL; 1.2636 + const UnicodeSet *groupingSet = NULL; 1.2637 + 1.2638 + if (decimalCharLength == decimalStringLength) { 1.2639 + decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse); 1.2640 + } 1.2641 + 1.2642 + if (groupingCharLength == groupingStringLength) { 1.2643 + if (strictParse) { 1.2644 + groupingSet = fStaticSets->fStrictDefaultGroupingSeparators; 1.2645 + } else { 1.2646 + groupingSet = fStaticSets->fDefaultGroupingSeparators; 1.2647 + } 1.2648 + } 1.2649 + 1.2650 + // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized. 1.2651 + // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet 1.2652 + // If a character matches decimalSet, don't consider it to be a member of the groupingSet. 1.2653 + 1.2654 + // We have to track digitCount ourselves, because digits.fCount will 1.2655 + // pin when the maximum allowable digits is reached. 1.2656 + int32_t digitCount = 0; 1.2657 + int32_t integerDigitCount = 0; 1.2658 + 1.2659 + for (; position < textLength; ) 1.2660 + { 1.2661 + UChar32 ch = text.char32At(position); 1.2662 + 1.2663 + /* We recognize all digit ranges, not only the Latin digit range 1.2664 + * '0'..'9'. We do so by using the Character.digit() method, 1.2665 + * which converts a valid Unicode digit to the range 0..9. 1.2666 + * 1.2667 + * The character 'ch' may be a digit. If so, place its value 1.2668 + * from 0 to 9 in 'digit'. First try using the locale digit, 1.2669 + * which may or MAY NOT be a standard Unicode digit range. If 1.2670 + * this fails, try using the standard Unicode digit ranges by 1.2671 + * calling Character.digit(). If this also fails, digit will 1.2672 + * have a value outside the range 0..9. 1.2673 + */ 1.2674 + digit = ch - zero; 1.2675 + if (digit < 0 || digit > 9) 1.2676 + { 1.2677 + digit = u_charDigitValue(ch); 1.2678 + } 1.2679 + 1.2680 + // As a last resort, look through the localized digits if the zero digit 1.2681 + // is not a "standard" Unicode digit. 1.2682 + if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) { 1.2683 + digit = 0; 1.2684 + if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) { 1.2685 + break; 1.2686 + } 1.2687 + for (digit = 1 ; digit < 10 ; digit++ ) { 1.2688 + if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) { 1.2689 + break; 1.2690 + } 1.2691 + } 1.2692 + } 1.2693 + 1.2694 + if (digit >= 0 && digit <= 9) 1.2695 + { 1.2696 + if (strictParse && backup != -1) { 1.2697 + // comma followed by digit, so group before comma is a 1.2698 + // secondary group. If there was a group separator 1.2699 + // before that, the group must == the secondary group 1.2700 + // length, else it can be <= the the secondary group 1.2701 + // length. 1.2702 + if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) || 1.2703 + (lastGroup == -1 && position - digitStart - 1 > gs2)) { 1.2704 + strictFail = TRUE; 1.2705 + break; 1.2706 + } 1.2707 + 1.2708 + lastGroup = backup; 1.2709 + } 1.2710 + 1.2711 + // Cancel out backup setting (see grouping handler below) 1.2712 + backup = -1; 1.2713 + sawDigit = TRUE; 1.2714 + 1.2715 + // Note: this will append leading zeros 1.2716 + parsedNum.append((char)(digit + '0'), err); 1.2717 + 1.2718 + // count any digit that's not a leading zero 1.2719 + if (digit > 0 || digitCount > 0 || sawDecimal) { 1.2720 + digitCount += 1; 1.2721 + 1.2722 + // count any integer digit that's not a leading zero 1.2723 + if (! sawDecimal) { 1.2724 + integerDigitCount += 1; 1.2725 + } 1.2726 + } 1.2727 + 1.2728 + position += U16_LENGTH(ch); 1.2729 + } 1.2730 + else if (groupingStringLength > 0 && 1.2731 + matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet, 1.2732 + decimalChar, decimalSet, 1.2733 + ch) && groupingUsed) 1.2734 + { 1.2735 + if (sawDecimal) { 1.2736 + break; 1.2737 + } 1.2738 + 1.2739 + if (strictParse) { 1.2740 + if ((!sawDigit || backup != -1)) { 1.2741 + // leading group, or two group separators in a row 1.2742 + strictFail = TRUE; 1.2743 + break; 1.2744 + } 1.2745 + } 1.2746 + 1.2747 + // Ignore grouping characters, if we are using them, but require 1.2748 + // that they be followed by a digit. Otherwise we backup and 1.2749 + // reprocess them. 1.2750 + backup = position; 1.2751 + position += groupingStringLength; 1.2752 + sawGrouping=TRUE; 1.2753 + // Once we see a grouping character, we only accept that grouping character from then on. 1.2754 + sawGroupingChar=ch; 1.2755 + } 1.2756 + else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch)) 1.2757 + { 1.2758 + if (strictParse) { 1.2759 + if (backup != -1 || 1.2760 + (lastGroup != -1 && position - lastGroup != fGroupingSize + 1)) { 1.2761 + strictFail = TRUE; 1.2762 + break; 1.2763 + } 1.2764 + } 1.2765 + 1.2766 + // If we're only parsing integers, or if we ALREADY saw the 1.2767 + // decimal, then don't parse this one. 1.2768 + if (isParseIntegerOnly() || sawDecimal) { 1.2769 + break; 1.2770 + } 1.2771 + 1.2772 + parsedNum.append('.', err); 1.2773 + position += decimalStringLength; 1.2774 + sawDecimal = TRUE; 1.2775 + // Once we see a decimal character, we only accept that decimal character from then on. 1.2776 + sawDecimalChar=ch; 1.2777 + // decimalSet is considered to consist of (ch,ch) 1.2778 + } 1.2779 + else { 1.2780 + 1.2781 + if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless.. 1.2782 + isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways 1.2783 + const UnicodeString *tmp; 1.2784 + tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 1.2785 + // TODO: CASE 1.2786 + if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit 1.2787 + { 1.2788 + // Parse sign, if present 1.2789 + int32_t pos = position + tmp->length(); 1.2790 + char exponentSign = '+'; 1.2791 + 1.2792 + if (pos < textLength) 1.2793 + { 1.2794 + tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1.2795 + if (!text.compare(pos, tmp->length(), *tmp)) 1.2796 + { 1.2797 + pos += tmp->length(); 1.2798 + } 1.2799 + else { 1.2800 + tmp = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1.2801 + if (!text.compare(pos, tmp->length(), *tmp)) 1.2802 + { 1.2803 + exponentSign = '-'; 1.2804 + pos += tmp->length(); 1.2805 + } 1.2806 + } 1.2807 + } 1.2808 + 1.2809 + UBool sawExponentDigit = FALSE; 1.2810 + while (pos < textLength) { 1.2811 + ch = text[(int32_t)pos]; 1.2812 + digit = ch - zero; 1.2813 + 1.2814 + if (digit < 0 || digit > 9) { 1.2815 + digit = u_charDigitValue(ch); 1.2816 + } 1.2817 + if (0 <= digit && digit <= 9) { 1.2818 + if (!sawExponentDigit) { 1.2819 + parsedNum.append('E', err); 1.2820 + parsedNum.append(exponentSign, err); 1.2821 + sawExponentDigit = TRUE; 1.2822 + } 1.2823 + ++pos; 1.2824 + parsedNum.append((char)(digit + '0'), err); 1.2825 + } else { 1.2826 + break; 1.2827 + } 1.2828 + } 1.2829 + 1.2830 + if (sawExponentDigit) { 1.2831 + position = pos; // Advance past the exponent 1.2832 + } 1.2833 + 1.2834 + break; // Whether we fail or succeed, we exit this loop 1.2835 + } else { 1.2836 + break; 1.2837 + } 1.2838 + } else { // not parsing exponent 1.2839 + break; 1.2840 + } 1.2841 + } 1.2842 + } 1.2843 + 1.2844 + if (backup != -1) 1.2845 + { 1.2846 + position = backup; 1.2847 + } 1.2848 + 1.2849 + if (strictParse && !sawDecimal) { 1.2850 + if (lastGroup != -1 && position - lastGroup != fGroupingSize + 1) { 1.2851 + strictFail = TRUE; 1.2852 + } 1.2853 + } 1.2854 + 1.2855 + if (strictFail) { 1.2856 + // only set with strictParse and a grouping separator error 1.2857 + 1.2858 + parsePosition.setIndex(oldStart); 1.2859 + parsePosition.setErrorIndex(position); 1.2860 + debug("strictFail!"); 1.2861 + return FALSE; 1.2862 + } 1.2863 + 1.2864 + // If there was no decimal point we have an integer 1.2865 + 1.2866 + // If none of the text string was recognized. For example, parse 1.2867 + // "x" with pattern "#0.00" (return index and error index both 0) 1.2868 + // parse "$" with pattern "$#0.00". (return index 0 and error index 1.2869 + // 1). 1.2870 + if (!sawDigit && digitCount == 0) { 1.2871 +#ifdef FMT_DEBUG 1.2872 + debug("none of text rec"); 1.2873 + printf("position=%d\n",position); 1.2874 +#endif 1.2875 + parsePosition.setIndex(oldStart); 1.2876 + parsePosition.setErrorIndex(oldStart); 1.2877 + return FALSE; 1.2878 + } 1.2879 + } 1.2880 + 1.2881 + // Match padding before suffix 1.2882 + if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) { 1.2883 + position = skipPadding(text, position); 1.2884 + } 1.2885 + 1.2886 + int32_t posSuffixMatch = -1, negSuffixMatch = -1; 1.2887 + 1.2888 + // Match positive and negative suffixes; prefer longest match. 1.2889 + if (posMatch >= 0 || (!strictParse && negMatch < 0)) { 1.2890 + posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency); 1.2891 + } 1.2892 + if (negMatch >= 0) { 1.2893 + negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency); 1.2894 + } 1.2895 + if (posSuffixMatch >= 0 && negSuffixMatch >= 0) { 1.2896 + if (posSuffixMatch > negSuffixMatch) { 1.2897 + negSuffixMatch = -1; 1.2898 + } else if (negSuffixMatch > posSuffixMatch) { 1.2899 + posSuffixMatch = -1; 1.2900 + } 1.2901 + } 1.2902 + 1.2903 + // Fail if neither or both 1.2904 + if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) { 1.2905 + parsePosition.setErrorIndex(position); 1.2906 + debug("neither or both"); 1.2907 + return FALSE; 1.2908 + } 1.2909 + 1.2910 + position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0)); 1.2911 + 1.2912 + // Match padding before suffix 1.2913 + if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) { 1.2914 + position = skipPadding(text, position); 1.2915 + } 1.2916 + 1.2917 + parsePosition.setIndex(position); 1.2918 + 1.2919 + parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-'; 1.2920 +#ifdef FMT_DEBUG 1.2921 +printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err)); 1.2922 +#endif 1.2923 + } /* end SLOW parse */ 1.2924 + if(parsePosition.getIndex() == oldStart) 1.2925 + { 1.2926 +#ifdef FMT_DEBUG 1.2927 + printf(" PP didnt move, err\n"); 1.2928 +#endif 1.2929 + parsePosition.setErrorIndex(position); 1.2930 + return FALSE; 1.2931 + } 1.2932 +#if UCONFIG_HAVE_PARSEALLINPUT 1.2933 + else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength) 1.2934 + { 1.2935 +#ifdef FMT_DEBUG 1.2936 + printf(" PP didnt consume all (UNUM_YES), err\n"); 1.2937 +#endif 1.2938 + parsePosition.setErrorIndex(position); 1.2939 + return FALSE; 1.2940 + } 1.2941 +#endif 1.2942 + // uint32_t bits = (fastParseOk?kFastpathOk:0) | 1.2943 + // (fastParseHadDecimal?0:kNoDecimal); 1.2944 + //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits); 1.2945 + digits.set(parsedNum.toStringPiece(), 1.2946 + err, 1.2947 + 0//bits 1.2948 + ); 1.2949 + 1.2950 + if (U_FAILURE(err)) { 1.2951 +#ifdef FMT_DEBUG 1.2952 + printf(" err setting %s\n", u_errorName(err)); 1.2953 +#endif 1.2954 + parsePosition.setErrorIndex(position); 1.2955 + return FALSE; 1.2956 + } 1.2957 + return TRUE; 1.2958 +} 1.2959 + 1.2960 +/** 1.2961 + * Starting at position, advance past a run of pad characters, if any. 1.2962 + * Return the index of the first character after position that is not a pad 1.2963 + * character. Result is >= position. 1.2964 + */ 1.2965 +int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const { 1.2966 + int32_t padLen = U16_LENGTH(fPad); 1.2967 + while (position < text.length() && 1.2968 + text.char32At(position) == fPad) { 1.2969 + position += padLen; 1.2970 + } 1.2971 + return position; 1.2972 +} 1.2973 + 1.2974 +/** 1.2975 + * Return the length matched by the given affix, or -1 if none. 1.2976 + * Runs of white space in the affix, match runs of white space in 1.2977 + * the input. Pattern white space and input white space are 1.2978 + * determined differently; see code. 1.2979 + * @param text input text 1.2980 + * @param pos offset into input at which to begin matching 1.2981 + * @param isNegative 1.2982 + * @param isPrefix 1.2983 + * @param affixPat affix pattern used for currency affix comparison. 1.2984 + * @param complexCurrencyParsing whether it is currency parsing or not 1.2985 + * @param type the currency type to parse against, LONG_NAME only or not. 1.2986 + * @param currency return value for parsed currency, for generic 1.2987 + * currency parsing mode, or null for normal parsing. In generic 1.2988 + * currency parsing mode, any currency is parsed, not just the 1.2989 + * currency that this formatter is set to. 1.2990 + * @return length of input that matches, or -1 if match failure 1.2991 + */ 1.2992 +int32_t DecimalFormat::compareAffix(const UnicodeString& text, 1.2993 + int32_t pos, 1.2994 + UBool isNegative, 1.2995 + UBool isPrefix, 1.2996 + const UnicodeString* affixPat, 1.2997 + UBool complexCurrencyParsing, 1.2998 + int8_t type, 1.2999 + UChar* currency) const 1.3000 +{ 1.3001 + const UnicodeString *patternToCompare; 1.3002 + if (fCurrencyChoice != NULL || currency != NULL || 1.3003 + (fCurrencySignCount != fgCurrencySignCountZero && complexCurrencyParsing)) { 1.3004 + 1.3005 + if (affixPat != NULL) { 1.3006 + return compareComplexAffix(*affixPat, text, pos, type, currency); 1.3007 + } 1.3008 + } 1.3009 + 1.3010 + if (isNegative) { 1.3011 + if (isPrefix) { 1.3012 + patternToCompare = &fNegativePrefix; 1.3013 + } 1.3014 + else { 1.3015 + patternToCompare = &fNegativeSuffix; 1.3016 + } 1.3017 + } 1.3018 + else { 1.3019 + if (isPrefix) { 1.3020 + patternToCompare = &fPositivePrefix; 1.3021 + } 1.3022 + else { 1.3023 + patternToCompare = &fPositiveSuffix; 1.3024 + } 1.3025 + } 1.3026 + return compareSimpleAffix(*patternToCompare, text, pos, isLenient()); 1.3027 +} 1.3028 + 1.3029 +UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const { 1.3030 + if (lhs == rhs) { 1.3031 + return TRUE; 1.3032 + } 1.3033 + U_ASSERT(fStaticSets != NULL); // should already be loaded 1.3034 + const UnicodeSet *minusSigns = fStaticSets->fMinusSigns; 1.3035 + const UnicodeSet *plusSigns = fStaticSets->fPlusSigns; 1.3036 + return (minusSigns->contains(lhs) && minusSigns->contains(rhs)) || 1.3037 + (plusSigns->contains(lhs) && plusSigns->contains(rhs)); 1.3038 +} 1.3039 + 1.3040 +// check for LRM 0x200E, RLM 0x200F, ALM 0x061C 1.3041 +#define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C) 1.3042 + 1.3043 +#define TRIM_BUFLEN 32 1.3044 +UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix) { 1.3045 + UChar trimBuf[TRIM_BUFLEN]; 1.3046 + int32_t affixLen = affix.length(); 1.3047 + int32_t affixPos, trimLen = 0; 1.3048 + 1.3049 + for (affixPos = 0; affixPos < affixLen; affixPos++) { 1.3050 + UChar c = affix.charAt(affixPos); 1.3051 + if (!IS_BIDI_MARK(c)) { 1.3052 + if (trimLen < TRIM_BUFLEN) { 1.3053 + trimBuf[trimLen++] = c; 1.3054 + } else { 1.3055 + trimLen = 0; 1.3056 + break; 1.3057 + } 1.3058 + } 1.3059 + } 1.3060 + return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix); 1.3061 +} 1.3062 + 1.3063 +/** 1.3064 + * Return the length matched by the given affix, or -1 if none. 1.3065 + * Runs of white space in the affix, match runs of white space in 1.3066 + * the input. Pattern white space and input white space are 1.3067 + * determined differently; see code. 1.3068 + * @param affix pattern string, taken as a literal 1.3069 + * @param input input text 1.3070 + * @param pos offset into input at which to begin matching 1.3071 + * @return length of input that matches, or -1 if match failure 1.3072 + */ 1.3073 +int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix, 1.3074 + const UnicodeString& input, 1.3075 + int32_t pos, 1.3076 + UBool lenient) const { 1.3077 + int32_t start = pos; 1.3078 + UnicodeString trimmedAffix; 1.3079 + // For more efficiency we should keep lazily-created trimmed affixes around in 1.3080 + // instance variables instead of trimming each time they are used (the next step) 1.3081 + trimMarksFromAffix(affix, trimmedAffix); 1.3082 + UChar32 affixChar = trimmedAffix.char32At(0); 1.3083 + int32_t affixLength = trimmedAffix.length(); 1.3084 + int32_t inputLength = input.length(); 1.3085 + int32_t affixCharLength = U16_LENGTH(affixChar); 1.3086 + UnicodeSet *affixSet; 1.3087 + UErrorCode status = U_ZERO_ERROR; 1.3088 + 1.3089 + U_ASSERT(fStaticSets != NULL); // should already be loaded 1.3090 + 1.3091 + if (U_FAILURE(status)) { 1.3092 + return -1; 1.3093 + } 1.3094 + if (!lenient) { 1.3095 + affixSet = fStaticSets->fStrictDashEquivalents; 1.3096 + 1.3097 + // If the trimmedAffix is exactly one character long and that character 1.3098 + // is in the dash set and the very next input character is also 1.3099 + // in the dash set, return a match. 1.3100 + if (affixCharLength == affixLength && affixSet->contains(affixChar)) { 1.3101 + UChar32 ic = input.char32At(pos); 1.3102 + if (affixSet->contains(ic)) { 1.3103 + pos += U16_LENGTH(ic); 1.3104 + pos = skipBidiMarks(input, pos); // skip any trailing bidi marks 1.3105 + return pos - start; 1.3106 + } 1.3107 + } 1.3108 + 1.3109 + for (int32_t i = 0; i < affixLength; ) { 1.3110 + UChar32 c = trimmedAffix.char32At(i); 1.3111 + int32_t len = U16_LENGTH(c); 1.3112 + if (PatternProps::isWhiteSpace(c)) { 1.3113 + // We may have a pattern like: \u200F \u0020 1.3114 + // and input text like: \u200F \u0020 1.3115 + // Note that U+200F and U+0020 are Pattern_White_Space but only 1.3116 + // U+0020 is UWhiteSpace. So we have to first do a direct 1.3117 + // match of the run of Pattern_White_Space in the pattern, 1.3118 + // then match any extra characters. 1.3119 + UBool literalMatch = FALSE; 1.3120 + while (pos < inputLength) { 1.3121 + UChar32 ic = input.char32At(pos); 1.3122 + if (ic == c) { 1.3123 + literalMatch = TRUE; 1.3124 + i += len; 1.3125 + pos += len; 1.3126 + if (i == affixLength) { 1.3127 + break; 1.3128 + } 1.3129 + c = trimmedAffix.char32At(i); 1.3130 + len = U16_LENGTH(c); 1.3131 + if (!PatternProps::isWhiteSpace(c)) { 1.3132 + break; 1.3133 + } 1.3134 + } else if (IS_BIDI_MARK(ic)) { 1.3135 + pos ++; // just skip over this input text 1.3136 + } else { 1.3137 + break; 1.3138 + } 1.3139 + } 1.3140 + 1.3141 + // Advance over run in pattern 1.3142 + i = skipPatternWhiteSpace(trimmedAffix, i); 1.3143 + 1.3144 + // Advance over run in input text 1.3145 + // Must see at least one white space char in input, 1.3146 + // unless we've already matched some characters literally. 1.3147 + int32_t s = pos; 1.3148 + pos = skipUWhiteSpace(input, pos); 1.3149 + if (pos == s && !literalMatch) { 1.3150 + return -1; 1.3151 + } 1.3152 + 1.3153 + // If we skip UWhiteSpace in the input text, we need to skip it in the pattern. 1.3154 + // Otherwise, the previous lines may have skipped over text (such as U+00A0) that 1.3155 + // is also in the trimmedAffix. 1.3156 + i = skipUWhiteSpace(trimmedAffix, i); 1.3157 + } else { 1.3158 + UBool match = FALSE; 1.3159 + while (pos < inputLength) { 1.3160 + UChar32 ic = input.char32At(pos); 1.3161 + if (!match && ic == c) { 1.3162 + i += len; 1.3163 + pos += len; 1.3164 + match = TRUE; 1.3165 + } else if (IS_BIDI_MARK(ic)) { 1.3166 + pos++; // just skip over this input text 1.3167 + } else { 1.3168 + break; 1.3169 + } 1.3170 + } 1.3171 + if (!match) { 1.3172 + return -1; 1.3173 + } 1.3174 + } 1.3175 + } 1.3176 + } else { 1.3177 + UBool match = FALSE; 1.3178 + 1.3179 + affixSet = fStaticSets->fDashEquivalents; 1.3180 + 1.3181 + if (affixCharLength == affixLength && affixSet->contains(affixChar)) { 1.3182 + pos = skipUWhiteSpaceAndMarks(input, pos); 1.3183 + UChar32 ic = input.char32At(pos); 1.3184 + 1.3185 + if (affixSet->contains(ic)) { 1.3186 + pos += U16_LENGTH(ic); 1.3187 + pos = skipBidiMarks(input, pos); 1.3188 + return pos - start; 1.3189 + } 1.3190 + } 1.3191 + 1.3192 + for (int32_t i = 0; i < affixLength; ) 1.3193 + { 1.3194 + //i = skipRuleWhiteSpace(trimmedAffix, i); 1.3195 + i = skipUWhiteSpace(trimmedAffix, i); 1.3196 + pos = skipUWhiteSpaceAndMarks(input, pos); 1.3197 + 1.3198 + if (i >= affixLength || pos >= inputLength) { 1.3199 + break; 1.3200 + } 1.3201 + 1.3202 + UChar32 c = trimmedAffix.char32At(i); 1.3203 + UChar32 ic = input.char32At(pos); 1.3204 + 1.3205 + if (!equalWithSignCompatibility(ic, c)) { 1.3206 + return -1; 1.3207 + } 1.3208 + 1.3209 + match = TRUE; 1.3210 + i += U16_LENGTH(c); 1.3211 + pos += U16_LENGTH(ic); 1.3212 + pos = skipBidiMarks(input, pos); 1.3213 + } 1.3214 + 1.3215 + if (affixLength > 0 && ! match) { 1.3216 + return -1; 1.3217 + } 1.3218 + } 1.3219 + return pos - start; 1.3220 +} 1.3221 + 1.3222 +/** 1.3223 + * Skip over a run of zero or more Pattern_White_Space characters at 1.3224 + * pos in text. 1.3225 + */ 1.3226 +int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) { 1.3227 + const UChar* s = text.getBuffer(); 1.3228 + return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s); 1.3229 +} 1.3230 + 1.3231 +/** 1.3232 + * Skip over a run of zero or more isUWhiteSpace() characters at pos 1.3233 + * in text. 1.3234 + */ 1.3235 +int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) { 1.3236 + while (pos < text.length()) { 1.3237 + UChar32 c = text.char32At(pos); 1.3238 + if (!u_isUWhiteSpace(c)) { 1.3239 + break; 1.3240 + } 1.3241 + pos += U16_LENGTH(c); 1.3242 + } 1.3243 + return pos; 1.3244 +} 1.3245 + 1.3246 +/** 1.3247 + * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos 1.3248 + * in text. 1.3249 + */ 1.3250 +int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos) { 1.3251 + while (pos < text.length()) { 1.3252 + UChar32 c = text.char32At(pos); 1.3253 + if (!u_isUWhiteSpace(c) && !IS_BIDI_MARK(c)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM 1.3254 + break; 1.3255 + } 1.3256 + pos += U16_LENGTH(c); 1.3257 + } 1.3258 + return pos; 1.3259 +} 1.3260 + 1.3261 +/** 1.3262 + * Skip over a run of zero or more bidi marks at pos in text. 1.3263 + */ 1.3264 +int32_t DecimalFormat::skipBidiMarks(const UnicodeString& text, int32_t pos) { 1.3265 + while (pos < text.length()) { 1.3266 + UChar c = text.charAt(pos); 1.3267 + if (!IS_BIDI_MARK(c)) { 1.3268 + break; 1.3269 + } 1.3270 + pos++; 1.3271 + } 1.3272 + return pos; 1.3273 +} 1.3274 + 1.3275 +/** 1.3276 + * Return the length matched by the given affix, or -1 if none. 1.3277 + * @param affixPat pattern string 1.3278 + * @param input input text 1.3279 + * @param pos offset into input at which to begin matching 1.3280 + * @param type the currency type to parse against, LONG_NAME only or not. 1.3281 + * @param currency return value for parsed currency, for generic 1.3282 + * currency parsing mode, or null for normal parsing. In generic 1.3283 + * currency parsing mode, any currency is parsed, not just the 1.3284 + * currency that this formatter is set to. 1.3285 + * @return length of input that matches, or -1 if match failure 1.3286 + */ 1.3287 +int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat, 1.3288 + const UnicodeString& text, 1.3289 + int32_t pos, 1.3290 + int8_t type, 1.3291 + UChar* currency) const 1.3292 +{ 1.3293 + int32_t start = pos; 1.3294 + U_ASSERT(currency != NULL || 1.3295 + (fCurrencyChoice != NULL && *getCurrency() != 0) || 1.3296 + fCurrencySignCount != fgCurrencySignCountZero); 1.3297 + 1.3298 + for (int32_t i=0; 1.3299 + i<affixPat.length() && pos >= 0; ) { 1.3300 + UChar32 c = affixPat.char32At(i); 1.3301 + i += U16_LENGTH(c); 1.3302 + 1.3303 + if (c == kQuote) { 1.3304 + U_ASSERT(i <= affixPat.length()); 1.3305 + c = affixPat.char32At(i); 1.3306 + i += U16_LENGTH(c); 1.3307 + 1.3308 + const UnicodeString* affix = NULL; 1.3309 + 1.3310 + switch (c) { 1.3311 + case kCurrencySign: { 1.3312 + // since the currency names in choice format is saved 1.3313 + // the same way as other currency names, 1.3314 + // do not need to do currency choice parsing here. 1.3315 + // the general currency parsing parse against all names, 1.3316 + // including names in choice format. 1.3317 + UBool intl = i<affixPat.length() && 1.3318 + affixPat.char32At(i) == kCurrencySign; 1.3319 + if (intl) { 1.3320 + ++i; 1.3321 + } 1.3322 + UBool plural = i<affixPat.length() && 1.3323 + affixPat.char32At(i) == kCurrencySign; 1.3324 + if (plural) { 1.3325 + ++i; 1.3326 + intl = FALSE; 1.3327 + } 1.3328 + // Parse generic currency -- anything for which we 1.3329 + // have a display name, or any 3-letter ISO code. 1.3330 + // Try to parse display name for our locale; first 1.3331 + // determine our locale. 1.3332 + const char* loc = fCurrencyPluralInfo->getLocale().getName(); 1.3333 + ParsePosition ppos(pos); 1.3334 + UChar curr[4]; 1.3335 + UErrorCode ec = U_ZERO_ERROR; 1.3336 + // Delegate parse of display name => ISO code to Currency 1.3337 + uprv_parseCurrency(loc, text, ppos, type, curr, ec); 1.3338 + 1.3339 + // If parse succeeds, populate currency[0] 1.3340 + if (U_SUCCESS(ec) && ppos.getIndex() != pos) { 1.3341 + if (currency) { 1.3342 + u_strcpy(currency, curr); 1.3343 + } else { 1.3344 + // The formatter is currency-style but the client has not requested 1.3345 + // the value of the parsed currency. In this case, if that value does 1.3346 + // not match the formatter's current value, then the parse fails. 1.3347 + UChar effectiveCurr[4]; 1.3348 + getEffectiveCurrency(effectiveCurr, ec); 1.3349 + if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) { 1.3350 + pos = -1; 1.3351 + continue; 1.3352 + } 1.3353 + } 1.3354 + pos = ppos.getIndex(); 1.3355 + } else if (!isLenient()){ 1.3356 + pos = -1; 1.3357 + } 1.3358 + continue; 1.3359 + } 1.3360 + case kPatternPercent: 1.3361 + affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 1.3362 + break; 1.3363 + case kPatternPerMill: 1.3364 + affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 1.3365 + break; 1.3366 + case kPatternPlus: 1.3367 + affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1.3368 + break; 1.3369 + case kPatternMinus: 1.3370 + affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1.3371 + break; 1.3372 + default: 1.3373 + // fall through to affix!=0 test, which will fail 1.3374 + break; 1.3375 + } 1.3376 + 1.3377 + if (affix != NULL) { 1.3378 + pos = match(text, pos, *affix); 1.3379 + continue; 1.3380 + } 1.3381 + } 1.3382 + 1.3383 + pos = match(text, pos, c); 1.3384 + if (PatternProps::isWhiteSpace(c)) { 1.3385 + i = skipPatternWhiteSpace(affixPat, i); 1.3386 + } 1.3387 + } 1.3388 + return pos - start; 1.3389 +} 1.3390 + 1.3391 +/** 1.3392 + * Match a single character at text[pos] and return the index of the 1.3393 + * next character upon success. Return -1 on failure. If 1.3394 + * ch is a Pattern_White_Space then match a run of white space in text. 1.3395 + */ 1.3396 +int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) { 1.3397 + if (PatternProps::isWhiteSpace(ch)) { 1.3398 + // Advance over run of white space in input text 1.3399 + // Must see at least one white space char in input 1.3400 + int32_t s = pos; 1.3401 + pos = skipPatternWhiteSpace(text, pos); 1.3402 + if (pos == s) { 1.3403 + return -1; 1.3404 + } 1.3405 + return pos; 1.3406 + } 1.3407 + return (pos >= 0 && text.char32At(pos) == ch) ? 1.3408 + (pos + U16_LENGTH(ch)) : -1; 1.3409 +} 1.3410 + 1.3411 +/** 1.3412 + * Match a string at text[pos] and return the index of the next 1.3413 + * character upon success. Return -1 on failure. Match a run of 1.3414 + * white space in str with a run of white space in text. 1.3415 + */ 1.3416 +int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) { 1.3417 + for (int32_t i=0; i<str.length() && pos >= 0; ) { 1.3418 + UChar32 ch = str.char32At(i); 1.3419 + i += U16_LENGTH(ch); 1.3420 + if (PatternProps::isWhiteSpace(ch)) { 1.3421 + i = skipPatternWhiteSpace(str, i); 1.3422 + } 1.3423 + pos = match(text, pos, ch); 1.3424 + } 1.3425 + return pos; 1.3426 +} 1.3427 + 1.3428 +UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol, 1.3429 + UnicodeSet *sset, UChar32 schar) 1.3430 +{ 1.3431 + if (sset != NULL) { 1.3432 + return sset->contains(schar); 1.3433 + } 1.3434 + 1.3435 + return text.compare(position, length, symbol) == 0; 1.3436 +} 1.3437 + 1.3438 +UBool DecimalFormat::matchDecimal(UChar32 symbolChar, 1.3439 + UBool sawDecimal, UChar32 sawDecimalChar, 1.3440 + const UnicodeSet *sset, UChar32 schar) { 1.3441 + if(sawDecimal) { 1.3442 + return schar==sawDecimalChar; 1.3443 + } else if(schar==symbolChar) { 1.3444 + return TRUE; 1.3445 + } else if(sset!=NULL) { 1.3446 + return sset->contains(schar); 1.3447 + } else { 1.3448 + return FALSE; 1.3449 + } 1.3450 +} 1.3451 + 1.3452 +UBool DecimalFormat::matchGrouping(UChar32 groupingChar, 1.3453 + UBool sawGrouping, UChar32 sawGroupingChar, 1.3454 + const UnicodeSet *sset, 1.3455 + UChar32 /*decimalChar*/, const UnicodeSet *decimalSet, 1.3456 + UChar32 schar) { 1.3457 + if(sawGrouping) { 1.3458 + return schar==sawGroupingChar; // previously found 1.3459 + } else if(schar==groupingChar) { 1.3460 + return TRUE; // char from symbols 1.3461 + } else if(sset!=NULL) { 1.3462 + return sset->contains(schar) && // in groupingSet but... 1.3463 + ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet 1.3464 + } else { 1.3465 + return FALSE; 1.3466 + } 1.3467 +} 1.3468 + 1.3469 + 1.3470 + 1.3471 +//------------------------------------------------------------------------------ 1.3472 +// Gets the pointer to the localized decimal format symbols 1.3473 + 1.3474 +const DecimalFormatSymbols* 1.3475 +DecimalFormat::getDecimalFormatSymbols() const 1.3476 +{ 1.3477 + return fSymbols; 1.3478 +} 1.3479 + 1.3480 +//------------------------------------------------------------------------------ 1.3481 +// De-owning the current localized symbols and adopt the new symbols. 1.3482 + 1.3483 +void 1.3484 +DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) 1.3485 +{ 1.3486 + if (symbolsToAdopt == NULL) { 1.3487 + return; // do not allow caller to set fSymbols to NULL 1.3488 + } 1.3489 + 1.3490 + UBool sameSymbols = FALSE; 1.3491 + if (fSymbols != NULL) { 1.3492 + sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == 1.3493 + symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) && 1.3494 + getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == 1.3495 + symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 1.3496 + delete fSymbols; 1.3497 + } 1.3498 + 1.3499 + fSymbols = symbolsToAdopt; 1.3500 + if (!sameSymbols) { 1.3501 + // If the currency symbols are the same, there is no need to recalculate. 1.3502 + setCurrencyForSymbols(); 1.3503 + } 1.3504 + expandAffixes(NULL); 1.3505 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3506 + handleChanged(); 1.3507 +#endif 1.3508 +} 1.3509 +//------------------------------------------------------------------------------ 1.3510 +// Setting the symbols is equlivalent to adopting a newly created localized 1.3511 +// symbols. 1.3512 + 1.3513 +void 1.3514 +DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) 1.3515 +{ 1.3516 + adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); 1.3517 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3518 + handleChanged(); 1.3519 +#endif 1.3520 +} 1.3521 + 1.3522 + 1.3523 +const CurrencyPluralInfo* 1.3524 +DecimalFormat::getCurrencyPluralInfo(void) const 1.3525 +{ 1.3526 + return fCurrencyPluralInfo; 1.3527 +} 1.3528 + 1.3529 + 1.3530 +void 1.3531 +DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) 1.3532 +{ 1.3533 + if (toAdopt != NULL) { 1.3534 + delete fCurrencyPluralInfo; 1.3535 + fCurrencyPluralInfo = toAdopt; 1.3536 + // re-set currency affix patterns and currency affixes. 1.3537 + if (fCurrencySignCount != fgCurrencySignCountZero) { 1.3538 + UErrorCode status = U_ZERO_ERROR; 1.3539 + if (fAffixPatternsForCurrency) { 1.3540 + deleteHashForAffixPattern(); 1.3541 + } 1.3542 + setupCurrencyAffixPatterns(status); 1.3543 + if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) { 1.3544 + // only setup the affixes of the plural pattern. 1.3545 + setupCurrencyAffixes(fFormatPattern, FALSE, TRUE, status); 1.3546 + } 1.3547 + } 1.3548 + } 1.3549 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3550 + handleChanged(); 1.3551 +#endif 1.3552 +} 1.3553 + 1.3554 +void 1.3555 +DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) 1.3556 +{ 1.3557 + adoptCurrencyPluralInfo(info.clone()); 1.3558 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3559 + handleChanged(); 1.3560 +#endif 1.3561 +} 1.3562 + 1.3563 + 1.3564 +/** 1.3565 + * Update the currency object to match the symbols. This method 1.3566 + * is used only when the caller has passed in a symbols object 1.3567 + * that may not be the default object for its locale. 1.3568 + */ 1.3569 +void 1.3570 +DecimalFormat::setCurrencyForSymbols() { 1.3571 + /*Bug 4212072 1.3572 + Update the affix strings accroding to symbols in order to keep 1.3573 + the affix strings up to date. 1.3574 + [Richard/GCL] 1.3575 + */ 1.3576 + 1.3577 + // With the introduction of the Currency object, the currency 1.3578 + // symbols in the DFS object are ignored. For backward 1.3579 + // compatibility, we check any explicitly set DFS object. If it 1.3580 + // is a default symbols object for its locale, we change the 1.3581 + // currency object to one for that locale. If it is custom, 1.3582 + // we set the currency to null. 1.3583 + UErrorCode ec = U_ZERO_ERROR; 1.3584 + const UChar* c = NULL; 1.3585 + const char* loc = fSymbols->getLocale().getName(); 1.3586 + UChar intlCurrencySymbol[4]; 1.3587 + ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec); 1.3588 + UnicodeString currencySymbol; 1.3589 + 1.3590 + uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec); 1.3591 + if (U_SUCCESS(ec) 1.3592 + && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol 1.3593 + && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == UnicodeString(intlCurrencySymbol)) 1.3594 + { 1.3595 + // Trap an error in mapping locale to currency. If we can't 1.3596 + // map, then don't fail and set the currency to "". 1.3597 + c = intlCurrencySymbol; 1.3598 + } 1.3599 + ec = U_ZERO_ERROR; // reset local error code! 1.3600 + setCurrencyInternally(c, ec); 1.3601 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3602 + handleChanged(); 1.3603 +#endif 1.3604 +} 1.3605 + 1.3606 + 1.3607 +//------------------------------------------------------------------------------ 1.3608 +// Gets the positive prefix of the number pattern. 1.3609 + 1.3610 +UnicodeString& 1.3611 +DecimalFormat::getPositivePrefix(UnicodeString& result) const 1.3612 +{ 1.3613 + result = fPositivePrefix; 1.3614 + return result; 1.3615 +} 1.3616 + 1.3617 +//------------------------------------------------------------------------------ 1.3618 +// Sets the positive prefix of the number pattern. 1.3619 + 1.3620 +void 1.3621 +DecimalFormat::setPositivePrefix(const UnicodeString& newValue) 1.3622 +{ 1.3623 + fPositivePrefix = newValue; 1.3624 + delete fPosPrefixPattern; 1.3625 + fPosPrefixPattern = 0; 1.3626 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3627 + handleChanged(); 1.3628 +#endif 1.3629 +} 1.3630 + 1.3631 +//------------------------------------------------------------------------------ 1.3632 +// Gets the negative prefix of the number pattern. 1.3633 + 1.3634 +UnicodeString& 1.3635 +DecimalFormat::getNegativePrefix(UnicodeString& result) const 1.3636 +{ 1.3637 + result = fNegativePrefix; 1.3638 + return result; 1.3639 +} 1.3640 + 1.3641 +//------------------------------------------------------------------------------ 1.3642 +// Gets the negative prefix of the number pattern. 1.3643 + 1.3644 +void 1.3645 +DecimalFormat::setNegativePrefix(const UnicodeString& newValue) 1.3646 +{ 1.3647 + fNegativePrefix = newValue; 1.3648 + delete fNegPrefixPattern; 1.3649 + fNegPrefixPattern = 0; 1.3650 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3651 + handleChanged(); 1.3652 +#endif 1.3653 +} 1.3654 + 1.3655 +//------------------------------------------------------------------------------ 1.3656 +// Gets the positive suffix of the number pattern. 1.3657 + 1.3658 +UnicodeString& 1.3659 +DecimalFormat::getPositiveSuffix(UnicodeString& result) const 1.3660 +{ 1.3661 + result = fPositiveSuffix; 1.3662 + return result; 1.3663 +} 1.3664 + 1.3665 +//------------------------------------------------------------------------------ 1.3666 +// Sets the positive suffix of the number pattern. 1.3667 + 1.3668 +void 1.3669 +DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) 1.3670 +{ 1.3671 + fPositiveSuffix = newValue; 1.3672 + delete fPosSuffixPattern; 1.3673 + fPosSuffixPattern = 0; 1.3674 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3675 + handleChanged(); 1.3676 +#endif 1.3677 +} 1.3678 + 1.3679 +//------------------------------------------------------------------------------ 1.3680 +// Gets the negative suffix of the number pattern. 1.3681 + 1.3682 +UnicodeString& 1.3683 +DecimalFormat::getNegativeSuffix(UnicodeString& result) const 1.3684 +{ 1.3685 + result = fNegativeSuffix; 1.3686 + return result; 1.3687 +} 1.3688 + 1.3689 +//------------------------------------------------------------------------------ 1.3690 +// Sets the negative suffix of the number pattern. 1.3691 + 1.3692 +void 1.3693 +DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) 1.3694 +{ 1.3695 + fNegativeSuffix = newValue; 1.3696 + delete fNegSuffixPattern; 1.3697 + fNegSuffixPattern = 0; 1.3698 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3699 + handleChanged(); 1.3700 +#endif 1.3701 +} 1.3702 + 1.3703 +//------------------------------------------------------------------------------ 1.3704 +// Gets the multiplier of the number pattern. 1.3705 +// Multipliers are stored as decimal numbers (DigitLists) because that 1.3706 +// is the most convenient for muliplying or dividing the numbers to be formatted. 1.3707 +// A NULL multiplier implies one, and the scaling operations are skipped. 1.3708 + 1.3709 +int32_t 1.3710 +DecimalFormat::getMultiplier() const 1.3711 +{ 1.3712 + if (fMultiplier == NULL) { 1.3713 + return 1; 1.3714 + } else { 1.3715 + return fMultiplier->getLong(); 1.3716 + } 1.3717 +} 1.3718 + 1.3719 +//------------------------------------------------------------------------------ 1.3720 +// Sets the multiplier of the number pattern. 1.3721 +void 1.3722 +DecimalFormat::setMultiplier(int32_t newValue) 1.3723 +{ 1.3724 +// if (newValue == 0) { 1.3725 +// throw new IllegalArgumentException("Bad multiplier: " + newValue); 1.3726 +// } 1.3727 + if (newValue == 0) { 1.3728 + newValue = 1; // one being the benign default value for a multiplier. 1.3729 + } 1.3730 + if (newValue == 1) { 1.3731 + delete fMultiplier; 1.3732 + fMultiplier = NULL; 1.3733 + } else { 1.3734 + if (fMultiplier == NULL) { 1.3735 + fMultiplier = new DigitList; 1.3736 + } 1.3737 + if (fMultiplier != NULL) { 1.3738 + fMultiplier->set(newValue); 1.3739 + } 1.3740 + } 1.3741 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3742 + handleChanged(); 1.3743 +#endif 1.3744 +} 1.3745 + 1.3746 +/** 1.3747 + * Get the rounding increment. 1.3748 + * @return A positive rounding increment, or 0.0 if rounding 1.3749 + * is not in effect. 1.3750 + * @see #setRoundingIncrement 1.3751 + * @see #getRoundingMode 1.3752 + * @see #setRoundingMode 1.3753 + */ 1.3754 +double DecimalFormat::getRoundingIncrement() const { 1.3755 + if (fRoundingIncrement == NULL) { 1.3756 + return 0.0; 1.3757 + } else { 1.3758 + return fRoundingIncrement->getDouble(); 1.3759 + } 1.3760 +} 1.3761 + 1.3762 +/** 1.3763 + * Set the rounding increment. This method also controls whether 1.3764 + * rounding is enabled. 1.3765 + * @param newValue A positive rounding increment, or 0.0 to disable rounding. 1.3766 + * Negative increments are equivalent to 0.0. 1.3767 + * @see #getRoundingIncrement 1.3768 + * @see #getRoundingMode 1.3769 + * @see #setRoundingMode 1.3770 + */ 1.3771 +void DecimalFormat::setRoundingIncrement(double newValue) { 1.3772 + if (newValue > 0.0) { 1.3773 + if (fRoundingIncrement == NULL) { 1.3774 + fRoundingIncrement = new DigitList(); 1.3775 + } 1.3776 + if (fRoundingIncrement != NULL) { 1.3777 + fRoundingIncrement->set(newValue); 1.3778 + return; 1.3779 + } 1.3780 + } 1.3781 + // These statements are executed if newValue is less than 0.0 1.3782 + // or fRoundingIncrement could not be created. 1.3783 + delete fRoundingIncrement; 1.3784 + fRoundingIncrement = NULL; 1.3785 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3786 + handleChanged(); 1.3787 +#endif 1.3788 +} 1.3789 + 1.3790 +/** 1.3791 + * Get the rounding mode. 1.3792 + * @return A rounding mode 1.3793 + * @see #setRoundingIncrement 1.3794 + * @see #getRoundingIncrement 1.3795 + * @see #setRoundingMode 1.3796 + */ 1.3797 +DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const { 1.3798 + return fRoundingMode; 1.3799 +} 1.3800 + 1.3801 +/** 1.3802 + * Set the rounding mode. This has no effect unless the rounding 1.3803 + * increment is greater than zero. 1.3804 + * @param roundingMode A rounding mode 1.3805 + * @see #setRoundingIncrement 1.3806 + * @see #getRoundingIncrement 1.3807 + * @see #getRoundingMode 1.3808 + */ 1.3809 +void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) { 1.3810 + fRoundingMode = roundingMode; 1.3811 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3812 + handleChanged(); 1.3813 +#endif 1.3814 +} 1.3815 + 1.3816 +/** 1.3817 + * Get the width to which the output of <code>format()</code> is padded. 1.3818 + * @return the format width, or zero if no padding is in effect 1.3819 + * @see #setFormatWidth 1.3820 + * @see #getPadCharacter 1.3821 + * @see #setPadCharacter 1.3822 + * @see #getPadPosition 1.3823 + * @see #setPadPosition 1.3824 + */ 1.3825 +int32_t DecimalFormat::getFormatWidth() const { 1.3826 + return fFormatWidth; 1.3827 +} 1.3828 + 1.3829 +/** 1.3830 + * Set the width to which the output of <code>format()</code> is padded. 1.3831 + * This method also controls whether padding is enabled. 1.3832 + * @param width the width to which to pad the result of 1.3833 + * <code>format()</code>, or zero to disable padding. A negative 1.3834 + * width is equivalent to 0. 1.3835 + * @see #getFormatWidth 1.3836 + * @see #getPadCharacter 1.3837 + * @see #setPadCharacter 1.3838 + * @see #getPadPosition 1.3839 + * @see #setPadPosition 1.3840 + */ 1.3841 +void DecimalFormat::setFormatWidth(int32_t width) { 1.3842 + fFormatWidth = (width > 0) ? width : 0; 1.3843 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3844 + handleChanged(); 1.3845 +#endif 1.3846 +} 1.3847 + 1.3848 +UnicodeString DecimalFormat::getPadCharacterString() const { 1.3849 + return UnicodeString(fPad); 1.3850 +} 1.3851 + 1.3852 +void DecimalFormat::setPadCharacter(const UnicodeString &padChar) { 1.3853 + if (padChar.length() > 0) { 1.3854 + fPad = padChar.char32At(0); 1.3855 + } 1.3856 + else { 1.3857 + fPad = kDefaultPad; 1.3858 + } 1.3859 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3860 + handleChanged(); 1.3861 +#endif 1.3862 +} 1.3863 + 1.3864 +/** 1.3865 + * Get the position at which padding will take place. This is the location 1.3866 + * at which padding will be inserted if the result of <code>format()</code> 1.3867 + * is shorter than the format width. 1.3868 + * @return the pad position, one of <code>kPadBeforePrefix</code>, 1.3869 + * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 1.3870 + * <code>kPadAfterSuffix</code>. 1.3871 + * @see #setFormatWidth 1.3872 + * @see #getFormatWidth 1.3873 + * @see #setPadCharacter 1.3874 + * @see #getPadCharacter 1.3875 + * @see #setPadPosition 1.3876 + * @see #kPadBeforePrefix 1.3877 + * @see #kPadAfterPrefix 1.3878 + * @see #kPadBeforeSuffix 1.3879 + * @see #kPadAfterSuffix 1.3880 + */ 1.3881 +DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const { 1.3882 + return fPadPosition; 1.3883 +} 1.3884 + 1.3885 +/** 1.3886 + * <strong><font face=helvetica color=red>NEW</font></strong> 1.3887 + * Set the position at which padding will take place. This is the location 1.3888 + * at which padding will be inserted if the result of <code>format()</code> 1.3889 + * is shorter than the format width. This has no effect unless padding is 1.3890 + * enabled. 1.3891 + * @param padPos the pad position, one of <code>kPadBeforePrefix</code>, 1.3892 + * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 1.3893 + * <code>kPadAfterSuffix</code>. 1.3894 + * @see #setFormatWidth 1.3895 + * @see #getFormatWidth 1.3896 + * @see #setPadCharacter 1.3897 + * @see #getPadCharacter 1.3898 + * @see #getPadPosition 1.3899 + * @see #kPadBeforePrefix 1.3900 + * @see #kPadAfterPrefix 1.3901 + * @see #kPadBeforeSuffix 1.3902 + * @see #kPadAfterSuffix 1.3903 + */ 1.3904 +void DecimalFormat::setPadPosition(EPadPosition padPos) { 1.3905 + fPadPosition = padPos; 1.3906 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3907 + handleChanged(); 1.3908 +#endif 1.3909 +} 1.3910 + 1.3911 +/** 1.3912 + * Return whether or not scientific notation is used. 1.3913 + * @return TRUE if this object formats and parses scientific notation 1.3914 + * @see #setScientificNotation 1.3915 + * @see #getMinimumExponentDigits 1.3916 + * @see #setMinimumExponentDigits 1.3917 + * @see #isExponentSignAlwaysShown 1.3918 + * @see #setExponentSignAlwaysShown 1.3919 + */ 1.3920 +UBool DecimalFormat::isScientificNotation() const { 1.3921 + return fUseExponentialNotation; 1.3922 +} 1.3923 + 1.3924 +/** 1.3925 + * Set whether or not scientific notation is used. 1.3926 + * @param useScientific TRUE if this object formats and parses scientific 1.3927 + * notation 1.3928 + * @see #isScientificNotation 1.3929 + * @see #getMinimumExponentDigits 1.3930 + * @see #setMinimumExponentDigits 1.3931 + * @see #isExponentSignAlwaysShown 1.3932 + * @see #setExponentSignAlwaysShown 1.3933 + */ 1.3934 +void DecimalFormat::setScientificNotation(UBool useScientific) { 1.3935 + fUseExponentialNotation = useScientific; 1.3936 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3937 + handleChanged(); 1.3938 +#endif 1.3939 +} 1.3940 + 1.3941 +/** 1.3942 + * Return the minimum exponent digits that will be shown. 1.3943 + * @return the minimum exponent digits that will be shown 1.3944 + * @see #setScientificNotation 1.3945 + * @see #isScientificNotation 1.3946 + * @see #setMinimumExponentDigits 1.3947 + * @see #isExponentSignAlwaysShown 1.3948 + * @see #setExponentSignAlwaysShown 1.3949 + */ 1.3950 +int8_t DecimalFormat::getMinimumExponentDigits() const { 1.3951 + return fMinExponentDigits; 1.3952 +} 1.3953 + 1.3954 +/** 1.3955 + * Set the minimum exponent digits that will be shown. This has no 1.3956 + * effect unless scientific notation is in use. 1.3957 + * @param minExpDig a value >= 1 indicating the fewest exponent digits 1.3958 + * that will be shown. Values less than 1 will be treated as 1. 1.3959 + * @see #setScientificNotation 1.3960 + * @see #isScientificNotation 1.3961 + * @see #getMinimumExponentDigits 1.3962 + * @see #isExponentSignAlwaysShown 1.3963 + * @see #setExponentSignAlwaysShown 1.3964 + */ 1.3965 +void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) { 1.3966 + fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1); 1.3967 +#if UCONFIG_FORMAT_FASTPATHS_49 1.3968 + handleChanged(); 1.3969 +#endif 1.3970 +} 1.3971 + 1.3972 +/** 1.3973 + * Return whether the exponent sign is always shown. 1.3974 + * @return TRUE if the exponent is always prefixed with either the 1.3975 + * localized minus sign or the localized plus sign, false if only negative 1.3976 + * exponents are prefixed with the localized minus sign. 1.3977 + * @see #setScientificNotation 1.3978 + * @see #isScientificNotation 1.3979 + * @see #setMinimumExponentDigits 1.3980 + * @see #getMinimumExponentDigits 1.3981 + * @see #setExponentSignAlwaysShown 1.3982 + */ 1.3983 +UBool DecimalFormat::isExponentSignAlwaysShown() const { 1.3984 + return fExponentSignAlwaysShown; 1.3985 +} 1.3986 + 1.3987 +/** 1.3988 + * Set whether the exponent sign is always shown. This has no effect 1.3989 + * unless scientific notation is in use. 1.3990 + * @param expSignAlways TRUE if the exponent is always prefixed with either 1.3991 + * the localized minus sign or the localized plus sign, false if only 1.3992 + * negative exponents are prefixed with the localized minus sign. 1.3993 + * @see #setScientificNotation 1.3994 + * @see #isScientificNotation 1.3995 + * @see #setMinimumExponentDigits 1.3996 + * @see #getMinimumExponentDigits 1.3997 + * @see #isExponentSignAlwaysShown 1.3998 + */ 1.3999 +void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { 1.4000 + fExponentSignAlwaysShown = expSignAlways; 1.4001 +#if UCONFIG_FORMAT_FASTPATHS_49 1.4002 + handleChanged(); 1.4003 +#endif 1.4004 +} 1.4005 + 1.4006 +//------------------------------------------------------------------------------ 1.4007 +// Gets the grouping size of the number pattern. For example, thousand or 10 1.4008 +// thousand groupings. 1.4009 + 1.4010 +int32_t 1.4011 +DecimalFormat::getGroupingSize() const 1.4012 +{ 1.4013 + return fGroupingSize; 1.4014 +} 1.4015 + 1.4016 +//------------------------------------------------------------------------------ 1.4017 +// Gets the grouping size of the number pattern. 1.4018 + 1.4019 +void 1.4020 +DecimalFormat::setGroupingSize(int32_t newValue) 1.4021 +{ 1.4022 + fGroupingSize = newValue; 1.4023 +#if UCONFIG_FORMAT_FASTPATHS_49 1.4024 + handleChanged(); 1.4025 +#endif 1.4026 +} 1.4027 + 1.4028 +//------------------------------------------------------------------------------ 1.4029 + 1.4030 +int32_t 1.4031 +DecimalFormat::getSecondaryGroupingSize() const 1.4032 +{ 1.4033 + return fGroupingSize2; 1.4034 +} 1.4035 + 1.4036 +//------------------------------------------------------------------------------ 1.4037 + 1.4038 +void 1.4039 +DecimalFormat::setSecondaryGroupingSize(int32_t newValue) 1.4040 +{ 1.4041 + fGroupingSize2 = newValue; 1.4042 +#if UCONFIG_FORMAT_FASTPATHS_49 1.4043 + handleChanged(); 1.4044 +#endif 1.4045 +} 1.4046 + 1.4047 +//------------------------------------------------------------------------------ 1.4048 +// Checks if to show the decimal separator. 1.4049 + 1.4050 +UBool 1.4051 +DecimalFormat::isDecimalSeparatorAlwaysShown() const 1.4052 +{ 1.4053 + return fDecimalSeparatorAlwaysShown; 1.4054 +} 1.4055 + 1.4056 +//------------------------------------------------------------------------------ 1.4057 +// Sets to always show the decimal separator. 1.4058 + 1.4059 +void 1.4060 +DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) 1.4061 +{ 1.4062 + fDecimalSeparatorAlwaysShown = newValue; 1.4063 +#if UCONFIG_FORMAT_FASTPATHS_49 1.4064 + handleChanged(); 1.4065 +#endif 1.4066 +} 1.4067 + 1.4068 +//------------------------------------------------------------------------------ 1.4069 +// Emits the pattern of this DecimalFormat instance. 1.4070 + 1.4071 +UnicodeString& 1.4072 +DecimalFormat::toPattern(UnicodeString& result) const 1.4073 +{ 1.4074 + return toPattern(result, FALSE); 1.4075 +} 1.4076 + 1.4077 +//------------------------------------------------------------------------------ 1.4078 +// Emits the localized pattern this DecimalFormat instance. 1.4079 + 1.4080 +UnicodeString& 1.4081 +DecimalFormat::toLocalizedPattern(UnicodeString& result) const 1.4082 +{ 1.4083 + return toPattern(result, TRUE); 1.4084 +} 1.4085 + 1.4086 +//------------------------------------------------------------------------------ 1.4087 +/** 1.4088 + * Expand the affix pattern strings into the expanded affix strings. If any 1.4089 + * affix pattern string is null, do not expand it. This method should be 1.4090 + * called any time the symbols or the affix patterns change in order to keep 1.4091 + * the expanded affix strings up to date. 1.4092 + * This method also will be called before formatting if format currency 1.4093 + * plural names, since the plural name is not a static one, it is 1.4094 + * based on the currency plural count, the affix will be known only 1.4095 + * after the currency plural count is know. 1.4096 + * In which case, the parameter 1.4097 + * 'pluralCount' will be a non-null currency plural count. 1.4098 + * In all other cases, the 'pluralCount' is null, which means it is not needed. 1.4099 + */ 1.4100 +void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) { 1.4101 + FieldPositionHandler none; 1.4102 + if (fPosPrefixPattern != 0) { 1.4103 + expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCount); 1.4104 + } 1.4105 + if (fPosSuffixPattern != 0) { 1.4106 + expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCount); 1.4107 + } 1.4108 + if (fNegPrefixPattern != 0) { 1.4109 + expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCount); 1.4110 + } 1.4111 + if (fNegSuffixPattern != 0) { 1.4112 + expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCount); 1.4113 + } 1.4114 +#ifdef FMT_DEBUG 1.4115 + UnicodeString s; 1.4116 + s.append(UnicodeString("[")) 1.4117 + .append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fPosSuffixPattern)) 1.4118 + .append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fNegSuffixPattern)) 1.4119 + .append((UnicodeString)"]->[") 1.4120 + .append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuffix) 1.4121 + .append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeString)"|").append(fNegativeSuffix) 1.4122 + .append((UnicodeString)"]\n"); 1.4123 + debugout(s); 1.4124 +#endif 1.4125 +} 1.4126 + 1.4127 +/** 1.4128 + * Expand an affix pattern into an affix string. All characters in the 1.4129 + * pattern are literal unless prefixed by kQuote. The following characters 1.4130 + * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, 1.4131 + * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote + 1.4132 + * kCurrencySign + kCurrencySign), it is interpreted as an international 1.4133 + * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as 1.4134 + * currency plural long names, such as "US Dollars". 1.4135 + * Any other character after a kQuote represents itself. 1.4136 + * kQuote must be followed by another character; kQuote may not occur by 1.4137 + * itself at the end of the pattern. 1.4138 + * 1.4139 + * This method is used in two distinct ways. First, it is used to expand 1.4140 + * the stored affix patterns into actual affixes. For this usage, doFormat 1.4141 + * must be false. Second, it is used to expand the stored affix patterns 1.4142 + * given a specific number (doFormat == true), for those rare cases in 1.4143 + * which a currency format references a ChoiceFormat (e.g., en_IN display 1.4144 + * name for INR). The number itself is taken from digitList. 1.4145 + * 1.4146 + * When used in the first way, this method has a side effect: It sets 1.4147 + * currencyChoice to a ChoiceFormat object, if the currency's display name 1.4148 + * in this locale is a ChoiceFormat pattern (very rare). It only does this 1.4149 + * if currencyChoice is null to start with. 1.4150 + * 1.4151 + * @param pattern the non-null, fPossibly empty pattern 1.4152 + * @param affix string to receive the expanded equivalent of pattern. 1.4153 + * Previous contents are deleted. 1.4154 + * @param doFormat if false, then the pattern will be expanded, and if a 1.4155 + * currency symbol is encountered that expands to a ChoiceFormat, the 1.4156 + * currencyChoice member variable will be initialized if it is null. If 1.4157 + * doFormat is true, then it is assumed that the currencyChoice has been 1.4158 + * created, and it will be used to format the value in digitList. 1.4159 + * @param pluralCount the plural count. It is only used for currency 1.4160 + * plural format. In which case, it is the plural 1.4161 + * count of the currency amount. For example, 1.4162 + * in en_US, it is the singular "one", or the plural 1.4163 + * "other". For all other cases, it is null, and 1.4164 + * is not being used. 1.4165 + */ 1.4166 +void DecimalFormat::expandAffix(const UnicodeString& pattern, 1.4167 + UnicodeString& affix, 1.4168 + double number, 1.4169 + FieldPositionHandler& handler, 1.4170 + UBool doFormat, 1.4171 + const UnicodeString* pluralCount) const { 1.4172 + affix.remove(); 1.4173 + for (int i=0; i<pattern.length(); ) { 1.4174 + UChar32 c = pattern.char32At(i); 1.4175 + i += U16_LENGTH(c); 1.4176 + if (c == kQuote) { 1.4177 + c = pattern.char32At(i); 1.4178 + i += U16_LENGTH(c); 1.4179 + int beginIdx = affix.length(); 1.4180 + switch (c) { 1.4181 + case kCurrencySign: { 1.4182 + // As of ICU 2.2 we use the currency object, and 1.4183 + // ignore the currency symbols in the DFS, unless 1.4184 + // we have a null currency object. This occurs if 1.4185 + // resurrecting a pre-2.2 object or if the user 1.4186 + // sets a custom DFS. 1.4187 + UBool intl = i<pattern.length() && 1.4188 + pattern.char32At(i) == kCurrencySign; 1.4189 + UBool plural = FALSE; 1.4190 + if (intl) { 1.4191 + ++i; 1.4192 + plural = i<pattern.length() && 1.4193 + pattern.char32At(i) == kCurrencySign; 1.4194 + if (plural) { 1.4195 + intl = FALSE; 1.4196 + ++i; 1.4197 + } 1.4198 + } 1.4199 + const UChar* currencyUChars = getCurrency(); 1.4200 + if (currencyUChars[0] != 0) { 1.4201 + UErrorCode ec = U_ZERO_ERROR; 1.4202 + if (plural && pluralCount != NULL) { 1.4203 + // plural name is only needed when pluralCount != null, 1.4204 + // which means when formatting currency plural names. 1.4205 + // For other cases, pluralCount == null, 1.4206 + // and plural names are not needed. 1.4207 + int32_t len; 1.4208 + CharString pluralCountChar; 1.4209 + pluralCountChar.appendInvariantChars(*pluralCount, ec); 1.4210 + UBool isChoiceFormat; 1.4211 + const UChar* s = ucurr_getPluralName(currencyUChars, 1.4212 + fSymbols != NULL ? fSymbols->getLocale().getName() : 1.4213 + Locale::getDefault().getName(), &isChoiceFormat, 1.4214 + pluralCountChar.data(), &len, &ec); 1.4215 + affix += UnicodeString(s, len); 1.4216 + handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 1.4217 + } else if(intl) { 1.4218 + affix.append(currencyUChars, -1); 1.4219 + handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 1.4220 + } else { 1.4221 + int32_t len; 1.4222 + UBool isChoiceFormat; 1.4223 + // If fSymbols is NULL, use default locale 1.4224 + const UChar* s = ucurr_getName(currencyUChars, 1.4225 + fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(), 1.4226 + UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec); 1.4227 + if (isChoiceFormat) { 1.4228 + // Two modes here: If doFormat is false, we set up 1.4229 + // currencyChoice. If doFormat is true, we use the 1.4230 + // previously created currencyChoice to format the 1.4231 + // value in digitList. 1.4232 + if (!doFormat) { 1.4233 + // If the currency is handled by a ChoiceFormat, 1.4234 + // then we're not going to use the expanded 1.4235 + // patterns. Instantiate the ChoiceFormat and 1.4236 + // return. 1.4237 + if (fCurrencyChoice == NULL) { 1.4238 + // TODO Replace double-check with proper thread-safe code 1.4239 + ChoiceFormat* fmt = new ChoiceFormat(UnicodeString(s), ec); 1.4240 + if (U_SUCCESS(ec)) { 1.4241 + umtx_lock(NULL); 1.4242 + if (fCurrencyChoice == NULL) { 1.4243 + // Cast away const 1.4244 + ((DecimalFormat*)this)->fCurrencyChoice = fmt; 1.4245 + fmt = NULL; 1.4246 + } 1.4247 + umtx_unlock(NULL); 1.4248 + delete fmt; 1.4249 + } 1.4250 + } 1.4251 + // We could almost return null or "" here, since the 1.4252 + // expanded affixes are almost not used at all 1.4253 + // in this situation. However, one method -- 1.4254 + // toPattern() -- still does use the expanded 1.4255 + // affixes, in order to set up a padding 1.4256 + // pattern. We use the CURRENCY_SIGN as a 1.4257 + // placeholder. 1.4258 + affix.append(kCurrencySign); 1.4259 + } else { 1.4260 + if (fCurrencyChoice != NULL) { 1.4261 + FieldPosition pos(0); // ignored 1.4262 + if (number < 0) { 1.4263 + number = -number; 1.4264 + } 1.4265 + fCurrencyChoice->format(number, affix, pos); 1.4266 + } else { 1.4267 + // We only arrive here if the currency choice 1.4268 + // format in the locale data is INVALID. 1.4269 + affix.append(currencyUChars, -1); 1.4270 + handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 1.4271 + } 1.4272 + } 1.4273 + continue; 1.4274 + } 1.4275 + affix += UnicodeString(s, len); 1.4276 + handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 1.4277 + } 1.4278 + } else { 1.4279 + if(intl) { 1.4280 + affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 1.4281 + } else { 1.4282 + affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol); 1.4283 + } 1.4284 + handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 1.4285 + } 1.4286 + break; 1.4287 + } 1.4288 + case kPatternPercent: 1.4289 + affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 1.4290 + handler.addAttribute(kPercentField, beginIdx, affix.length()); 1.4291 + break; 1.4292 + case kPatternPerMill: 1.4293 + affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 1.4294 + handler.addAttribute(kPermillField, beginIdx, affix.length()); 1.4295 + break; 1.4296 + case kPatternPlus: 1.4297 + affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1.4298 + handler.addAttribute(kSignField, beginIdx, affix.length()); 1.4299 + break; 1.4300 + case kPatternMinus: 1.4301 + affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1.4302 + handler.addAttribute(kSignField, beginIdx, affix.length()); 1.4303 + break; 1.4304 + default: 1.4305 + affix.append(c); 1.4306 + break; 1.4307 + } 1.4308 + } 1.4309 + else { 1.4310 + affix.append(c); 1.4311 + } 1.4312 + } 1.4313 +} 1.4314 + 1.4315 +/** 1.4316 + * Append an affix to the given StringBuffer. 1.4317 + * @param buf buffer to append to 1.4318 + * @param isNegative 1.4319 + * @param isPrefix 1.4320 + */ 1.4321 +int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number, 1.4322 + FieldPositionHandler& handler, 1.4323 + UBool isNegative, UBool isPrefix) const { 1.4324 + // plural format precedes choice format 1.4325 + if (fCurrencyChoice != 0 && 1.4326 + fCurrencySignCount != fgCurrencySignCountInPluralFormat) { 1.4327 + const UnicodeString* affixPat; 1.4328 + if (isPrefix) { 1.4329 + affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern; 1.4330 + } else { 1.4331 + affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern; 1.4332 + } 1.4333 + if (affixPat) { 1.4334 + UnicodeString affixBuf; 1.4335 + expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL); 1.4336 + buf.append(affixBuf); 1.4337 + return affixBuf.length(); 1.4338 + } 1.4339 + // else someone called a function that reset the pattern. 1.4340 + } 1.4341 + 1.4342 + const UnicodeString* affix; 1.4343 + if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) { 1.4344 + // TODO: get an accurate count of visible fraction digits. 1.4345 + UnicodeString pluralCount; 1.4346 + int32_t minFractionDigits = this->getMinimumFractionDigits(); 1.4347 + if (minFractionDigits > 0) { 1.4348 + FixedDecimal ni(number, this->getMinimumFractionDigits()); 1.4349 + pluralCount = fCurrencyPluralInfo->getPluralRules()->select(ni); 1.4350 + } else { 1.4351 + pluralCount = fCurrencyPluralInfo->getPluralRules()->select(number); 1.4352 + } 1.4353 + AffixesForCurrency* oneSet; 1.4354 + if (fStyle == UNUM_CURRENCY_PLURAL) { 1.4355 + oneSet = (AffixesForCurrency*)fPluralAffixesForCurrency->get(pluralCount); 1.4356 + } else { 1.4357 + oneSet = (AffixesForCurrency*)fAffixesForCurrency->get(pluralCount); 1.4358 + } 1.4359 + if (isPrefix) { 1.4360 + affix = isNegative ? &oneSet->negPrefixForCurrency : 1.4361 + &oneSet->posPrefixForCurrency; 1.4362 + } else { 1.4363 + affix = isNegative ? &oneSet->negSuffixForCurrency : 1.4364 + &oneSet->posSuffixForCurrency; 1.4365 + } 1.4366 + } else { 1.4367 + if (isPrefix) { 1.4368 + affix = isNegative ? &fNegativePrefix : &fPositivePrefix; 1.4369 + } else { 1.4370 + affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix; 1.4371 + } 1.4372 + } 1.4373 + 1.4374 + int32_t begin = (int) buf.length(); 1.4375 + 1.4376 + buf.append(*affix); 1.4377 + 1.4378 + if (handler.isRecording()) { 1.4379 + int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol)); 1.4380 + if (offset > -1) { 1.4381 + UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol); 1.4382 + handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length()); 1.4383 + } 1.4384 + 1.4385 + offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 1.4386 + if (offset > -1) { 1.4387 + UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 1.4388 + handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length()); 1.4389 + } 1.4390 + 1.4391 + offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)); 1.4392 + if (offset > -1) { 1.4393 + UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1.4394 + handler.addAttribute(kSignField, begin + offset, begin + offset + aff.length()); 1.4395 + } 1.4396 + 1.4397 + offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)); 1.4398 + if (offset > -1) { 1.4399 + UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 1.4400 + handler.addAttribute(kPercentField, begin + offset, begin + offset + aff.length()); 1.4401 + } 1.4402 + 1.4403 + offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)); 1.4404 + if (offset > -1) { 1.4405 + UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 1.4406 + handler.addAttribute(kPermillField, begin + offset, begin + offset + aff.length()); 1.4407 + } 1.4408 + } 1.4409 + return affix->length(); 1.4410 +} 1.4411 + 1.4412 +/** 1.4413 + * Appends an affix pattern to the given StringBuffer, quoting special 1.4414 + * characters as needed. Uses the internal affix pattern, if that exists, 1.4415 + * or the literal affix, if the internal affix pattern is null. The 1.4416 + * appended string will generate the same affix pattern (or literal affix) 1.4417 + * when passed to toPattern(). 1.4418 + * 1.4419 + * @param appendTo the affix string is appended to this 1.4420 + * @param affixPattern a pattern such as fPosPrefixPattern; may be null 1.4421 + * @param expAffix a corresponding expanded affix, such as fPositivePrefix. 1.4422 + * Ignored unless affixPattern is null. If affixPattern is null, then 1.4423 + * expAffix is appended as a literal affix. 1.4424 + * @param localized true if the appended pattern should contain localized 1.4425 + * pattern characters; otherwise, non-localized pattern chars are appended 1.4426 + */ 1.4427 +void DecimalFormat::appendAffixPattern(UnicodeString& appendTo, 1.4428 + const UnicodeString* affixPattern, 1.4429 + const UnicodeString& expAffix, 1.4430 + UBool localized) const { 1.4431 + if (affixPattern == 0) { 1.4432 + appendAffixPattern(appendTo, expAffix, localized); 1.4433 + } else { 1.4434 + int i; 1.4435 + for (int pos=0; pos<affixPattern->length(); pos=i) { 1.4436 + i = affixPattern->indexOf(kQuote, pos); 1.4437 + if (i < 0) { 1.4438 + UnicodeString s; 1.4439 + affixPattern->extractBetween(pos, affixPattern->length(), s); 1.4440 + appendAffixPattern(appendTo, s, localized); 1.4441 + break; 1.4442 + } 1.4443 + if (i > pos) { 1.4444 + UnicodeString s; 1.4445 + affixPattern->extractBetween(pos, i, s); 1.4446 + appendAffixPattern(appendTo, s, localized); 1.4447 + } 1.4448 + UChar32 c = affixPattern->char32At(++i); 1.4449 + ++i; 1.4450 + if (c == kQuote) { 1.4451 + appendTo.append(c).append(c); 1.4452 + // Fall through and append another kQuote below 1.4453 + } else if (c == kCurrencySign && 1.4454 + i<affixPattern->length() && 1.4455 + affixPattern->char32At(i) == kCurrencySign) { 1.4456 + ++i; 1.4457 + appendTo.append(c).append(c); 1.4458 + } else if (localized) { 1.4459 + switch (c) { 1.4460 + case kPatternPercent: 1.4461 + appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 1.4462 + break; 1.4463 + case kPatternPerMill: 1.4464 + appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 1.4465 + break; 1.4466 + case kPatternPlus: 1.4467 + appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1.4468 + break; 1.4469 + case kPatternMinus: 1.4470 + appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1.4471 + break; 1.4472 + default: 1.4473 + appendTo.append(c); 1.4474 + } 1.4475 + } else { 1.4476 + appendTo.append(c); 1.4477 + } 1.4478 + } 1.4479 + } 1.4480 +} 1.4481 + 1.4482 +/** 1.4483 + * Append an affix to the given StringBuffer, using quotes if 1.4484 + * there are special characters. Single quotes themselves must be 1.4485 + * escaped in either case. 1.4486 + */ 1.4487 +void 1.4488 +DecimalFormat::appendAffixPattern(UnicodeString& appendTo, 1.4489 + const UnicodeString& affix, 1.4490 + UBool localized) const { 1.4491 + UBool needQuote; 1.4492 + if(localized) { 1.4493 + needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0 1.4494 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0 1.4495 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0 1.4496 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0 1.4497 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0 1.4498 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0 1.4499 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0 1.4500 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0 1.4501 + || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0 1.4502 + || affix.indexOf(kCurrencySign) >= 0; 1.4503 + } 1.4504 + else { 1.4505 + needQuote = affix.indexOf(kPatternZeroDigit) >= 0 1.4506 + || affix.indexOf(kPatternGroupingSeparator) >= 0 1.4507 + || affix.indexOf(kPatternDecimalSeparator) >= 0 1.4508 + || affix.indexOf(kPatternPercent) >= 0 1.4509 + || affix.indexOf(kPatternPerMill) >= 0 1.4510 + || affix.indexOf(kPatternDigit) >= 0 1.4511 + || affix.indexOf(kPatternSeparator) >= 0 1.4512 + || affix.indexOf(kPatternExponent) >= 0 1.4513 + || affix.indexOf(kPatternPlus) >= 0 1.4514 + || affix.indexOf(kPatternMinus) >= 0 1.4515 + || affix.indexOf(kCurrencySign) >= 0; 1.4516 + } 1.4517 + if (needQuote) 1.4518 + appendTo += (UChar)0x0027 /*'\''*/; 1.4519 + if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0) 1.4520 + appendTo += affix; 1.4521 + else { 1.4522 + for (int32_t j = 0; j < affix.length(); ) { 1.4523 + UChar32 c = affix.char32At(j); 1.4524 + j += U16_LENGTH(c); 1.4525 + appendTo += c; 1.4526 + if (c == 0x0027 /*'\''*/) 1.4527 + appendTo += c; 1.4528 + } 1.4529 + } 1.4530 + if (needQuote) 1.4531 + appendTo += (UChar)0x0027 /*'\''*/; 1.4532 +} 1.4533 + 1.4534 +//------------------------------------------------------------------------------ 1.4535 + 1.4536 +UnicodeString& 1.4537 +DecimalFormat::toPattern(UnicodeString& result, UBool localized) const 1.4538 +{ 1.4539 + if (fStyle == UNUM_CURRENCY_PLURAL) { 1.4540 + // the prefix or suffix pattern might not be defined yet, 1.4541 + // so they can not be synthesized, 1.4542 + // instead, get them directly. 1.4543 + // but it might not be the actual pattern used in formatting. 1.4544 + // the actual pattern used in formatting depends on the 1.4545 + // formatted number's plural count. 1.4546 + result = fFormatPattern; 1.4547 + return result; 1.4548 + } 1.4549 + result.remove(); 1.4550 + UChar32 zero, sigDigit = kPatternSignificantDigit; 1.4551 + UnicodeString digit, group; 1.4552 + int32_t i; 1.4553 + int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits 1.4554 + UnicodeString roundingDigits; 1.4555 + int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1; 1.4556 + UnicodeString padSpec; 1.4557 + UBool useSigDig = areSignificantDigitsUsed(); 1.4558 + 1.4559 + if (localized) { 1.4560 + digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)); 1.4561 + group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)); 1.4562 + zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 1.4563 + if (useSigDig) { 1.4564 + sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); 1.4565 + } 1.4566 + } 1.4567 + else { 1.4568 + digit.append((UChar)kPatternDigit); 1.4569 + group.append((UChar)kPatternGroupingSeparator); 1.4570 + zero = (UChar32)kPatternZeroDigit; 1.4571 + } 1.4572 + if (fFormatWidth > 0) { 1.4573 + if (localized) { 1.4574 + padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol)); 1.4575 + } 1.4576 + else { 1.4577 + padSpec.append((UChar)kPatternPadEscape); 1.4578 + } 1.4579 + padSpec.append(fPad); 1.4580 + } 1.4581 + if (fRoundingIncrement != NULL) { 1.4582 + for(i=0; i<fRoundingIncrement->getCount(); ++i) { 1.4583 + roundingDigits.append(zero+(fRoundingIncrement->getDigitValue(i))); // Convert to Unicode digit 1.4584 + } 1.4585 + roundingDecimalPos = fRoundingIncrement->getDecimalAt(); 1.4586 + } 1.4587 + for (int32_t part=0; part<2; ++part) { 1.4588 + if (padPos == kPadBeforePrefix) { 1.4589 + result.append(padSpec); 1.4590 + } 1.4591 + appendAffixPattern(result, 1.4592 + (part==0 ? fPosPrefixPattern : fNegPrefixPattern), 1.4593 + (part==0 ? fPositivePrefix : fNegativePrefix), 1.4594 + localized); 1.4595 + if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) { 1.4596 + result.append(padSpec); 1.4597 + } 1.4598 + int32_t sub0Start = result.length(); 1.4599 + int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0; 1.4600 + if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) { 1.4601 + g += fGroupingSize2; 1.4602 + } 1.4603 + int32_t maxDig = 0, minDig = 0, maxSigDig = 0; 1.4604 + if (useSigDig) { 1.4605 + minDig = getMinimumSignificantDigits(); 1.4606 + maxDig = maxSigDig = getMaximumSignificantDigits(); 1.4607 + } else { 1.4608 + minDig = getMinimumIntegerDigits(); 1.4609 + maxDig = getMaximumIntegerDigits(); 1.4610 + } 1.4611 + if (fUseExponentialNotation) { 1.4612 + if (maxDig > kMaxScientificIntegerDigits) { 1.4613 + maxDig = 1; 1.4614 + } 1.4615 + } else if (useSigDig) { 1.4616 + maxDig = _max(maxDig, g+1); 1.4617 + } else { 1.4618 + maxDig = _max(_max(g, getMinimumIntegerDigits()), 1.4619 + roundingDecimalPos) + 1; 1.4620 + } 1.4621 + for (i = maxDig; i > 0; --i) { 1.4622 + if (!fUseExponentialNotation && i<maxDig && 1.4623 + isGroupingPosition(i)) { 1.4624 + result.append(group); 1.4625 + } 1.4626 + if (useSigDig) { 1.4627 + // #@,@### (maxSigDig == 5, minSigDig == 2) 1.4628 + // 65 4321 (1-based pos, count from the right) 1.4629 + // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig) 1.4630 + // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig 1.4631 + if (maxSigDig >= i && i > (maxSigDig - minDig)) { 1.4632 + result.append(sigDigit); 1.4633 + } else { 1.4634 + result.append(digit); 1.4635 + } 1.4636 + } else { 1.4637 + if (! roundingDigits.isEmpty()) { 1.4638 + int32_t pos = roundingDecimalPos - i; 1.4639 + if (pos >= 0 && pos < roundingDigits.length()) { 1.4640 + result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero)); 1.4641 + continue; 1.4642 + } 1.4643 + } 1.4644 + if (i<=minDig) { 1.4645 + result.append(zero); 1.4646 + } else { 1.4647 + result.append(digit); 1.4648 + } 1.4649 + } 1.4650 + } 1.4651 + if (!useSigDig) { 1.4652 + if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) { 1.4653 + if (localized) { 1.4654 + result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1.4655 + } 1.4656 + else { 1.4657 + result.append((UChar)kPatternDecimalSeparator); 1.4658 + } 1.4659 + } 1.4660 + int32_t pos = roundingDecimalPos; 1.4661 + for (i = 0; i < getMaximumFractionDigits(); ++i) { 1.4662 + if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) { 1.4663 + if (pos < 0) { 1.4664 + result.append(zero); 1.4665 + } 1.4666 + else { 1.4667 + result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero)); 1.4668 + } 1.4669 + ++pos; 1.4670 + continue; 1.4671 + } 1.4672 + if (i<getMinimumFractionDigits()) { 1.4673 + result.append(zero); 1.4674 + } 1.4675 + else { 1.4676 + result.append(digit); 1.4677 + } 1.4678 + } 1.4679 + } 1.4680 + if (fUseExponentialNotation) { 1.4681 + if (localized) { 1.4682 + result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 1.4683 + } 1.4684 + else { 1.4685 + result.append((UChar)kPatternExponent); 1.4686 + } 1.4687 + if (fExponentSignAlwaysShown) { 1.4688 + if (localized) { 1.4689 + result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1.4690 + } 1.4691 + else { 1.4692 + result.append((UChar)kPatternPlus); 1.4693 + } 1.4694 + } 1.4695 + for (i=0; i<fMinExponentDigits; ++i) { 1.4696 + result.append(zero); 1.4697 + } 1.4698 + } 1.4699 + if (! padSpec.isEmpty() && !fUseExponentialNotation) { 1.4700 + int32_t add = fFormatWidth - result.length() + sub0Start 1.4701 + - ((part == 0) 1.4702 + ? fPositivePrefix.length() + fPositiveSuffix.length() 1.4703 + : fNegativePrefix.length() + fNegativeSuffix.length()); 1.4704 + while (add > 0) { 1.4705 + result.insert(sub0Start, digit); 1.4706 + ++maxDig; 1.4707 + --add; 1.4708 + // Only add a grouping separator if we have at least 1.4709 + // 2 additional characters to be added, so we don't 1.4710 + // end up with ",###". 1.4711 + if (add>1 && isGroupingPosition(maxDig)) { 1.4712 + result.insert(sub0Start, group); 1.4713 + --add; 1.4714 + } 1.4715 + } 1.4716 + } 1.4717 + if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) { 1.4718 + result.append(padSpec); 1.4719 + } 1.4720 + if (part == 0) { 1.4721 + appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized); 1.4722 + if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) { 1.4723 + result.append(padSpec); 1.4724 + } 1.4725 + UBool isDefault = FALSE; 1.4726 + if ((fNegSuffixPattern == fPosSuffixPattern && // both null 1.4727 + fNegativeSuffix == fPositiveSuffix) 1.4728 + || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 && 1.4729 + *fNegSuffixPattern == *fPosSuffixPattern)) 1.4730 + { 1.4731 + if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL) 1.4732 + { 1.4733 + int32_t length = fPosPrefixPattern->length(); 1.4734 + isDefault = fNegPrefixPattern->length() == (length+2) && 1.4735 + (*fNegPrefixPattern)[(int32_t)0] == kQuote && 1.4736 + (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus && 1.4737 + fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0; 1.4738 + } 1.4739 + if (!isDefault && 1.4740 + fNegPrefixPattern == NULL && fPosPrefixPattern == NULL) 1.4741 + { 1.4742 + int32_t length = fPositivePrefix.length(); 1.4743 + isDefault = fNegativePrefix.length() == (length+1) && 1.4744 + fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 && 1.4745 + fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0; 1.4746 + } 1.4747 + } 1.4748 + if (isDefault) { 1.4749 + break; // Don't output default negative subpattern 1.4750 + } else { 1.4751 + if (localized) { 1.4752 + result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol); 1.4753 + } 1.4754 + else { 1.4755 + result.append((UChar)kPatternSeparator); 1.4756 + } 1.4757 + } 1.4758 + } else { 1.4759 + appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized); 1.4760 + if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) { 1.4761 + result.append(padSpec); 1.4762 + } 1.4763 + } 1.4764 + } 1.4765 + 1.4766 + return result; 1.4767 +} 1.4768 + 1.4769 +//------------------------------------------------------------------------------ 1.4770 + 1.4771 +void 1.4772 +DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) 1.4773 +{ 1.4774 + UParseError parseError; 1.4775 + applyPattern(pattern, FALSE, parseError, status); 1.4776 +} 1.4777 + 1.4778 +//------------------------------------------------------------------------------ 1.4779 + 1.4780 +void 1.4781 +DecimalFormat::applyPattern(const UnicodeString& pattern, 1.4782 + UParseError& parseError, 1.4783 + UErrorCode& status) 1.4784 +{ 1.4785 + applyPattern(pattern, FALSE, parseError, status); 1.4786 +} 1.4787 +//------------------------------------------------------------------------------ 1.4788 + 1.4789 +void 1.4790 +DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status) 1.4791 +{ 1.4792 + UParseError parseError; 1.4793 + applyPattern(pattern, TRUE,parseError,status); 1.4794 +} 1.4795 + 1.4796 +//------------------------------------------------------------------------------ 1.4797 + 1.4798 +void 1.4799 +DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, 1.4800 + UParseError& parseError, 1.4801 + UErrorCode& status) 1.4802 +{ 1.4803 + applyPattern(pattern, TRUE,parseError,status); 1.4804 +} 1.4805 + 1.4806 +//------------------------------------------------------------------------------ 1.4807 + 1.4808 +void 1.4809 +DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern, 1.4810 + UBool localized, 1.4811 + UParseError& parseError, 1.4812 + UErrorCode& status) 1.4813 +{ 1.4814 + if (U_FAILURE(status)) 1.4815 + { 1.4816 + return; 1.4817 + } 1.4818 + // Clear error struct 1.4819 + parseError.offset = -1; 1.4820 + parseError.preContext[0] = parseError.postContext[0] = (UChar)0; 1.4821 + 1.4822 + // Set the significant pattern symbols 1.4823 + UChar32 zeroDigit = kPatternZeroDigit; // '0' 1.4824 + UChar32 sigDigit = kPatternSignificantDigit; // '@' 1.4825 + UnicodeString groupingSeparator ((UChar)kPatternGroupingSeparator); 1.4826 + UnicodeString decimalSeparator ((UChar)kPatternDecimalSeparator); 1.4827 + UnicodeString percent ((UChar)kPatternPercent); 1.4828 + UnicodeString perMill ((UChar)kPatternPerMill); 1.4829 + UnicodeString digit ((UChar)kPatternDigit); // '#' 1.4830 + UnicodeString separator ((UChar)kPatternSeparator); 1.4831 + UnicodeString exponent ((UChar)kPatternExponent); 1.4832 + UnicodeString plus ((UChar)kPatternPlus); 1.4833 + UnicodeString minus ((UChar)kPatternMinus); 1.4834 + UnicodeString padEscape ((UChar)kPatternPadEscape); 1.4835 + // Substitute with the localized symbols if necessary 1.4836 + if (localized) { 1.4837 + zeroDigit = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 1.4838 + sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); 1.4839 + groupingSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)); 1.4840 + decimalSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)); 1.4841 + percent. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)); 1.4842 + perMill. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)); 1.4843 + digit. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)); 1.4844 + separator. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)); 1.4845 + exponent. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol)); 1.4846 + plus. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)); 1.4847 + minus. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)); 1.4848 + padEscape. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol)); 1.4849 + } 1.4850 + UChar nineDigit = (UChar)(zeroDigit + 9); 1.4851 + int32_t digitLen = digit.length(); 1.4852 + int32_t groupSepLen = groupingSeparator.length(); 1.4853 + int32_t decimalSepLen = decimalSeparator.length(); 1.4854 + 1.4855 + int32_t pos = 0; 1.4856 + int32_t patLen = pattern.length(); 1.4857 + // Part 0 is the positive pattern. Part 1, if present, is the negative 1.4858 + // pattern. 1.4859 + for (int32_t part=0; part<2 && pos<patLen; ++part) { 1.4860 + // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 1.4861 + // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is 1.4862 + // between the prefix and suffix, and consists of pattern 1.4863 + // characters. In the prefix and suffix, percent, perMill, and 1.4864 + // currency symbols are recognized and translated. 1.4865 + int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0; 1.4866 + 1.4867 + // It's important that we don't change any fields of this object 1.4868 + // prematurely. We set the following variables for the multiplier, 1.4869 + // grouping, etc., and then only change the actual object fields if 1.4870 + // everything parses correctly. This also lets us register 1.4871 + // the data from part 0 and ignore the part 1, except for the 1.4872 + // prefix and suffix. 1.4873 + UnicodeString prefix; 1.4874 + UnicodeString suffix; 1.4875 + int32_t decimalPos = -1; 1.4876 + int32_t multiplier = 1; 1.4877 + int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0; 1.4878 + int8_t groupingCount = -1; 1.4879 + int8_t groupingCount2 = -1; 1.4880 + int32_t padPos = -1; 1.4881 + UChar32 padChar = 0; 1.4882 + int32_t roundingPos = -1; 1.4883 + DigitList roundingInc; 1.4884 + int8_t expDigits = -1; 1.4885 + UBool expSignAlways = FALSE; 1.4886 + 1.4887 + // The affix is either the prefix or the suffix. 1.4888 + UnicodeString* affix = &prefix; 1.4889 + 1.4890 + int32_t start = pos; 1.4891 + UBool isPartDone = FALSE; 1.4892 + UChar32 ch; 1.4893 + 1.4894 + for (; !isPartDone && pos < patLen; ) { 1.4895 + // Todo: account for surrogate pairs 1.4896 + ch = pattern.char32At(pos); 1.4897 + switch (subpart) { 1.4898 + case 0: // Pattern proper subpart (between prefix & suffix) 1.4899 + // Process the digits, decimal, and grouping characters. We 1.4900 + // record five pieces of information. We expect the digits 1.4901 + // to occur in the pattern ####00.00####, and we record the 1.4902 + // number of left digits, zero (central) digits, and right 1.4903 + // digits. The position of the last grouping character is 1.4904 + // recorded (should be somewhere within the first two blocks 1.4905 + // of characters), as is the position of the decimal point, 1.4906 + // if any (should be in the zero digits). If there is no 1.4907 + // decimal point, then there should be no right digits. 1.4908 + if (pattern.compare(pos, digitLen, digit) == 0) { 1.4909 + if (zeroDigitCount > 0 || sigDigitCount > 0) { 1.4910 + ++digitRightCount; 1.4911 + } else { 1.4912 + ++digitLeftCount; 1.4913 + } 1.4914 + if (groupingCount >= 0 && decimalPos < 0) { 1.4915 + ++groupingCount; 1.4916 + } 1.4917 + pos += digitLen; 1.4918 + } else if ((ch >= zeroDigit && ch <= nineDigit) || 1.4919 + ch == sigDigit) { 1.4920 + if (digitRightCount > 0) { 1.4921 + // Unexpected '0' 1.4922 + debug("Unexpected '0'") 1.4923 + status = U_UNEXPECTED_TOKEN; 1.4924 + syntaxError(pattern,pos,parseError); 1.4925 + return; 1.4926 + } 1.4927 + if (ch == sigDigit) { 1.4928 + ++sigDigitCount; 1.4929 + } else { 1.4930 + if (ch != zeroDigit && roundingPos < 0) { 1.4931 + roundingPos = digitLeftCount + zeroDigitCount; 1.4932 + } 1.4933 + if (roundingPos >= 0) { 1.4934 + roundingInc.append((char)(ch - zeroDigit + '0')); 1.4935 + } 1.4936 + ++zeroDigitCount; 1.4937 + } 1.4938 + if (groupingCount >= 0 && decimalPos < 0) { 1.4939 + ++groupingCount; 1.4940 + } 1.4941 + pos += U16_LENGTH(ch); 1.4942 + } else if (pattern.compare(pos, groupSepLen, groupingSeparator) == 0) { 1.4943 + if (decimalPos >= 0) { 1.4944 + // Grouping separator after decimal 1.4945 + debug("Grouping separator after decimal") 1.4946 + status = U_UNEXPECTED_TOKEN; 1.4947 + syntaxError(pattern,pos,parseError); 1.4948 + return; 1.4949 + } 1.4950 + groupingCount2 = groupingCount; 1.4951 + groupingCount = 0; 1.4952 + pos += groupSepLen; 1.4953 + } else if (pattern.compare(pos, decimalSepLen, decimalSeparator) == 0) { 1.4954 + if (decimalPos >= 0) { 1.4955 + // Multiple decimal separators 1.4956 + debug("Multiple decimal separators") 1.4957 + status = U_MULTIPLE_DECIMAL_SEPARATORS; 1.4958 + syntaxError(pattern,pos,parseError); 1.4959 + return; 1.4960 + } 1.4961 + // Intentionally incorporate the digitRightCount, 1.4962 + // even though it is illegal for this to be > 0 1.4963 + // at this point. We check pattern syntax below. 1.4964 + decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; 1.4965 + pos += decimalSepLen; 1.4966 + } else { 1.4967 + if (pattern.compare(pos, exponent.length(), exponent) == 0) { 1.4968 + if (expDigits >= 0) { 1.4969 + // Multiple exponential symbols 1.4970 + debug("Multiple exponential symbols") 1.4971 + status = U_MULTIPLE_EXPONENTIAL_SYMBOLS; 1.4972 + syntaxError(pattern,pos,parseError); 1.4973 + return; 1.4974 + } 1.4975 + if (groupingCount >= 0) { 1.4976 + // Grouping separator in exponential pattern 1.4977 + debug("Grouping separator in exponential pattern") 1.4978 + status = U_MALFORMED_EXPONENTIAL_PATTERN; 1.4979 + syntaxError(pattern,pos,parseError); 1.4980 + return; 1.4981 + } 1.4982 + pos += exponent.length(); 1.4983 + // Check for positive prefix 1.4984 + if (pos < patLen 1.4985 + && pattern.compare(pos, plus.length(), plus) == 0) { 1.4986 + expSignAlways = TRUE; 1.4987 + pos += plus.length(); 1.4988 + } 1.4989 + // Use lookahead to parse out the exponential part of the 1.4990 + // pattern, then jump into suffix subpart. 1.4991 + expDigits = 0; 1.4992 + while (pos < patLen && 1.4993 + pattern.char32At(pos) == zeroDigit) { 1.4994 + ++expDigits; 1.4995 + pos += U16_LENGTH(zeroDigit); 1.4996 + } 1.4997 + 1.4998 + // 1. Require at least one mantissa pattern digit 1.4999 + // 2. Disallow "#+ @" in mantissa 1.5000 + // 3. Require at least one exponent pattern digit 1.5001 + if (((digitLeftCount + zeroDigitCount) < 1 && 1.5002 + (sigDigitCount + digitRightCount) < 1) || 1.5003 + (sigDigitCount > 0 && digitLeftCount > 0) || 1.5004 + expDigits < 1) { 1.5005 + // Malformed exponential pattern 1.5006 + debug("Malformed exponential pattern") 1.5007 + status = U_MALFORMED_EXPONENTIAL_PATTERN; 1.5008 + syntaxError(pattern,pos,parseError); 1.5009 + return; 1.5010 + } 1.5011 + } 1.5012 + // Transition to suffix subpart 1.5013 + subpart = 2; // suffix subpart 1.5014 + affix = &suffix; 1.5015 + sub0Limit = pos; 1.5016 + continue; 1.5017 + } 1.5018 + break; 1.5019 + case 1: // Prefix subpart 1.5020 + case 2: // Suffix subpart 1.5021 + // Process the prefix / suffix characters 1.5022 + // Process unquoted characters seen in prefix or suffix 1.5023 + // subpart. 1.5024 + 1.5025 + // Several syntax characters implicitly begins the 1.5026 + // next subpart if we are in the prefix; otherwise 1.5027 + // they are illegal if unquoted. 1.5028 + if (!pattern.compare(pos, digitLen, digit) || 1.5029 + !pattern.compare(pos, groupSepLen, groupingSeparator) || 1.5030 + !pattern.compare(pos, decimalSepLen, decimalSeparator) || 1.5031 + (ch >= zeroDigit && ch <= nineDigit) || 1.5032 + ch == sigDigit) { 1.5033 + if (subpart == 1) { // prefix subpart 1.5034 + subpart = 0; // pattern proper subpart 1.5035 + sub0Start = pos; // Reprocess this character 1.5036 + continue; 1.5037 + } else { 1.5038 + status = U_UNQUOTED_SPECIAL; 1.5039 + syntaxError(pattern,pos,parseError); 1.5040 + return; 1.5041 + } 1.5042 + } else if (ch == kCurrencySign) { 1.5043 + affix->append(kQuote); // Encode currency 1.5044 + // Use lookahead to determine if the currency sign is 1.5045 + // doubled or not. 1.5046 + U_ASSERT(U16_LENGTH(kCurrencySign) == 1); 1.5047 + if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) { 1.5048 + affix->append(kCurrencySign); 1.5049 + ++pos; // Skip over the doubled character 1.5050 + if ((pos+1) < pattern.length() && 1.5051 + pattern[pos+1] == kCurrencySign) { 1.5052 + affix->append(kCurrencySign); 1.5053 + ++pos; // Skip over the doubled character 1.5054 + fCurrencySignCount = fgCurrencySignCountInPluralFormat; 1.5055 + } else { 1.5056 + fCurrencySignCount = fgCurrencySignCountInISOFormat; 1.5057 + } 1.5058 + } else { 1.5059 + fCurrencySignCount = fgCurrencySignCountInSymbolFormat; 1.5060 + } 1.5061 + // Fall through to append(ch) 1.5062 + } else if (ch == kQuote) { 1.5063 + // A quote outside quotes indicates either the opening 1.5064 + // quote or two quotes, which is a quote literal. That is, 1.5065 + // we have the first quote in 'do' or o''clock. 1.5066 + U_ASSERT(U16_LENGTH(kQuote) == 1); 1.5067 + ++pos; 1.5068 + if (pos < pattern.length() && pattern[pos] == kQuote) { 1.5069 + affix->append(kQuote); // Encode quote 1.5070 + // Fall through to append(ch) 1.5071 + } else { 1.5072 + subpart += 2; // open quote 1.5073 + continue; 1.5074 + } 1.5075 + } else if (pattern.compare(pos, separator.length(), separator) == 0) { 1.5076 + // Don't allow separators in the prefix, and don't allow 1.5077 + // separators in the second pattern (part == 1). 1.5078 + if (subpart == 1 || part == 1) { 1.5079 + // Unexpected separator 1.5080 + debug("Unexpected separator") 1.5081 + status = U_UNEXPECTED_TOKEN; 1.5082 + syntaxError(pattern,pos,parseError); 1.5083 + return; 1.5084 + } 1.5085 + sub2Limit = pos; 1.5086 + isPartDone = TRUE; // Go to next part 1.5087 + pos += separator.length(); 1.5088 + break; 1.5089 + } else if (pattern.compare(pos, percent.length(), percent) == 0) { 1.5090 + // Next handle characters which are appended directly. 1.5091 + if (multiplier != 1) { 1.5092 + // Too many percent/perMill characters 1.5093 + debug("Too many percent characters") 1.5094 + status = U_MULTIPLE_PERCENT_SYMBOLS; 1.5095 + syntaxError(pattern,pos,parseError); 1.5096 + return; 1.5097 + } 1.5098 + affix->append(kQuote); // Encode percent/perMill 1.5099 + affix->append(kPatternPercent); // Use unlocalized pattern char 1.5100 + multiplier = 100; 1.5101 + pos += percent.length(); 1.5102 + break; 1.5103 + } else if (pattern.compare(pos, perMill.length(), perMill) == 0) { 1.5104 + // Next handle characters which are appended directly. 1.5105 + if (multiplier != 1) { 1.5106 + // Too many percent/perMill characters 1.5107 + debug("Too many perMill characters") 1.5108 + status = U_MULTIPLE_PERMILL_SYMBOLS; 1.5109 + syntaxError(pattern,pos,parseError); 1.5110 + return; 1.5111 + } 1.5112 + affix->append(kQuote); // Encode percent/perMill 1.5113 + affix->append(kPatternPerMill); // Use unlocalized pattern char 1.5114 + multiplier = 1000; 1.5115 + pos += perMill.length(); 1.5116 + break; 1.5117 + } else if (pattern.compare(pos, padEscape.length(), padEscape) == 0) { 1.5118 + if (padPos >= 0 || // Multiple pad specifiers 1.5119 + (pos+1) == pattern.length()) { // Nothing after padEscape 1.5120 + debug("Multiple pad specifiers") 1.5121 + status = U_MULTIPLE_PAD_SPECIFIERS; 1.5122 + syntaxError(pattern,pos,parseError); 1.5123 + return; 1.5124 + } 1.5125 + padPos = pos; 1.5126 + pos += padEscape.length(); 1.5127 + padChar = pattern.char32At(pos); 1.5128 + pos += U16_LENGTH(padChar); 1.5129 + break; 1.5130 + } else if (pattern.compare(pos, minus.length(), minus) == 0) { 1.5131 + affix->append(kQuote); // Encode minus 1.5132 + affix->append(kPatternMinus); 1.5133 + pos += minus.length(); 1.5134 + break; 1.5135 + } else if (pattern.compare(pos, plus.length(), plus) == 0) { 1.5136 + affix->append(kQuote); // Encode plus 1.5137 + affix->append(kPatternPlus); 1.5138 + pos += plus.length(); 1.5139 + break; 1.5140 + } 1.5141 + // Unquoted, non-special characters fall through to here, as 1.5142 + // well as other code which needs to append something to the 1.5143 + // affix. 1.5144 + affix->append(ch); 1.5145 + pos += U16_LENGTH(ch); 1.5146 + break; 1.5147 + case 3: // Prefix subpart, in quote 1.5148 + case 4: // Suffix subpart, in quote 1.5149 + // A quote within quotes indicates either the closing 1.5150 + // quote or two quotes, which is a quote literal. That is, 1.5151 + // we have the second quote in 'do' or 'don''t'. 1.5152 + if (ch == kQuote) { 1.5153 + ++pos; 1.5154 + if (pos < pattern.length() && pattern[pos] == kQuote) { 1.5155 + affix->append(kQuote); // Encode quote 1.5156 + // Fall through to append(ch) 1.5157 + } else { 1.5158 + subpart -= 2; // close quote 1.5159 + continue; 1.5160 + } 1.5161 + } 1.5162 + affix->append(ch); 1.5163 + pos += U16_LENGTH(ch); 1.5164 + break; 1.5165 + } 1.5166 + } 1.5167 + 1.5168 + if (sub0Limit == 0) { 1.5169 + sub0Limit = pattern.length(); 1.5170 + } 1.5171 + 1.5172 + if (sub2Limit == 0) { 1.5173 + sub2Limit = pattern.length(); 1.5174 + } 1.5175 + 1.5176 + /* Handle patterns with no '0' pattern character. These patterns 1.5177 + * are legal, but must be recodified to make sense. "##.###" -> 1.5178 + * "#0.###". ".###" -> ".0##". 1.5179 + * 1.5180 + * We allow patterns of the form "####" to produce a zeroDigitCount 1.5181 + * of zero (got that?); although this seems like it might make it 1.5182 + * possible for format() to produce empty strings, format() checks 1.5183 + * for this condition and outputs a zero digit in this situation. 1.5184 + * Having a zeroDigitCount of zero yields a minimum integer digits 1.5185 + * of zero, which allows proper round-trip patterns. We don't want 1.5186 + * "#" to become "#0" when toPattern() is called (even though that's 1.5187 + * what it really is, semantically). 1.5188 + */ 1.5189 + if (zeroDigitCount == 0 && sigDigitCount == 0 && 1.5190 + digitLeftCount > 0 && decimalPos >= 0) { 1.5191 + // Handle "###.###" and "###." and ".###" 1.5192 + int n = decimalPos; 1.5193 + if (n == 0) 1.5194 + ++n; // Handle ".###" 1.5195 + digitRightCount = digitLeftCount - n; 1.5196 + digitLeftCount = n - 1; 1.5197 + zeroDigitCount = 1; 1.5198 + } 1.5199 + 1.5200 + // Do syntax checking on the digits, decimal points, and quotes. 1.5201 + if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || 1.5202 + (decimalPos >= 0 && 1.5203 + (sigDigitCount > 0 || 1.5204 + decimalPos < digitLeftCount || 1.5205 + decimalPos > (digitLeftCount + zeroDigitCount))) || 1.5206 + groupingCount == 0 || groupingCount2 == 0 || 1.5207 + (sigDigitCount > 0 && zeroDigitCount > 0) || 1.5208 + subpart > 2) 1.5209 + { // subpart > 2 == unmatched quote 1.5210 + debug("Syntax error") 1.5211 + status = U_PATTERN_SYNTAX_ERROR; 1.5212 + syntaxError(pattern,pos,parseError); 1.5213 + return; 1.5214 + } 1.5215 + 1.5216 + // Make sure pad is at legal position before or after affix. 1.5217 + if (padPos >= 0) { 1.5218 + if (padPos == start) { 1.5219 + padPos = kPadBeforePrefix; 1.5220 + } else if (padPos+2 == sub0Start) { 1.5221 + padPos = kPadAfterPrefix; 1.5222 + } else if (padPos == sub0Limit) { 1.5223 + padPos = kPadBeforeSuffix; 1.5224 + } else if (padPos+2 == sub2Limit) { 1.5225 + padPos = kPadAfterSuffix; 1.5226 + } else { 1.5227 + // Illegal pad position 1.5228 + debug("Illegal pad position") 1.5229 + status = U_ILLEGAL_PAD_POSITION; 1.5230 + syntaxError(pattern,pos,parseError); 1.5231 + return; 1.5232 + } 1.5233 + } 1.5234 + 1.5235 + if (part == 0) { 1.5236 + delete fPosPrefixPattern; 1.5237 + delete fPosSuffixPattern; 1.5238 + delete fNegPrefixPattern; 1.5239 + delete fNegSuffixPattern; 1.5240 + fPosPrefixPattern = new UnicodeString(prefix); 1.5241 + /* test for NULL */ 1.5242 + if (fPosPrefixPattern == 0) { 1.5243 + status = U_MEMORY_ALLOCATION_ERROR; 1.5244 + return; 1.5245 + } 1.5246 + fPosSuffixPattern = new UnicodeString(suffix); 1.5247 + /* test for NULL */ 1.5248 + if (fPosSuffixPattern == 0) { 1.5249 + status = U_MEMORY_ALLOCATION_ERROR; 1.5250 + delete fPosPrefixPattern; 1.5251 + return; 1.5252 + } 1.5253 + fNegPrefixPattern = 0; 1.5254 + fNegSuffixPattern = 0; 1.5255 + 1.5256 + fUseExponentialNotation = (expDigits >= 0); 1.5257 + if (fUseExponentialNotation) { 1.5258 + fMinExponentDigits = expDigits; 1.5259 + } 1.5260 + fExponentSignAlwaysShown = expSignAlways; 1.5261 + int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; 1.5262 + // The effectiveDecimalPos is the position the decimal is at or 1.5263 + // would be at if there is no decimal. Note that if 1.5264 + // decimalPos<0, then digitTotalCount == digitLeftCount + 1.5265 + // zeroDigitCount. 1.5266 + int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount; 1.5267 + UBool isSigDig = (sigDigitCount > 0); 1.5268 + setSignificantDigitsUsed(isSigDig); 1.5269 + if (isSigDig) { 1.5270 + setMinimumSignificantDigits(sigDigitCount); 1.5271 + setMaximumSignificantDigits(sigDigitCount + digitRightCount); 1.5272 + } else { 1.5273 + int32_t minInt = effectiveDecimalPos - digitLeftCount; 1.5274 + setMinimumIntegerDigits(minInt); 1.5275 + setMaximumIntegerDigits(fUseExponentialNotation 1.5276 + ? digitLeftCount + getMinimumIntegerDigits() 1.5277 + : NumberFormat::gDefaultMaxIntegerDigits); 1.5278 + setMaximumFractionDigits(decimalPos >= 0 1.5279 + ? (digitTotalCount - decimalPos) : 0); 1.5280 + setMinimumFractionDigits(decimalPos >= 0 1.5281 + ? (digitLeftCount + zeroDigitCount - decimalPos) : 0); 1.5282 + } 1.5283 + setGroupingUsed(groupingCount > 0); 1.5284 + fGroupingSize = (groupingCount > 0) ? groupingCount : 0; 1.5285 + fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) 1.5286 + ? groupingCount2 : 0; 1.5287 + setMultiplier(multiplier); 1.5288 + setDecimalSeparatorAlwaysShown(decimalPos == 0 1.5289 + || decimalPos == digitTotalCount); 1.5290 + if (padPos >= 0) { 1.5291 + fPadPosition = (EPadPosition) padPos; 1.5292 + // To compute the format width, first set up sub0Limit - 1.5293 + // sub0Start. Add in prefix/suffix length later. 1.5294 + 1.5295 + // fFormatWidth = prefix.length() + suffix.length() + 1.5296 + // sub0Limit - sub0Start; 1.5297 + fFormatWidth = sub0Limit - sub0Start; 1.5298 + fPad = padChar; 1.5299 + } else { 1.5300 + fFormatWidth = 0; 1.5301 + } 1.5302 + if (roundingPos >= 0) { 1.5303 + roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos); 1.5304 + if (fRoundingIncrement != NULL) { 1.5305 + *fRoundingIncrement = roundingInc; 1.5306 + } else { 1.5307 + fRoundingIncrement = new DigitList(roundingInc); 1.5308 + /* test for NULL */ 1.5309 + if (fRoundingIncrement == NULL) { 1.5310 + status = U_MEMORY_ALLOCATION_ERROR; 1.5311 + delete fPosPrefixPattern; 1.5312 + delete fPosSuffixPattern; 1.5313 + return; 1.5314 + } 1.5315 + } 1.5316 + fRoundingMode = kRoundHalfEven; 1.5317 + } else { 1.5318 + setRoundingIncrement(0.0); 1.5319 + } 1.5320 + } else { 1.5321 + fNegPrefixPattern = new UnicodeString(prefix); 1.5322 + /* test for NULL */ 1.5323 + if (fNegPrefixPattern == 0) { 1.5324 + status = U_MEMORY_ALLOCATION_ERROR; 1.5325 + return; 1.5326 + } 1.5327 + fNegSuffixPattern = new UnicodeString(suffix); 1.5328 + /* test for NULL */ 1.5329 + if (fNegSuffixPattern == 0) { 1.5330 + delete fNegPrefixPattern; 1.5331 + status = U_MEMORY_ALLOCATION_ERROR; 1.5332 + return; 1.5333 + } 1.5334 + } 1.5335 + } 1.5336 + 1.5337 + if (pattern.length() == 0) { 1.5338 + delete fNegPrefixPattern; 1.5339 + delete fNegSuffixPattern; 1.5340 + fNegPrefixPattern = NULL; 1.5341 + fNegSuffixPattern = NULL; 1.5342 + if (fPosPrefixPattern != NULL) { 1.5343 + fPosPrefixPattern->remove(); 1.5344 + } else { 1.5345 + fPosPrefixPattern = new UnicodeString(); 1.5346 + /* test for NULL */ 1.5347 + if (fPosPrefixPattern == 0) { 1.5348 + status = U_MEMORY_ALLOCATION_ERROR; 1.5349 + return; 1.5350 + } 1.5351 + } 1.5352 + if (fPosSuffixPattern != NULL) { 1.5353 + fPosSuffixPattern->remove(); 1.5354 + } else { 1.5355 + fPosSuffixPattern = new UnicodeString(); 1.5356 + /* test for NULL */ 1.5357 + if (fPosSuffixPattern == 0) { 1.5358 + delete fPosPrefixPattern; 1.5359 + status = U_MEMORY_ALLOCATION_ERROR; 1.5360 + return; 1.5361 + } 1.5362 + } 1.5363 + 1.5364 + setMinimumIntegerDigits(0); 1.5365 + setMaximumIntegerDigits(kDoubleIntegerDigits); 1.5366 + setMinimumFractionDigits(0); 1.5367 + setMaximumFractionDigits(kDoubleFractionDigits); 1.5368 + 1.5369 + fUseExponentialNotation = FALSE; 1.5370 + fCurrencySignCount = fgCurrencySignCountZero; 1.5371 + setGroupingUsed(FALSE); 1.5372 + fGroupingSize = 0; 1.5373 + fGroupingSize2 = 0; 1.5374 + setMultiplier(1); 1.5375 + setDecimalSeparatorAlwaysShown(FALSE); 1.5376 + fFormatWidth = 0; 1.5377 + setRoundingIncrement(0.0); 1.5378 + } 1.5379 + 1.5380 + // If there was no negative pattern, or if the negative pattern is 1.5381 + // identical to the positive pattern, then prepend the minus sign to the 1.5382 + // positive pattern to form the negative pattern. 1.5383 + if (fNegPrefixPattern == NULL || 1.5384 + (*fNegPrefixPattern == *fPosPrefixPattern 1.5385 + && *fNegSuffixPattern == *fPosSuffixPattern)) { 1.5386 + _copy_ptr(&fNegSuffixPattern, fPosSuffixPattern); 1.5387 + if (fNegPrefixPattern == NULL) { 1.5388 + fNegPrefixPattern = new UnicodeString(); 1.5389 + /* test for NULL */ 1.5390 + if (fNegPrefixPattern == 0) { 1.5391 + status = U_MEMORY_ALLOCATION_ERROR; 1.5392 + return; 1.5393 + } 1.5394 + } else { 1.5395 + fNegPrefixPattern->remove(); 1.5396 + } 1.5397 + fNegPrefixPattern->append(kQuote).append(kPatternMinus) 1.5398 + .append(*fPosPrefixPattern); 1.5399 + } 1.5400 +#ifdef FMT_DEBUG 1.5401 + UnicodeString s; 1.5402 + s.append((UnicodeString)"\"").append(pattern).append((UnicodeString)"\"->"); 1.5403 + debugout(s); 1.5404 +#endif 1.5405 + 1.5406 + // save the pattern 1.5407 + fFormatPattern = pattern; 1.5408 +} 1.5409 + 1.5410 + 1.5411 +void 1.5412 +DecimalFormat::expandAffixAdjustWidth(const UnicodeString* pluralCount) { 1.5413 + expandAffixes(pluralCount); 1.5414 + if (fFormatWidth > 0) { 1.5415 + // Finish computing format width (see above) 1.5416 + // TODO: how to handle fFormatWidth, 1.5417 + // need to save in f(Plural)AffixesForCurrecy? 1.5418 + fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length(); 1.5419 + } 1.5420 +} 1.5421 + 1.5422 + 1.5423 +void 1.5424 +DecimalFormat::applyPattern(const UnicodeString& pattern, 1.5425 + UBool localized, 1.5426 + UParseError& parseError, 1.5427 + UErrorCode& status) 1.5428 +{ 1.5429 + // do the following re-set first. since they change private data by 1.5430 + // apply pattern again. 1.5431 + if (pattern.indexOf(kCurrencySign) != -1) { 1.5432 + if (fCurrencyPluralInfo == NULL) { 1.5433 + // initialize currencyPluralInfo if needed 1.5434 + fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status); 1.5435 + } 1.5436 + if (fAffixPatternsForCurrency == NULL) { 1.5437 + setupCurrencyAffixPatterns(status); 1.5438 + } 1.5439 + if (pattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) { 1.5440 + // only setup the affixes of the current pattern. 1.5441 + setupCurrencyAffixes(pattern, TRUE, FALSE, status); 1.5442 + } 1.5443 + } 1.5444 + applyPatternWithoutExpandAffix(pattern, localized, parseError, status); 1.5445 + expandAffixAdjustWidth(NULL); 1.5446 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5447 + handleChanged(); 1.5448 +#endif 1.5449 +} 1.5450 + 1.5451 + 1.5452 +void 1.5453 +DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount, 1.5454 + const UnicodeString& pattern, 1.5455 + UBool localized, 1.5456 + UParseError& parseError, 1.5457 + UErrorCode& status) { 1.5458 + applyPatternWithoutExpandAffix(pattern, localized, parseError, status); 1.5459 + expandAffixAdjustWidth(&pluralCount); 1.5460 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5461 + handleChanged(); 1.5462 +#endif 1.5463 +} 1.5464 + 1.5465 + 1.5466 +/** 1.5467 + * Sets the maximum number of digits allowed in the integer portion of a 1.5468 + * number. 1.5469 + * @see NumberFormat#setMaximumIntegerDigits 1.5470 + */ 1.5471 +void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) { 1.5472 + NumberFormat::setMaximumIntegerDigits(_min(newValue, gDefaultMaxIntegerDigits)); 1.5473 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5474 + handleChanged(); 1.5475 +#endif 1.5476 +} 1.5477 + 1.5478 +/** 1.5479 + * Sets the minimum number of digits allowed in the integer portion of a 1.5480 + * number. This override limits the integer digit count to 309. 1.5481 + * @see NumberFormat#setMinimumIntegerDigits 1.5482 + */ 1.5483 +void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) { 1.5484 + NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits)); 1.5485 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5486 + handleChanged(); 1.5487 +#endif 1.5488 +} 1.5489 + 1.5490 +/** 1.5491 + * Sets the maximum number of digits allowed in the fraction portion of a 1.5492 + * number. This override limits the fraction digit count to 340. 1.5493 + * @see NumberFormat#setMaximumFractionDigits 1.5494 + */ 1.5495 +void DecimalFormat::setMaximumFractionDigits(int32_t newValue) { 1.5496 + NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits)); 1.5497 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5498 + handleChanged(); 1.5499 +#endif 1.5500 +} 1.5501 + 1.5502 +/** 1.5503 + * Sets the minimum number of digits allowed in the fraction portion of a 1.5504 + * number. This override limits the fraction digit count to 340. 1.5505 + * @see NumberFormat#setMinimumFractionDigits 1.5506 + */ 1.5507 +void DecimalFormat::setMinimumFractionDigits(int32_t newValue) { 1.5508 + NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits)); 1.5509 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5510 + handleChanged(); 1.5511 +#endif 1.5512 +} 1.5513 + 1.5514 +int32_t DecimalFormat::getMinimumSignificantDigits() const { 1.5515 + return fMinSignificantDigits; 1.5516 +} 1.5517 + 1.5518 +int32_t DecimalFormat::getMaximumSignificantDigits() const { 1.5519 + return fMaxSignificantDigits; 1.5520 +} 1.5521 + 1.5522 +void DecimalFormat::setMinimumSignificantDigits(int32_t min) { 1.5523 + if (min < 1) { 1.5524 + min = 1; 1.5525 + } 1.5526 + // pin max sig dig to >= min 1.5527 + int32_t max = _max(fMaxSignificantDigits, min); 1.5528 + fMinSignificantDigits = min; 1.5529 + fMaxSignificantDigits = max; 1.5530 + fUseSignificantDigits = TRUE; 1.5531 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5532 + handleChanged(); 1.5533 +#endif 1.5534 +} 1.5535 + 1.5536 +void DecimalFormat::setMaximumSignificantDigits(int32_t max) { 1.5537 + if (max < 1) { 1.5538 + max = 1; 1.5539 + } 1.5540 + // pin min sig dig to 1..max 1.5541 + U_ASSERT(fMinSignificantDigits >= 1); 1.5542 + int32_t min = _min(fMinSignificantDigits, max); 1.5543 + fMinSignificantDigits = min; 1.5544 + fMaxSignificantDigits = max; 1.5545 + fUseSignificantDigits = TRUE; 1.5546 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5547 + handleChanged(); 1.5548 +#endif 1.5549 +} 1.5550 + 1.5551 +UBool DecimalFormat::areSignificantDigitsUsed() const { 1.5552 + return fUseSignificantDigits; 1.5553 +} 1.5554 + 1.5555 +void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) { 1.5556 + fUseSignificantDigits = useSignificantDigits; 1.5557 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5558 + handleChanged(); 1.5559 +#endif 1.5560 +} 1.5561 + 1.5562 +void DecimalFormat::setCurrencyInternally(const UChar* theCurrency, 1.5563 + UErrorCode& ec) { 1.5564 + // If we are a currency format, then modify our affixes to 1.5565 + // encode the currency symbol for the given currency in our 1.5566 + // locale, and adjust the decimal digits and rounding for the 1.5567 + // given currency. 1.5568 + 1.5569 + // Note: The code is ordered so that this object is *not changed* 1.5570 + // until we are sure we are going to succeed. 1.5571 + 1.5572 + // NULL or empty currency is *legal* and indicates no currency. 1.5573 + UBool isCurr = (theCurrency && *theCurrency); 1.5574 + 1.5575 + double rounding = 0.0; 1.5576 + int32_t frac = 0; 1.5577 + if (fCurrencySignCount != fgCurrencySignCountZero && isCurr) { 1.5578 + rounding = ucurr_getRoundingIncrement(theCurrency, &ec); 1.5579 + frac = ucurr_getDefaultFractionDigits(theCurrency, &ec); 1.5580 + } 1.5581 + 1.5582 + NumberFormat::setCurrency(theCurrency, ec); 1.5583 + if (U_FAILURE(ec)) return; 1.5584 + 1.5585 + if (fCurrencySignCount != fgCurrencySignCountZero) { 1.5586 + // NULL or empty currency is *legal* and indicates no currency. 1.5587 + if (isCurr) { 1.5588 + setRoundingIncrement(rounding); 1.5589 + setMinimumFractionDigits(frac); 1.5590 + setMaximumFractionDigits(frac); 1.5591 + } 1.5592 + expandAffixes(NULL); 1.5593 + } 1.5594 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5595 + handleChanged(); 1.5596 +#endif 1.5597 +} 1.5598 + 1.5599 +void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { 1.5600 + // set the currency before compute affixes to get the right currency names 1.5601 + NumberFormat::setCurrency(theCurrency, ec); 1.5602 + if (fFormatPattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) { 1.5603 + UnicodeString savedPtn = fFormatPattern; 1.5604 + setupCurrencyAffixes(fFormatPattern, TRUE, TRUE, ec); 1.5605 + UParseError parseErr; 1.5606 + applyPattern(savedPtn, FALSE, parseErr, ec); 1.5607 + } 1.5608 + // set the currency after apply pattern to get the correct rounding/fraction 1.5609 + setCurrencyInternally(theCurrency, ec); 1.5610 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5611 + handleChanged(); 1.5612 +#endif 1.5613 +} 1.5614 + 1.5615 +// Deprecated variant with no UErrorCode parameter 1.5616 +void DecimalFormat::setCurrency(const UChar* theCurrency) { 1.5617 + UErrorCode ec = U_ZERO_ERROR; 1.5618 + setCurrency(theCurrency, ec); 1.5619 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5620 + handleChanged(); 1.5621 +#endif 1.5622 +} 1.5623 + 1.5624 +void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { 1.5625 + if (fSymbols == NULL) { 1.5626 + ec = U_MEMORY_ALLOCATION_ERROR; 1.5627 + return; 1.5628 + } 1.5629 + ec = U_ZERO_ERROR; 1.5630 + const UChar* c = getCurrency(); 1.5631 + if (*c == 0) { 1.5632 + const UnicodeString &intl = 1.5633 + fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 1.5634 + c = intl.getBuffer(); // ok for intl to go out of scope 1.5635 + } 1.5636 + u_strncpy(result, c, 3); 1.5637 + result[3] = 0; 1.5638 +} 1.5639 + 1.5640 +/** 1.5641 + * Return the number of fraction digits to display, or the total 1.5642 + * number of digits for significant digit formats and exponential 1.5643 + * formats. 1.5644 + */ 1.5645 +int32_t 1.5646 +DecimalFormat::precision() const { 1.5647 + if (areSignificantDigitsUsed()) { 1.5648 + return getMaximumSignificantDigits(); 1.5649 + } else if (fUseExponentialNotation) { 1.5650 + return getMinimumIntegerDigits() + getMaximumFractionDigits(); 1.5651 + } else { 1.5652 + return getMaximumFractionDigits(); 1.5653 + } 1.5654 +} 1.5655 + 1.5656 + 1.5657 +// TODO: template algorithm 1.5658 +Hashtable* 1.5659 +DecimalFormat::initHashForAffix(UErrorCode& status) { 1.5660 + if ( U_FAILURE(status) ) { 1.5661 + return NULL; 1.5662 + } 1.5663 + Hashtable* hTable; 1.5664 + if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 1.5665 + status = U_MEMORY_ALLOCATION_ERROR; 1.5666 + return NULL; 1.5667 + } 1.5668 + if ( U_FAILURE(status) ) { 1.5669 + delete hTable; 1.5670 + return NULL; 1.5671 + } 1.5672 + hTable->setValueComparator(decimfmtAffixValueComparator); 1.5673 + return hTable; 1.5674 +} 1.5675 + 1.5676 +Hashtable* 1.5677 +DecimalFormat::initHashForAffixPattern(UErrorCode& status) { 1.5678 + if ( U_FAILURE(status) ) { 1.5679 + return NULL; 1.5680 + } 1.5681 + Hashtable* hTable; 1.5682 + if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 1.5683 + status = U_MEMORY_ALLOCATION_ERROR; 1.5684 + return NULL; 1.5685 + } 1.5686 + if ( U_FAILURE(status) ) { 1.5687 + delete hTable; 1.5688 + return NULL; 1.5689 + } 1.5690 + hTable->setValueComparator(decimfmtAffixPatternValueComparator); 1.5691 + return hTable; 1.5692 +} 1.5693 + 1.5694 +void 1.5695 +DecimalFormat::deleteHashForAffix(Hashtable*& table) 1.5696 +{ 1.5697 + if ( table == NULL ) { 1.5698 + return; 1.5699 + } 1.5700 + int32_t pos = -1; 1.5701 + const UHashElement* element = NULL; 1.5702 + while ( (element = table->nextElement(pos)) != NULL ) { 1.5703 + const UHashTok valueTok = element->value; 1.5704 + const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer; 1.5705 + delete value; 1.5706 + } 1.5707 + delete table; 1.5708 + table = NULL; 1.5709 +} 1.5710 + 1.5711 + 1.5712 + 1.5713 +void 1.5714 +DecimalFormat::deleteHashForAffixPattern() 1.5715 +{ 1.5716 + if ( fAffixPatternsForCurrency == NULL ) { 1.5717 + return; 1.5718 + } 1.5719 + int32_t pos = -1; 1.5720 + const UHashElement* element = NULL; 1.5721 + while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 1.5722 + const UHashTok valueTok = element->value; 1.5723 + const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; 1.5724 + delete value; 1.5725 + } 1.5726 + delete fAffixPatternsForCurrency; 1.5727 + fAffixPatternsForCurrency = NULL; 1.5728 +} 1.5729 + 1.5730 + 1.5731 +void 1.5732 +DecimalFormat::copyHashForAffixPattern(const Hashtable* source, 1.5733 + Hashtable* target, 1.5734 + UErrorCode& status) { 1.5735 + if ( U_FAILURE(status) ) { 1.5736 + return; 1.5737 + } 1.5738 + int32_t pos = -1; 1.5739 + const UHashElement* element = NULL; 1.5740 + if ( source ) { 1.5741 + while ( (element = source->nextElement(pos)) != NULL ) { 1.5742 + const UHashTok keyTok = element->key; 1.5743 + const UnicodeString* key = (UnicodeString*)keyTok.pointer; 1.5744 + const UHashTok valueTok = element->value; 1.5745 + const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; 1.5746 + AffixPatternsForCurrency* copy = new AffixPatternsForCurrency( 1.5747 + value->negPrefixPatternForCurrency, 1.5748 + value->negSuffixPatternForCurrency, 1.5749 + value->posPrefixPatternForCurrency, 1.5750 + value->posSuffixPatternForCurrency, 1.5751 + value->patternType); 1.5752 + target->put(UnicodeString(*key), copy, status); 1.5753 + if ( U_FAILURE(status) ) { 1.5754 + return; 1.5755 + } 1.5756 + } 1.5757 + } 1.5758 +} 1.5759 + 1.5760 +DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, 1.5761 + int32_t newValue, 1.5762 + UErrorCode &status) { 1.5763 + if(U_FAILURE(status)) return *this; 1.5764 + 1.5765 + switch(attr) { 1.5766 + case UNUM_LENIENT_PARSE: 1.5767 + setLenient(newValue!=0); 1.5768 + break; 1.5769 + 1.5770 + case UNUM_PARSE_INT_ONLY: 1.5771 + setParseIntegerOnly(newValue!=0); 1.5772 + break; 1.5773 + 1.5774 + case UNUM_GROUPING_USED: 1.5775 + setGroupingUsed(newValue!=0); 1.5776 + break; 1.5777 + 1.5778 + case UNUM_DECIMAL_ALWAYS_SHOWN: 1.5779 + setDecimalSeparatorAlwaysShown(newValue!=0); 1.5780 + break; 1.5781 + 1.5782 + case UNUM_MAX_INTEGER_DIGITS: 1.5783 + setMaximumIntegerDigits(newValue); 1.5784 + break; 1.5785 + 1.5786 + case UNUM_MIN_INTEGER_DIGITS: 1.5787 + setMinimumIntegerDigits(newValue); 1.5788 + break; 1.5789 + 1.5790 + case UNUM_INTEGER_DIGITS: 1.5791 + setMinimumIntegerDigits(newValue); 1.5792 + setMaximumIntegerDigits(newValue); 1.5793 + break; 1.5794 + 1.5795 + case UNUM_MAX_FRACTION_DIGITS: 1.5796 + setMaximumFractionDigits(newValue); 1.5797 + break; 1.5798 + 1.5799 + case UNUM_MIN_FRACTION_DIGITS: 1.5800 + setMinimumFractionDigits(newValue); 1.5801 + break; 1.5802 + 1.5803 + case UNUM_FRACTION_DIGITS: 1.5804 + setMinimumFractionDigits(newValue); 1.5805 + setMaximumFractionDigits(newValue); 1.5806 + break; 1.5807 + 1.5808 + case UNUM_SIGNIFICANT_DIGITS_USED: 1.5809 + setSignificantDigitsUsed(newValue!=0); 1.5810 + break; 1.5811 + 1.5812 + case UNUM_MAX_SIGNIFICANT_DIGITS: 1.5813 + setMaximumSignificantDigits(newValue); 1.5814 + break; 1.5815 + 1.5816 + case UNUM_MIN_SIGNIFICANT_DIGITS: 1.5817 + setMinimumSignificantDigits(newValue); 1.5818 + break; 1.5819 + 1.5820 + case UNUM_MULTIPLIER: 1.5821 + setMultiplier(newValue); 1.5822 + break; 1.5823 + 1.5824 + case UNUM_GROUPING_SIZE: 1.5825 + setGroupingSize(newValue); 1.5826 + break; 1.5827 + 1.5828 + case UNUM_ROUNDING_MODE: 1.5829 + setRoundingMode((DecimalFormat::ERoundingMode)newValue); 1.5830 + break; 1.5831 + 1.5832 + case UNUM_FORMAT_WIDTH: 1.5833 + setFormatWidth(newValue); 1.5834 + break; 1.5835 + 1.5836 + case UNUM_PADDING_POSITION: 1.5837 + /** The position at which padding will take place. */ 1.5838 + setPadPosition((DecimalFormat::EPadPosition)newValue); 1.5839 + break; 1.5840 + 1.5841 + case UNUM_SECONDARY_GROUPING_SIZE: 1.5842 + setSecondaryGroupingSize(newValue); 1.5843 + break; 1.5844 + 1.5845 +#if UCONFIG_HAVE_PARSEALLINPUT 1.5846 + case UNUM_PARSE_ALL_INPUT: 1.5847 + setParseAllInput((UNumberFormatAttributeValue)newValue); 1.5848 + break; 1.5849 +#endif 1.5850 + 1.5851 + /* These are stored in fBoolFlags */ 1.5852 + case UNUM_PARSE_NO_EXPONENT: 1.5853 + case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 1.5854 + if(!fBoolFlags.isValidValue(newValue)) { 1.5855 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.5856 + } else { 1.5857 + fBoolFlags.set(attr, newValue); 1.5858 + } 1.5859 + break; 1.5860 + 1.5861 + case UNUM_SCALE: 1.5862 + fScale = newValue; 1.5863 + break; 1.5864 + 1.5865 + default: 1.5866 + status = U_UNSUPPORTED_ERROR; 1.5867 + break; 1.5868 + } 1.5869 + return *this; 1.5870 +} 1.5871 + 1.5872 +int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr, 1.5873 + UErrorCode &status ) const { 1.5874 + if(U_FAILURE(status)) return -1; 1.5875 + switch(attr) { 1.5876 + case UNUM_LENIENT_PARSE: 1.5877 + return isLenient(); 1.5878 + 1.5879 + case UNUM_PARSE_INT_ONLY: 1.5880 + return isParseIntegerOnly(); 1.5881 + 1.5882 + case UNUM_GROUPING_USED: 1.5883 + return isGroupingUsed(); 1.5884 + 1.5885 + case UNUM_DECIMAL_ALWAYS_SHOWN: 1.5886 + return isDecimalSeparatorAlwaysShown(); 1.5887 + 1.5888 + case UNUM_MAX_INTEGER_DIGITS: 1.5889 + return getMaximumIntegerDigits(); 1.5890 + 1.5891 + case UNUM_MIN_INTEGER_DIGITS: 1.5892 + return getMinimumIntegerDigits(); 1.5893 + 1.5894 + case UNUM_INTEGER_DIGITS: 1.5895 + // TBD: what should this return? 1.5896 + return getMinimumIntegerDigits(); 1.5897 + 1.5898 + case UNUM_MAX_FRACTION_DIGITS: 1.5899 + return getMaximumFractionDigits(); 1.5900 + 1.5901 + case UNUM_MIN_FRACTION_DIGITS: 1.5902 + return getMinimumFractionDigits(); 1.5903 + 1.5904 + case UNUM_FRACTION_DIGITS: 1.5905 + // TBD: what should this return? 1.5906 + return getMinimumFractionDigits(); 1.5907 + 1.5908 + case UNUM_SIGNIFICANT_DIGITS_USED: 1.5909 + return areSignificantDigitsUsed(); 1.5910 + 1.5911 + case UNUM_MAX_SIGNIFICANT_DIGITS: 1.5912 + return getMaximumSignificantDigits(); 1.5913 + 1.5914 + case UNUM_MIN_SIGNIFICANT_DIGITS: 1.5915 + return getMinimumSignificantDigits(); 1.5916 + 1.5917 + case UNUM_MULTIPLIER: 1.5918 + return getMultiplier(); 1.5919 + 1.5920 + case UNUM_GROUPING_SIZE: 1.5921 + return getGroupingSize(); 1.5922 + 1.5923 + case UNUM_ROUNDING_MODE: 1.5924 + return getRoundingMode(); 1.5925 + 1.5926 + case UNUM_FORMAT_WIDTH: 1.5927 + return getFormatWidth(); 1.5928 + 1.5929 + case UNUM_PADDING_POSITION: 1.5930 + return getPadPosition(); 1.5931 + 1.5932 + case UNUM_SECONDARY_GROUPING_SIZE: 1.5933 + return getSecondaryGroupingSize(); 1.5934 + 1.5935 + /* These are stored in fBoolFlags */ 1.5936 + case UNUM_PARSE_NO_EXPONENT: 1.5937 + case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 1.5938 + return fBoolFlags.get(attr); 1.5939 + 1.5940 + case UNUM_SCALE: 1.5941 + return fScale; 1.5942 + 1.5943 + default: 1.5944 + status = U_UNSUPPORTED_ERROR; 1.5945 + break; 1.5946 + } 1.5947 + 1.5948 + return -1; /* undefined */ 1.5949 +} 1.5950 + 1.5951 +#if UCONFIG_HAVE_PARSEALLINPUT 1.5952 +void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { 1.5953 + fParseAllInput = value; 1.5954 +#if UCONFIG_FORMAT_FASTPATHS_49 1.5955 + handleChanged(); 1.5956 +#endif 1.5957 +} 1.5958 +#endif 1.5959 + 1.5960 +void 1.5961 +DecimalFormat::copyHashForAffix(const Hashtable* source, 1.5962 + Hashtable* target, 1.5963 + UErrorCode& status) { 1.5964 + if ( U_FAILURE(status) ) { 1.5965 + return; 1.5966 + } 1.5967 + int32_t pos = -1; 1.5968 + const UHashElement* element = NULL; 1.5969 + if ( source ) { 1.5970 + while ( (element = source->nextElement(pos)) != NULL ) { 1.5971 + const UHashTok keyTok = element->key; 1.5972 + const UnicodeString* key = (UnicodeString*)keyTok.pointer; 1.5973 + 1.5974 + const UHashTok valueTok = element->value; 1.5975 + const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer; 1.5976 + AffixesForCurrency* copy = new AffixesForCurrency( 1.5977 + value->negPrefixForCurrency, 1.5978 + value->negSuffixForCurrency, 1.5979 + value->posPrefixForCurrency, 1.5980 + value->posSuffixForCurrency); 1.5981 + target->put(UnicodeString(*key), copy, status); 1.5982 + if ( U_FAILURE(status) ) { 1.5983 + return; 1.5984 + } 1.5985 + } 1.5986 + } 1.5987 +} 1.5988 + 1.5989 +U_NAMESPACE_END 1.5990 + 1.5991 +#endif /* #if !UCONFIG_NO_FORMATTING */ 1.5992 + 1.5993 +//eof