Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(416)

Side by Side Diff: source/i18n/decimfmt.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/i18n/decimalformatpatternimpl.h ('k') | source/i18n/decimfmtimpl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ******************************************************************************* 2 *******************************************************************************
3 * Copyright (C) 1997-2014, International Business Machines Corporation and * 3 * Copyright (C) 1997-2015, International Business Machines Corporation and *
4 * others. All Rights Reserved. * 4 * others. All Rights Reserved. *
5 ******************************************************************************* 5 *******************************************************************************
6 * 6 *
7 * File DECIMFMT.CPP 7 * File DECIMFMT.CPP
8 * 8 *
9 * Modification History: 9 * Modification History:
10 * 10 *
11 * Date Name Description 11 * Date Name Description
12 * 02/19/97 aliu Converted from java. 12 * 02/19/97 aliu Converted from java.
13 * 03/20/97 clhuang Implemented with new APIs. 13 * 03/20/97 clhuang Implemented with new APIs.
(...skipping 20 matching lines...) Expand all
34 * 06/28/99 stephen Fixed bugs in toPattern(). 34 * 06/28/99 stephen Fixed bugs in toPattern().
35 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad, 35 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
36 * fPadPosition 36 * fPadPosition
37 ******************************************************************************** 37 ********************************************************************************
38 */ 38 */
39 39
40 #include "unicode/utypes.h" 40 #include "unicode/utypes.h"
41 41
42 #if !UCONFIG_NO_FORMATTING 42 #if !UCONFIG_NO_FORMATTING
43 43
44 #include "fphdlimp.h"
45 #include "unicode/decimfmt.h"
46 #include "unicode/choicfmt.h"
47 #include "unicode/ucurr.h"
48 #include "unicode/ustring.h"
49 #include "unicode/dcfmtsym.h"
50 #include "unicode/ures.h"
51 #include "unicode/uchar.h"
52 #include "unicode/uniset.h" 44 #include "unicode/uniset.h"
53 #include "unicode/curramt.h"
54 #include "unicode/currpinf.h" 45 #include "unicode/currpinf.h"
55 #include "unicode/plurrule.h" 46 #include "unicode/plurrule.h"
56 #include "unicode/utf16.h" 47 #include "unicode/utf16.h"
57 #include "unicode/numsys.h" 48 #include "unicode/numsys.h"
58 #include "unicode/localpointer.h" 49 #include "unicode/localpointer.h"
59 #include "uresimp.h" 50 #include "uresimp.h"
60 #include "ucurrimp.h" 51 #include "ucurrimp.h"
61 #include "charstr.h" 52 #include "charstr.h"
62 #include "cmemory.h"
63 #include "patternprops.h" 53 #include "patternprops.h"
64 #include "digitlst.h"
65 #include "cstring.h" 54 #include "cstring.h"
66 #include "umutex.h"
67 #include "uassert.h" 55 #include "uassert.h"
68 #include "putilimp.h"
69 #include <math.h>
70 #include "hash.h" 56 #include "hash.h"
71 #include "decfmtst.h" 57 #include "decfmtst.h"
72 #include "dcfmtimp.h"
73 #include "plurrule_impl.h" 58 #include "plurrule_impl.h"
74 #include "decimalformatpattern.h" 59 #include "decimalformatpattern.h"
60 #include "fmtableimp.h"
61 #include "decimfmtimpl.h"
62 #include "visibledigits.h"
75 63
76 /* 64 /*
77 * On certain platforms, round is a macro defined in math.h 65 * On certain platforms, round is a macro defined in math.h
78 * This undefine is to avoid conflict between the macro and 66 * This undefine is to avoid conflict between the macro and
79 * the function defined below. 67 * the function defined below.
80 */ 68 */
81 #ifdef round 69 #ifdef round
82 #undef round 70 #undef round
83 #endif 71 #endif
84 72
(...skipping 10 matching lines...) Expand all
95 #define debugout(x) _debugout(__FILE__,__LINE__,x) 83 #define debugout(x) _debugout(__FILE__,__LINE__,x)
96 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); 84 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
97 static const UnicodeString dbg_null("<NULL>",""); 85 static const UnicodeString dbg_null("<NULL>","");
98 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) 86 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
99 #else 87 #else
100 #define debugout(x) 88 #define debugout(x)
101 #define debug(x) 89 #define debug(x)
102 #endif 90 #endif
103 91
104 92
105
106 /* == Fastpath calculation. ==
107 */
108 #if UCONFIG_FORMAT_FASTPATHS_49
109 inline DecimalFormatInternal& internalData(uint8_t *reserved) {
110 return *reinterpret_cast<DecimalFormatInternal*>(reserved);
111 }
112 inline const DecimalFormatInternal& internalData(const uint8_t *reserved) {
113 return *reinterpret_cast<const DecimalFormatInternal*>(reserved);
114 }
115 #else
116 #endif
117
118 /* For currency parsing purose, 93 /* For currency parsing purose,
119 * Need to remember all prefix patterns and suffix patterns of 94 * Need to remember all prefix patterns and suffix patterns of
120 * every currency format pattern, 95 * every currency format pattern,
121 * including the pattern of default currecny style 96 * including the pattern of default currecny style
122 * and plural currency style. And the patterns are set through applyPattern. 97 * and plural currency style. And the patterns are set through applyPattern.
123 */ 98 */
124 struct AffixPatternsForCurrency : public UMemory { 99 struct AffixPatternsForCurrency : public UMemory {
125 // negative prefix pattern 100 // negative prefix pattern
126 UnicodeString negPrefixPatternForCurrency; 101 UnicodeString negPrefixPatternForCurrency;
127 // negative suffix pattern 102 // negative suffix pattern
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 posSuffixForCurrency + (UnicodeString)"\" )"); 163 posSuffixForCurrency + (UnicodeString)"\" )");
189 } 164 }
190 #endif 165 #endif
191 }; 166 };
192 167
193 U_CDECL_BEGIN 168 U_CDECL_BEGIN
194 169
195 /** 170 /**
196 * @internal ICU 4.2 171 * @internal ICU 4.2
197 */ 172 */
198 static UBool U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val 2);
199
200 /**
201 * @internal ICU 4.2
202 */
203 static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHash Tok val2); 173 static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHash Tok val2);
204 174
205 175
206 static UBool 176 static UBool
207 U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2) {
208 const AffixesForCurrency* affix_1 =
209 (AffixesForCurrency*)val1.pointer;
210 const AffixesForCurrency* affix_2 =
211 (AffixesForCurrency*)val2.pointer;
212 return affix_1->negPrefixForCurrency == affix_2->negPrefixForCurrency &&
213 affix_1->negSuffixForCurrency == affix_2->negSuffixForCurrency &&
214 affix_1->posPrefixForCurrency == affix_2->posPrefixForCurrency &&
215 affix_1->posSuffixForCurrency == affix_2->posSuffixForCurrency;
216 }
217
218
219 static UBool
220 U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) { 177 U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
221 const AffixPatternsForCurrency* affix_1 = 178 const AffixPatternsForCurrency* affix_1 =
222 (AffixPatternsForCurrency*)val1.pointer; 179 (AffixPatternsForCurrency*)val1.pointer;
223 const AffixPatternsForCurrency* affix_2 = 180 const AffixPatternsForCurrency* affix_2 =
224 (AffixPatternsForCurrency*)val2.pointer; 181 (AffixPatternsForCurrency*)val2.pointer;
225 return affix_1->negPrefixPatternForCurrency == 182 return affix_1->negPrefixPatternForCurrency ==
226 affix_2->negPrefixPatternForCurrency && 183 affix_2->negPrefixPatternForCurrency &&
227 affix_1->negSuffixPatternForCurrency == 184 affix_1->negSuffixPatternForCurrency ==
228 affix_2->negSuffixPatternForCurrency && 185 affix_2->negSuffixPatternForCurrency &&
229 affix_1->posPrefixPatternForCurrency == 186 affix_1->posPrefixPatternForCurrency ==
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 * These are the tags we expect to see in normal resource bundle files associate d 234 * These are the tags we expect to see in normal resource bundle files associate d
278 * with a locale. 235 * with a locale.
279 */ 236 */
280 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - n ot used 237 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - n ot used
281 static const char fgNumberElements[]="NumberElements"; 238 static const char fgNumberElements[]="NumberElements";
282 static const char fgLatn[]="latn"; 239 static const char fgLatn[]="latn";
283 static const char fgPatterns[]="patterns"; 240 static const char fgPatterns[]="patterns";
284 static const char fgDecimalFormat[]="decimalFormat"; 241 static const char fgDecimalFormat[]="decimalFormat";
285 static const char fgCurrencyFormat[]="currencyFormat"; 242 static const char fgCurrencyFormat[]="currencyFormat";
286 243
287 static const UChar fgTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
288
289 inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; } 244 inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
290 inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; } 245 inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
291 246
292 static void copyString(const UnicodeString& src, UBool isBogus, UnicodeString *& dest, UErrorCode &status) {
293 if (U_FAILURE(status)) {
294 return;
295 }
296 if (isBogus) {
297 delete dest;
298 dest = NULL;
299 } else {
300 if (dest != NULL) {
301 *dest = src;
302 } else {
303 dest = new UnicodeString(src);
304 if (dest == NULL) {
305 status = U_MEMORY_ALLOCATION_ERROR;
306 return;
307 }
308 }
309 }
310 }
311
312
313 //------------------------------------------------------------------------------ 247 //------------------------------------------------------------------------------
314 // Constructs a DecimalFormat instance in the default locale. 248 // Constructs a DecimalFormat instance in the default locale.
315 249
316 DecimalFormat::DecimalFormat(UErrorCode& status) { 250 DecimalFormat::DecimalFormat(UErrorCode& status) {
317 init(); 251 init();
318 UParseError parseError; 252 UParseError parseError;
319 construct(status, parseError); 253 construct(status, parseError);
320 } 254 }
321 255
322 //------------------------------------------------------------------------------ 256 //------------------------------------------------------------------------------
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 } 318 }
385 319
386 //----------------------------------------------------------------------------- 320 //-----------------------------------------------------------------------------
387 // Common DecimalFormat initialization. 321 // Common DecimalFormat initialization.
388 // Put all fields of an uninitialized object into a known state. 322 // Put all fields of an uninitialized object into a known state.
389 // Common code, shared by all constructors. 323 // Common code, shared by all constructors.
390 // Can not fail. Leave the object in good enough shape that the destructor 324 // Can not fail. Leave the object in good enough shape that the destructor
391 // or assignment operator can run successfully. 325 // or assignment operator can run successfully.
392 void 326 void
393 DecimalFormat::init() { 327 DecimalFormat::init() {
394 fPosPrefixPattern = 0;
395 fPosSuffixPattern = 0;
396 fNegPrefixPattern = 0;
397 fNegSuffixPattern = 0;
398 fCurrencyChoice = 0;
399 fMultiplier = NULL;
400 fScale = 0;
401 fGroupingSize = 0;
402 fGroupingSize2 = 0;
403 fDecimalSeparatorAlwaysShown = FALSE;
404 fSymbols = NULL;
405 fUseSignificantDigits = FALSE;
406 fMinSignificantDigits = 1;
407 fMaxSignificantDigits = 6;
408 fUseExponentialNotation = FALSE;
409 fMinExponentDigits = 0;
410 fExponentSignAlwaysShown = FALSE;
411 fBoolFlags.clear(); 328 fBoolFlags.clear();
412 fRoundingIncrement = 0;
413 fRoundingMode = kRoundHalfEven;
414 fPad = 0;
415 fFormatWidth = 0;
416 fPadPosition = kPadBeforePrefix;
417 fStyle = UNUM_DECIMAL; 329 fStyle = UNUM_DECIMAL;
418 fCurrencySignCount = fgCurrencySignCountZero;
419 fAffixPatternsForCurrency = NULL; 330 fAffixPatternsForCurrency = NULL;
420 fAffixesForCurrency = NULL;
421 fPluralAffixesForCurrency = NULL;
422 fCurrencyPluralInfo = NULL; 331 fCurrencyPluralInfo = NULL;
423 fCurrencyUsage = UCURR_USAGE_STANDARD;
424 #if UCONFIG_HAVE_PARSEALLINPUT 332 #if UCONFIG_HAVE_PARSEALLINPUT
425 fParseAllInput = UNUM_MAYBE; 333 fParseAllInput = UNUM_MAYBE;
426 #endif 334 #endif
427 335
428 #if UCONFIG_FORMAT_FASTPATHS_49
429 DecimalFormatInternal &data = internalData(fReserved);
430 data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastp ath until later.
431 data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpa th until later.
432 #endif
433 fStaticSets = NULL; 336 fStaticSets = NULL;
337 fImpl = NULL;
434 } 338 }
435 339
436 //------------------------------------------------------------------------------ 340 //------------------------------------------------------------------------------
437 // Constructs a DecimalFormat instance with the specified number format 341 // Constructs a DecimalFormat instance with the specified number format
438 // pattern and the number format symbols in the desired locale. The 342 // pattern and the number format symbols in the desired locale. The
439 // created instance owns the symbols. 343 // created instance owns the symbols.
440 344
441 void 345 void
442 DecimalFormat::construct(UErrorCode& status, 346 DecimalFormat::construct(UErrorCode& status,
443 UParseError& parseErr, 347 UParseError& parseErr,
444 const UnicodeString* pattern, 348 const UnicodeString* pattern,
445 DecimalFormatSymbols* symbolsToAdopt) 349 DecimalFormatSymbols* symbolsToAdopt)
446 { 350 {
447 fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!! 351 LocalPointer<DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
448 fRoundingIncrement = NULL;
449 fRoundingMode = kRoundHalfEven;
450 fPad = kPatternPadEscape;
451 fPadPosition = kPadBeforePrefix;
452 if (U_FAILURE(status)) 352 if (U_FAILURE(status))
453 return; 353 return;
454 354
455 fPosPrefixPattern = fPosSuffixPattern = NULL; 355 if (adoptedSymbols.isNull())
456 fNegPrefixPattern = fNegSuffixPattern = NULL;
457 setMultiplier(1);
458 fGroupingSize = 3;
459 fGroupingSize2 = 0;
460 fDecimalSeparatorAlwaysShown = FALSE;
461 fUseExponentialNotation = FALSE;
462 fMinExponentDigits = 0;
463
464 if (fSymbols == NULL)
465 { 356 {
466 fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status); 357 adoptedSymbols.adoptInstead(
467 if (fSymbols == 0) { 358 new DecimalFormatSymbols(Locale::getDefault(), status));
359 if (adoptedSymbols.isNull() && U_SUCCESS(status)) {
468 status = U_MEMORY_ALLOCATION_ERROR; 360 status = U_MEMORY_ALLOCATION_ERROR;
361 }
362 if (U_FAILURE(status)) {
469 return; 363 return;
470 } 364 }
471 } 365 }
472 fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 366 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
473 if (U_FAILURE(status)) { 367 if (U_FAILURE(status)) {
474 return; 368 return;
475 } 369 }
476 UErrorCode nsStatus = U_ZERO_ERROR;
477 NumberingSystem *ns = NumberingSystem::createInstance(nsStatus);
478 if (U_FAILURE(nsStatus)) {
479 status = nsStatus;
480 return;
481 }
482 370
483 UnicodeString str; 371 UnicodeString str;
484 // Uses the default locale's number format pattern if there isn't 372 // Uses the default locale's number format pattern if there isn't
485 // one specified. 373 // one specified.
486 if (pattern == NULL) 374 if (pattern == NULL)
487 { 375 {
376 UErrorCode nsStatus = U_ZERO_ERROR;
377 LocalPointer<NumberingSystem> ns(
378 NumberingSystem::createInstance(nsStatus));
379 if (U_FAILURE(nsStatus)) {
380 status = nsStatus;
381 return;
382 }
383
488 int32_t len = 0; 384 int32_t len = 0;
489 UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), & status); 385 UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), & status);
490 386
491 UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberEleme nts, NULL, &status); 387 UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberEleme nts, NULL, &status);
492 resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status); 388 resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status);
493 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &st atus); 389 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &st atus);
494 const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecima lFormat, &len, &status); 390 const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecima lFormat, &len, &status);
495 if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getNam e())) { 391 if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getNam e())) {
496 status = U_ZERO_ERROR; 392 status = U_ZERO_ERROR;
497 resource = ures_getByKeyWithFallback(top, fgNumberElements, resource , &status); 393 resource = ures_getByKeyWithFallback(top, fgNumberElements, resource , &status);
498 resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &st atus); 394 resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &st atus);
499 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 395 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status);
500 resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 396 resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status);
501 } 397 }
502 str.setTo(TRUE, resStr, len); 398 str.setTo(TRUE, resStr, len);
503 pattern = &str; 399 pattern = &str;
504 ures_close(resource); 400 ures_close(resource);
505 ures_close(top); 401 ures_close(top);
506 } 402 }
507 403
508 delete ns; 404 fImpl = new DecimalFormatImpl(this, *pattern, adoptedSymbols.getAlias(), par seErr, status);
405 if (fImpl) {
406 adoptedSymbols.orphan();
407 } else if (U_SUCCESS(status)) {
408 status = U_MEMORY_ALLOCATION_ERROR;
409 }
410 if (U_FAILURE(status)) {
411 return;
412 }
509 413
510 if (U_FAILURE(status)) 414 if (U_FAILURE(status))
511 { 415 {
512 return; 416 return;
513 } 417 }
514 418
515 if (pattern->indexOf((UChar)kCurrencySign) >= 0) {
516 // If it looks like we are going to use a currency pattern
517 // then do the time consuming lookup.
518 setCurrencyForSymbols();
519 } else {
520 setCurrencyInternally(NULL, status);
521 }
522
523 const UnicodeString* patternUsed; 419 const UnicodeString* patternUsed;
524 UnicodeString currencyPluralPatternForOther; 420 UnicodeString currencyPluralPatternForOther;
525 // apply pattern 421 // apply pattern
526 if (fStyle == UNUM_CURRENCY_PLURAL) { 422 if (fStyle == UNUM_CURRENCY_PLURAL) {
527 fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), stat us); 423 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale( ), status);
528 if (U_FAILURE(status)) { 424 if (U_FAILURE(status)) {
529 return; 425 return;
530 } 426 }
531 427
532 // the pattern used in format is not fixed until formatting, 428 // the pattern used in format is not fixed until formatting,
533 // in which, the number is known and 429 // in which, the number is known and
534 // will be used to pick the right pattern based on plural count. 430 // will be used to pick the right pattern based on plural count.
535 // Here, set the pattern as the pattern of plural count == "other". 431 // Here, set the pattern as the pattern of plural count == "other".
536 // For most locale, the patterns are probably the same for all 432 // For most locale, the patterns are probably the same for all
537 // plural count. If not, the right pattern need to be re-applied 433 // plural count. If not, the right pattern need to be re-applied
538 // during format. 434 // during format.
539 fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5) , currencyPluralPatternForOther); 435 fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5) , currencyPluralPatternForOther);
436 // TODO(refactor): Revisit, we are setting the pattern twice.
437 fImpl->applyPatternFavorCurrencyPrecision(
438 currencyPluralPatternForOther, status);
540 patternUsed = &currencyPluralPatternForOther; 439 patternUsed = &currencyPluralPatternForOther;
541 // TODO: not needed?
542 setCurrencyForSymbols();
543 440
544 } else { 441 } else {
545 patternUsed = pattern; 442 patternUsed = pattern;
546 } 443 }
547 444
548 if (patternUsed->indexOf(kCurrencySign) != -1) { 445 if (patternUsed->indexOf(kCurrencySign) != -1) {
549 // initialize for currency, not only for plural format, 446 // initialize for currency, not only for plural format,
550 // but also for mix parsing 447 // but also for mix parsing
551 if (fCurrencyPluralInfo == NULL) { 448 if (fCurrencyPluralInfo == NULL) {
552 fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), s tatus); 449 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLoca le(), status);
553 if (U_FAILURE(status)) { 450 if (U_FAILURE(status)) {
554 return; 451 return;
555 } 452 }
556 } 453 }
557 // need it for mix parsing 454 // need it for mix parsing
558 setupCurrencyAffixPatterns(status); 455 setupCurrencyAffixPatterns(status);
559 // expanded affixes for plural names
560 if (patternUsed->indexOf(fgTripleCurrencySign, 3, 0) != -1) {
561 setupCurrencyAffixes(*patternUsed, TRUE, TRUE, status);
562 }
563 } 456 }
564
565 applyPatternWithoutExpandAffix(*patternUsed,FALSE, parseErr, status);
566
567 // expand affixes
568 if (fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
569 expandAffixAdjustWidth(NULL);
570 }
571
572 // If it was a currency format, apply the appropriate rounding by
573 // resetting the currency. NOTE: this copies fCurrency on top of itself.
574 if (fCurrencySignCount != fgCurrencySignCountZero) {
575 setCurrencyInternally(getCurrency(), status);
576 }
577 #if UCONFIG_FORMAT_FASTPATHS_49
578 DecimalFormatInternal &data = internalData(fReserved);
579 data.fFastFormatStatus = kFastpathNO; // allow it to be calculated
580 data.fFastParseStatus = kFastpathNO; // allow it to be calculated
581 handleChanged();
582 #endif
583 } 457 }
584 458
459 static void
460 applyPatternWithNoSideEffects(
461 const UnicodeString& pattern,
462 UParseError& parseError,
463 UnicodeString &negPrefix,
464 UnicodeString &negSuffix,
465 UnicodeString &posPrefix,
466 UnicodeString &posSuffix,
467 UErrorCode& status) {
468 if (U_FAILURE(status))
469 {
470 return;
471 }
472 DecimalFormatPatternParser patternParser;
473 DecimalFormatPattern out;
474 patternParser.applyPatternWithoutExpandAffix(
475 pattern,
476 out,
477 parseError,
478 status);
479 if (U_FAILURE(status)) {
480 return;
481 }
482 negPrefix = out.fNegPrefixPattern;
483 negSuffix = out.fNegSuffixPattern;
484 posPrefix = out.fPosPrefixPattern;
485 posSuffix = out.fPosSuffixPattern;
486 }
585 487
586 void 488 void
587 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) { 489 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
588 if (U_FAILURE(status)) { 490 if (U_FAILURE(status)) {
589 return; 491 return;
590 } 492 }
591 UParseError parseErr; 493 UParseError parseErr;
592 fAffixPatternsForCurrency = initHashForAffixPattern(status); 494 fAffixPatternsForCurrency = initHashForAffixPattern(status);
593 if (U_FAILURE(status)) { 495 if (U_FAILURE(status)) {
594 return; 496 return;
595 } 497 }
596 498
597 NumberingSystem *ns = NumberingSystem::createInstance(fSymbols->getLocale(), status); 499 NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLo cale(),status);
598 if (U_FAILURE(status)) { 500 if (U_FAILURE(status)) {
599 return; 501 return;
600 } 502 }
601 503
602 // Save the default currency patterns of this locale. 504 // Save the default currency patterns of this locale.
603 // Here, chose onlyApplyPatternWithoutExpandAffix without 505 // Here, chose onlyApplyPatternWithoutExpandAffix without
604 // expanding the affix patterns into affixes. 506 // expanding the affix patterns into affixes.
605 UnicodeString currencyPattern; 507 UnicodeString currencyPattern;
606 UErrorCode error = U_ZERO_ERROR; 508 UErrorCode error = U_ZERO_ERROR;
607 509
608 UResourceBundle *resource = ures_open(NULL, fSymbols->getLocale().getName(), &error); 510 UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().get Name(), &error);
609 UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberE lements, NULL, &error); 511 UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberE lements, NULL, &error);
610 resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, & error); 512 resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, & error);
611 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error) ; 513 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error) ;
612 int32_t patLen = 0; 514 int32_t patLen = 0;
613 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrenc yFormat, &patLen, &error); 515 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrenc yFormat, &patLen, &error);
614 if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) { 516 if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) {
615 error = U_ZERO_ERROR; 517 error = U_ZERO_ERROR;
616 resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &err or); 518 resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &err or);
617 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &er ror); 519 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &er ror);
618 patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 520 patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error);
619 } 521 }
620 ures_close(numElements); 522 ures_close(numElements);
621 ures_close(resource); 523 ures_close(resource);
622 delete ns; 524 delete ns;
623 525
624 if (U_SUCCESS(error)) { 526 if (U_SUCCESS(error)) {
625 applyPatternWithoutExpandAffix(UnicodeString(patResStr, patLen), false, 527 UnicodeString negPrefix;
626 parseErr, status); 528 UnicodeString negSuffix;
529 UnicodeString posPrefix;
530 UnicodeString posSuffix;
531 applyPatternWithNoSideEffects(UnicodeString(patResStr, patLen),
532 parseErr,
533 negPrefix, negSuffix, posPrefix, posSuffix, status);
627 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 534 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
628 *fNegPrefixPattern, 535 negPrefix,
629 *fNegSuffixPattern, 536 negSuffix,
630 *fPosPrefixPattern, 537 posPrefix,
631 *fPosSuffixPattern, 538 posSuffix,
632 UCURR_SYMBOL_NAME); 539 UCURR_SYMBOL_NAME);
633 fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, s tatus); 540 fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, s tatus);
634 } 541 }
635 542
636 // save the unique currency plural patterns of this locale. 543 // save the unique currency plural patterns of this locale.
637 Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPatter n; 544 Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPatter n;
638 const UHashElement* element = NULL; 545 const UHashElement* element = NULL;
639 int32_t pos = -1; 546 int32_t pos = UHASH_FIRST;
640 Hashtable pluralPatternSet; 547 Hashtable pluralPatternSet;
641 while ((element = pluralPtn->nextElement(pos)) != NULL) { 548 while ((element = pluralPtn->nextElement(pos)) != NULL) {
642 const UHashTok valueTok = element->value; 549 const UHashTok valueTok = element->value;
643 const UnicodeString* value = (UnicodeString*)valueTok.pointer; 550 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
644 const UHashTok keyTok = element->key; 551 const UHashTok keyTok = element->key;
645 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 552 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
646 if (pluralPatternSet.geti(*value) != 1) { 553 if (pluralPatternSet.geti(*value) != 1) {
554 UnicodeString negPrefix;
555 UnicodeString negSuffix;
556 UnicodeString posPrefix;
557 UnicodeString posSuffix;
647 pluralPatternSet.puti(*value, 1, status); 558 pluralPatternSet.puti(*value, 1, status);
648 applyPatternWithoutExpandAffix(*value, false, parseErr, status); 559 applyPatternWithNoSideEffects(
560 *value, parseErr,
561 negPrefix, negSuffix, posPrefix, posSuffix, status);
649 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 562 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
650 *fNegPrefixPattern, 563 negPrefix,
651 *fNegSuffixPattern, 564 negSuffix,
652 *fPosPrefixPattern, 565 posPrefix,
653 *fPosSuffixPattern, 566 posSuffix,
654 UCURR_LONG_NAME); 567 UCURR_LONG_NAME);
655 fAffixPatternsForCurrency->put(*key, affixPtn, status); 568 fAffixPatternsForCurrency->put(*key, affixPtn, status);
656 } 569 }
657 } 570 }
658 } 571 }
659 572
660 573
661 void
662 DecimalFormat::setupCurrencyAffixes(const UnicodeString& pattern,
663 UBool setupForCurrentPattern,
664 UBool setupForPluralPattern,
665 UErrorCode& status) {
666 if (U_FAILURE(status)) {
667 return;
668 }
669 UParseError parseErr;
670 if (setupForCurrentPattern) {
671 if (fAffixesForCurrency) {
672 deleteHashForAffix(fAffixesForCurrency);
673 }
674 fAffixesForCurrency = initHashForAffix(status);
675 if (U_SUCCESS(status)) {
676 applyPatternWithoutExpandAffix(pattern, false, parseErr, status);
677 const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules ();
678 StringEnumeration* keywords = pluralRules->getKeywords(status);
679 if (U_SUCCESS(status)) {
680 const UnicodeString* pluralCount;
681 while ((pluralCount = keywords->snext(status)) != NULL) {
682 if ( U_SUCCESS(status) ) {
683 expandAffixAdjustWidth(pluralCount);
684 AffixesForCurrency* affix = new AffixesForCurrency(
685 fNegativePrefix, fNegativeSuffix, fPositivePrefix, f PositiveSuffix);
686 fAffixesForCurrency->put(*pluralCount, affix, status);
687 }
688 }
689 }
690 delete keywords;
691 }
692 }
693
694 if (U_FAILURE(status)) {
695 return;
696 }
697
698 if (setupForPluralPattern) {
699 if (fPluralAffixesForCurrency) {
700 deleteHashForAffix(fPluralAffixesForCurrency);
701 }
702 fPluralAffixesForCurrency = initHashForAffix(status);
703 if (U_SUCCESS(status)) {
704 const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules ();
705 StringEnumeration* keywords = pluralRules->getKeywords(status);
706 if (U_SUCCESS(status)) {
707 const UnicodeString* pluralCount;
708 while ((pluralCount = keywords->snext(status)) != NULL) {
709 if ( U_SUCCESS(status) ) {
710 UnicodeString ptn;
711 fCurrencyPluralInfo->getCurrencyPluralPattern(*pluralCou nt, ptn);
712 applyPatternInternally(*pluralCount, ptn, false, parseEr r, status);
713 AffixesForCurrency* affix = new AffixesForCurrency(
714 fNegativePrefix, fNegativeSuffix, fPositivePrefix, f PositiveSuffix);
715 fPluralAffixesForCurrency->put(*pluralCount, affix, stat us);
716 }
717 }
718 }
719 delete keywords;
720 }
721 }
722 }
723
724
725 //------------------------------------------------------------------------------ 574 //------------------------------------------------------------------------------
726 575
727 DecimalFormat::~DecimalFormat() 576 DecimalFormat::~DecimalFormat()
728 { 577 {
729 delete fPosPrefixPattern;
730 delete fPosSuffixPattern;
731 delete fNegPrefixPattern;
732 delete fNegSuffixPattern;
733 delete fCurrencyChoice;
734 delete fMultiplier;
735 delete fSymbols;
736 delete fRoundingIncrement;
737 deleteHashForAffixPattern(); 578 deleteHashForAffixPattern();
738 deleteHashForAffix(fAffixesForCurrency);
739 deleteHashForAffix(fPluralAffixesForCurrency);
740 delete fCurrencyPluralInfo; 579 delete fCurrencyPluralInfo;
580 delete fImpl;
741 } 581 }
742 582
743 //------------------------------------------------------------------------------ 583 //------------------------------------------------------------------------------
744 // copy constructor 584 // copy constructor
745 585
746 DecimalFormat::DecimalFormat(const DecimalFormat &source) : 586 DecimalFormat::DecimalFormat(const DecimalFormat &source) :
747 NumberFormat(source) { 587 NumberFormat(source) {
748 init(); 588 init();
749 *this = source; 589 *this = source;
750 } 590 }
751 591
752 //------------------------------------------------------------------------------ 592 //------------------------------------------------------------------------------
753 // assignment operator 593 // assignment operator
754 594
755 template <class T> 595 template <class T>
756 static void _copy_ptr(T** pdest, const T* source) {
757 if (source == NULL) {
758 delete *pdest;
759 *pdest = NULL;
760 } else if (*pdest == NULL) {
761 *pdest = new T(*source);
762 } else {
763 **pdest = *source;
764 }
765 }
766
767 template <class T>
768 static void _clone_ptr(T** pdest, const T* source) { 596 static void _clone_ptr(T** pdest, const T* source) {
769 delete *pdest; 597 delete *pdest;
770 if (source == NULL) { 598 if (source == NULL) {
771 *pdest = NULL; 599 *pdest = NULL;
772 } else { 600 } else {
773 *pdest = static_cast<T*>(source->clone()); 601 *pdest = static_cast<T*>(source->clone());
774 } 602 }
775 } 603 }
776 604
777 DecimalFormat& 605 DecimalFormat&
778 DecimalFormat::operator=(const DecimalFormat& rhs) 606 DecimalFormat::operator=(const DecimalFormat& rhs)
779 { 607 {
780 if(this != &rhs) { 608 if(this != &rhs) {
781 UErrorCode status = U_ZERO_ERROR; 609 UErrorCode status = U_ZERO_ERROR;
782 NumberFormat::operator=(rhs); 610 NumberFormat::operator=(rhs);
611 if (fImpl == NULL) {
612 fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status);
613 } else {
614 fImpl->assign(*rhs.fImpl, status);
615 }
783 fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 616 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
784 fPositivePrefix = rhs.fPositivePrefix;
785 fPositiveSuffix = rhs.fPositiveSuffix;
786 fNegativePrefix = rhs.fNegativePrefix;
787 fNegativeSuffix = rhs.fNegativeSuffix;
788 _copy_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern);
789 _copy_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern);
790 _copy_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern);
791 _copy_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern);
792 _clone_ptr(&fCurrencyChoice, rhs.fCurrencyChoice);
793 setRoundingIncrement(rhs.getRoundingIncrement());
794 fRoundingMode = rhs.fRoundingMode;
795 setMultiplier(rhs.getMultiplier());
796 fGroupingSize = rhs.fGroupingSize;
797 fGroupingSize2 = rhs.fGroupingSize2;
798 fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown;
799 _copy_ptr(&fSymbols, rhs.fSymbols);
800 fUseExponentialNotation = rhs.fUseExponentialNotation;
801 fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown;
802 fBoolFlags = rhs.fBoolFlags;
803 /*Bertrand A. D. Update 98.03.17*/
804 fCurrencySignCount = rhs.fCurrencySignCount;
805 /*end of Update*/
806 fMinExponentDigits = rhs.fMinExponentDigits;
807
808 /* sfb 990629 */
809 fFormatWidth = rhs.fFormatWidth;
810 fPad = rhs.fPad;
811 fPadPosition = rhs.fPadPosition;
812 /* end sfb */
813 fMinSignificantDigits = rhs.fMinSignificantDigits;
814 fMaxSignificantDigits = rhs.fMaxSignificantDigits;
815 fUseSignificantDigits = rhs.fUseSignificantDigits;
816 fFormatPattern = rhs.fFormatPattern;
817 fCurrencyUsage = rhs.fCurrencyUsage;
818 fStyle = rhs.fStyle; 617 fStyle = rhs.fStyle;
819 _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo); 618 _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo);
820 deleteHashForAffixPattern(); 619 deleteHashForAffixPattern();
821 if (rhs.fAffixPatternsForCurrency) { 620 if (rhs.fAffixPatternsForCurrency) {
822 UErrorCode status = U_ZERO_ERROR; 621 UErrorCode status = U_ZERO_ERROR;
823 fAffixPatternsForCurrency = initHashForAffixPattern(status); 622 fAffixPatternsForCurrency = initHashForAffixPattern(status);
824 copyHashForAffixPattern(rhs.fAffixPatternsForCurrency, 623 copyHashForAffixPattern(rhs.fAffixPatternsForCurrency,
825 fAffixPatternsForCurrency, status); 624 fAffixPatternsForCurrency, status);
826 } 625 }
827 deleteHashForAffix(fAffixesForCurrency);
828 if (rhs.fAffixesForCurrency) {
829 UErrorCode status = U_ZERO_ERROR;
830 fAffixesForCurrency = initHashForAffixPattern(status);
831 copyHashForAffix(rhs.fAffixesForCurrency, fAffixesForCurrency, statu s);
832 }
833 deleteHashForAffix(fPluralAffixesForCurrency);
834 if (rhs.fPluralAffixesForCurrency) {
835 UErrorCode status = U_ZERO_ERROR;
836 fPluralAffixesForCurrency = initHashForAffixPattern(status);
837 copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCur rency, status);
838 }
839 #if UCONFIG_FORMAT_FASTPATHS_49
840 DecimalFormatInternal &data = internalData(fReserved);
841 const DecimalFormatInternal &rhsData = internalData(rhs.fReserved);
842 data = rhsData;
843 #endif
844 } 626 }
627
845 return *this; 628 return *this;
846 } 629 }
847 630
848 //------------------------------------------------------------------------------ 631 //------------------------------------------------------------------------------
849 632
850 UBool 633 UBool
851 DecimalFormat::operator==(const Format& that) const 634 DecimalFormat::operator==(const Format& that) const
852 { 635 {
853 if (this == &that) 636 if (this == &that)
854 return TRUE; 637 return TRUE;
855 638
856 // NumberFormat::operator== guarantees this cast is safe 639 // NumberFormat::operator== guarantees this cast is safe
857 const DecimalFormat* other = (DecimalFormat*)&that; 640 const DecimalFormat* other = (DecimalFormat*)&that;
858 641
859 #ifdef FMT_DEBUG
860 // This code makes it easy to determine why two format objects that should
861 // be equal aren't.
862 UBool first = TRUE;
863 if (!NumberFormat::operator==(that)) {
864 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
865 debug("NumberFormat::!=");
866 } else {
867 if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null
868 fPositivePrefix == other->fPositivePrefix)
869 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
870 *fPosPrefixPattern == *other->fPosPrefixPattern))) {
871 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
872 debug("Pos Prefix !=");
873 }
874 if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null
875 fPositiveSuffix == other->fPositiveSuffix)
876 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
877 *fPosSuffixPattern == *other->fPosSuffixPattern))) {
878 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
879 debug("Pos Suffix !=");
880 }
881 if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null
882 fNegativePrefix == other->fNegativePrefix)
883 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
884 *fNegPrefixPattern == *other->fNegPrefixPattern))) {
885 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
886 debug("Neg Prefix ");
887 if (fNegPrefixPattern == NULL) {
888 debug("NULL(");
889 debugout(fNegativePrefix);
890 debug(")");
891 } else {
892 debugout(*fNegPrefixPattern);
893 }
894 debug(" != ");
895 if (other->fNegPrefixPattern == NULL) {
896 debug("NULL(");
897 debugout(other->fNegativePrefix);
898 debug(")");
899 } else {
900 debugout(*other->fNegPrefixPattern);
901 }
902 }
903 if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null
904 fNegativeSuffix == other->fNegativeSuffix)
905 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
906 *fNegSuffixPattern == *other->fNegSuffixPattern))) {
907 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
908 debug("Neg Suffix ");
909 if (fNegSuffixPattern == NULL) {
910 debug("NULL(");
911 debugout(fNegativeSuffix);
912 debug(")");
913 } else {
914 debugout(*fNegSuffixPattern);
915 }
916 debug(" != ");
917 if (other->fNegSuffixPattern == NULL) {
918 debug("NULL(");
919 debugout(other->fNegativeSuffix);
920 debug(")");
921 } else {
922 debugout(*other->fNegSuffixPattern);
923 }
924 }
925 if (!((fRoundingIncrement == other->fRoundingIncrement) // both null
926 || (fRoundingIncrement != NULL &&
927 other->fRoundingIncrement != NULL &&
928 *fRoundingIncrement == *other->fRoundingIncrement))) {
929 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
930 debug("Rounding Increment !=");
931 }
932 if (fRoundingMode != other->fRoundingMode) {
933 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
934 printf("Rounding Mode %d != %d", (int)fRoundingMode, (int)other->fRoundi ngMode);
935 }
936 if (getMultiplier() != other->getMultiplier()) {
937 if (first) { printf("[ "); first = FALSE; }
938 printf("Multiplier %ld != %ld", getMultiplier(), other->getMultiplier()) ;
939 }
940 if (fGroupingSize != other->fGroupingSize) {
941 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
942 printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize);
943 }
944 if (fGroupingSize2 != other->fGroupingSize2) {
945 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
946 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGro upingSize2);
947 }
948 if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) {
949 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
950 printf("fDecimalSeparatorAlwaysShown %d != %d", fDecimalSeparatorAlwaysS hown, other->fDecimalSeparatorAlwaysShown);
951 }
952 if (fUseExponentialNotation != other->fUseExponentialNotation) {
953 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
954 debug("fUseExponentialNotation !=");
955 }
956 if (fUseExponentialNotation &&
957 fMinExponentDigits != other->fMinExponentDigits) {
958 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
959 debug("fMinExponentDigits !=");
960 }
961 if (fUseExponentialNotation &&
962 fExponentSignAlwaysShown != other->fExponentSignAlwaysShown) {
963 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
964 debug("fExponentSignAlwaysShown !=");
965 }
966 if (fBoolFlags.getAll() != other->fBoolFlags.getAll()) {
967 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
968 debug("fBoolFlags !=");
969 }
970 if (*fSymbols != *(other->fSymbols)) {
971 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
972 debug("Symbols !=");
973 }
974 // TODO Add debug stuff for significant digits here
975 if (fUseSignificantDigits != other->fUseSignificantDigits) {
976 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
977 debug("fUseSignificantDigits !=");
978 }
979 if (fUseSignificantDigits &&
980 fMinSignificantDigits != other->fMinSignificantDigits) {
981 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
982 debug("fMinSignificantDigits !=");
983 }
984 if (fUseSignificantDigits &&
985 fMaxSignificantDigits != other->fMaxSignificantDigits) {
986 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
987 debug("fMaxSignificantDigits !=");
988 }
989 if (fFormatWidth != other->fFormatWidth) {
990 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
991 debug("fFormatWidth !=");
992 }
993 if (fPad != other->fPad) {
994 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
995 debug("fPad !=");
996 }
997 if (fPadPosition != other->fPadPosition) {
998 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
999 debug("fPadPosition !=");
1000 }
1001 if (fStyle == UNUM_CURRENCY_PLURAL &&
1002 fStyle != other->fStyle)
1003 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
1004 debug("fStyle !=");
1005 }
1006 if (fStyle == UNUM_CURRENCY_PLURAL &&
1007 fFormatPattern != other->fFormatPattern) {
1008 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
1009 debug("fFormatPattern !=");
1010 }
1011
1012 if (!first) { printf(" ]"); }
1013 if (fCurrencySignCount != other->fCurrencySignCount) {
1014 debug("fCurrencySignCount !=");
1015 }
1016 if (fCurrencyPluralInfo == other->fCurrencyPluralInfo) {
1017 debug("fCurrencyPluralInfo == ");
1018 if (fCurrencyPluralInfo == NULL) {
1019 debug("fCurrencyPluralInfo == NULL");
1020 }
1021 }
1022 if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL &&
1023 *fCurrencyPluralInfo != *(other->fCurrencyPluralInfo)) {
1024 debug("fCurrencyPluralInfo !=");
1025 }
1026 if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo == NULL ||
1027 fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo != NULL) {
1028 debug("fCurrencyPluralInfo one NULL, the other not");
1029 }
1030 if (fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo == NULL) {
1031 debug("fCurrencyPluralInfo == ");
1032 }
1033 }
1034 #endif
1035
1036 return ( 642 return (
1037 NumberFormat::operator==(that) && 643 NumberFormat::operator==(that) &&
644 fBoolFlags.getAll() == other->fBoolFlags.getAll() &&
645 *fImpl == *other->fImpl);
1038 646
1039 ((fCurrencySignCount == fgCurrencySignCountInPluralFormat) ?
1040 (fAffixPatternsForCurrency->equals(*other->fAffixPatternsForCurrency)) :
1041 (((fPosPrefixPattern == other->fPosPrefixPattern && // both null
1042 fPositivePrefix == other->fPositivePrefix)
1043 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
1044 *fPosPrefixPattern == *other->fPosPrefixPattern)) &&
1045 ((fPosSuffixPattern == other->fPosSuffixPattern && // both null
1046 fPositiveSuffix == other->fPositiveSuffix)
1047 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
1048 *fPosSuffixPattern == *other->fPosSuffixPattern)) &&
1049 ((fNegPrefixPattern == other->fNegPrefixPattern && // both null
1050 fNegativePrefix == other->fNegativePrefix)
1051 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
1052 *fNegPrefixPattern == *other->fNegPrefixPattern)) &&
1053 ((fNegSuffixPattern == other->fNegSuffixPattern && // both null
1054 fNegativeSuffix == other->fNegativeSuffix)
1055 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
1056 *fNegSuffixPattern == *other->fNegSuffixPattern)))) &&
1057
1058 ((fRoundingIncrement == other->fRoundingIncrement) // both null
1059 || (fRoundingIncrement != NULL &&
1060 other->fRoundingIncrement != NULL &&
1061 *fRoundingIncrement == *other->fRoundingIncrement)) &&
1062
1063 fRoundingMode == other->fRoundingMode &&
1064 getMultiplier() == other->getMultiplier() &&
1065 fGroupingSize == other->fGroupingSize &&
1066 fGroupingSize2 == other->fGroupingSize2 &&
1067 fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown &&
1068 fUseExponentialNotation == other->fUseExponentialNotation &&
1069
1070 (!fUseExponentialNotation ||
1071 (fMinExponentDigits == other->fMinExponentDigits && fExponentSignAlw aysShown == other->fExponentSignAlwaysShown)) &&
1072
1073 fBoolFlags.getAll() == other->fBoolFlags.getAll() &&
1074 *fSymbols == *(other->fSymbols) &&
1075 fUseSignificantDigits == other->fUseSignificantDigits &&
1076
1077 (!fUseSignificantDigits ||
1078 (fMinSignificantDigits == other->fMinSignificantDigits && fMaxSignif icantDigits == other->fMaxSignificantDigits)) &&
1079
1080 fFormatWidth == other->fFormatWidth &&
1081 fPad == other->fPad &&
1082 fPadPosition == other->fPadPosition &&
1083
1084 (fStyle != UNUM_CURRENCY_PLURAL ||
1085 (fStyle == other->fStyle && fFormatPattern == other->fFormatPattern) ) &&
1086
1087 fCurrencySignCount == other->fCurrencySignCount &&
1088
1089 ((fCurrencyPluralInfo == other->fCurrencyPluralInfo &&
1090 fCurrencyPluralInfo == NULL) ||
1091 (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL &&
1092 *fCurrencyPluralInfo == *(other->fCurrencyPluralInfo))) &&
1093
1094 fCurrencyUsage == other->fCurrencyUsage
1095
1096 // depending on other settings we may also need to compare
1097 // fCurrencyChoice (mostly deprecated?),
1098 // fAffixesForCurrency & fPluralAffixesForCurrency (only relevant in som e cases)
1099 );
1100 } 647 }
1101 648
1102 //------------------------------------------------------------------------------ 649 //------------------------------------------------------------------------------
1103 650
1104 Format* 651 Format*
1105 DecimalFormat::clone() const 652 DecimalFormat::clone() const
1106 { 653 {
1107 return new DecimalFormat(*this); 654 return new DecimalFormat(*this);
1108 } 655 }
1109 656
1110 657
1111 FixedDecimal 658 FixedDecimal
1112 DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const { 659 DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const {
1113 FixedDecimal result; 660 VisibleDigitsWithExponent digits;
1114 661 initVisibleDigitsWithExponent(number, digits, status);
1115 if (U_FAILURE(status)) {
1116 return result;
1117 }
1118
1119 if (uprv_isNaN(number) || uprv_isPositiveInfinity(fabs(number))) {
1120 // For NaN and Infinity the state of the formatter is ignored.
1121 result.init(number);
1122 return result;
1123 }
1124
1125 if (fMultiplier == NULL && fScale == 0 && fRoundingIncrement == 0 && areSign ificantDigitsUsed() == FALSE &&
1126 result.quickInit(number) && result.visibleDecimalDigitCount <= getMa ximumFractionDigits()) {
1127 // Fast Path. Construction of an exact FixedDecimal directly from the do uble, without passing
1128 // through a DigitList, was successful, and the formatter is doing not hing tricky with rounding.
1129 // printf("getFixedDecimal(%g): taking fast path.\n", number);
1130 result.adjustForMinFractionDigits(getMinimumFractionDigits());
1131 } else {
1132 // Slow path. Create a DigitList, and have this formatter round it accor ding to the
1133 // requirements of the format, and fill the fixedDecimal from that.
1134 DigitList digits;
1135 digits.set(number);
1136 result = getFixedDecimal(digits, status);
1137 }
1138 return result;
1139 }
1140
1141 // MSVC optimizer bug?
1142 // turn off optimization as it causes different behavior in the int64->double->i nt64 conversion
1143 #if defined (_MSC_VER)
1144 #pragma optimize ( "", off )
1145 #endif
1146 FixedDecimal
1147 DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) co nst {
1148 if (U_FAILURE(status)) { 662 if (U_FAILURE(status)) {
1149 return FixedDecimal(); 663 return FixedDecimal();
1150 } 664 }
665 return FixedDecimal(digits.getMantissa());
666 }
667
668 VisibleDigitsWithExponent &
669 DecimalFormat::initVisibleDigitsWithExponent(
670 double number,
671 VisibleDigitsWithExponent &digits,
672 UErrorCode &status) const {
673 return fImpl->initVisibleDigitsWithExponent(number, digits, status);
674 }
675
676 FixedDecimal
677 DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) co nst {
678 VisibleDigitsWithExponent digits;
679 initVisibleDigitsWithExponent(number, digits, status);
680 if (U_FAILURE(status)) {
681 return FixedDecimal();
682 }
683 return FixedDecimal(digits.getMantissa());
684 }
685
686 VisibleDigitsWithExponent &
687 DecimalFormat::initVisibleDigitsWithExponent(
688 const Formattable &number,
689 VisibleDigitsWithExponent &digits,
690 UErrorCode &status) const {
691 if (U_FAILURE(status)) {
692 return digits;
693 }
1151 if (!number.isNumeric()) { 694 if (!number.isNumeric()) {
1152 status = U_ILLEGAL_ARGUMENT_ERROR; 695 status = U_ILLEGAL_ARGUMENT_ERROR;
1153 return FixedDecimal(); 696 return digits;
1154 } 697 }
1155 698
1156 DigitList *dl = number.getDigitList(); 699 DigitList *dl = number.getDigitList();
1157 if (dl != NULL) { 700 if (dl != NULL) {
1158 DigitList clonedDL(*dl); 701 DigitList dlCopy(*dl);
1159 return getFixedDecimal(clonedDL, status); 702 return fImpl->initVisibleDigitsWithExponent(
703 dlCopy, digits, status);
1160 } 704 }
1161 705
1162 Formattable::Type type = number.getType(); 706 Formattable::Type type = number.getType();
1163 if (type == Formattable::kDouble || type == Formattable::kLong) { 707 if (type == Formattable::kDouble || type == Formattable::kLong) {
1164 return getFixedDecimal(number.getDouble(status), status); 708 return fImpl->initVisibleDigitsWithExponent(
709 number.getDouble(status), digits, status);
1165 } 710 }
1166 711 return fImpl->initVisibleDigitsWithExponent(
1167 if (type == Formattable::kInt64) { 712 number.getInt64(), digits, status);
1168 // "volatile" here is a workaround to avoid optimization issues.
1169 volatile double fdv = number.getDouble(status);
1170 // Note: conversion of int64_t -> double rounds with some compilers to
1171 // values beyond what can be represented as a 64 bit int. Subseque nt
1172 // testing or conversion with int64_t produces bad results.
1173 // So filter the problematic values, route them to DigitList.
1174 if (fdv != (double)U_INT64_MAX && fdv != (double)U_INT64_MIN &&
1175 number.getInt64() == (int64_t)fdv) {
1176 return getFixedDecimal(number.getDouble(status), status);
1177 }
1178 }
1179
1180 // The only case left is type==int64_t, with a value with more digits than a double can represent.
1181 // Any formattable originating as a big decimal will have had a pre-existing digit list.
1182 // Any originating as a double or int32 will have been handled as a double.
1183
1184 U_ASSERT(type == Formattable::kInt64);
1185 DigitList digits;
1186 digits.set(number.getInt64());
1187 return getFixedDecimal(digits, status);
1188 } 713 }
1189 // end workaround MSVC optimizer bug
1190 #if defined (_MSC_VER)
1191 #pragma optimize ( "", on )
1192 #endif
1193 714
1194 715
1195 // Create a fixed decimal from a DigitList. 716 // Create a fixed decimal from a DigitList.
1196 // The digit list may be modified. 717 // The digit list may be modified.
1197 // Internal function only. 718 // Internal function only.
1198 FixedDecimal 719 FixedDecimal
1199 DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const { 720 DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const {
1200 // Round the number according to the requirements of this Format. 721 VisibleDigitsWithExponent digits;
1201 FixedDecimal result; 722 initVisibleDigitsWithExponent(number, digits, status);
1202 _round(number, number, result.isNegative, status); 723 if (U_FAILURE(status)) {
724 return FixedDecimal();
725 }
726 return FixedDecimal(digits.getMantissa());
727 }
1203 728
1204 // The int64_t fields in FixedDecimal can easily overflow. 729 VisibleDigitsWithExponent &
1205 // In deciding what to discard in this event, consider that fixedDecimal 730 DecimalFormat::initVisibleDigitsWithExponent(
1206 // is being used only with PluralRules, and those rules mostly look at lea st significant 731 DigitList &number,
1207 // few digits of the integer part, and whether the fraction part is zero o r not. 732 VisibleDigitsWithExponent &digits,
1208 // 733 UErrorCode &status) const {
1209 // So, in case of overflow when filling in the fields of the FixedDecimal ob ject, 734 return fImpl->initVisibleDigitsWithExponent(
1210 // for the integer part, discard the most significant digits. 735 number, digits, status);
1211 // for the fraction part, discard the least significant digits,
1212 // don't truncate the fraction value to zero.
1213 // For simplicity, the int64_t fields are limited to 18 decimal digits, even
1214 // though they could hold most (but not all) 19 digit values.
1215
1216 // Integer Digits.
1217 int32_t di = number.getDecimalAt()-18; // Take at most 18 digits.
1218 if (di < 0) {
1219 di = 0;
1220 }
1221 result.intValue = 0;
1222 for (; di<number.getDecimalAt(); di++) {
1223 result.intValue = result.intValue * 10 + (number.getDigit(di) & 0x0f);
1224 }
1225 if (result.intValue == 0 && number.getDecimalAt()-18 > 0) {
1226 // The number is something like 100000000000000000000000.
1227 // More than 18 digits integer digits, but the least significant 18 are all zero.
1228 // We don't want to return zero as the int part, but want to keep zeros
1229 // for several of the least significant digits.
1230 result.intValue = 100000000000000000LL;
1231 }
1232
1233 // Fraction digits.
1234 result.decimalDigits = result.decimalDigitsWithoutTrailingZeros = result.vis ibleDecimalDigitCount = 0;
1235 for (di = number.getDecimalAt(); di < number.getCount(); di++) {
1236 result.visibleDecimalDigitCount++;
1237 if (result.decimalDigits < 100000000000000000LL) {
1238 // 9223372036854775807 Largest 64 bit signed integer
1239 int32_t digitVal = number.getDigit(di) & 0x0f; // getDigit() return s a char, '0'-'9'.
1240 result.decimalDigits = result.decimalDigits * 10 + digitVal;
1241 if (digitVal > 0) {
1242 result.decimalDigitsWithoutTrailingZeros = result.decimalDigits;
1243 }
1244 }
1245 }
1246
1247 result.hasIntegerValue = (result.decimalDigits == 0);
1248
1249 // Trailing fraction zeros. The format specification may require more traili ng
1250 // zeros than the numeric value. Add any such on now.
1251
1252 int32_t minFractionDigits;
1253 if (areSignificantDigitsUsed()) {
1254 minFractionDigits = getMinimumSignificantDigits() - number.getDecimalAt( );
1255 if (minFractionDigits < 0) {
1256 minFractionDigits = 0;
1257 }
1258 } else {
1259 minFractionDigits = getMinimumFractionDigits();
1260 }
1261 result.adjustForMinFractionDigits(minFractionDigits);
1262
1263 return result;
1264 } 736 }
1265 737
1266 738
1267 //------------------------------------------------------------------------------ 739 //------------------------------------------------------------------------------
1268 740
1269 UnicodeString& 741 UnicodeString&
1270 DecimalFormat::format(int32_t number, 742 DecimalFormat::format(int32_t number,
1271 UnicodeString& appendTo, 743 UnicodeString& appendTo,
1272 FieldPosition& fieldPosition) const 744 FieldPosition& fieldPosition) const
1273 { 745 {
1274 return format((int64_t)number, appendTo, fieldPosition); 746 UErrorCode status = U_ZERO_ERROR;
747 return fImpl->format(number, appendTo, fieldPosition, status);
1275 } 748 }
1276 749
1277 UnicodeString& 750 UnicodeString&
1278 DecimalFormat::format(int32_t number, 751 DecimalFormat::format(int32_t number,
1279 UnicodeString& appendTo, 752 UnicodeString& appendTo,
1280 FieldPosition& fieldPosition, 753 FieldPosition& fieldPosition,
1281 UErrorCode& status) const 754 UErrorCode& status) const
1282 { 755 {
1283 return format((int64_t)number, appendTo, fieldPosition, status); 756 return fImpl->format(number, appendTo, fieldPosition, status);
1284 } 757 }
1285 758
1286 UnicodeString& 759 UnicodeString&
1287 DecimalFormat::format(int32_t number, 760 DecimalFormat::format(int32_t number,
1288 UnicodeString& appendTo, 761 UnicodeString& appendTo,
1289 FieldPositionIterator* posIter, 762 FieldPositionIterator* posIter,
1290 UErrorCode& status) const 763 UErrorCode& status) const
1291 { 764 {
1292 return format((int64_t)number, appendTo, posIter, status); 765 return fImpl->format(number, appendTo, posIter, status);
1293 } 766 }
1294 767
1295 768
1296 #if UCONFIG_FORMAT_FASTPATHS_49
1297 void DecimalFormat::handleChanged() {
1298 DecimalFormatInternal &data = internalData(fReserved);
1299
1300 if(data.fFastFormatStatus == kFastpathUNKNOWN || data.fFastParseStatus == kFas tpathUNKNOWN) {
1301 return; // still constructing. Wait.
1302 }
1303
1304 data.fFastParseStatus = data.fFastFormatStatus = kFastpathNO;
1305
1306 #if UCONFIG_HAVE_PARSEALLINPUT
1307 if(fParseAllInput == UNUM_NO) {
1308 debug("No Parse fastpath: fParseAllInput==UNUM_NO");
1309 } else
1310 #endif
1311 if (fFormatWidth!=0) {
1312 debug("No Parse fastpath: fFormatWidth");
1313 } else if(fPositivePrefix.length()>0) {
1314 debug("No Parse fastpath: positive prefix");
1315 } else if(fPositiveSuffix.length()>0) {
1316 debug("No Parse fastpath: positive suffix");
1317 } else if(fNegativePrefix.length()>1
1318 || ((fNegativePrefix.length()==1) && (fNegativePrefix.charAt(0)!=0x0 02D))) {
1319 debug("No Parse fastpath: negative prefix that isn't '-'");
1320 } else if(fNegativeSuffix.length()>0) {
1321 debug("No Parse fastpath: negative suffix");
1322 } else {
1323 data.fFastParseStatus = kFastpathYES;
1324 debug("parse fastpath: YES");
1325 }
1326
1327 if(fUseExponentialNotation) {
1328 debug("No format fastpath: fUseExponentialNotation");
1329 } else if(fFormatWidth!=0) {
1330 debug("No format fastpath: fFormatWidth!=0");
1331 } else if(fMinSignificantDigits!=1) {
1332 debug("No format fastpath: fMinSignificantDigits!=1");
1333 } else if(fMultiplier!=NULL) {
1334 debug("No format fastpath: fMultiplier!=NULL");
1335 } else if(fScale!=0) {
1336 debug("No format fastpath: fScale!=0");
1337 } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).cha r32At(0)) {
1338 debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZ eroDigitSymbol).char32At(0)");
1339 } else if(fDecimalSeparatorAlwaysShown) {
1340 debug("No format fastpath: fDecimalSeparatorAlwaysShown");
1341 } else if(getMinimumFractionDigits()>0) {
1342 debug("No format fastpath: fMinFractionDigits>0");
1343 } else if(fCurrencySignCount != fgCurrencySignCountZero) {
1344 debug("No format fastpath: fCurrencySignCount != fgCurrencySignCountZero");
1345 } else if(fRoundingIncrement!=0) {
1346 debug("No format fastpath: fRoundingIncrement!=0");
1347 } else if (fGroupingSize!=0 && isGroupingUsed()) {
1348 debug("Maybe format fastpath: fGroupingSize!=0 and grouping is used");
1349 #ifdef FMT_DEBUG
1350 printf("groupingsize=%d\n", fGroupingSize);
1351 #endif
1352
1353 if (getMinimumIntegerDigits() <= fGroupingSize) {
1354 data.fFastFormatStatus = kFastpathMAYBE;
1355 }
1356 } else if(fGroupingSize2!=0 && isGroupingUsed()) {
1357 debug("No format fastpath: fGroupingSize2!=0");
1358 } else {
1359 data.fFastFormatStatus = kFastpathYES;
1360 debug("format:kFastpathYES!");
1361 }
1362
1363
1364 }
1365 #endif
1366 //------------------------------------------------------------------------------ 769 //------------------------------------------------------------------------------
1367 770
1368 UnicodeString& 771 UnicodeString&
1369 DecimalFormat::format(int64_t number, 772 DecimalFormat::format(int64_t number,
1370 UnicodeString& appendTo, 773 UnicodeString& appendTo,
1371 FieldPosition& fieldPosition) const 774 FieldPosition& fieldPosition) const
1372 { 775 {
1373 UErrorCode status = U_ZERO_ERROR; /* ignored */ 776 UErrorCode status = U_ZERO_ERROR; /* ignored */
1374 FieldPositionOnlyHandler handler(fieldPosition); 777 return fImpl->format(number, appendTo, fieldPosition, status);
1375 return _format(number, appendTo, handler, status);
1376 } 778 }
1377 779
1378 UnicodeString& 780 UnicodeString&
1379 DecimalFormat::format(int64_t number, 781 DecimalFormat::format(int64_t number,
1380 UnicodeString& appendTo, 782 UnicodeString& appendTo,
1381 FieldPosition& fieldPosition, 783 FieldPosition& fieldPosition,
1382 UErrorCode& status) const 784 UErrorCode& status) const
1383 { 785 {
1384 FieldPositionOnlyHandler handler(fieldPosition); 786 return fImpl->format(number, appendTo, fieldPosition, status);
1385 return _format(number, appendTo, handler, status);
1386 } 787 }
1387 788
1388 UnicodeString& 789 UnicodeString&
1389 DecimalFormat::format(int64_t number, 790 DecimalFormat::format(int64_t number,
1390 UnicodeString& appendTo, 791 UnicodeString& appendTo,
1391 FieldPositionIterator* posIter, 792 FieldPositionIterator* posIter,
1392 UErrorCode& status) const 793 UErrorCode& status) const
1393 { 794 {
1394 FieldPositionIteratorHandler handler(posIter, status); 795 return fImpl->format(number, appendTo, posIter, status);
1395 return _format(number, appendTo, handler, status);
1396 }
1397
1398 UnicodeString&
1399 DecimalFormat::_format(int64_t number,
1400 UnicodeString& appendTo,
1401 FieldPositionHandler& handler,
1402 UErrorCode &status) const
1403 {
1404 // Bottleneck function for formatting int64_t
1405 if (U_FAILURE(status)) {
1406 return appendTo;
1407 }
1408
1409 #if UCONFIG_FORMAT_FASTPATHS_49
1410 // const UnicodeString *posPrefix = fPosPrefixPattern;
1411 // const UnicodeString *posSuffix = fPosSuffixPattern;
1412 // const UnicodeString *negSuffix = fNegSuffixPattern;
1413
1414 const DecimalFormatInternal &data = internalData(fReserved);
1415
1416 #ifdef FMT_DEBUG
1417 data.dump();
1418 printf("fastpath? [%d]\n", number);
1419 #endif
1420
1421 if( data.fFastFormatStatus==kFastpathYES ||
1422 data.fFastFormatStatus==kFastpathMAYBE) {
1423 int32_t noGroupingThreshold = 0;
1424
1425 #define kZero 0x0030
1426 const int32_t MAX_IDX = MAX_DIGITS+2;
1427 UChar outputStr[MAX_IDX];
1428 int32_t destIdx = MAX_IDX;
1429 outputStr[--destIdx] = 0; // term
1430
1431 if (data.fFastFormatStatus==kFastpathMAYBE) {
1432 noGroupingThreshold = destIdx - fGroupingSize;
1433 }
1434 int64_t n = number;
1435 if (number < 1) {
1436 // Negative numbers are slightly larger than positive
1437 // output the first digit (or the leading zero)
1438 outputStr[--destIdx] = (-(n % 10) + kZero);
1439 n /= -10;
1440 }
1441 // get any remaining digits
1442 while (n > 0) {
1443 if (destIdx == noGroupingThreshold) {
1444 goto slowPath;
1445 }
1446 outputStr[--destIdx] = (n % 10) + kZero;
1447 n /= 10;
1448 }
1449
1450 // Slide the number to the start of the output str
1451 U_ASSERT(destIdx >= 0);
1452 int32_t length = MAX_IDX - destIdx -1;
1453 /*int32_t prefixLen = */ appendAffix(appendTo, static_cast<double>(number), handler, number<0, TRUE);
1454 int32_t maxIntDig = getMaximumIntegerDigits();
1455 int32_t destlength = length<=maxIntDig?length:maxIntDig; // dest length pinn ed to max int digits
1456
1457 if(length>maxIntDig && fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX _DIGITS)) {
1458 status = U_ILLEGAL_ARGUMENT_ERROR;
1459 }
1460
1461 int32_t prependZero = getMinimumIntegerDigits() - destlength;
1462
1463 #ifdef FMT_DEBUG
1464 printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d s kip=%d\n", prependZero, length, getMinimumIntegerDigits(), maxIntDig, destlength , length-destlength);
1465 #endif
1466 int32_t intBegin = appendTo.length();
1467
1468 while((prependZero--)>0) {
1469 appendTo.append((UChar)0x0030); // '0'
1470 }
1471
1472 appendTo.append(outputStr+destIdx+
1473 (length-destlength), // skip any leading digits
1474 destlength);
1475 handler.addAttribute(kIntegerField, intBegin, appendTo.length());
1476
1477 /*int32_t suffixLen =*/ appendAffix(appendTo, static_cast<double>(number), h andler, number<0, FALSE);
1478
1479 //outputStr[length]=0;
1480
1481 #ifdef FMT_DEBUG
1482 printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr+destIdx, length, MAX_IDX, number);
1483 #endif
1484
1485 #undef kZero
1486
1487 return appendTo;
1488 } // end fastpath
1489 #endif
1490 slowPath:
1491
1492 // Else the slow way - via DigitList
1493 DigitList digits;
1494 digits.set(number);
1495 return _format(digits, appendTo, handler, status);
1496 } 796 }
1497 797
1498 //------------------------------------------------------------------------------ 798 //------------------------------------------------------------------------------
1499 799
1500 UnicodeString& 800 UnicodeString&
1501 DecimalFormat::format( double number, 801 DecimalFormat::format( double number,
1502 UnicodeString& appendTo, 802 UnicodeString& appendTo,
1503 FieldPosition& fieldPosition) const 803 FieldPosition& fieldPosition) const
1504 { 804 {
1505 UErrorCode status = U_ZERO_ERROR; /* ignored */ 805 UErrorCode status = U_ZERO_ERROR; /* ignored */
1506 FieldPositionOnlyHandler handler(fieldPosition); 806 return fImpl->format(number, appendTo, fieldPosition, status);
1507 return _format(number, appendTo, handler, status);
1508 } 807 }
1509 808
1510 UnicodeString& 809 UnicodeString&
1511 DecimalFormat::format( double number, 810 DecimalFormat::format( double number,
1512 UnicodeString& appendTo, 811 UnicodeString& appendTo,
1513 FieldPosition& fieldPosition, 812 FieldPosition& fieldPosition,
1514 UErrorCode& status) const 813 UErrorCode& status) const
1515 { 814 {
1516 FieldPositionOnlyHandler handler(fieldPosition); 815 return fImpl->format(number, appendTo, fieldPosition, status);
1517 return _format(number, appendTo, handler, status);
1518 } 816 }
1519 817
1520 UnicodeString& 818 UnicodeString&
1521 DecimalFormat::format( double number, 819 DecimalFormat::format( double number,
1522 UnicodeString& appendTo, 820 UnicodeString& appendTo,
1523 FieldPositionIterator* posIter, 821 FieldPositionIterator* posIter,
1524 UErrorCode& status) const 822 UErrorCode& status) const
1525 { 823 {
1526 FieldPositionIteratorHandler handler(posIter, status); 824 return fImpl->format(number, appendTo, posIter, status);
1527 return _format(number, appendTo, handler, status);
1528 }
1529
1530 UnicodeString&
1531 DecimalFormat::_format( double number,
1532 UnicodeString& appendTo,
1533 FieldPositionHandler& handler,
1534 UErrorCode &status) const
1535 {
1536 if (U_FAILURE(status)) {
1537 return appendTo;
1538 }
1539 // Special case for NaN, sets the begin and end index to be the
1540 // the string length of localized name of NaN.
1541 // TODO: let NaNs go through DigitList.
1542 if (uprv_isNaN(number))
1543 {
1544 int begin = appendTo.length();
1545 appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1546
1547 handler.addAttribute(kIntegerField, begin, appendTo.length());
1548
1549 addPadding(appendTo, handler, 0, 0);
1550 return appendTo;
1551 }
1552
1553 DigitList digits;
1554 digits.set(number);
1555 _format(digits, appendTo, handler, status);
1556 // No way to return status from here.
1557 return appendTo;
1558 } 825 }
1559 826
1560 //------------------------------------------------------------------------------ 827 //------------------------------------------------------------------------------
1561 828
1562 829
1563 UnicodeString& 830 UnicodeString&
1564 DecimalFormat::format(const StringPiece &number, 831 DecimalFormat::format(const StringPiece &number,
1565 UnicodeString &toAppendTo, 832 UnicodeString &toAppendTo,
1566 FieldPositionIterator *posIter, 833 FieldPositionIterator *posIter,
1567 UErrorCode &status) const 834 UErrorCode &status) const
1568 { 835 {
1569 #if UCONFIG_FORMAT_FASTPATHS_49 836 return fImpl->format(number, toAppendTo, posIter, status);
1570 // don't bother if the int64 path is not optimized
1571 int32_t len = number.length();
1572
1573 if(len>0&&len<10) { /* 10 or more digits may not be an int64 */
1574 const char *data = number.data();
1575 int64_t num = 0;
1576 UBool neg = FALSE;
1577 UBool ok = TRUE;
1578
1579 int32_t start = 0;
1580
1581 if(data[start]=='+') {
1582 start++;
1583 } else if(data[start]=='-') {
1584 neg=TRUE;
1585 start++;
1586 }
1587
1588 int32_t place = 1; /* 1, 10, ... */
1589 for(int32_t i=len-1;i>=start;i--) {
1590 if(data[i]>='0'&&data[i]<='9') {
1591 num+=place*(int64_t)(data[i]-'0');
1592 } else {
1593 ok=FALSE;
1594 break;
1595 }
1596 place *= 10;
1597 }
1598
1599 if(ok) {
1600 if(neg) {
1601 num = -num;// add minus bit
1602 }
1603 // format as int64_t
1604 return format(num, toAppendTo, posIter, status);
1605 }
1606 // else fall through
1607 }
1608 #endif
1609
1610 DigitList dnum;
1611 dnum.set(number, status);
1612 if (U_FAILURE(status)) {
1613 return toAppendTo;
1614 }
1615 FieldPositionIteratorHandler handler(posIter, status);
1616 _format(dnum, toAppendTo, handler, status);
1617 return toAppendTo;
1618 } 837 }
1619 838
1620 839
1621 UnicodeString& 840 UnicodeString&
1622 DecimalFormat::format(const DigitList &number, 841 DecimalFormat::format(const DigitList &number,
1623 UnicodeString &appendTo, 842 UnicodeString &appendTo,
1624 FieldPositionIterator *posIter, 843 FieldPositionIterator *posIter,
1625 UErrorCode &status) const { 844 UErrorCode &status) const {
1626 FieldPositionIteratorHandler handler(posIter, status); 845 return fImpl->format(number, appendTo, posIter, status);
1627 _format(number, appendTo, handler, status);
1628 return appendTo;
1629 } 846 }
1630 847
1631 848
1632
1633 UnicodeString& 849 UnicodeString&
1634 DecimalFormat::format(const DigitList &number, 850 DecimalFormat::format(const DigitList &number,
1635 UnicodeString& appendTo, 851 UnicodeString& appendTo,
1636 FieldPosition& pos, 852 FieldPosition& pos,
1637 UErrorCode &status) const { 853 UErrorCode &status) const {
1638 FieldPositionOnlyHandler handler(pos); 854 return fImpl->format(number, appendTo, pos, status);
1639 _format(number, appendTo, handler, status);
1640 return appendTo;
1641 }
1642
1643 DigitList&
1644 DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& is Negative, UErrorCode &status) const {
1645 if (U_FAILURE(status)) {
1646 return adjustedNum;
1647 }
1648
1649 // note: number and adjustedNum may refer to the same DigitList, in cases wh ere a copy
1650 // is not needed by the caller.
1651
1652 adjustedNum = number;
1653 isNegative = false;
1654 if (number.isNaN()) {
1655 return adjustedNum;
1656 }
1657
1658 // Do this BEFORE checking to see if value is infinite or negative! Sets the
1659 // begin and end index to be length of the string composed of
1660 // localized name of Infinite and the positive/negative localized
1661 // signs.
1662
1663 adjustedNum.setRoundingMode(fRoundingMode);
1664 if (fMultiplier != NULL) {
1665 adjustedNum.mult(*fMultiplier, status);
1666 if (U_FAILURE(status)) {
1667 return adjustedNum;
1668 }
1669 }
1670
1671 if (fScale != 0) {
1672 DigitList ten;
1673 ten.set((int32_t)10);
1674 if (fScale > 0) {
1675 for (int32_t i = fScale ; i > 0 ; i--) {
1676 adjustedNum.mult(ten, status);
1677 if (U_FAILURE(status)) {
1678 return adjustedNum;
1679 }
1680 }
1681 } else {
1682 for (int32_t i = fScale ; i < 0 ; i++) {
1683 adjustedNum.div(ten, status);
1684 if (U_FAILURE(status)) {
1685 return adjustedNum;
1686 }
1687 }
1688 }
1689 }
1690
1691 /*
1692 * Note: sign is important for zero as well as non-zero numbers.
1693 * Proper detection of -0.0 is needed to deal with the
1694 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
1695 */
1696 isNegative = !adjustedNum.isPositive();
1697
1698 // Apply rounding after multiplier
1699
1700 adjustedNum.fContext.status &= ~DEC_Inexact;
1701 if (fRoundingIncrement != NULL) {
1702 adjustedNum.div(*fRoundingIncrement, status);
1703 adjustedNum.toIntegralValue();
1704 adjustedNum.mult(*fRoundingIncrement, status);
1705 adjustedNum.trim();
1706 if (U_FAILURE(status)) {
1707 return adjustedNum;
1708 }
1709 }
1710 if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC _Inexact)) {
1711 status = U_FORMAT_INEXACT_ERROR;
1712 return adjustedNum;
1713 }
1714
1715 if (adjustedNum.isInfinite()) {
1716 return adjustedNum;
1717 }
1718
1719 if (fUseExponentialNotation || areSignificantDigitsUsed()) {
1720 int32_t sigDigits = precision();
1721 if (sigDigits > 0) {
1722 adjustedNum.round(sigDigits);
1723 // Travis Keep (21/2/2014): Calling round on a digitList does not ne cessarily
1724 // preserve the sign of that digit list. Preserving the sign is espe cially
1725 // important when formatting -0.0 for instance. Not preserving the s ign seems
1726 // like a bug because I cannot think of any case where the sign woul d actually
1727 // have to change when rounding. For now, we preserve the sign by se tting the
1728 // positive attribute directly.
1729 adjustedNum.setPositive(!isNegative);
1730 }
1731 } else {
1732 // Fixed point format. Round to a set number of fraction digits.
1733 int32_t numFractionDigits = precision();
1734 adjustedNum.roundFixedPoint(numFractionDigits);
1735 }
1736 if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC _Inexact)) {
1737 status = U_FORMAT_INEXACT_ERROR;
1738 return adjustedNum;
1739 }
1740 return adjustedNum;
1741 } 855 }
1742 856
1743 UnicodeString& 857 UnicodeString&
1744 DecimalFormat::_format(const DigitList &number, 858 DecimalFormat::format(const VisibleDigitsWithExponent &number,
1745 UnicodeString& appendTo, 859 UnicodeString &appendTo,
1746 FieldPositionHandler& handler, 860 FieldPositionIterator *posIter,
1747 UErrorCode &status) const 861 UErrorCode &status) const {
1748 { 862 return fImpl->format(number, appendTo, posIter, status);
1749 if (U_FAILURE(status)) {
1750 return appendTo;
1751 }
1752
1753 // Special case for NaN, sets the begin and end index to be the
1754 // the string length of localized name of NaN.
1755 if (number.isNaN())
1756 {
1757 int begin = appendTo.length();
1758 appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1759
1760 handler.addAttribute(kIntegerField, begin, appendTo.length());
1761
1762 addPadding(appendTo, handler, 0, 0);
1763 return appendTo;
1764 }
1765
1766 DigitList adjustedNum;
1767 UBool isNegative;
1768 _round(number, adjustedNum, isNegative, status);
1769 if (U_FAILURE(status)) {
1770 return appendTo;
1771 }
1772
1773 // Special case for INFINITE,
1774 if (adjustedNum.isInfinite()) {
1775 int32_t prefixLen = appendAffix(appendTo, adjustedNum.getDouble(), handl er, isNegative, TRUE);
1776
1777 int begin = appendTo.length();
1778 appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
1779
1780 handler.addAttribute(kIntegerField, begin, appendTo.length());
1781
1782 int32_t suffixLen = appendAffix(appendTo, adjustedNum.getDouble(), handl er, isNegative, FALSE);
1783
1784 addPadding(appendTo, handler, prefixLen, suffixLen);
1785 return appendTo;
1786 }
1787 return subformat(appendTo, handler, adjustedNum, FALSE, status);
1788 } 863 }
1789 864
1790 /** 865
1791 * Return true if a grouping separator belongs at the given 866 UnicodeString&
1792 * position, based on whether grouping is in use and the values of 867 DecimalFormat::format(const VisibleDigitsWithExponent &number,
1793 * the primary and secondary grouping interval. 868 UnicodeString& appendTo,
1794 * @param pos the number of integer digits to the right of 869 FieldPosition& pos,
1795 * the current position. Zero indicates the position after the 870 UErrorCode &status) const {
1796 * rightmost integer digit. 871 return fImpl->format(number, appendTo, pos, status);
1797 * @return true if a grouping character belongs at the current
1798 * position.
1799 */
1800 UBool DecimalFormat::isGroupingPosition(int32_t pos) const {
1801 UBool result = FALSE;
1802 if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) {
1803 if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) {
1804 result = ((pos - fGroupingSize) % fGroupingSize2) == 0;
1805 } else {
1806 result = pos % fGroupingSize == 0;
1807 }
1808 }
1809 return result;
1810 } 872 }
1811 873
1812 //------------------------------------------------------------------------------ 874 DigitList&
1813 875 DecimalFormat::_round(const DigitList& number, DigitList& adjustedNum, UBool& is Negative, UErrorCode& status) const {
1814 /** 876 adjustedNum = number;
1815 * Complete the formatting of a finite number. On entry, the DigitList must 877 fImpl->round(adjustedNum, status);
1816 * be filled in with the correct digits. 878 isNegative = !adjustedNum.isPositive();
1817 */ 879 return adjustedNum;
1818 UnicodeString&
1819 DecimalFormat::subformat(UnicodeString& appendTo,
1820 FieldPositionHandler& handler,
1821 DigitList& digits,
1822 UBool isInteger,
1823 UErrorCode& status) const
1824 {
1825 // char zero = '0';
1826 // DigitList returns digits as '0' thru '9', so we will need to
1827 // always need to subtract the character 0 to get the numeric value to use f or indexing.
1828
1829 UChar32 localizedDigits[10];
1830 localizedDigits[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol). char32At(0);
1831 localizedDigits[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).c har32At(0);
1832 localizedDigits[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).c har32At(0);
1833 localizedDigits[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol) .char32At(0);
1834 localizedDigits[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol). char32At(0);
1835 localizedDigits[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol). char32At(0);
1836 localizedDigits[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).c har32At(0);
1837 localizedDigits[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol) .char32At(0);
1838 localizedDigits[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol) .char32At(0);
1839 localizedDigits[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol). char32At(0);
1840
1841 const UnicodeString *grouping ;
1842 if(fCurrencySignCount == fgCurrencySignCountZero) {
1843 grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbo l);
1844 }else{
1845 grouping = &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSepara torSymbol);
1846 }
1847 const UnicodeString *decimal;
1848 if(fCurrencySignCount == fgCurrencySignCountZero) {
1849 decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol) ;
1850 } else {
1851 decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol );
1852 }
1853 UBool useSigDig = areSignificantDigitsUsed();
1854 int32_t maxIntDig = getMaximumIntegerDigits();
1855 int32_t minIntDig = getMinimumIntegerDigits();
1856
1857 // Appends the prefix.
1858 double doubleValue = digits.getDouble();
1859 int32_t prefixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPo sitive(), TRUE);
1860
1861 if (fUseExponentialNotation)
1862 {
1863 int currentLength = appendTo.length();
1864 int intBegin = currentLength;
1865 int intEnd = -1;
1866 int fracBegin = -1;
1867
1868 int32_t minFracDig = 0;
1869 if (useSigDig) {
1870 maxIntDig = minIntDig = 1;
1871 minFracDig = getMinimumSignificantDigits() - 1;
1872 } else {
1873 minFracDig = getMinimumFractionDigits();
1874 if (maxIntDig > kMaxScientificIntegerDigits) {
1875 maxIntDig = 1;
1876 if (maxIntDig < minIntDig) {
1877 maxIntDig = minIntDig;
1878 }
1879 }
1880 if (maxIntDig > minIntDig) {
1881 minIntDig = 1;
1882 }
1883 }
1884
1885 // Minimum integer digits are handled in exponential format by
1886 // adjusting the exponent. For example, 0.01234 with 3 minimum
1887 // integer digits is "123.4E-4".
1888
1889 // Maximum integer digits are interpreted as indicating the
1890 // repeating range. This is useful for engineering notation, in
1891 // which the exponent is restricted to a multiple of 3. For
1892 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1893 // If maximum integer digits are defined and are larger than
1894 // minimum integer digits, then minimum integer digits are
1895 // ignored.
1896 digits.reduce(); // Removes trailing zero digits.
1897 int32_t exponent = digits.getDecimalAt();
1898 if (maxIntDig > 1 && maxIntDig != minIntDig) {
1899 // A exponent increment is defined; adjust to it.
1900 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
1901 : (exponent / maxIntDig) - 1;
1902 exponent *= maxIntDig;
1903 } else {
1904 // No exponent increment is defined; use minimum integer digits.
1905 // If none is specified, as in "#E0", generate 1 integer digit.
1906 exponent -= (minIntDig > 0 || minFracDig > 0)
1907 ? minIntDig : 1;
1908 }
1909
1910 // We now output a minimum number of digits, and more if there
1911 // are more digits, up to the maximum number of digits. We
1912 // place the decimal point after the "integer" digits, which
1913 // are the first (decimalAt - exponent) digits.
1914 int32_t minimumDigits = minIntDig + minFracDig;
1915 // The number of integer digits is handled specially if the number
1916 // is zero, since then there may be no digits.
1917 int32_t integerDigits = digits.isZero() ? minIntDig :
1918 digits.getDecimalAt() - exponent;
1919 int32_t totalDigits = digits.getCount();
1920 if (minimumDigits > totalDigits)
1921 totalDigits = minimumDigits;
1922 if (integerDigits > totalDigits)
1923 totalDigits = integerDigits;
1924
1925 // totalDigits records total number of digits needs to be processed
1926 int32_t i;
1927 for (i=0; i<totalDigits; ++i)
1928 {
1929 if (i == integerDigits)
1930 {
1931 intEnd = appendTo.length();
1932 handler.addAttribute(kIntegerField, intBegin, intEnd);
1933
1934 appendTo += *decimal;
1935
1936 fracBegin = appendTo.length();
1937 handler.addAttribute(kDecimalSeparatorField, fracBegin - 1, frac Begin);
1938 }
1939 // Restores the digit character or pads the buffer with zeros.
1940 UChar32 c = (UChar32)((i < digits.getCount()) ?
1941 localizedDigits[digits.getDigitValue(i)] :
1942 localizedDigits[0]);
1943 appendTo += c;
1944 }
1945
1946 currentLength = appendTo.length();
1947
1948 if (intEnd < 0) {
1949 handler.addAttribute(kIntegerField, intBegin, currentLength);
1950 }
1951 if (fracBegin > 0) {
1952 handler.addAttribute(kFractionField, fracBegin, currentLength);
1953 }
1954
1955 // The exponent is output using the pattern-specified minimum
1956 // exponent digits. There is no maximum limit to the exponent
1957 // digits, since truncating the exponent would appendTo in an
1958 // unacceptable inaccuracy.
1959 appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
1960
1961 handler.addAttribute(kExponentSymbolField, currentLength, appendTo.lengt h());
1962 currentLength = appendTo.length();
1963
1964 // For zero values, we force the exponent to zero. We
1965 // must do this here, and not earlier, because the value
1966 // is used to determine integer digit count above.
1967 if (digits.isZero())
1968 exponent = 0;
1969
1970 if (exponent < 0) {
1971 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1972 handler.addAttribute(kExponentSignField, currentLength, appendTo.len gth());
1973 } else if (fExponentSignAlwaysShown) {
1974 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1975 handler.addAttribute(kExponentSignField, currentLength, appendTo.len gth());
1976 }
1977
1978 currentLength = appendTo.length();
1979
1980 DigitList expDigits;
1981 expDigits.set(exponent);
1982 {
1983 int expDig = fMinExponentDigits;
1984 if (fUseExponentialNotation && expDig < 1) {
1985 expDig = 1;
1986 }
1987 for (i=expDigits.getDecimalAt(); i<expDig; ++i)
1988 appendTo += (localizedDigits[0]);
1989 }
1990 for (i=0; i<expDigits.getDecimalAt(); ++i)
1991 {
1992 UChar32 c = (UChar32)((i < expDigits.getCount()) ?
1993 localizedDigits[expDigits.getDigitValue(i)] :
1994 localizedDigits[0]);
1995 appendTo += c;
1996 }
1997
1998 handler.addAttribute(kExponentField, currentLength, appendTo.length());
1999 }
2000 else // Not using exponential notation
2001 {
2002 int currentLength = appendTo.length();
2003 int intBegin = currentLength;
2004
2005 int32_t sigCount = 0;
2006 int32_t minSigDig = getMinimumSignificantDigits();
2007 int32_t maxSigDig = getMaximumSignificantDigits();
2008 if (!useSigDig) {
2009 minSigDig = 0;
2010 maxSigDig = INT32_MAX;
2011 }
2012
2013 // Output the integer portion. Here 'count' is the total
2014 // number of integer digits we will display, including both
2015 // leading zeros required to satisfy getMinimumIntegerDigits,
2016 // and actual digits present in the number.
2017 int32_t count = useSigDig ?
2018 _max(1, digits.getDecimalAt()) : minIntDig;
2019 if (digits.getDecimalAt() > 0 && count < digits.getDecimalAt()) {
2020 count = digits.getDecimalAt();
2021 }
2022
2023 // Handle the case where getMaximumIntegerDigits() is smaller
2024 // than the real number of integer digits. If this is so, we
2025 // output the least significant max integer digits. For example,
2026 // the value 1997 printed with 2 max integer digits is just "97".
2027
2028 int32_t digitIndex = 0; // Index into digitList.fDigits[]
2029 if (count > maxIntDig && maxIntDig >= 0) {
2030 count = maxIntDig;
2031 digitIndex = digits.getDecimalAt() - count;
2032 if(fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) {
2033 status = U_ILLEGAL_ARGUMENT_ERROR;
2034 }
2035 }
2036
2037 int32_t sizeBeforeIntegerPart = appendTo.length();
2038
2039 int32_t i;
2040 for (i=count-1; i>=0; --i)
2041 {
2042 if (i < digits.getDecimalAt() && digitIndex < digits.getCount() &&
2043 sigCount < maxSigDig) {
2044 // Output a real digit
2045 appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitI ndex++)];
2046 ++sigCount;
2047 }
2048 else
2049 {
2050 // Output a zero (leading or trailing)
2051 appendTo += localizedDigits[0];
2052 if (sigCount > 0) {
2053 ++sigCount;
2054 }
2055 }
2056
2057 // Output grouping separator if necessary.
2058 if (isGroupingPosition(i)) {
2059 currentLength = appendTo.length();
2060 appendTo.append(*grouping);
2061 handler.addAttribute(kGroupingSeparatorField, currentLength, app endTo.length());
2062 }
2063 }
2064
2065 // This handles the special case of formatting 0. For zero only, we coun t the
2066 // zero to the left of the decimal point as one signficant digit. Ordina rily we
2067 // do not count any leading 0's as significant. If the number we are for matting
2068 // is not zero, then either sigCount or digits.getCount() will be non-ze ro.
2069 if (sigCount == 0 && digits.getCount() == 0) {
2070 sigCount = 1;
2071 }
2072
2073 // TODO(dlf): this looks like it was a bug, we marked the int field as e nding
2074 // before the zero was generated.
2075 // Record field information for caller.
2076 // if (fieldPosition.getField() == NumberFormat::kIntegerField)
2077 // fieldPosition.setEndIndex(appendTo.length());
2078
2079 // Determine whether or not there are any printable fractional
2080 // digits. If we've used up the digits we know there aren't.
2081 UBool fractionPresent = (!isInteger && digitIndex < digits.getCount()) | |
2082 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
2083
2084 // If there is no fraction present, and we haven't printed any
2085 // integer digits, then print a zero. Otherwise we won't print
2086 // _any_ digits, and we won't be able to parse this string.
2087 if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart)
2088 appendTo += localizedDigits[0];
2089
2090 currentLength = appendTo.length();
2091 handler.addAttribute(kIntegerField, intBegin, currentLength);
2092
2093 // Output the decimal separator if we always do so.
2094 if (fDecimalSeparatorAlwaysShown || fractionPresent) {
2095 appendTo += *decimal;
2096 handler.addAttribute(kDecimalSeparatorField, currentLength, appendTo .length());
2097 currentLength = appendTo.length();
2098 }
2099
2100 int fracBegin = currentLength;
2101
2102 count = useSigDig ? INT32_MAX : getMaximumFractionDigits();
2103 if (useSigDig && (sigCount == maxSigDig ||
2104 (sigCount >= minSigDig && digitIndex == digits.getCoun t()))) {
2105 count = 0;
2106 }
2107
2108 for (i=0; i < count; ++i) {
2109 // Here is where we escape from the loop. We escape
2110 // if we've output the maximum fraction digits
2111 // (specified in the for expression above). We also
2112 // stop when we've output the minimum digits and
2113 // either: we have an integer, so there is no
2114 // fractional stuff to display, or we're out of
2115 // significant digits.
2116 if (!useSigDig && i >= getMinimumFractionDigits() &&
2117 (isInteger || digitIndex >= digits.getCount())) {
2118 break;
2119 }
2120
2121 // Output leading fractional zeros. These are zeros
2122 // that come after the decimal but before any
2123 // significant digits. These are only output if
2124 // abs(number being formatted) < 1.0.
2125 if (-1-i > (digits.getDecimalAt()-1)) {
2126 appendTo += localizedDigits[0];
2127 continue;
2128 }
2129
2130 // Output a digit, if we have any precision left, or a
2131 // zero if we don't. We don't want to output noise digits.
2132 if (!isInteger && digitIndex < digits.getCount()) {
2133 appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitI ndex++)];
2134 } else {
2135 appendTo += localizedDigits[0];
2136 }
2137
2138 // If we reach the maximum number of significant
2139 // digits, or if we output all the real digits and
2140 // reach the minimum, then we are done.
2141 ++sigCount;
2142 if (useSigDig &&
2143 (sigCount == maxSigDig ||
2144 (digitIndex == digits.getCount() && sigCount >= minSigDig))) {
2145 break;
2146 }
2147 }
2148
2149 handler.addAttribute(kFractionField, fracBegin, appendTo.length());
2150 }
2151
2152 int32_t suffixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPo sitive(), FALSE);
2153
2154 addPadding(appendTo, handler, prefixLen, suffixLen);
2155 return appendTo;
2156 } 880 }
2157 881
2158 /**
2159 * Inserts the character fPad as needed to expand result to fFormatWidth.
2160 * @param result the string to be padded
2161 */
2162 void DecimalFormat::addPadding(UnicodeString& appendTo,
2163 FieldPositionHandler& handler,
2164 int32_t prefixLen,
2165 int32_t suffixLen) const
2166 {
2167 if (fFormatWidth > 0) {
2168 int32_t len = fFormatWidth - appendTo.length();
2169 if (len > 0) {
2170 UnicodeString padding;
2171 for (int32_t i=0; i<len; ++i) {
2172 padding += fPad;
2173 }
2174 switch (fPadPosition) {
2175 case kPadAfterPrefix:
2176 appendTo.insert(prefixLen, padding);
2177 break;
2178 case kPadBeforePrefix:
2179 appendTo.insert(0, padding);
2180 break;
2181 case kPadBeforeSuffix:
2182 appendTo.insert(appendTo.length() - suffixLen, padding);
2183 break;
2184 case kPadAfterSuffix:
2185 appendTo += padding;
2186 break;
2187 }
2188 if (fPadPosition == kPadBeforePrefix || fPadPosition == kPadAfterPre fix) {
2189 handler.shiftLast(len);
2190 }
2191 }
2192 }
2193 }
2194
2195 //------------------------------------------------------------------------------
2196
2197 void 882 void
2198 DecimalFormat::parse(const UnicodeString& text, 883 DecimalFormat::parse(const UnicodeString& text,
2199 Formattable& result, 884 Formattable& result,
2200 ParsePosition& parsePosition) const { 885 ParsePosition& parsePosition) const {
2201 parse(text, result, parsePosition, NULL); 886 parse(text, result, parsePosition, NULL);
2202 } 887 }
2203 888
2204 CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, 889 CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
2205 ParsePosition& pos) const { 890 ParsePosition& pos) const {
2206 Formattable parseResult; 891 Formattable parseResult;
2207 int32_t start = pos.getIndex(); 892 int32_t start = pos.getIndex();
2208 UChar curbuf[4] = {}; 893 UChar curbuf[4] = {};
2209 parse(text, parseResult, pos, curbuf); 894 parse(text, parseResult, pos, curbuf);
2210 if (pos.getIndex() != start) { 895 if (pos.getIndex() != start) {
2211 UErrorCode ec = U_ZERO_ERROR; 896 UErrorCode ec = U_ZERO_ERROR;
2212 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, cur buf, ec)); 897 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, cur buf, ec), ec);
2213 if (U_FAILURE(ec)) { 898 if (U_FAILURE(ec)) {
2214 pos.setIndex(start); // indicate failure 899 pos.setIndex(start); // indicate failure
2215 } else { 900 } else {
2216 return currAmt.orphan(); 901 return currAmt.orphan();
2217 } 902 }
2218 } 903 }
2219 return NULL; 904 return NULL;
2220 } 905 }
2221 906
2222 /** 907 /**
(...skipping 20 matching lines...) Expand all
2243 // clear any old contents in the result. In particular, clears any DigitLis t 928 // clear any old contents in the result. In particular, clears any DigitLis t
2244 // that it may be holding. 929 // that it may be holding.
2245 result.setLong(0); 930 result.setLong(0);
2246 if (currency != NULL) { 931 if (currency != NULL) {
2247 for (int32_t ci=0; ci<4; ci++) { 932 for (int32_t ci=0; ci<4; ci++) {
2248 currency[ci] = 0; 933 currency[ci] = 0;
2249 } 934 }
2250 } 935 }
2251 936
2252 // Handle NaN as a special case: 937 // Handle NaN as a special case:
938 int32_t formatWidth = fImpl->getOldFormatWidth();
2253 939
2254 // Skip padding characters, if around prefix 940 // Skip padding characters, if around prefix
2255 if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix || 941 if (formatWidth > 0 && (
2256 fPadPosition == kPadAfterPrefix)) { 942 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePr efix ||
943 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPre fix)) {
2257 i = skipPadding(text, i); 944 i = skipPadding(text, i);
2258 } 945 }
2259 946
2260 if (isLenient()) { 947 if (isLenient()) {
2261 // skip any leading whitespace 948 // skip any leading whitespace
2262 i = backup = skipUWhiteSpace(text, i); 949 i = backup = skipUWhiteSpace(text, i);
2263 } 950 }
2264 951
2265 // If the text is composed of the representation of NaN, returns NaN.length 952 // If the text is composed of the representation of NaN, returns NaN.length
2266 const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol) ; 953 const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaN Symbol);
2267 int32_t nanLen = (text.compare(i, nan->length(), *nan) 954 int32_t nanLen = (text.compare(i, nan->length(), *nan)
2268 ? 0 : nan->length()); 955 ? 0 : nan->length());
2269 if (nanLen) { 956 if (nanLen) {
2270 i += nanLen; 957 i += nanLen;
2271 if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix || 958 if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndP adding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPaddi ng::kPadAfterSuffix)) {
2272 fPadPosition == kPadAfterSuffix)) {
2273 i = skipPadding(text, i); 959 i = skipPadding(text, i);
2274 } 960 }
2275 parsePosition.setIndex(i); 961 parsePosition.setIndex(i);
2276 result.setDouble(uprv_getNaN()); 962 result.setDouble(uprv_getNaN());
2277 return; 963 return;
2278 } 964 }
2279 965
2280 // NaN parse failed; start over 966 // NaN parse failed; start over
2281 i = backup; 967 i = backup;
2282 parsePosition.setIndex(i); 968 parsePosition.setIndex(i);
2283 969
2284 // status is used to record whether a number is infinite. 970 // status is used to record whether a number is infinite.
2285 UBool status[fgStatusLength]; 971 UBool status[fgStatusLength];
2286 972
2287 DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer 973 DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
2288 if (digits == NULL) { 974 if (digits == NULL) {
2289 return; // no way to report error from here. 975 return; // no way to report error from here.
2290 } 976 }
2291 977
2292 if (fCurrencySignCount != fgCurrencySignCountZero) { 978 if (fImpl->fMonetary) {
2293 if (!parseForCurrency(text, parsePosition, *digits, 979 if (!parseForCurrency(text, parsePosition, *digits,
2294 status, currency)) { 980 status, currency)) {
2295 return; 981 return;
2296 } 982 }
2297 } else { 983 } else {
2298 if (!subparse(text, 984 if (!subparse(text,
2299 fNegPrefixPattern, fNegSuffixPattern, 985 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toStrin g(),
2300 fPosPrefixPattern, fPosSuffixPattern, 986 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toStrin g(),
987 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toStrin g(),
988 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toStrin g(),
2301 FALSE, UCURR_SYMBOL_NAME, 989 FALSE, UCURR_SYMBOL_NAME,
2302 parsePosition, *digits, status, currency)) { 990 parsePosition, *digits, status, currency)) {
2303 debug("!subparse(...) - rewind"); 991 debug("!subparse(...) - rewind");
2304 parsePosition.setIndex(startIdx); 992 parsePosition.setIndex(startIdx);
2305 return; 993 return;
2306 } 994 }
2307 } 995 }
2308 996
2309 // Handle infinity 997 // Handle infinity
2310 if (status[fgStatusInfinite]) { 998 if (status[fgStatusInfinite]) {
2311 double inf = uprv_getInfinity(); 999 double inf = uprv_getInfinity();
2312 result.setDouble(digits->isPositive() ? inf : -inf); 1000 result.setDouble(digits->isPositive() ? inf : -inf);
2313 // TODO: set the dl to infinity, and let it fall into the code below. 1001 // TODO: set the dl to infinity, and let it fall into the code below.
2314 } 1002 }
2315 1003
2316 else { 1004 else {
2317 1005
2318 if (fMultiplier != NULL) { 1006 if (!fImpl->fMultiplier.isZero()) {
2319 UErrorCode ec = U_ZERO_ERROR; 1007 UErrorCode ec = U_ZERO_ERROR;
2320 digits->div(*fMultiplier, ec); 1008 digits->div(fImpl->fMultiplier, ec);
2321 } 1009 }
2322 1010
2323 if (fScale != 0) { 1011 if (fImpl->fScale != 0) {
2324 DigitList ten; 1012 DigitList ten;
2325 ten.set((int32_t)10); 1013 ten.set((int32_t)10);
2326 if (fScale > 0) { 1014 if (fImpl->fScale > 0) {
2327 for (int32_t i = fScale; i > 0; i--) { 1015 for (int32_t i = fImpl->fScale; i > 0; i--) {
2328 UErrorCode ec = U_ZERO_ERROR; 1016 UErrorCode ec = U_ZERO_ERROR;
2329 digits->div(ten,ec); 1017 digits->div(ten,ec);
2330 } 1018 }
2331 } else { 1019 } else {
2332 for (int32_t i = fScale; i < 0; i++) { 1020 for (int32_t i = fImpl->fScale; i < 0; i++) {
2333 UErrorCode ec = U_ZERO_ERROR; 1021 UErrorCode ec = U_ZERO_ERROR;
2334 digits->mult(ten,ec); 1022 digits->mult(ten,ec);
2335 } 1023 }
2336 } 1024 }
2337 } 1025 }
2338 1026
2339 // Negative zero special case: 1027 // Negative zero special case:
2340 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable. 1028 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
2341 // if not parsing integerOnly, leave as -0, which a double can repres ent. 1029 // if not parsing integerOnly, leave as -0, which a double can repres ent.
2342 if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) { 1030 if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) {
2343 digits->setPositive(TRUE); 1031 digits->setPositive(TRUE);
2344 } 1032 }
2345 result.adoptDigitList(digits); 1033 result.adoptDigitList(digits);
2346 } 1034 }
2347 } 1035 }
2348 1036
2349 1037
2350 1038
2351 UBool 1039 UBool
2352 DecimalFormat::parseForCurrency(const UnicodeString& text, 1040 DecimalFormat::parseForCurrency(const UnicodeString& text,
2353 ParsePosition& parsePosition, 1041 ParsePosition& parsePosition,
2354 DigitList& digits, 1042 DigitList& digits,
2355 UBool* status, 1043 UBool* status,
2356 UChar* currency) const { 1044 UChar* currency) const {
1045 UnicodeString positivePrefix;
1046 UnicodeString positiveSuffix;
1047 UnicodeString negativePrefix;
1048 UnicodeString negativeSuffix;
1049 fImpl->fPositivePrefixPattern.toString(positivePrefix);
1050 fImpl->fPositiveSuffixPattern.toString(positiveSuffix);
1051 fImpl->fNegativePrefixPattern.toString(negativePrefix);
1052 fImpl->fNegativeSuffixPattern.toString(negativeSuffix);
1053
2357 int origPos = parsePosition.getIndex(); 1054 int origPos = parsePosition.getIndex();
2358 int maxPosIndex = origPos; 1055 int maxPosIndex = origPos;
2359 int maxErrorPos = -1; 1056 int maxErrorPos = -1;
2360 // First, parse against current pattern. 1057 // First, parse against current pattern.
2361 // Since current pattern could be set by applyPattern(), 1058 // Since current pattern could be set by applyPattern(),
2362 // it could be an arbitrary pattern, and it may not be the one 1059 // it could be an arbitrary pattern, and it may not be the one
2363 // defined in current locale. 1060 // defined in current locale.
2364 UBool tmpStatus[fgStatusLength]; 1061 UBool tmpStatus[fgStatusLength];
2365 ParsePosition tmpPos(origPos); 1062 ParsePosition tmpPos(origPos);
2366 DigitList tmpDigitList; 1063 DigitList tmpDigitList;
2367 UBool found; 1064 UBool found;
2368 if (fStyle == UNUM_CURRENCY_PLURAL) { 1065 if (fStyle == UNUM_CURRENCY_PLURAL) {
2369 found = subparse(text, 1066 found = subparse(text,
2370 fNegPrefixPattern, fNegSuffixPattern, 1067 &negativePrefix, &negativeSuffix,
2371 fPosPrefixPattern, fPosSuffixPattern, 1068 &positivePrefix, &positiveSuffix,
2372 TRUE, UCURR_LONG_NAME, 1069 TRUE, UCURR_LONG_NAME,
2373 tmpPos, tmpDigitList, tmpStatus, currency); 1070 tmpPos, tmpDigitList, tmpStatus, currency);
2374 } else { 1071 } else {
2375 found = subparse(text, 1072 found = subparse(text,
2376 fNegPrefixPattern, fNegSuffixPattern, 1073 &negativePrefix, &negativeSuffix,
2377 fPosPrefixPattern, fPosSuffixPattern, 1074 &positivePrefix, &positiveSuffix,
2378 TRUE, UCURR_SYMBOL_NAME, 1075 TRUE, UCURR_SYMBOL_NAME,
2379 tmpPos, tmpDigitList, tmpStatus, currency); 1076 tmpPos, tmpDigitList, tmpStatus, currency);
2380 } 1077 }
2381 if (found) { 1078 if (found) {
2382 if (tmpPos.getIndex() > maxPosIndex) { 1079 if (tmpPos.getIndex() > maxPosIndex) {
2383 maxPosIndex = tmpPos.getIndex(); 1080 maxPosIndex = tmpPos.getIndex();
2384 for (int32_t i = 0; i < fgStatusLength; ++i) { 1081 for (int32_t i = 0; i < fgStatusLength; ++i) {
2385 status[i] = tmpStatus[i]; 1082 status[i] = tmpStatus[i];
2386 } 1083 }
2387 digits = tmpDigitList; 1084 digits = tmpDigitList;
2388 } 1085 }
2389 } else { 1086 } else {
2390 maxErrorPos = tmpPos.getErrorIndex(); 1087 maxErrorPos = tmpPos.getErrorIndex();
2391 } 1088 }
2392 // Then, parse against affix patterns. 1089 // Then, parse against affix patterns.
2393 // Those are currency patterns and currency plural patterns. 1090 // Those are currency patterns and currency plural patterns.
2394 int32_t pos = -1; 1091 int32_t pos = UHASH_FIRST;
2395 const UHashElement* element = NULL; 1092 const UHashElement* element = NULL;
2396 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 1093 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
2397 const UHashTok valueTok = element->value; 1094 const UHashTok valueTok = element->value;
2398 const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)va lueTok.pointer; 1095 const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)va lueTok.pointer;
2399 UBool tmpStatus[fgStatusLength]; 1096 UBool tmpStatus[fgStatusLength];
2400 ParsePosition tmpPos(origPos); 1097 ParsePosition tmpPos(origPos);
2401 DigitList tmpDigitList; 1098 DigitList tmpDigitList;
2402 1099
2403 #ifdef FMT_DEBUG 1100 #ifdef FMT_DEBUG
2404 debug("trying affix for currency.."); 1101 debug("trying affix for currency..");
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2439 // output currency is not requested. After the complex currency 1136 // output currency is not requested. After the complex currency
2440 // parsing implementation was introduced, the default currency 1137 // parsing implementation was introduced, the default currency
2441 // instance parsing slowed down because of the new code flow. 1138 // instance parsing slowed down because of the new code flow.
2442 // I filed #10312 - Yoshito 1139 // I filed #10312 - Yoshito
2443 UBool tmpStatus_2[fgStatusLength]; 1140 UBool tmpStatus_2[fgStatusLength];
2444 ParsePosition tmpPos_2(origPos); 1141 ParsePosition tmpPos_2(origPos);
2445 DigitList tmpDigitList_2; 1142 DigitList tmpDigitList_2;
2446 1143
2447 // Disable complex currency parsing and try it again. 1144 // Disable complex currency parsing and try it again.
2448 UBool result = subparse(text, 1145 UBool result = subparse(text,
2449 &fNegativePrefix, &fNegativeSuffix, 1146 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().t oString(),
2450 &fPositivePrefix, &fPositiveSuffix, 1147 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().t oString(),
1148 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().t oString(),
1149 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().t oString(),
2451 FALSE /* disable complex currency parsing */, UCURR_ SYMBOL_NAME, 1150 FALSE /* disable complex currency parsing */, UCURR_ SYMBOL_NAME,
2452 tmpPos_2, tmpDigitList_2, tmpStatus_2, 1151 tmpPos_2, tmpDigitList_2, tmpStatus_2,
2453 currency); 1152 currency);
2454 if (result) { 1153 if (result) {
2455 if (tmpPos_2.getIndex() > maxPosIndex) { 1154 if (tmpPos_2.getIndex() > maxPosIndex) {
2456 maxPosIndex = tmpPos_2.getIndex(); 1155 maxPosIndex = tmpPos_2.getIndex();
2457 for (int32_t i = 0; i < fgStatusLength; ++i) { 1156 for (int32_t i = 0; i < fgStatusLength; ++i) {
2458 status[i] = tmpStatus_2[i]; 1157 status[i] = tmpStatus_2[i];
2459 } 1158 }
2460 digits = tmpDigitList_2; 1159 digits = tmpDigitList_2;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2511 // will be acceptable to the decNumber library, then at the end passes that string 1210 // will be acceptable to the decNumber library, then at the end passes that string
2512 // off for conversion to a decNumber. 1211 // off for conversion to a decNumber.
2513 UErrorCode err = U_ZERO_ERROR; 1212 UErrorCode err = U_ZERO_ERROR;
2514 CharString parsedNum; 1213 CharString parsedNum;
2515 digits.setToZero(); 1214 digits.setToZero();
2516 1215
2517 int32_t position = parsePosition.getIndex(); 1216 int32_t position = parsePosition.getIndex();
2518 int32_t oldStart = position; 1217 int32_t oldStart = position;
2519 int32_t textLength = text.length(); // One less pointer to follow 1218 int32_t textLength = text.length(); // One less pointer to follow
2520 UBool strictParse = !isLenient(); 1219 UBool strictParse = !isLenient();
2521 UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32 At(0); 1220 UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol) .char32At(0);
2522 const UnicodeString *groupingString = &getConstSymbol(fCurrencySignCount == fgCurrencySignCountZero ? 1221 const UnicodeString *groupingString = &fImpl->getConstSymbol(
2523 DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::k MonetaryGroupingSeparatorSymbol); 1222 !fImpl->fMonetary ?
1223 DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbol s::kMonetaryGroupingSeparatorSymbol);
2524 UChar32 groupingChar = groupingString->char32At(0); 1224 UChar32 groupingChar = groupingString->char32At(0);
2525 int32_t groupingStringLength = groupingString->length(); 1225 int32_t groupingStringLength = groupingString->length();
2526 int32_t groupingCharLength = U16_LENGTH(groupingChar); 1226 int32_t groupingCharLength = U16_LENGTH(groupingChar);
2527 UBool groupingUsed = isGroupingUsed(); 1227 UBool groupingUsed = isGroupingUsed();
2528 #ifdef FMT_DEBUG 1228 #ifdef FMT_DEBUG
2529 UChar dbgbuf[300]; 1229 UChar dbgbuf[300];
2530 UnicodeString s(dbgbuf,0,300);; 1230 UnicodeString s(dbgbuf,0,300);;
2531 s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).app end((UnicodeString)"\" " ); 1231 s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).app end((UnicodeString)"\" " );
2532 #define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeStr ing(" ")); } else { s.append(UnicodeString(#x "=NULL ")); } 1232 #define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeStr ing(" ")); } else { s.append(UnicodeString(#x "=NULL ")); }
2533 DBGAPPD(negPrefix); 1233 DBGAPPD(negPrefix);
2534 DBGAPPD(negSuffix); 1234 DBGAPPD(negSuffix);
2535 DBGAPPD(posPrefix); 1235 DBGAPPD(posPrefix);
2536 DBGAPPD(posSuffix); 1236 DBGAPPD(posSuffix);
2537 debugout(s); 1237 debugout(s);
2538 printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.leng th=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, (isParseIntegerOnly())?'Y ':'N', text.length(), negPrefix!=NULL?negPrefix->length():-1);
2539 #endif 1238 #endif
2540 1239
2541 UBool fastParseOk = false; /* TRUE iff fast parse is OK */ 1240 UBool fastParseOk = false; /* TRUE iff fast parse is OK */
2542 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal po int. */ 1241 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal po int. */
2543 const DecimalFormatInternal &data = internalData(fReserved); 1242 if((fImpl->isParseFastpath()) && !fImpl->fMonetary &&
2544 if((data.fFastParseStatus==kFastpathYES) &&
2545 fCurrencySignCount == fgCurrencySignCountZero &&
2546 // (negPrefix!=NULL&&negPrefix->isEmpty()) ||
2547 text.length()>0 && 1243 text.length()>0 &&
2548 text.length()<32 && 1244 text.length()<32 &&
2549 (posPrefix==NULL||posPrefix->isEmpty()) && 1245 (posPrefix==NULL||posPrefix->isEmpty()) &&
2550 (posSuffix==NULL||posSuffix->isEmpty()) && 1246 (posSuffix==NULL||posSuffix->isEmpty()) &&
2551 // (negPrefix==NULL||negPrefix->isEmpty()) && 1247 // (negPrefix==NULL||negPrefix->isEmpty()) &&
2552 // (negSuffix==NULL||(negSuffix->isEmpty()) ) && 1248 // (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
2553 TRUE) { // optimized path 1249 TRUE) { // optimized path
2554 int j=position; 1250 int j=position;
2555 int l=text.length(); 1251 int l=text.length();
2556 int digitCount=0; 1252 int digitCount=0;
2557 UChar32 ch = text.char32At(j); 1253 UChar32 ch = text.char32At(j);
2558 const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols: :kDecimalSeparatorSymbol); 1254 const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatS ymbols::kDecimalSeparatorSymbol);
2559 UChar32 decimalChar = 0; 1255 UChar32 decimalChar = 0;
2560 UBool intOnly = FALSE; 1256 UBool intOnly = FALSE;
2561 UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0 ; 1257 UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0 ;
2562 1258
2563 int32_t decimalCount = decimalString->countChar32(0,3); 1259 int32_t decimalCount = decimalString->countChar32(0,3);
2564 if(isParseIntegerOnly()) { 1260 if(isParseIntegerOnly()) {
2565 decimalChar = 0; // not allowed 1261 decimalChar = 0; // not allowed
2566 intOnly = TRUE; // Don't look for decimals. 1262 intOnly = TRUE; // Don't look for decimals.
2567 } else if(decimalCount==1) { 1263 } else if(decimalCount==1) {
2568 decimalChar = decimalString->char32At(0); // Look for this decimal 1264 decimalChar = decimalString->char32At(0); // Look for this decimal
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 } else { 1306 } else {
2611 digitCount=-1; // fail - fall through to slow parse 1307 digitCount=-1; // fail - fall through to slow parse
2612 break; 1308 break;
2613 } 1309 }
2614 j+=U16_LENGTH(ch); 1310 j+=U16_LENGTH(ch);
2615 ch = text.char32At(j); // for next 1311 ch = text.char32At(j); // for next
2616 } 1312 }
2617 if( 1313 if(
2618 ((j==l)||intOnly) // end OR only parsing integer 1314 ((j==l)||intOnly) // end OR only parsing integer
2619 && (digitCount>0)) { // and have at least one digit 1315 && (digitCount>0)) { // and have at least one digit
2620 #ifdef FMT_DEBUG
2621 printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGrouping Size2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2);
2622 #endif
2623 fastParseOk=true; // Fast parse OK! 1316 fastParseOk=true; // Fast parse OK!
2624 1317
2625 #ifdef SKIP_OPT 1318 #ifdef SKIP_OPT
2626 debug("SKIP_OPT"); 1319 debug("SKIP_OPT");
2627 /* for testing, try it the slow way. also */ 1320 /* for testing, try it the slow way. also */
2628 fastParseOk=false; 1321 fastParseOk=false;
2629 parsedNum.clear(); 1322 parsedNum.clear();
2630 #else 1323 #else
2631 parsePosition.setIndex(position=j); 1324 parsePosition.setIndex(position=j);
2632 status[fgStatusInfinite]=false; 1325 status[fgStatusInfinite]=false;
2633 #endif 1326 #endif
2634 } else { 1327 } else {
2635 // was not OK. reset, retry 1328 // was not OK. reset, retry
2636 #ifdef FMT_DEBUG 1329 #ifdef FMT_DEBUG
2637 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount); 1330 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount);
2638 #endif 1331 #endif
2639 parsedNum.clear(); 1332 parsedNum.clear();
2640 } 1333 }
2641 } else { 1334 } else {
2642 #ifdef FMT_DEBUG 1335 #ifdef FMT_DEBUG
2643 printf("Could not fastpath parse. "); 1336 printf("Could not fastpath parse. ");
2644 printf("fFormatWidth=%d ", fFormatWidth);
2645 printf("text.length()=%d ", text.length()); 1337 printf("text.length()=%d ", text.length());
2646 printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix); 1338 printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
2647 1339
2648 printf("\n"); 1340 printf("\n");
2649 #endif 1341 #endif
2650 } 1342 }
2651 1343
1344 UnicodeString formatPattern;
1345 toPattern(formatPattern);
1346
2652 if(!fastParseOk 1347 if(!fastParseOk
2653 #if UCONFIG_HAVE_PARSEALLINPUT 1348 #if UCONFIG_HAVE_PARSEALLINPUT
2654 && fParseAllInput!=UNUM_YES 1349 && fParseAllInput!=UNUM_YES
2655 #endif 1350 #endif
2656 ) 1351 )
2657 { 1352 {
1353 int32_t formatWidth = fImpl->getOldFormatWidth();
2658 // Match padding before prefix 1354 // Match padding before prefix
2659 if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) { 1355 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPaddin g::kPadBeforePrefix) {
2660 position = skipPadding(text, position); 1356 position = skipPadding(text, position);
2661 } 1357 }
2662 1358
2663 // Match positive and negative prefixes; prefer longest match. 1359 // Match positive and negative prefixes; prefer longest match.
2664 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, comp lexCurrencyParsing, type, currency); 1360 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, comp lexCurrencyParsing, type, currency);
2665 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, comp lexCurrencyParsing, type, currency); 1361 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, comp lexCurrencyParsing, type, currency);
2666 if (posMatch >= 0 && negMatch >= 0) { 1362 if (posMatch >= 0 && negMatch >= 0) {
2667 if (posMatch > negMatch) { 1363 if (posMatch > negMatch) {
2668 negMatch = -1; 1364 negMatch = -1;
2669 } else if (negMatch > posMatch) { 1365 } else if (negMatch > posMatch) {
2670 posMatch = -1; 1366 posMatch = -1;
2671 } 1367 }
2672 } 1368 }
2673 if (posMatch >= 0) { 1369 if (posMatch >= 0) {
2674 position += posMatch; 1370 position += posMatch;
2675 parsedNum.append('+', err); 1371 parsedNum.append('+', err);
2676 } else if (negMatch >= 0) { 1372 } else if (negMatch >= 0) {
2677 position += negMatch; 1373 position += negMatch;
2678 parsedNum.append('-', err); 1374 parsedNum.append('-', err);
2679 } else if (strictParse){ 1375 } else if (strictParse){
2680 parsePosition.setErrorIndex(position); 1376 parsePosition.setErrorIndex(position);
2681 return FALSE; 1377 return FALSE;
2682 } else { 1378 } else {
2683 // Temporary set positive. This might be changed after checking suffix 1379 // Temporary set positive. This might be changed after checking suffix
2684 parsedNum.append('+', err); 1380 parsedNum.append('+', err);
2685 } 1381 }
2686 1382
2687 // Match padding before prefix 1383 // Match padding before prefix
2688 if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) { 1384 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPaddin g::kPadAfterPrefix) {
2689 position = skipPadding(text, position); 1385 position = skipPadding(text, position);
2690 } 1386 }
2691 1387
2692 if (! strictParse) { 1388 if (! strictParse) {
2693 position = skipUWhiteSpace(text, position); 1389 position = skipUWhiteSpace(text, position);
2694 } 1390 }
2695 1391
2696 // process digits or Inf, find decimal position 1392 // process digits or Inf, find decimal position
2697 const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySy mbol); 1393 const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInf initySymbol);
2698 int32_t infLen = (text.compare(position, inf->length(), *inf) 1394 int32_t infLen = (text.compare(position, inf->length(), *inf)
2699 ? 0 : inf->length()); 1395 ? 0 : inf->length());
2700 position += infLen; // infLen is non-zero when it does equal to infinity 1396 position += infLen; // infLen is non-zero when it does equal to infinity
2701 status[fgStatusInfinite] = infLen != 0; 1397 status[fgStatusInfinite] = infLen != 0;
2702 1398
2703 if (infLen != 0) { 1399 if (infLen != 0) {
2704 parsedNum.append("Infinity", err); 1400 parsedNum.append("Infinity", err);
2705 } else { 1401 } else {
2706 // We now have a string of digits, possibly with grouping symbols, 1402 // We now have a string of digits, possibly with grouping symbols,
2707 // and decimal points. We want to process these into a DigitList. 1403 // and decimal points. We want to process these into a DigitList.
2708 // We don't want to put a bunch of leading zeros into the DigitList 1404 // We don't want to put a bunch of leading zeros into the DigitList
2709 // though, so we keep track of the location of the decimal point, 1405 // though, so we keep track of the location of the decimal point,
2710 // put only significant digits into the DigitList, and adjust the 1406 // put only significant digits into the DigitList, and adjust the
2711 // exponent as needed. 1407 // exponent as needed.
2712 1408
2713 1409
2714 UBool strictFail = FALSE; // did we exit with a strict parse failure? 1410 UBool strictFail = FALSE; // did we exit with a strict parse failure?
2715 int32_t lastGroup = -1; // where did we last see a grouping separator? 1411 int32_t lastGroup = -1; // where did we last see a grouping separator?
2716 int32_t digitStart = position; 1412 int32_t digitStart = position;
2717 int32_t gs2 = fGroupingSize2 == 0 ? fGroupingSize : fGroupingSize2; 1413 int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping. fGrouping : fImpl->fEffGrouping.fGrouping2;
2718 1414
2719 const UnicodeString *decimalString; 1415 const UnicodeString *decimalString;
2720 if (fCurrencySignCount != fgCurrencySignCountZero) { 1416 if (fImpl->fMonetary) {
2721 decimalString = &getConstSymbol(DecimalFormatSymbols::kMonetarySepar atorSymbol); 1417 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMoneta rySeparatorSymbol);
2722 } else { 1418 } else {
2723 decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSepara torSymbol); 1419 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecima lSeparatorSymbol);
2724 } 1420 }
2725 UChar32 decimalChar = decimalString->char32At(0); 1421 UChar32 decimalChar = decimalString->char32At(0);
2726 int32_t decimalStringLength = decimalString->length(); 1422 int32_t decimalStringLength = decimalString->length();
2727 int32_t decimalCharLength = U16_LENGTH(decimalChar); 1423 int32_t decimalCharLength = U16_LENGTH(decimalChar);
2728 1424
2729 UBool sawDecimal = FALSE; 1425 UBool sawDecimal = FALSE;
2730 UChar32 sawDecimalChar = 0xFFFF; 1426 UChar32 sawDecimalChar = 0xFFFF;
2731 UBool sawGrouping = FALSE; 1427 UBool sawGrouping = FALSE;
2732 UChar32 sawGroupingChar = 0xFFFF; 1428 UChar32 sawGroupingChar = 0xFFFF;
2733 UBool sawDigit = FALSE; 1429 UBool sawDigit = FALSE;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2777 digit = ch - zero; 1473 digit = ch - zero;
2778 if (digit < 0 || digit > 9) 1474 if (digit < 0 || digit > 9)
2779 { 1475 {
2780 digit = u_charDigitValue(ch); 1476 digit = u_charDigitValue(ch);
2781 } 1477 }
2782 1478
2783 // As a last resort, look through the localized digits if the zero d igit 1479 // As a last resort, look through the localized digits if the zero d igit
2784 // is not a "standard" Unicode digit. 1480 // is not a "standard" Unicode digit.
2785 if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) { 1481 if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) {
2786 digit = 0; 1482 digit = 0;
2787 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)( DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) { 1483 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatS ymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) {
2788 break; 1484 break;
2789 } 1485 }
2790 for (digit = 1 ; digit < 10 ; digit++ ) { 1486 for (digit = 1 ; digit < 10 ; digit++ ) {
2791 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymb ol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) { 1487 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFor matSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
2792 break; 1488 break;
2793 } 1489 }
2794 } 1490 }
2795 } 1491 }
2796 1492
2797 if (digit >= 0 && digit <= 9) 1493 if (digit >= 0 && digit <= 9)
2798 { 1494 {
2799 if (strictParse && backup != -1) { 1495 if (strictParse && backup != -1) {
2800 // comma followed by digit, so group before comma is a 1496 // comma followed by digit, so group before comma is a
2801 // secondary group. If there was a group separator 1497 // secondary group. If there was a group separator
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 backup = position; 1549 backup = position;
2854 position += groupingStringLength; 1550 position += groupingStringLength;
2855 sawGrouping=TRUE; 1551 sawGrouping=TRUE;
2856 // Once we see a grouping character, we only accept that groupin g character from then on. 1552 // Once we see a grouping character, we only accept that groupin g character from then on.
2857 sawGroupingChar=ch; 1553 sawGroupingChar=ch;
2858 } 1554 }
2859 else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimal Set, ch)) 1555 else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimal Set, ch))
2860 { 1556 {
2861 if (strictParse) { 1557 if (strictParse) {
2862 if (backup != -1 || 1558 if (backup != -1 ||
2863 (lastGroup != -1 && position - lastGroup != fGroupingSiz e + 1)) { 1559 (lastGroup != -1 && position - lastGroup != fImpl->fEffG rouping.fGrouping + 1)) {
2864 strictFail = TRUE; 1560 strictFail = TRUE;
2865 break; 1561 break;
2866 } 1562 }
2867 } 1563 }
2868 1564
2869 // If we're only parsing integers, or if we ALREADY saw the 1565 // If we're only parsing integers, or if we ALREADY saw the
2870 // decimal, then don't parse this one. 1566 // decimal, then don't parse this one.
2871 if (isParseIntegerOnly() || sawDecimal) { 1567 if (isParseIntegerOnly() || sawDecimal) {
2872 break; 1568 break;
2873 } 1569 }
2874 1570
2875 parsedNum.append('.', err); 1571 parsedNum.append('.', err);
2876 position += decimalStringLength; 1572 position += decimalStringLength;
2877 sawDecimal = TRUE; 1573 sawDecimal = TRUE;
2878 // Once we see a decimal character, we only accept that decimal character from then on. 1574 // Once we see a decimal character, we only accept that decimal character from then on.
2879 sawDecimalChar=ch; 1575 sawDecimalChar=ch;
2880 // decimalSet is considered to consist of (ch,ch) 1576 // decimalSet is considered to consist of (ch,ch)
2881 } 1577 }
2882 else { 1578 else {
2883 1579
2884 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't pars e if this is set unless.. 1580 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't pars e if this is set unless..
2885 isScientificNotation()) { // .. it's an exponent format - ign ore setting and parse anyways 1581 isScientificNotation()) { // .. it's an exponent format - ign ore setting and parse anyways
2886 const UnicodeString *tmp; 1582 const UnicodeString *tmp;
2887 tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymb ol); 1583 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponent ialSymbol);
2888 // TODO: CASE 1584 // TODO: CASE
2889 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_ CASE_DEFAULT)) // error code is set below if !sawDigit 1585 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_ CASE_DEFAULT)) // error code is set below if !sawDigit
2890 { 1586 {
2891 // Parse sign, if present 1587 // Parse sign, if present
2892 int32_t pos = position + tmp->length(); 1588 int32_t pos = position + tmp->length();
2893 char exponentSign = '+'; 1589 char exponentSign = '+';
2894 1590
2895 if (pos < textLength) 1591 if (pos < textLength)
2896 { 1592 {
2897 tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSig nSymbol); 1593 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::k PlusSignSymbol);
2898 if (!text.compare(pos, tmp->length(), *tmp)) 1594 if (!text.compare(pos, tmp->length(), *tmp))
2899 { 1595 {
2900 pos += tmp->length(); 1596 pos += tmp->length();
2901 } 1597 }
2902 else { 1598 else {
2903 tmp = &getConstSymbol(DecimalFormatSymbols::kMin usSignSymbol); 1599 tmp = &fImpl->getConstSymbol(DecimalFormatSymbol s::kMinusSignSymbol);
2904 if (!text.compare(pos, tmp->length(), *tmp)) 1600 if (!text.compare(pos, tmp->length(), *tmp))
2905 { 1601 {
2906 exponentSign = '-'; 1602 exponentSign = '-';
2907 pos += tmp->length(); 1603 pos += tmp->length();
2908 } 1604 }
2909 } 1605 }
2910 } 1606 }
2911 1607
2912 UBool sawExponentDigit = FALSE; 1608 UBool sawExponentDigit = FALSE;
2913 while (pos < textLength) { 1609 while (pos < textLength) {
(...skipping 26 matching lines...) Expand all
2940 } 1636 }
2941 } else { // not parsing exponent 1637 } else { // not parsing exponent
2942 break; 1638 break;
2943 } 1639 }
2944 } 1640 }
2945 } 1641 }
2946 1642
2947 // if we didn't see a decimal and it is required, check to see if the pa ttern had one 1643 // if we didn't see a decimal and it is required, check to see if the pa ttern had one
2948 if(!sawDecimal && isDecimalPatternMatchRequired()) 1644 if(!sawDecimal && isDecimalPatternMatchRequired())
2949 { 1645 {
2950 if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSym bol) != 0) 1646 if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymb ol) != 0)
2951 { 1647 {
2952 parsePosition.setIndex(oldStart); 1648 parsePosition.setIndex(oldStart);
2953 parsePosition.setErrorIndex(position); 1649 parsePosition.setErrorIndex(position);
2954 debug("decimal point match required fail!"); 1650 debug("decimal point match required fail!");
2955 return FALSE; 1651 return FALSE;
2956 } 1652 }
2957 } 1653 }
2958 1654
2959 if (backup != -1) 1655 if (backup != -1)
2960 { 1656 {
2961 position = backup; 1657 position = backup;
2962 } 1658 }
2963 1659
2964 if (strictParse && !sawDecimal) { 1660 if (strictParse && !sawDecimal) {
2965 if (lastGroup != -1 && position - lastGroup != fGroupingSize + 1) { 1661 if (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.f Grouping + 1) {
2966 strictFail = TRUE; 1662 strictFail = TRUE;
2967 } 1663 }
2968 } 1664 }
2969 1665
2970 if (strictFail) { 1666 if (strictFail) {
2971 // only set with strictParse and a grouping separator error 1667 // only set with strictParse and a grouping separator error
2972 1668
2973 parsePosition.setIndex(oldStart); 1669 parsePosition.setIndex(oldStart);
2974 parsePosition.setErrorIndex(position); 1670 parsePosition.setErrorIndex(position);
2975 debug("strictFail!"); 1671 debug("strictFail!");
(...skipping 11 matching lines...) Expand all
2987 debug("none of text rec"); 1683 debug("none of text rec");
2988 printf("position=%d\n",position); 1684 printf("position=%d\n",position);
2989 #endif 1685 #endif
2990 parsePosition.setIndex(oldStart); 1686 parsePosition.setIndex(oldStart);
2991 parsePosition.setErrorIndex(oldStart); 1687 parsePosition.setErrorIndex(oldStart);
2992 return FALSE; 1688 return FALSE;
2993 } 1689 }
2994 } 1690 }
2995 1691
2996 // Match padding before suffix 1692 // Match padding before suffix
2997 if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) { 1693 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPaddin g::kPadBeforeSuffix) {
2998 position = skipPadding(text, position); 1694 position = skipPadding(text, position);
2999 } 1695 }
3000 1696
3001 int32_t posSuffixMatch = -1, negSuffixMatch = -1; 1697 int32_t posSuffixMatch = -1, negSuffixMatch = -1;
3002 1698
3003 // Match positive and negative suffixes; prefer longest match. 1699 // Match positive and negative suffixes; prefer longest match.
3004 if (posMatch >= 0 || (!strictParse && negMatch < 0)) { 1700 if (posMatch >= 0 || (!strictParse && negMatch < 0)) {
3005 posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, c omplexCurrencyParsing, type, currency); 1701 posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, c omplexCurrencyParsing, type, currency);
3006 } 1702 }
3007 if (negMatch >= 0) { 1703 if (negMatch >= 0) {
(...skipping 10 matching lines...) Expand all
3018 // Fail if neither or both 1714 // Fail if neither or both
3019 if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) { 1715 if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) {
3020 parsePosition.setErrorIndex(position); 1716 parsePosition.setErrorIndex(position);
3021 debug("neither or both"); 1717 debug("neither or both");
3022 return FALSE; 1718 return FALSE;
3023 } 1719 }
3024 1720
3025 position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? n egSuffixMatch : 0)); 1721 position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? n egSuffixMatch : 0));
3026 1722
3027 // Match padding before suffix 1723 // Match padding before suffix
3028 if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) { 1724 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPaddin g::kPadAfterSuffix) {
3029 position = skipPadding(text, position); 1725 position = skipPadding(text, position);
3030 } 1726 }
3031 1727
3032 parsePosition.setIndex(position); 1728 parsePosition.setIndex(position);
3033 1729
3034 parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-'; 1730 parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-';
3035 #ifdef FMT_DEBUG 1731 #ifdef FMT_DEBUG
3036 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d ata(), parsePosition.getIndex(),oldStart,u_errorName(err)); 1732 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d ata(), parsePosition.getIndex(),oldStart,u_errorName(err));
3037 #endif 1733 #endif
3038 } /* end SLOW parse */ 1734 } /* end SLOW parse */
(...skipping 27 matching lines...) Expand all
3066 #ifdef FMT_DEBUG 1762 #ifdef FMT_DEBUG
3067 printf(" err setting %s\n", u_errorName(err)); 1763 printf(" err setting %s\n", u_errorName(err));
3068 #endif 1764 #endif
3069 parsePosition.setErrorIndex(position); 1765 parsePosition.setErrorIndex(position);
3070 return FALSE; 1766 return FALSE;
3071 } 1767 }
3072 1768
3073 // check if we missed a required decimal point 1769 // check if we missed a required decimal point
3074 if(fastParseOk && isDecimalPatternMatchRequired()) 1770 if(fastParseOk && isDecimalPatternMatchRequired())
3075 { 1771 {
3076 if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0) 1772 if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
3077 { 1773 {
3078 parsePosition.setIndex(oldStart); 1774 parsePosition.setIndex(oldStart);
3079 parsePosition.setErrorIndex(position); 1775 parsePosition.setErrorIndex(position);
3080 debug("decimal point match required fail!"); 1776 debug("decimal point match required fail!");
3081 return FALSE; 1777 return FALSE;
3082 } 1778 }
3083 } 1779 }
3084 1780
3085 1781
3086 return TRUE; 1782 return TRUE;
3087 } 1783 }
3088 1784
3089 /** 1785 /**
3090 * Starting at position, advance past a run of pad characters, if any. 1786 * Starting at position, advance past a run of pad characters, if any.
3091 * Return the index of the first character after position that is not a pad 1787 * Return the index of the first character after position that is not a pad
3092 * character. Result is >= position. 1788 * character. Result is >= position.
3093 */ 1789 */
3094 int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const { 1790 int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
3095 int32_t padLen = U16_LENGTH(fPad); 1791 int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar);
3096 while (position < text.length() && 1792 while (position < text.length() &&
3097 text.char32At(position) == fPad) { 1793 text.char32At(position) == fImpl->fAffixes.fPadChar) {
3098 position += padLen; 1794 position += padLen;
3099 } 1795 }
3100 return position; 1796 return position;
3101 } 1797 }
3102 1798
3103 /** 1799 /**
3104 * Return the length matched by the given affix, or -1 if none. 1800 * Return the length matched by the given affix, or -1 if none.
3105 * Runs of white space in the affix, match runs of white space in 1801 * Runs of white space in the affix, match runs of white space in
3106 * the input. Pattern white space and input white space are 1802 * the input. Pattern white space and input white space are
3107 * determined differently; see code. 1803 * determined differently; see code.
(...skipping 13 matching lines...) Expand all
3121 int32_t DecimalFormat::compareAffix(const UnicodeString& text, 1817 int32_t DecimalFormat::compareAffix(const UnicodeString& text,
3122 int32_t pos, 1818 int32_t pos,
3123 UBool isNegative, 1819 UBool isNegative,
3124 UBool isPrefix, 1820 UBool isPrefix,
3125 const UnicodeString* affixPat, 1821 const UnicodeString* affixPat,
3126 UBool complexCurrencyParsing, 1822 UBool complexCurrencyParsing,
3127 int8_t type, 1823 int8_t type,
3128 UChar* currency) const 1824 UChar* currency) const
3129 { 1825 {
3130 const UnicodeString *patternToCompare; 1826 const UnicodeString *patternToCompare;
3131 if (fCurrencyChoice != NULL || currency != NULL || 1827 if (currency != NULL ||
3132 (fCurrencySignCount != fgCurrencySignCountZero && complexCurrencyParsing )) { 1828 (fImpl->fMonetary && complexCurrencyParsing)) {
3133 1829
3134 if (affixPat != NULL) { 1830 if (affixPat != NULL) {
3135 return compareComplexAffix(*affixPat, text, pos, type, currency); 1831 return compareComplexAffix(*affixPat, text, pos, type, currency);
3136 } 1832 }
3137 } 1833 }
3138 1834
3139 if (isNegative) { 1835 if (isNegative) {
3140 if (isPrefix) { 1836 if (isPrefix) {
3141 patternToCompare = &fNegativePrefix; 1837 patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant( ).toString();
3142 } 1838 }
3143 else { 1839 else {
3144 patternToCompare = &fNegativeSuffix; 1840 patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant( ).toString();
3145 } 1841 }
3146 } 1842 }
3147 else { 1843 else {
3148 if (isPrefix) { 1844 if (isPrefix) {
3149 patternToCompare = &fPositivePrefix; 1845 patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant( ).toString();
3150 } 1846 }
3151 else { 1847 else {
3152 patternToCompare = &fPositiveSuffix; 1848 patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant( ).toString();
3153 } 1849 }
3154 } 1850 }
3155 return compareSimpleAffix(*patternToCompare, text, pos, isLenient()); 1851 return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
3156 } 1852 }
3157 1853
3158 UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const { 1854 UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const {
3159 if (lhs == rhs) { 1855 if (lhs == rhs) {
3160 return TRUE; 1856 return TRUE;
3161 } 1857 }
3162 U_ASSERT(fStaticSets != NULL); // should already be loaded 1858 U_ASSERT(fStaticSets != NULL); // should already be loaded
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
3413 * currency that this formatter is set to. 2109 * currency that this formatter is set to.
3414 * @return length of input that matches, or -1 if match failure 2110 * @return length of input that matches, or -1 if match failure
3415 */ 2111 */
3416 int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat, 2112 int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
3417 const UnicodeString& text, 2113 const UnicodeString& text,
3418 int32_t pos, 2114 int32_t pos,
3419 int8_t type, 2115 int8_t type,
3420 UChar* currency) const 2116 UChar* currency) const
3421 { 2117 {
3422 int32_t start = pos; 2118 int32_t start = pos;
3423 U_ASSERT(currency != NULL || 2119 U_ASSERT(currency != NULL || fImpl->fMonetary);
3424 (fCurrencyChoice != NULL && *getCurrency() != 0) ||
3425 fCurrencySignCount != fgCurrencySignCountZero);
3426 2120
3427 for (int32_t i=0; 2121 for (int32_t i=0;
3428 i<affixPat.length() && pos >= 0; ) { 2122 i<affixPat.length() && pos >= 0; ) {
3429 UChar32 c = affixPat.char32At(i); 2123 UChar32 c = affixPat.char32At(i);
3430 i += U16_LENGTH(c); 2124 i += U16_LENGTH(c);
3431 2125
3432 if (c == kQuote) { 2126 if (c == kQuote) {
3433 U_ASSERT(i <= affixPat.length()); 2127 U_ASSERT(i <= affixPat.length());
3434 c = affixPat.char32At(i); 2128 c = affixPat.char32At(i);
3435 i += U16_LENGTH(c); 2129 i += U16_LENGTH(c);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3480 continue; 2174 continue;
3481 } 2175 }
3482 } 2176 }
3483 pos = ppos.getIndex(); 2177 pos = ppos.getIndex();
3484 } else if (!isLenient()){ 2178 } else if (!isLenient()){
3485 pos = -1; 2179 pos = -1;
3486 } 2180 }
3487 continue; 2181 continue;
3488 } 2182 }
3489 case kPatternPercent: 2183 case kPatternPercent:
3490 affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 2184 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSym bol);
3491 break; 2185 break;
3492 case kPatternPerMill: 2186 case kPatternPerMill:
3493 affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 2187 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSym bol);
3494 break; 2188 break;
3495 case kPatternPlus: 2189 case kPatternPlus:
3496 affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 2190 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSy mbol);
3497 break; 2191 break;
3498 case kPatternMinus: 2192 case kPatternMinus:
3499 affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 2193 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignS ymbol);
3500 break; 2194 break;
3501 default: 2195 default:
3502 // fall through to affix!=0 test, which will fail 2196 // fall through to affix!=0 test, which will fail
3503 break; 2197 break;
3504 } 2198 }
3505 2199
3506 if (affix != NULL) { 2200 if (affix != NULL) {
3507 pos = match(text, pos, *affix); 2201 pos = match(text, pos, *affix);
3508 continue; 2202 continue;
3509 } 2203 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3596 } 2290 }
3597 2291
3598 2292
3599 2293
3600 //------------------------------------------------------------------------------ 2294 //------------------------------------------------------------------------------
3601 // Gets the pointer to the localized decimal format symbols 2295 // Gets the pointer to the localized decimal format symbols
3602 2296
3603 const DecimalFormatSymbols* 2297 const DecimalFormatSymbols*
3604 DecimalFormat::getDecimalFormatSymbols() const 2298 DecimalFormat::getDecimalFormatSymbols() const
3605 { 2299 {
3606 return fSymbols; 2300 return &fImpl->getDecimalFormatSymbols();
3607 } 2301 }
3608 2302
3609 //------------------------------------------------------------------------------ 2303 //------------------------------------------------------------------------------
3610 // De-owning the current localized symbols and adopt the new symbols. 2304 // De-owning the current localized symbols and adopt the new symbols.
3611 2305
3612 void 2306 void
3613 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) 2307 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
3614 { 2308 {
3615 if (symbolsToAdopt == NULL) { 2309 if (symbolsToAdopt == NULL) {
3616 return; // do not allow caller to set fSymbols to NULL 2310 return; // do not allow caller to set fSymbols to NULL
3617 } 2311 }
3618 2312 fImpl->adoptDecimalFormatSymbols(symbolsToAdopt);
3619 UBool sameSymbols = FALSE;
3620 if (fSymbols != NULL) {
3621 sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymb ol) ==
3622 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol ) &&
3623 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
3624 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySy mbol));
3625 delete fSymbols;
3626 }
3627
3628 fSymbols = symbolsToAdopt;
3629 if (!sameSymbols) {
3630 // If the currency symbols are the same, there is no need to recalculate .
3631 setCurrencyForSymbols();
3632 }
3633 expandAffixes(NULL);
3634 #if UCONFIG_FORMAT_FASTPATHS_49
3635 handleChanged();
3636 #endif
3637 } 2313 }
3638 //------------------------------------------------------------------------------ 2314 //------------------------------------------------------------------------------
3639 // Setting the symbols is equlivalent to adopting a newly created localized 2315 // Setting the symbols is equlivalent to adopting a newly created localized
3640 // symbols. 2316 // symbols.
3641 2317
3642 void 2318 void
3643 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) 2319 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
3644 { 2320 {
3645 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); 2321 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
3646 #if UCONFIG_FORMAT_FASTPATHS_49
3647 handleChanged();
3648 #endif
3649 } 2322 }
3650 2323
3651 2324
3652 const CurrencyPluralInfo* 2325 const CurrencyPluralInfo*
3653 DecimalFormat::getCurrencyPluralInfo(void) const 2326 DecimalFormat::getCurrencyPluralInfo(void) const
3654 { 2327 {
3655 return fCurrencyPluralInfo; 2328 return fCurrencyPluralInfo;
3656 } 2329 }
3657 2330
3658 2331
3659 void 2332 void
3660 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) 2333 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt)
3661 { 2334 {
3662 if (toAdopt != NULL) { 2335 if (toAdopt != NULL) {
3663 delete fCurrencyPluralInfo; 2336 delete fCurrencyPluralInfo;
3664 fCurrencyPluralInfo = toAdopt; 2337 fCurrencyPluralInfo = toAdopt;
3665 // re-set currency affix patterns and currency affixes. 2338 // re-set currency affix patterns and currency affixes.
3666 if (fCurrencySignCount != fgCurrencySignCountZero) { 2339 if (fImpl->fMonetary) {
3667 UErrorCode status = U_ZERO_ERROR; 2340 UErrorCode status = U_ZERO_ERROR;
3668 if (fAffixPatternsForCurrency) { 2341 if (fAffixPatternsForCurrency) {
3669 deleteHashForAffixPattern(); 2342 deleteHashForAffixPattern();
3670 } 2343 }
3671 setupCurrencyAffixPatterns(status); 2344 setupCurrencyAffixPatterns(status);
3672 if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
3673 // only setup the affixes of the plural pattern.
3674 setupCurrencyAffixes(fFormatPattern, FALSE, TRUE, status);
3675 }
3676 } 2345 }
3677 } 2346 }
3678 #if UCONFIG_FORMAT_FASTPATHS_49
3679 handleChanged();
3680 #endif
3681 } 2347 }
3682 2348
3683 void 2349 void
3684 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) 2350 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
3685 { 2351 {
3686 adoptCurrencyPluralInfo(info.clone()); 2352 adoptCurrencyPluralInfo(info.clone());
3687 #if UCONFIG_FORMAT_FASTPATHS_49
3688 handleChanged();
3689 #endif
3690 } 2353 }
3691 2354
3692 2355
3693 /**
3694 * Update the currency object to match the symbols. This method
3695 * is used only when the caller has passed in a symbols object
3696 * that may not be the default object for its locale.
3697 */
3698 void
3699 DecimalFormat::setCurrencyForSymbols() {
3700 /*Bug 4212072
3701 Update the affix strings accroding to symbols in order to keep
3702 the affix strings up to date.
3703 [Richard/GCL]
3704 */
3705
3706 // With the introduction of the Currency object, the currency
3707 // symbols in the DFS object are ignored. For backward
3708 // compatibility, we check any explicitly set DFS object. If it
3709 // is a default symbols object for its locale, we change the
3710 // currency object to one for that locale. If it is custom,
3711 // we set the currency to null.
3712 UErrorCode ec = U_ZERO_ERROR;
3713 const UChar* c = NULL;
3714 const char* loc = fSymbols->getLocale().getName();
3715 UChar intlCurrencySymbol[4];
3716 ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec);
3717 UnicodeString currencySymbol;
3718
3719 uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec);
3720 if (U_SUCCESS(ec)
3721 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymb ol
3722 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == UnicodeS tring(intlCurrencySymbol))
3723 {
3724 // Trap an error in mapping locale to currency. If we can't
3725 // map, then don't fail and set the currency to "".
3726 c = intlCurrencySymbol;
3727 }
3728 ec = U_ZERO_ERROR; // reset local error code!
3729 setCurrencyInternally(c, ec);
3730 #if UCONFIG_FORMAT_FASTPATHS_49
3731 handleChanged();
3732 #endif
3733 }
3734
3735
3736 //------------------------------------------------------------------------------ 2356 //------------------------------------------------------------------------------
3737 // Gets the positive prefix of the number pattern. 2357 // Gets the positive prefix of the number pattern.
3738 2358
3739 UnicodeString& 2359 UnicodeString&
3740 DecimalFormat::getPositivePrefix(UnicodeString& result) const 2360 DecimalFormat::getPositivePrefix(UnicodeString& result) const
3741 { 2361 {
3742 result = fPositivePrefix; 2362 return fImpl->getPositivePrefix(result);
3743 return result;
3744 } 2363 }
3745 2364
3746 //------------------------------------------------------------------------------ 2365 //------------------------------------------------------------------------------
3747 // Sets the positive prefix of the number pattern. 2366 // Sets the positive prefix of the number pattern.
3748 2367
3749 void 2368 void
3750 DecimalFormat::setPositivePrefix(const UnicodeString& newValue) 2369 DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
3751 { 2370 {
3752 fPositivePrefix = newValue; 2371 fImpl->setPositivePrefix(newValue);
3753 delete fPosPrefixPattern;
3754 fPosPrefixPattern = 0;
3755 #if UCONFIG_FORMAT_FASTPATHS_49
3756 handleChanged();
3757 #endif
3758 } 2372 }
3759 2373
3760 //------------------------------------------------------------------------------ 2374 //------------------------------------------------------------------------------
3761 // Gets the negative prefix of the number pattern. 2375 // Gets the negative prefix of the number pattern.
3762 2376
3763 UnicodeString& 2377 UnicodeString&
3764 DecimalFormat::getNegativePrefix(UnicodeString& result) const 2378 DecimalFormat::getNegativePrefix(UnicodeString& result) const
3765 { 2379 {
3766 result = fNegativePrefix; 2380 return fImpl->getNegativePrefix(result);
3767 return result;
3768 } 2381 }
3769 2382
3770 //------------------------------------------------------------------------------ 2383 //------------------------------------------------------------------------------
3771 // Gets the negative prefix of the number pattern. 2384 // Gets the negative prefix of the number pattern.
3772 2385
3773 void 2386 void
3774 DecimalFormat::setNegativePrefix(const UnicodeString& newValue) 2387 DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
3775 { 2388 {
3776 fNegativePrefix = newValue; 2389 fImpl->setNegativePrefix(newValue);
3777 delete fNegPrefixPattern;
3778 fNegPrefixPattern = 0;
3779 #if UCONFIG_FORMAT_FASTPATHS_49
3780 handleChanged();
3781 #endif
3782 } 2390 }
3783 2391
3784 //------------------------------------------------------------------------------ 2392 //------------------------------------------------------------------------------
3785 // Gets the positive suffix of the number pattern. 2393 // Gets the positive suffix of the number pattern.
3786 2394
3787 UnicodeString& 2395 UnicodeString&
3788 DecimalFormat::getPositiveSuffix(UnicodeString& result) const 2396 DecimalFormat::getPositiveSuffix(UnicodeString& result) const
3789 { 2397 {
3790 result = fPositiveSuffix; 2398 return fImpl->getPositiveSuffix(result);
3791 return result;
3792 } 2399 }
3793 2400
3794 //------------------------------------------------------------------------------ 2401 //------------------------------------------------------------------------------
3795 // Sets the positive suffix of the number pattern. 2402 // Sets the positive suffix of the number pattern.
3796 2403
3797 void 2404 void
3798 DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) 2405 DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
3799 { 2406 {
3800 fPositiveSuffix = newValue; 2407 fImpl->setPositiveSuffix(newValue);
3801 delete fPosSuffixPattern;
3802 fPosSuffixPattern = 0;
3803 #if UCONFIG_FORMAT_FASTPATHS_49
3804 handleChanged();
3805 #endif
3806 } 2408 }
3807 2409
3808 //------------------------------------------------------------------------------ 2410 //------------------------------------------------------------------------------
3809 // Gets the negative suffix of the number pattern. 2411 // Gets the negative suffix of the number pattern.
3810 2412
3811 UnicodeString& 2413 UnicodeString&
3812 DecimalFormat::getNegativeSuffix(UnicodeString& result) const 2414 DecimalFormat::getNegativeSuffix(UnicodeString& result) const
3813 { 2415 {
3814 result = fNegativeSuffix; 2416 return fImpl->getNegativeSuffix(result);
3815 return result;
3816 } 2417 }
3817 2418
3818 //------------------------------------------------------------------------------ 2419 //------------------------------------------------------------------------------
3819 // Sets the negative suffix of the number pattern. 2420 // Sets the negative suffix of the number pattern.
3820 2421
3821 void 2422 void
3822 DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) 2423 DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
3823 { 2424 {
3824 fNegativeSuffix = newValue; 2425 fImpl->setNegativeSuffix(newValue);
3825 delete fNegSuffixPattern;
3826 fNegSuffixPattern = 0;
3827 #if UCONFIG_FORMAT_FASTPATHS_49
3828 handleChanged();
3829 #endif
3830 } 2426 }
3831 2427
3832 //------------------------------------------------------------------------------ 2428 //------------------------------------------------------------------------------
3833 // Gets the multiplier of the number pattern. 2429 // Gets the multiplier of the number pattern.
3834 // Multipliers are stored as decimal numbers (DigitLists) because that 2430 // Multipliers are stored as decimal numbers (DigitLists) because that
3835 // is the most convenient for muliplying or dividing the numbers to be form atted. 2431 // is the most convenient for muliplying or dividing the numbers to be form atted.
3836 // A NULL multiplier implies one, and the scaling operations are skipped. 2432 // A NULL multiplier implies one, and the scaling operations are skipped.
3837 2433
3838 int32_t 2434 int32_t
3839 DecimalFormat::getMultiplier() const 2435 DecimalFormat::getMultiplier() const
3840 { 2436 {
3841 if (fMultiplier == NULL) { 2437 return fImpl->getMultiplier();
3842 return 1;
3843 } else {
3844 return fMultiplier->getLong();
3845 }
3846 } 2438 }
3847 2439
3848 //------------------------------------------------------------------------------ 2440 //------------------------------------------------------------------------------
3849 // Sets the multiplier of the number pattern. 2441 // Sets the multiplier of the number pattern.
3850 void 2442 void
3851 DecimalFormat::setMultiplier(int32_t newValue) 2443 DecimalFormat::setMultiplier(int32_t newValue)
3852 { 2444 {
3853 // if (newValue == 0) { 2445 fImpl->setMultiplier(newValue);
3854 // throw new IllegalArgumentException("Bad multiplier: " + newValue);
3855 // }
3856 if (newValue == 0) {
3857 newValue = 1; // one being the benign default value for a multiplier .
3858 }
3859 if (newValue == 1) {
3860 delete fMultiplier;
3861 fMultiplier = NULL;
3862 } else {
3863 if (fMultiplier == NULL) {
3864 fMultiplier = new DigitList;
3865 }
3866 if (fMultiplier != NULL) {
3867 fMultiplier->set(newValue);
3868 }
3869 }
3870 #if UCONFIG_FORMAT_FASTPATHS_49
3871 handleChanged();
3872 #endif
3873 } 2446 }
3874 2447
3875 /** 2448 /**
3876 * Get the rounding increment. 2449 * Get the rounding increment.
3877 * @return A positive rounding increment, or 0.0 if rounding 2450 * @return A positive rounding increment, or 0.0 if rounding
3878 * is not in effect. 2451 * is not in effect.
3879 * @see #setRoundingIncrement 2452 * @see #setRoundingIncrement
3880 * @see #getRoundingMode 2453 * @see #getRoundingMode
3881 * @see #setRoundingMode 2454 * @see #setRoundingMode
3882 */ 2455 */
3883 double DecimalFormat::getRoundingIncrement() const { 2456 double DecimalFormat::getRoundingIncrement() const {
3884 if (fRoundingIncrement == NULL) { 2457 return fImpl->getRoundingIncrement();
3885 return 0.0;
3886 } else {
3887 return fRoundingIncrement->getDouble();
3888 }
3889 } 2458 }
3890 2459
3891 /** 2460 /**
3892 * Set the rounding increment. This method also controls whether 2461 * Set the rounding increment. This method also controls whether
3893 * rounding is enabled. 2462 * rounding is enabled.
3894 * @param newValue A positive rounding increment, or 0.0 to disable rounding. 2463 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
3895 * Negative increments are equivalent to 0.0. 2464 * Negative increments are equivalent to 0.0.
3896 * @see #getRoundingIncrement 2465 * @see #getRoundingIncrement
3897 * @see #getRoundingMode 2466 * @see #getRoundingMode
3898 * @see #setRoundingMode 2467 * @see #setRoundingMode
3899 */ 2468 */
3900 void DecimalFormat::setRoundingIncrement(double newValue) { 2469 void DecimalFormat::setRoundingIncrement(double newValue) {
3901 if (newValue > 0.0) { 2470 fImpl->setRoundingIncrement(newValue);
3902 if (fRoundingIncrement == NULL) {
3903 fRoundingIncrement = new DigitList();
3904 }
3905 if (fRoundingIncrement != NULL) {
3906 fRoundingIncrement->set(newValue);
3907 return;
3908 }
3909 }
3910 // These statements are executed if newValue is less than 0.0
3911 // or fRoundingIncrement could not be created.
3912 delete fRoundingIncrement;
3913 fRoundingIncrement = NULL;
3914 #if UCONFIG_FORMAT_FASTPATHS_49
3915 handleChanged();
3916 #endif
3917 } 2471 }
3918 2472
3919 /** 2473 /**
3920 * Get the rounding mode. 2474 * Get the rounding mode.
3921 * @return A rounding mode 2475 * @return A rounding mode
3922 * @see #setRoundingIncrement 2476 * @see #setRoundingIncrement
3923 * @see #getRoundingIncrement 2477 * @see #getRoundingIncrement
3924 * @see #setRoundingMode 2478 * @see #setRoundingMode
3925 */ 2479 */
3926 DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const { 2480 DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
3927 return fRoundingMode; 2481 return fImpl->getRoundingMode();
3928 } 2482 }
3929 2483
3930 /** 2484 /**
3931 * Set the rounding mode. This has no effect unless the rounding 2485 * Set the rounding mode. This has no effect unless the rounding
3932 * increment is greater than zero. 2486 * increment is greater than zero.
3933 * @param roundingMode A rounding mode 2487 * @param roundingMode A rounding mode
3934 * @see #setRoundingIncrement 2488 * @see #setRoundingIncrement
3935 * @see #getRoundingIncrement 2489 * @see #getRoundingIncrement
3936 * @see #getRoundingMode 2490 * @see #getRoundingMode
3937 */ 2491 */
3938 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) { 2492 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
3939 fRoundingMode = roundingMode; 2493 fImpl->setRoundingMode(roundingMode);
3940 #if UCONFIG_FORMAT_FASTPATHS_49
3941 handleChanged();
3942 #endif
3943 } 2494 }
3944 2495
3945 /** 2496 /**
3946 * Get the width to which the output of <code>format()</code> is padded. 2497 * Get the width to which the output of <code>format()</code> is padded.
3947 * @return the format width, or zero if no padding is in effect 2498 * @return the format width, or zero if no padding is in effect
3948 * @see #setFormatWidth 2499 * @see #setFormatWidth
3949 * @see #getPadCharacter 2500 * @see #getPadCharacter
3950 * @see #setPadCharacter 2501 * @see #setPadCharacter
3951 * @see #getPadPosition 2502 * @see #getPadPosition
3952 * @see #setPadPosition 2503 * @see #setPadPosition
3953 */ 2504 */
3954 int32_t DecimalFormat::getFormatWidth() const { 2505 int32_t DecimalFormat::getFormatWidth() const {
3955 return fFormatWidth; 2506 return fImpl->getFormatWidth();
3956 } 2507 }
3957 2508
3958 /** 2509 /**
3959 * Set the width to which the output of <code>format()</code> is padded. 2510 * Set the width to which the output of <code>format()</code> is padded.
3960 * This method also controls whether padding is enabled. 2511 * This method also controls whether padding is enabled.
3961 * @param width the width to which to pad the result of 2512 * @param width the width to which to pad the result of
3962 * <code>format()</code>, or zero to disable padding. A negative 2513 * <code>format()</code>, or zero to disable padding. A negative
3963 * width is equivalent to 0. 2514 * width is equivalent to 0.
3964 * @see #getFormatWidth 2515 * @see #getFormatWidth
3965 * @see #getPadCharacter 2516 * @see #getPadCharacter
3966 * @see #setPadCharacter 2517 * @see #setPadCharacter
3967 * @see #getPadPosition 2518 * @see #getPadPosition
3968 * @see #setPadPosition 2519 * @see #setPadPosition
3969 */ 2520 */
3970 void DecimalFormat::setFormatWidth(int32_t width) { 2521 void DecimalFormat::setFormatWidth(int32_t width) {
3971 fFormatWidth = (width > 0) ? width : 0; 2522 int32_t formatWidth = (width > 0) ? width : 0;
3972 #if UCONFIG_FORMAT_FASTPATHS_49 2523 fImpl->setFormatWidth(formatWidth);
3973 handleChanged();
3974 #endif
3975 } 2524 }
3976 2525
3977 UnicodeString DecimalFormat::getPadCharacterString() const { 2526 UnicodeString DecimalFormat::getPadCharacterString() const {
3978 return UnicodeString(fPad); 2527 return UnicodeString(fImpl->getPadCharacter());
3979 } 2528 }
3980 2529
3981 void DecimalFormat::setPadCharacter(const UnicodeString &padChar) { 2530 void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
2531 UChar pad;
3982 if (padChar.length() > 0) { 2532 if (padChar.length() > 0) {
3983 fPad = padChar.char32At(0); 2533 pad = padChar.char32At(0);
3984 } 2534 }
3985 else { 2535 else {
3986 fPad = kDefaultPad; 2536 pad = kDefaultPad;
3987 } 2537 }
3988 #if UCONFIG_FORMAT_FASTPATHS_49 2538 fImpl->setPadCharacter(pad);
3989 handleChanged(); 2539 }
3990 #endif 2540
2541 static DecimalFormat::EPadPosition fromPadPosition(DigitAffixesAndPadding::EPadP osition padPos) {
2542 switch (padPos) {
2543 case DigitAffixesAndPadding::kPadBeforePrefix:
2544 return DecimalFormat::kPadBeforePrefix;
2545 case DigitAffixesAndPadding::kPadAfterPrefix:
2546 return DecimalFormat::kPadAfterPrefix;
2547 case DigitAffixesAndPadding::kPadBeforeSuffix:
2548 return DecimalFormat::kPadBeforeSuffix;
2549 case DigitAffixesAndPadding::kPadAfterSuffix:
2550 return DecimalFormat::kPadAfterSuffix;
2551 default:
2552 U_ASSERT(FALSE);
2553 break;
2554 }
2555 return DecimalFormat::kPadBeforePrefix;
3991 } 2556 }
3992 2557
3993 /** 2558 /**
3994 * Get the position at which padding will take place. This is the location 2559 * Get the position at which padding will take place. This is the location
3995 * at which padding will be inserted if the result of <code>format()</code> 2560 * at which padding will be inserted if the result of <code>format()</code>
3996 * is shorter than the format width. 2561 * is shorter than the format width.
3997 * @return the pad position, one of <code>kPadBeforePrefix</code>, 2562 * @return the pad position, one of <code>kPadBeforePrefix</code>,
3998 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 2563 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3999 * <code>kPadAfterSuffix</code>. 2564 * <code>kPadAfterSuffix</code>.
4000 * @see #setFormatWidth 2565 * @see #setFormatWidth
4001 * @see #getFormatWidth 2566 * @see #getFormatWidth
4002 * @see #setPadCharacter 2567 * @see #setPadCharacter
4003 * @see #getPadCharacter 2568 * @see #getPadCharacter
4004 * @see #setPadPosition 2569 * @see #setPadPosition
4005 * @see #kPadBeforePrefix 2570 * @see #kPadBeforePrefix
4006 * @see #kPadAfterPrefix 2571 * @see #kPadAfterPrefix
4007 * @see #kPadBeforeSuffix 2572 * @see #kPadBeforeSuffix
4008 * @see #kPadAfterSuffix 2573 * @see #kPadAfterSuffix
4009 */ 2574 */
4010 DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const { 2575 DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
4011 return fPadPosition; 2576 return fromPadPosition(fImpl->getPadPosition());
2577 }
2578
2579 static DigitAffixesAndPadding::EPadPosition toPadPosition(DecimalFormat::EPadPos ition padPos) {
2580 switch (padPos) {
2581 case DecimalFormat::kPadBeforePrefix:
2582 return DigitAffixesAndPadding::kPadBeforePrefix;
2583 case DecimalFormat::kPadAfterPrefix:
2584 return DigitAffixesAndPadding::kPadAfterPrefix;
2585 case DecimalFormat::kPadBeforeSuffix:
2586 return DigitAffixesAndPadding::kPadBeforeSuffix;
2587 case DecimalFormat::kPadAfterSuffix:
2588 return DigitAffixesAndPadding::kPadAfterSuffix;
2589 default:
2590 U_ASSERT(FALSE);
2591 break;
2592 }
2593 return DigitAffixesAndPadding::kPadBeforePrefix;
4012 } 2594 }
4013 2595
4014 /** 2596 /**
4015 * <strong><font face=helvetica color=red>NEW</font></strong> 2597 * <strong><font face=helvetica color=red>NEW</font></strong>
4016 * Set the position at which padding will take place. This is the location 2598 * Set the position at which padding will take place. This is the location
4017 * at which padding will be inserted if the result of <code>format()</code> 2599 * at which padding will be inserted if the result of <code>format()</code>
4018 * is shorter than the format width. This has no effect unless padding is 2600 * is shorter than the format width. This has no effect unless padding is
4019 * enabled. 2601 * enabled.
4020 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>, 2602 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
4021 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 2603 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
4022 * <code>kPadAfterSuffix</code>. 2604 * <code>kPadAfterSuffix</code>.
4023 * @see #setFormatWidth 2605 * @see #setFormatWidth
4024 * @see #getFormatWidth 2606 * @see #getFormatWidth
4025 * @see #setPadCharacter 2607 * @see #setPadCharacter
4026 * @see #getPadCharacter 2608 * @see #getPadCharacter
4027 * @see #getPadPosition 2609 * @see #getPadPosition
4028 * @see #kPadBeforePrefix 2610 * @see #kPadBeforePrefix
4029 * @see #kPadAfterPrefix 2611 * @see #kPadAfterPrefix
4030 * @see #kPadBeforeSuffix 2612 * @see #kPadBeforeSuffix
4031 * @see #kPadAfterSuffix 2613 * @see #kPadAfterSuffix
4032 */ 2614 */
4033 void DecimalFormat::setPadPosition(EPadPosition padPos) { 2615 void DecimalFormat::setPadPosition(EPadPosition padPos) {
4034 fPadPosition = padPos; 2616 fImpl->setPadPosition(toPadPosition(padPos));
4035 #if UCONFIG_FORMAT_FASTPATHS_49
4036 handleChanged();
4037 #endif
4038 } 2617 }
4039 2618
4040 /** 2619 /**
4041 * Return whether or not scientific notation is used. 2620 * Return whether or not scientific notation is used.
4042 * @return TRUE if this object formats and parses scientific notation 2621 * @return TRUE if this object formats and parses scientific notation
4043 * @see #setScientificNotation 2622 * @see #setScientificNotation
4044 * @see #getMinimumExponentDigits 2623 * @see #getMinimumExponentDigits
4045 * @see #setMinimumExponentDigits 2624 * @see #setMinimumExponentDigits
4046 * @see #isExponentSignAlwaysShown 2625 * @see #isExponentSignAlwaysShown
4047 * @see #setExponentSignAlwaysShown 2626 * @see #setExponentSignAlwaysShown
4048 */ 2627 */
4049 UBool DecimalFormat::isScientificNotation() const { 2628 UBool DecimalFormat::isScientificNotation() const {
4050 return fUseExponentialNotation; 2629 return fImpl->isScientificNotation();
4051 } 2630 }
4052 2631
4053 /** 2632 /**
4054 * Set whether or not scientific notation is used. 2633 * Set whether or not scientific notation is used.
4055 * @param useScientific TRUE if this object formats and parses scientific 2634 * @param useScientific TRUE if this object formats and parses scientific
4056 * notation 2635 * notation
4057 * @see #isScientificNotation 2636 * @see #isScientificNotation
4058 * @see #getMinimumExponentDigits 2637 * @see #getMinimumExponentDigits
4059 * @see #setMinimumExponentDigits 2638 * @see #setMinimumExponentDigits
4060 * @see #isExponentSignAlwaysShown 2639 * @see #isExponentSignAlwaysShown
4061 * @see #setExponentSignAlwaysShown 2640 * @see #setExponentSignAlwaysShown
4062 */ 2641 */
4063 void DecimalFormat::setScientificNotation(UBool useScientific) { 2642 void DecimalFormat::setScientificNotation(UBool useScientific) {
4064 fUseExponentialNotation = useScientific; 2643 fImpl->setScientificNotation(useScientific);
4065 #if UCONFIG_FORMAT_FASTPATHS_49
4066 handleChanged();
4067 #endif
4068 } 2644 }
4069 2645
4070 /** 2646 /**
4071 * Return the minimum exponent digits that will be shown. 2647 * Return the minimum exponent digits that will be shown.
4072 * @return the minimum exponent digits that will be shown 2648 * @return the minimum exponent digits that will be shown
4073 * @see #setScientificNotation 2649 * @see #setScientificNotation
4074 * @see #isScientificNotation 2650 * @see #isScientificNotation
4075 * @see #setMinimumExponentDigits 2651 * @see #setMinimumExponentDigits
4076 * @see #isExponentSignAlwaysShown 2652 * @see #isExponentSignAlwaysShown
4077 * @see #setExponentSignAlwaysShown 2653 * @see #setExponentSignAlwaysShown
4078 */ 2654 */
4079 int8_t DecimalFormat::getMinimumExponentDigits() const { 2655 int8_t DecimalFormat::getMinimumExponentDigits() const {
4080 return fMinExponentDigits; 2656 return fImpl->getMinimumExponentDigits();
4081 } 2657 }
4082 2658
4083 /** 2659 /**
4084 * Set the minimum exponent digits that will be shown. This has no 2660 * Set the minimum exponent digits that will be shown. This has no
4085 * effect unless scientific notation is in use. 2661 * effect unless scientific notation is in use.
4086 * @param minExpDig a value >= 1 indicating the fewest exponent digits 2662 * @param minExpDig a value >= 1 indicating the fewest exponent digits
4087 * that will be shown. Values less than 1 will be treated as 1. 2663 * that will be shown. Values less than 1 will be treated as 1.
4088 * @see #setScientificNotation 2664 * @see #setScientificNotation
4089 * @see #isScientificNotation 2665 * @see #isScientificNotation
4090 * @see #getMinimumExponentDigits 2666 * @see #getMinimumExponentDigits
4091 * @see #isExponentSignAlwaysShown 2667 * @see #isExponentSignAlwaysShown
4092 * @see #setExponentSignAlwaysShown 2668 * @see #setExponentSignAlwaysShown
4093 */ 2669 */
4094 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) { 2670 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
4095 fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1); 2671 int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
4096 #if UCONFIG_FORMAT_FASTPATHS_49 2672 fImpl->setMinimumExponentDigits(minExponentDigits);
4097 handleChanged();
4098 #endif
4099 } 2673 }
4100 2674
4101 /** 2675 /**
4102 * Return whether the exponent sign is always shown. 2676 * Return whether the exponent sign is always shown.
4103 * @return TRUE if the exponent is always prefixed with either the 2677 * @return TRUE if the exponent is always prefixed with either the
4104 * localized minus sign or the localized plus sign, false if only negative 2678 * localized minus sign or the localized plus sign, false if only negative
4105 * exponents are prefixed with the localized minus sign. 2679 * exponents are prefixed with the localized minus sign.
4106 * @see #setScientificNotation 2680 * @see #setScientificNotation
4107 * @see #isScientificNotation 2681 * @see #isScientificNotation
4108 * @see #setMinimumExponentDigits 2682 * @see #setMinimumExponentDigits
4109 * @see #getMinimumExponentDigits 2683 * @see #getMinimumExponentDigits
4110 * @see #setExponentSignAlwaysShown 2684 * @see #setExponentSignAlwaysShown
4111 */ 2685 */
4112 UBool DecimalFormat::isExponentSignAlwaysShown() const { 2686 UBool DecimalFormat::isExponentSignAlwaysShown() const {
4113 return fExponentSignAlwaysShown; 2687 return fImpl->isExponentSignAlwaysShown();
4114 } 2688 }
4115 2689
4116 /** 2690 /**
4117 * Set whether the exponent sign is always shown. This has no effect 2691 * Set whether the exponent sign is always shown. This has no effect
4118 * unless scientific notation is in use. 2692 * unless scientific notation is in use.
4119 * @param expSignAlways TRUE if the exponent is always prefixed with either 2693 * @param expSignAlways TRUE if the exponent is always prefixed with either
4120 * the localized minus sign or the localized plus sign, false if only 2694 * the localized minus sign or the localized plus sign, false if only
4121 * negative exponents are prefixed with the localized minus sign. 2695 * negative exponents are prefixed with the localized minus sign.
4122 * @see #setScientificNotation 2696 * @see #setScientificNotation
4123 * @see #isScientificNotation 2697 * @see #isScientificNotation
4124 * @see #setMinimumExponentDigits 2698 * @see #setMinimumExponentDigits
4125 * @see #getMinimumExponentDigits 2699 * @see #getMinimumExponentDigits
4126 * @see #isExponentSignAlwaysShown 2700 * @see #isExponentSignAlwaysShown
4127 */ 2701 */
4128 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { 2702 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
4129 fExponentSignAlwaysShown = expSignAlways; 2703 fImpl->setExponentSignAlwaysShown(expSignAlways);
4130 #if UCONFIG_FORMAT_FASTPATHS_49
4131 handleChanged();
4132 #endif
4133 } 2704 }
4134 2705
4135 //------------------------------------------------------------------------------ 2706 //------------------------------------------------------------------------------
4136 // Gets the grouping size of the number pattern. For example, thousand or 10 2707 // Gets the grouping size of the number pattern. For example, thousand or 10
4137 // thousand groupings. 2708 // thousand groupings.
4138 2709
4139 int32_t 2710 int32_t
4140 DecimalFormat::getGroupingSize() const 2711 DecimalFormat::getGroupingSize() const
4141 { 2712 {
4142 return isGroupingUsed() ? fGroupingSize : 0; 2713 return fImpl->getGroupingSize();
4143 } 2714 }
4144 2715
4145 //------------------------------------------------------------------------------ 2716 //------------------------------------------------------------------------------
4146 // Gets the grouping size of the number pattern. 2717 // Gets the grouping size of the number pattern.
4147 2718
4148 void 2719 void
4149 DecimalFormat::setGroupingSize(int32_t newValue) 2720 DecimalFormat::setGroupingSize(int32_t newValue)
4150 { 2721 {
4151 fGroupingSize = newValue; 2722 fImpl->setGroupingSize(newValue);
4152 #if UCONFIG_FORMAT_FASTPATHS_49
4153 handleChanged();
4154 #endif
4155 } 2723 }
4156 2724
4157 //------------------------------------------------------------------------------ 2725 //------------------------------------------------------------------------------
4158 2726
4159 int32_t 2727 int32_t
4160 DecimalFormat::getSecondaryGroupingSize() const 2728 DecimalFormat::getSecondaryGroupingSize() const
4161 { 2729 {
4162 return fGroupingSize2; 2730 return fImpl->getSecondaryGroupingSize();
4163 } 2731 }
4164 2732
4165 //------------------------------------------------------------------------------ 2733 //------------------------------------------------------------------------------
4166 2734
4167 void 2735 void
4168 DecimalFormat::setSecondaryGroupingSize(int32_t newValue) 2736 DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
4169 { 2737 {
4170 fGroupingSize2 = newValue; 2738 fImpl->setSecondaryGroupingSize(newValue);
4171 #if UCONFIG_FORMAT_FASTPATHS_49
4172 handleChanged();
4173 #endif
4174 } 2739 }
4175 2740
4176 //------------------------------------------------------------------------------ 2741 //------------------------------------------------------------------------------
2742
2743 int32_t
2744 DecimalFormat::getMinimumGroupingDigits() const
2745 {
2746 return fImpl->getMinimumGroupingDigits();
2747 }
2748
2749 //------------------------------------------------------------------------------
2750
2751 void
2752 DecimalFormat::setMinimumGroupingDigits(int32_t newValue)
2753 {
2754 fImpl->setMinimumGroupingDigits(newValue);
2755 }
2756
2757 //------------------------------------------------------------------------------
4177 // Checks if to show the decimal separator. 2758 // Checks if to show the decimal separator.
4178 2759
4179 UBool 2760 UBool
4180 DecimalFormat::isDecimalSeparatorAlwaysShown() const 2761 DecimalFormat::isDecimalSeparatorAlwaysShown() const
4181 { 2762 {
4182 return fDecimalSeparatorAlwaysShown; 2763 return fImpl->isDecimalSeparatorAlwaysShown();
4183 } 2764 }
4184 2765
4185 //------------------------------------------------------------------------------ 2766 //------------------------------------------------------------------------------
4186 // Sets to always show the decimal separator. 2767 // Sets to always show the decimal separator.
4187 2768
4188 void 2769 void
4189 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) 2770 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
4190 { 2771 {
4191 fDecimalSeparatorAlwaysShown = newValue; 2772 fImpl->setDecimalSeparatorAlwaysShown(newValue);
4192 #if UCONFIG_FORMAT_FASTPATHS_49
4193 handleChanged();
4194 #endif
4195 } 2773 }
4196 2774
4197 //------------------------------------------------------------------------------ 2775 //------------------------------------------------------------------------------
4198 // Checks if decimal point pattern match is required 2776 // Checks if decimal point pattern match is required
4199 UBool 2777 UBool
4200 DecimalFormat::isDecimalPatternMatchRequired(void) const 2778 DecimalFormat::isDecimalPatternMatchRequired(void) const
4201 { 2779 {
4202 return fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED); 2780 return fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED);
4203 } 2781 }
4204 2782
4205 //------------------------------------------------------------------------------ 2783 //------------------------------------------------------------------------------
4206 // Checks if decimal point pattern match is required 2784 // Checks if decimal point pattern match is required
4207 2785
4208 void 2786 void
4209 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) 2787 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue)
4210 { 2788 {
4211 fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue); 2789 fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue);
4212 } 2790 }
4213 2791
4214 2792
4215 //------------------------------------------------------------------------------ 2793 //------------------------------------------------------------------------------
4216 // Emits the pattern of this DecimalFormat instance. 2794 // Emits the pattern of this DecimalFormat instance.
4217 2795
4218 UnicodeString& 2796 UnicodeString&
4219 DecimalFormat::toPattern(UnicodeString& result) const 2797 DecimalFormat::toPattern(UnicodeString& result) const
4220 { 2798 {
4221 return toPattern(result, FALSE); 2799 return fImpl->toPattern(result);
4222 } 2800 }
4223 2801
4224 //------------------------------------------------------------------------------ 2802 //------------------------------------------------------------------------------
4225 // Emits the localized pattern this DecimalFormat instance. 2803 // Emits the localized pattern this DecimalFormat instance.
4226 2804
4227 UnicodeString& 2805 UnicodeString&
4228 DecimalFormat::toLocalizedPattern(UnicodeString& result) const 2806 DecimalFormat::toLocalizedPattern(UnicodeString& result) const
4229 { 2807 {
4230 return toPattern(result, TRUE); 2808 // toLocalizedPattern is deprecated, so we just make it the same as
2809 // toPattern.
2810 return fImpl->toPattern(result);
4231 } 2811 }
4232 2812
4233 //------------------------------------------------------------------------------ 2813 //------------------------------------------------------------------------------
4234 /**
4235 * Expand the affix pattern strings into the expanded affix strings. If any
4236 * affix pattern string is null, do not expand it. This method should be
4237 * called any time the symbols or the affix patterns change in order to keep
4238 * the expanded affix strings up to date.
4239 * This method also will be called before formatting if format currency
4240 * plural names, since the plural name is not a static one, it is
4241 * based on the currency plural count, the affix will be known only
4242 * after the currency plural count is know.
4243 * In which case, the parameter
4244 * 'pluralCount' will be a non-null currency plural count.
4245 * In all other cases, the 'pluralCount' is null, which means it is not needed.
4246 */
4247 void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
4248 FieldPositionHandler none;
4249 if (fPosPrefixPattern != 0) {
4250 expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCou nt);
4251 }
4252 if (fPosSuffixPattern != 0) {
4253 expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCou nt);
4254 }
4255 if (fNegPrefixPattern != 0) {
4256 expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCou nt);
4257 }
4258 if (fNegSuffixPattern != 0) {
4259 expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCou nt);
4260 }
4261 #ifdef FMT_DEBUG
4262 UnicodeString s;
4263 s.append(UnicodeString("["))
4264 .append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DER EFSTR(fPosSuffixPattern))
4265 .append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((U nicodeString)"|").append(DEREFSTR(fNegSuffixPattern))
4266 .append((UnicodeString)"]->[")
4267 .append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuff ix)
4268 .append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeStri ng)"|").append(fNegativeSuffix)
4269 .append((UnicodeString)"]\n");
4270 debugout(s);
4271 #endif
4272 }
4273
4274 /**
4275 * Expand an affix pattern into an affix string. All characters in the
4276 * pattern are literal unless prefixed by kQuote. The following characters
4277 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
4278 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
4279 * kCurrencySign + kCurrencySign), it is interpreted as an international
4280 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
4281 * currency plural long names, such as "US Dollars".
4282 * Any other character after a kQuote represents itself.
4283 * kQuote must be followed by another character; kQuote may not occur by
4284 * itself at the end of the pattern.
4285 *
4286 * This method is used in two distinct ways. First, it is used to expand
4287 * the stored affix patterns into actual affixes. For this usage, doFormat
4288 * must be false. Second, it is used to expand the stored affix patterns
4289 * given a specific number (doFormat == true), for those rare cases in
4290 * which a currency format references a ChoiceFormat (e.g., en_IN display
4291 * name for INR). The number itself is taken from digitList.
4292 *
4293 * When used in the first way, this method has a side effect: It sets
4294 * currencyChoice to a ChoiceFormat object, if the currency's display name
4295 * in this locale is a ChoiceFormat pattern (very rare). It only does this
4296 * if currencyChoice is null to start with.
4297 *
4298 * @param pattern the non-null, fPossibly empty pattern
4299 * @param affix string to receive the expanded equivalent of pattern.
4300 * Previous contents are deleted.
4301 * @param doFormat if false, then the pattern will be expanded, and if a
4302 * currency symbol is encountered that expands to a ChoiceFormat, the
4303 * currencyChoice member variable will be initialized if it is null. If
4304 * doFormat is true, then it is assumed that the currencyChoice has been
4305 * created, and it will be used to format the value in digitList.
4306 * @param pluralCount the plural count. It is only used for currency
4307 * plural format. In which case, it is the plural
4308 * count of the currency amount. For example,
4309 * in en_US, it is the singular "one", or the plural
4310 * "other". For all other cases, it is null, and
4311 * is not being used.
4312 */
4313 void DecimalFormat::expandAffix(const UnicodeString& pattern,
4314 UnicodeString& affix,
4315 double number,
4316 FieldPositionHandler& handler,
4317 UBool doFormat,
4318 const UnicodeString* pluralCount) const {
4319 affix.remove();
4320 for (int i=0; i<pattern.length(); ) {
4321 UChar32 c = pattern.char32At(i);
4322 i += U16_LENGTH(c);
4323 if (c == kQuote) {
4324 c = pattern.char32At(i);
4325 i += U16_LENGTH(c);
4326 int beginIdx = affix.length();
4327 switch (c) {
4328 case kCurrencySign: {
4329 // As of ICU 2.2 we use the currency object, and
4330 // ignore the currency symbols in the DFS, unless
4331 // we have a null currency object. This occurs if
4332 // resurrecting a pre-2.2 object or if the user
4333 // sets a custom DFS.
4334 UBool intl = i<pattern.length() &&
4335 pattern.char32At(i) == kCurrencySign;
4336 UBool plural = FALSE;
4337 if (intl) {
4338 ++i;
4339 plural = i<pattern.length() &&
4340 pattern.char32At(i) == kCurrencySign;
4341 if (plural) {
4342 intl = FALSE;
4343 ++i;
4344 }
4345 }
4346 const UChar* currencyUChars = getCurrency();
4347 if (currencyUChars[0] != 0) {
4348 UErrorCode ec = U_ZERO_ERROR;
4349 if (plural && pluralCount != NULL) {
4350 // plural name is only needed when pluralCount != null,
4351 // which means when formatting currency plural names.
4352 // For other cases, pluralCount == null,
4353 // and plural names are not needed.
4354 int32_t len;
4355 CharString pluralCountChar;
4356 pluralCountChar.appendInvariantChars(*pluralCount, ec);
4357 UBool isChoiceFormat;
4358 const UChar* s = ucurr_getPluralName(currencyUChars,
4359 fSymbols != NULL ? fSymbols->getLocale().getName() :
4360 Locale::getDefault().getName(), &isChoiceFormat,
4361 pluralCountChar.data(), &len, &ec);
4362 affix += UnicodeString(s, len);
4363 handler.addAttribute(kCurrencyField, beginIdx, affix.len gth());
4364 } else if(intl) {
4365 affix.append(currencyUChars, -1);
4366 handler.addAttribute(kCurrencyField, beginIdx, affix.len gth());
4367 } else {
4368 int32_t len;
4369 UBool isChoiceFormat;
4370 // If fSymbols is NULL, use default locale
4371 const UChar* s = ucurr_getName(currencyUChars,
4372 fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(),
4373 UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
4374 if (isChoiceFormat) {
4375 // Two modes here: If doFormat is false, we set up
4376 // currencyChoice. If doFormat is true, we use the
4377 // previously created currencyChoice to format the
4378 // value in digitList.
4379 if (!doFormat) {
4380 // If the currency is handled by a ChoiceFormat,
4381 // then we're not going to use the expanded
4382 // patterns. Instantiate the ChoiceFormat and
4383 // return.
4384 if (fCurrencyChoice == NULL) {
4385 // TODO Replace double-check with proper thr ead-safe code
4386 ChoiceFormat* fmt = new ChoiceFormat(Unicode String(s), ec);
4387 if (U_SUCCESS(ec)) {
4388 umtx_lock(NULL);
4389 if (fCurrencyChoice == NULL) {
4390 // Cast away const
4391 ((DecimalFormat*)this)->fCurrencyCho ice = fmt;
4392 fmt = NULL;
4393 }
4394 umtx_unlock(NULL);
4395 delete fmt;
4396 }
4397 }
4398 // We could almost return null or "" here, since the
4399 // expanded affixes are almost not used at all
4400 // in this situation. However, one method --
4401 // toPattern() -- still does use the expanded
4402 // affixes, in order to set up a padding
4403 // pattern. We use the CURRENCY_SIGN as a
4404 // placeholder.
4405 affix.append(kCurrencySign);
4406 } else {
4407 if (fCurrencyChoice != NULL) {
4408 FieldPosition pos(0); // ignored
4409 if (number < 0) {
4410 number = -number;
4411 }
4412 fCurrencyChoice->format(number, affix, pos);
4413 } else {
4414 // We only arrive here if the currency choic e
4415 // format in the locale data is INVALID.
4416 affix.append(currencyUChars, -1);
4417 handler.addAttribute(kCurrencyField, beginId x, affix.length());
4418 }
4419 }
4420 continue;
4421 }
4422 affix += UnicodeString(s, len);
4423 handler.addAttribute(kCurrencyField, beginIdx, affix.len gth());
4424 }
4425 } else {
4426 if(intl) {
4427 affix += getConstSymbol(DecimalFormatSymbols::kIntlCurre ncySymbol);
4428 } else {
4429 affix += getConstSymbol(DecimalFormatSymbols::kCurrencyS ymbol);
4430 }
4431 handler.addAttribute(kCurrencyField, beginIdx, affix.length( ));
4432 }
4433 break;
4434 }
4435 case kPatternPercent:
4436 affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
4437 handler.addAttribute(kPercentField, beginIdx, affix.length());
4438 break;
4439 case kPatternPerMill:
4440 affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
4441 handler.addAttribute(kPermillField, beginIdx, affix.length());
4442 break;
4443 case kPatternPlus:
4444 affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
4445 handler.addAttribute(kSignField, beginIdx, affix.length());
4446 break;
4447 case kPatternMinus:
4448 affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
4449 handler.addAttribute(kSignField, beginIdx, affix.length());
4450 break;
4451 default:
4452 affix.append(c);
4453 break;
4454 }
4455 }
4456 else {
4457 affix.append(c);
4458 }
4459 }
4460 }
4461
4462 /**
4463 * Append an affix to the given StringBuffer.
4464 * @param buf buffer to append to
4465 * @param isNegative
4466 * @param isPrefix
4467 */
4468 int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
4469 FieldPositionHandler& handler,
4470 UBool isNegative, UBool isPrefix) const {
4471 // plural format precedes choice format
4472 if (fCurrencyChoice != 0 &&
4473 fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
4474 const UnicodeString* affixPat;
4475 if (isPrefix) {
4476 affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern;
4477 } else {
4478 affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern;
4479 }
4480 if (affixPat) {
4481 UnicodeString affixBuf;
4482 expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL);
4483 buf.append(affixBuf);
4484 return affixBuf.length();
4485 }
4486 // else someone called a function that reset the pattern.
4487 }
4488
4489 const UnicodeString* affix;
4490 if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
4491 // TODO: get an accurate count of visible fraction digits.
4492 UnicodeString pluralCount;
4493 int32_t minFractionDigits = this->getMinimumFractionDigits();
4494 if (minFractionDigits > 0) {
4495 FixedDecimal ni(number, this->getMinimumFractionDigits());
4496 pluralCount = fCurrencyPluralInfo->getPluralRules()->select(ni);
4497 } else {
4498 pluralCount = fCurrencyPluralInfo->getPluralRules()->select(number);
4499 }
4500 AffixesForCurrency* oneSet;
4501 if (fStyle == UNUM_CURRENCY_PLURAL) {
4502 oneSet = (AffixesForCurrency*)fPluralAffixesForCurrency->get(pluralC ount);
4503 } else {
4504 oneSet = (AffixesForCurrency*)fAffixesForCurrency->get(pluralCount);
4505 }
4506 if (isPrefix) {
4507 affix = isNegative ? &oneSet->negPrefixForCurrency :
4508 &oneSet->posPrefixForCurrency;
4509 } else {
4510 affix = isNegative ? &oneSet->negSuffixForCurrency :
4511 &oneSet->posSuffixForCurrency;
4512 }
4513 } else {
4514 if (isPrefix) {
4515 affix = isNegative ? &fNegativePrefix : &fPositivePrefix;
4516 } else {
4517 affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
4518 }
4519 }
4520
4521 int32_t begin = (int) buf.length();
4522
4523 buf.append(*affix);
4524
4525 if (handler.isRecording()) {
4526 int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbol s::kCurrencySymbol));
4527 if (offset > -1) {
4528 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol );
4529 handler.addAttribute(kCurrencyField, begin + offset, begin + offset + af f.length());
4530 }
4531
4532 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntl CurrencySymbol));
4533 if (offset > -1) {
4534 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySy mbol);
4535 handler.addAttribute(kCurrencyField, begin + offset, begin + offset + af f.length());
4536 }
4537
4538 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinu sSignSymbol));
4539 if (offset > -1) {
4540 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbo l);
4541 handler.addAttribute(kSignField, begin + offset, begin + offset + aff.le ngth());
4542 }
4543
4544 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerc entSymbol));
4545 if (offset > -1) {
4546 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol) ;
4547 handler.addAttribute(kPercentField, begin + offset, begin + offset + aff .length());
4548 }
4549
4550 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerM illSymbol));
4551 if (offset > -1) {
4552 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol) ;
4553 handler.addAttribute(kPermillField, begin + offset, begin + offset + aff .length());
4554 }
4555 }
4556 return affix->length();
4557 }
4558
4559 /**
4560 * Appends an affix pattern to the given StringBuffer, quoting special
4561 * characters as needed. Uses the internal affix pattern, if that exists,
4562 * or the literal affix, if the internal affix pattern is null. The
4563 * appended string will generate the same affix pattern (or literal affix)
4564 * when passed to toPattern().
4565 *
4566 * @param appendTo the affix string is appended to this
4567 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
4568 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
4569 * Ignored unless affixPattern is null. If affixPattern is null, then
4570 * expAffix is appended as a literal affix.
4571 * @param localized true if the appended pattern should contain localized
4572 * pattern characters; otherwise, non-localized pattern chars are appended
4573 */
4574 void DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
4575 const UnicodeString* affixPattern,
4576 const UnicodeString& expAffix,
4577 UBool localized) const {
4578 if (affixPattern == 0) {
4579 appendAffixPattern(appendTo, expAffix, localized);
4580 } else {
4581 int i;
4582 for (int pos=0; pos<affixPattern->length(); pos=i) {
4583 i = affixPattern->indexOf(kQuote, pos);
4584 if (i < 0) {
4585 UnicodeString s;
4586 affixPattern->extractBetween(pos, affixPattern->length(), s);
4587 appendAffixPattern(appendTo, s, localized);
4588 break;
4589 }
4590 if (i > pos) {
4591 UnicodeString s;
4592 affixPattern->extractBetween(pos, i, s);
4593 appendAffixPattern(appendTo, s, localized);
4594 }
4595 UChar32 c = affixPattern->char32At(++i);
4596 ++i;
4597 if (c == kQuote) {
4598 appendTo.append(c).append(c);
4599 // Fall through and append another kQuote below
4600 } else if (c == kCurrencySign &&
4601 i<affixPattern->length() &&
4602 affixPattern->char32At(i) == kCurrencySign) {
4603 ++i;
4604 appendTo.append(c).append(c);
4605 } else if (localized) {
4606 switch (c) {
4607 case kPatternPercent:
4608 appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSym bol);
4609 break;
4610 case kPatternPerMill:
4611 appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSym bol);
4612 break;
4613 case kPatternPlus:
4614 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSy mbol);
4615 break;
4616 case kPatternMinus:
4617 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignS ymbol);
4618 break;
4619 default:
4620 appendTo.append(c);
4621 }
4622 } else {
4623 appendTo.append(c);
4624 }
4625 }
4626 }
4627 }
4628
4629 /**
4630 * Append an affix to the given StringBuffer, using quotes if
4631 * there are special characters. Single quotes themselves must be
4632 * escaped in either case.
4633 */
4634 void
4635 DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
4636 const UnicodeString& affix,
4637 UBool localized) const {
4638 UBool needQuote;
4639 if(localized) {
4640 needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigi tSymbol)) >= 0
4641 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSepar atorSymbol)) >= 0
4642 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSepara torSymbol)) >= 0
4643 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol )) >= 0
4644 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol )) >= 0
4645 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0
4646 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSepara torSymbol)) >= 0
4647 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbo l)) >= 0
4648 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymb ol)) >= 0
4649 || affix.indexOf(kCurrencySign) >= 0;
4650 }
4651 else {
4652 needQuote = affix.indexOf(kPatternZeroDigit) >= 0
4653 || affix.indexOf(kPatternGroupingSeparator) >= 0
4654 || affix.indexOf(kPatternDecimalSeparator) >= 0
4655 || affix.indexOf(kPatternPercent) >= 0
4656 || affix.indexOf(kPatternPerMill) >= 0
4657 || affix.indexOf(kPatternDigit) >= 0
4658 || affix.indexOf(kPatternSeparator) >= 0
4659 || affix.indexOf(kPatternExponent) >= 0
4660 || affix.indexOf(kPatternPlus) >= 0
4661 || affix.indexOf(kPatternMinus) >= 0
4662 || affix.indexOf(kCurrencySign) >= 0;
4663 }
4664 if (needQuote)
4665 appendTo += (UChar)0x0027 /*'\''*/;
4666 if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0)
4667 appendTo += affix;
4668 else {
4669 for (int32_t j = 0; j < affix.length(); ) {
4670 UChar32 c = affix.char32At(j);
4671 j += U16_LENGTH(c);
4672 appendTo += c;
4673 if (c == 0x0027 /*'\''*/)
4674 appendTo += c;
4675 }
4676 }
4677 if (needQuote)
4678 appendTo += (UChar)0x0027 /*'\''*/;
4679 }
4680
4681 //------------------------------------------------------------------------------
4682
4683 UnicodeString&
4684 DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
4685 {
4686 if (fStyle == UNUM_CURRENCY_PLURAL) {
4687 // the prefix or suffix pattern might not be defined yet,
4688 // so they can not be synthesized,
4689 // instead, get them directly.
4690 // but it might not be the actual pattern used in formatting.
4691 // the actual pattern used in formatting depends on the
4692 // formatted number's plural count.
4693 result = fFormatPattern;
4694 return result;
4695 }
4696 result.remove();
4697 UChar32 zero, sigDigit = kPatternSignificantDigit;
4698 UnicodeString digit, group;
4699 int32_t i;
4700 int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits
4701 UnicodeString roundingDigits;
4702 int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1;
4703 UnicodeString padSpec;
4704 UBool useSigDig = areSignificantDigitsUsed();
4705
4706 if (localized) {
4707 digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
4708 group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymb ol));
4709 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0 );
4710 if (useSigDig) {
4711 sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSym bol).char32At(0);
4712 }
4713 }
4714 else {
4715 digit.append((UChar)kPatternDigit);
4716 group.append((UChar)kPatternGroupingSeparator);
4717 zero = (UChar32)kPatternZeroDigit;
4718 }
4719 if (fFormatWidth > 0) {
4720 if (localized) {
4721 padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol ));
4722 }
4723 else {
4724 padSpec.append((UChar)kPatternPadEscape);
4725 }
4726 padSpec.append(fPad);
4727 }
4728 if (fRoundingIncrement != NULL) {
4729 for(i=0; i<fRoundingIncrement->getCount(); ++i) {
4730 roundingDigits.append(zero+(fRoundingIncrement->getDigitValue(i))); // Convert to Unicode digit
4731 }
4732 roundingDecimalPos = fRoundingIncrement->getDecimalAt();
4733 }
4734 for (int32_t part=0; part<2; ++part) {
4735 if (padPos == kPadBeforePrefix) {
4736 result.append(padSpec);
4737 }
4738 appendAffixPattern(result,
4739 (part==0 ? fPosPrefixPattern : fNegPrefixPattern),
4740 (part==0 ? fPositivePrefix : fNegativePrefix),
4741 localized);
4742 if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) {
4743 result.append(padSpec);
4744 }
4745 int32_t sub0Start = result.length();
4746 int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0;
4747 if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
4748 g += fGroupingSize2;
4749 }
4750 int32_t maxDig = 0, minDig = 0, maxSigDig = 0;
4751 if (useSigDig) {
4752 minDig = getMinimumSignificantDigits();
4753 maxDig = maxSigDig = getMaximumSignificantDigits();
4754 } else {
4755 minDig = getMinimumIntegerDigits();
4756 maxDig = getMaximumIntegerDigits();
4757 }
4758 if (fUseExponentialNotation) {
4759 if (maxDig > kMaxScientificIntegerDigits) {
4760 maxDig = 1;
4761 }
4762 } else if (useSigDig) {
4763 maxDig = _max(maxDig, g+1);
4764 } else {
4765 maxDig = _max(_max(g, getMinimumIntegerDigits()),
4766 roundingDecimalPos) + 1;
4767 }
4768 for (i = maxDig; i > 0; --i) {
4769 if (!fUseExponentialNotation && i<maxDig &&
4770 isGroupingPosition(i)) {
4771 result.append(group);
4772 }
4773 if (useSigDig) {
4774 // #@,@### (maxSigDig == 5, minSigDig == 2)
4775 // 65 4321 (1-based pos, count from the right)
4776 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDi g)
4777 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
4778 if (maxSigDig >= i && i > (maxSigDig - minDig)) {
4779 result.append(sigDigit);
4780 } else {
4781 result.append(digit);
4782 }
4783 } else {
4784 if (! roundingDigits.isEmpty()) {
4785 int32_t pos = roundingDecimalPos - i;
4786 if (pos >= 0 && pos < roundingDigits.length()) {
4787 result.append((UChar) (roundingDigits.char32At(pos) - kP atternZeroDigit + zero));
4788 continue;
4789 }
4790 }
4791 if (i<=minDig) {
4792 result.append(zero);
4793 } else {
4794 result.append(digit);
4795 }
4796 }
4797 }
4798 if (!useSigDig) {
4799 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) {
4800 if (localized) {
4801 result += getConstSymbol(DecimalFormatSymbols::kDecimalSepar atorSymbol);
4802 }
4803 else {
4804 result.append((UChar)kPatternDecimalSeparator);
4805 }
4806 }
4807 int32_t pos = roundingDecimalPos;
4808 for (i = 0; i < getMaximumFractionDigits(); ++i) {
4809 if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) {
4810 if (pos < 0) {
4811 result.append(zero);
4812 }
4813 else {
4814 result.append((UChar)(roundingDigits.char32At(pos) - kPa tternZeroDigit + zero));
4815 }
4816 ++pos;
4817 continue;
4818 }
4819 if (i<getMinimumFractionDigits()) {
4820 result.append(zero);
4821 }
4822 else {
4823 result.append(digit);
4824 }
4825 }
4826 }
4827 if (fUseExponentialNotation) {
4828 if (localized) {
4829 result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbo l);
4830 }
4831 else {
4832 result.append((UChar)kPatternExponent);
4833 }
4834 if (fExponentSignAlwaysShown) {
4835 if (localized) {
4836 result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymb ol);
4837 }
4838 else {
4839 result.append((UChar)kPatternPlus);
4840 }
4841 }
4842 for (i=0; i<fMinExponentDigits; ++i) {
4843 result.append(zero);
4844 }
4845 }
4846 if (! padSpec.isEmpty() && !fUseExponentialNotation) {
4847 int32_t add = fFormatWidth - result.length() + sub0Start
4848 - ((part == 0)
4849 ? fPositivePrefix.length() + fPositiveSuffix.length()
4850 : fNegativePrefix.length() + fNegativeSuffix.length());
4851 while (add > 0) {
4852 result.insert(sub0Start, digit);
4853 ++maxDig;
4854 --add;
4855 // Only add a grouping separator if we have at least
4856 // 2 additional characters to be added, so we don't
4857 // end up with ",###".
4858 if (add>1 && isGroupingPosition(maxDig)) {
4859 result.insert(sub0Start, group);
4860 --add;
4861 }
4862 }
4863 }
4864 if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) {
4865 result.append(padSpec);
4866 }
4867 if (part == 0) {
4868 appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, local ized);
4869 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
4870 result.append(padSpec);
4871 }
4872 UBool isDefault = FALSE;
4873 if ((fNegSuffixPattern == fPosSuffixPattern && // both null
4874 fNegativeSuffix == fPositiveSuffix)
4875 || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 &&
4876 *fNegSuffixPattern == *fPosSuffixPattern))
4877 {
4878 if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL)
4879 {
4880 int32_t length = fPosPrefixPattern->length();
4881 isDefault = fNegPrefixPattern->length() == (length+2) &&
4882 (*fNegPrefixPattern)[(int32_t)0] == kQuote &&
4883 (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus &&
4884 fNegPrefixPattern->compare(2, length, *fPosPrefixPattern , 0, length) == 0;
4885 }
4886 if (!isDefault &&
4887 fNegPrefixPattern == NULL && fPosPrefixPattern == NULL)
4888 {
4889 int32_t length = fPositivePrefix.length();
4890 isDefault = fNegativePrefix.length() == (length+1) &&
4891 fNegativePrefix.compare(getConstSymbol(DecimalFormatSymb ols::kMinusSignSymbol)) == 0 &&
4892 fNegativePrefix.compare(1, length, fPositivePrefix, 0, l ength) == 0;
4893 }
4894 }
4895 if (isDefault) {
4896 break; // Don't output default negative subpattern
4897 } else {
4898 if (localized) {
4899 result += getConstSymbol(DecimalFormatSymbols::kPatternSepar atorSymbol);
4900 }
4901 else {
4902 result.append((UChar)kPatternSeparator);
4903 }
4904 }
4905 } else {
4906 appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, local ized);
4907 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
4908 result.append(padSpec);
4909 }
4910 }
4911 }
4912
4913 return result;
4914 }
4915
4916 //------------------------------------------------------------------------------
4917 2814
4918 void 2815 void
4919 DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) 2816 DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
4920 { 2817 {
4921 UParseError parseError; 2818 fImpl->applyPattern(pattern, status);
4922 applyPattern(pattern, FALSE, parseError, status);
4923 } 2819 }
4924 2820
4925 //------------------------------------------------------------------------------ 2821 //------------------------------------------------------------------------------
4926 2822
4927 void 2823 void
4928 DecimalFormat::applyPattern(const UnicodeString& pattern, 2824 DecimalFormat::applyPattern(const UnicodeString& pattern,
4929 UParseError& parseError, 2825 UParseError& parseError,
4930 UErrorCode& status) 2826 UErrorCode& status)
4931 { 2827 {
4932 applyPattern(pattern, FALSE, parseError, status); 2828 fImpl->applyPattern(pattern, parseError, status);
4933 } 2829 }
4934 //------------------------------------------------------------------------------ 2830 //------------------------------------------------------------------------------
4935 2831
4936 void 2832 void
4937 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& s tatus) 2833 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& s tatus)
4938 { 2834 {
4939 UParseError parseError; 2835 fImpl->applyLocalizedPattern(pattern, status);
4940 applyPattern(pattern, TRUE,parseError,status);
4941 } 2836 }
4942 2837
4943 //------------------------------------------------------------------------------ 2838 //------------------------------------------------------------------------------
4944 2839
4945 void 2840 void
4946 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, 2841 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
4947 UParseError& parseError, 2842 UParseError& parseError,
4948 UErrorCode& status) 2843 UErrorCode& status)
4949 { 2844 {
4950 applyPattern(pattern, TRUE,parseError,status); 2845 fImpl->applyLocalizedPattern(pattern, parseError, status);
4951 } 2846 }
4952 2847
4953 //------------------------------------------------------------------------------ 2848 //------------------------------------------------------------------------------
4954 2849
4955 void
4956 DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern,
4957 UBool localized,
4958 UParseError& parseError,
4959 UErrorCode& status)
4960 {
4961 if (U_FAILURE(status))
4962 {
4963 return;
4964 }
4965 DecimalFormatPatternParser patternParser;
4966 if (localized) {
4967 patternParser.useSymbols(*fSymbols);
4968 }
4969 fFormatPattern = pattern;
4970 DecimalFormatPattern out;
4971 patternParser.applyPatternWithoutExpandAffix(
4972 pattern,
4973 out,
4974 parseError,
4975 status);
4976 if (U_FAILURE(status)) {
4977 return;
4978 }
4979
4980 setMinimumIntegerDigits(out.fMinimumIntegerDigits);
4981 setMaximumIntegerDigits(out.fMaximumIntegerDigits);
4982 setMinimumFractionDigits(out.fMinimumFractionDigits);
4983 setMaximumFractionDigits(out.fMaximumFractionDigits);
4984 setSignificantDigitsUsed(out.fUseSignificantDigits);
4985 if (out.fUseSignificantDigits) {
4986 setMinimumSignificantDigits(out.fMinimumSignificantDigits);
4987 setMaximumSignificantDigits(out.fMaximumSignificantDigits);
4988 }
4989 fUseExponentialNotation = out.fUseExponentialNotation;
4990 if (out.fUseExponentialNotation) {
4991 fMinExponentDigits = out.fMinExponentDigits;
4992 }
4993 fExponentSignAlwaysShown = out.fExponentSignAlwaysShown;
4994 fCurrencySignCount = out.fCurrencySignCount;
4995 setGroupingUsed(out.fGroupingUsed);
4996 if (out.fGroupingUsed) {
4997 fGroupingSize = out.fGroupingSize;
4998 fGroupingSize2 = out.fGroupingSize2;
4999 }
5000 setMultiplier(out.fMultiplier);
5001 fDecimalSeparatorAlwaysShown = out.fDecimalSeparatorAlwaysShown;
5002 fFormatWidth = out.fFormatWidth;
5003 if (out.fRoundingIncrementUsed) {
5004 if (fRoundingIncrement != NULL) {
5005 *fRoundingIncrement = out.fRoundingIncrement;
5006 } else {
5007 fRoundingIncrement = new DigitList(out.fRoundingIncrement);
5008 /* test for NULL */
5009 if (fRoundingIncrement == NULL) {
5010 status = U_MEMORY_ALLOCATION_ERROR;
5011 return;
5012 }
5013 }
5014 } else {
5015 setRoundingIncrement(0.0);
5016 }
5017 fPad = out.fPad;
5018 switch (out.fPadPosition) {
5019 case DecimalFormatPattern::kPadBeforePrefix:
5020 fPadPosition = kPadBeforePrefix;
5021 break;
5022 case DecimalFormatPattern::kPadAfterPrefix:
5023 fPadPosition = kPadAfterPrefix;
5024 break;
5025 case DecimalFormatPattern::kPadBeforeSuffix:
5026 fPadPosition = kPadBeforeSuffix;
5027 break;
5028 case DecimalFormatPattern::kPadAfterSuffix:
5029 fPadPosition = kPadAfterSuffix;
5030 break;
5031 }
5032 copyString(out.fNegPrefixPattern, out.fNegPatternsBogus, fNegPrefixPattern, status);
5033 copyString(out.fNegSuffixPattern, out.fNegPatternsBogus, fNegSuffixPattern, status);
5034 copyString(out.fPosPrefixPattern, out.fPosPatternsBogus, fPosPrefixPattern, status);
5035 copyString(out.fPosSuffixPattern, out.fPosPatternsBogus, fPosSuffixPattern, status);
5036 }
5037
5038
5039 void
5040 DecimalFormat::expandAffixAdjustWidth(const UnicodeString* pluralCount) {
5041 expandAffixes(pluralCount);
5042 if (fFormatWidth > 0) {
5043 // Finish computing format width (see above)
5044 // TODO: how to handle fFormatWidth,
5045 // need to save in f(Plural)AffixesForCurrecy?
5046 fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length();
5047 }
5048 }
5049
5050
5051 void
5052 DecimalFormat::applyPattern(const UnicodeString& pattern,
5053 UBool localized,
5054 UParseError& parseError,
5055 UErrorCode& status)
5056 {
5057 // do the following re-set first. since they change private data by
5058 // apply pattern again.
5059 if (pattern.indexOf(kCurrencySign) != -1) {
5060 if (fCurrencyPluralInfo == NULL) {
5061 // initialize currencyPluralInfo if needed
5062 fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
5063 }
5064 if (fAffixPatternsForCurrency == NULL) {
5065 setupCurrencyAffixPatterns(status);
5066 }
5067 if (pattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) {
5068 // only setup the affixes of the current pattern.
5069 setupCurrencyAffixes(pattern, TRUE, FALSE, status);
5070 }
5071 }
5072 applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
5073 expandAffixAdjustWidth(NULL);
5074 #if UCONFIG_FORMAT_FASTPATHS_49
5075 handleChanged();
5076 #endif
5077 }
5078
5079
5080 void
5081 DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount,
5082 const UnicodeString& pattern,
5083 UBool localized,
5084 UParseError& parseError,
5085 UErrorCode& status) {
5086 applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
5087 expandAffixAdjustWidth(&pluralCount);
5088 #if UCONFIG_FORMAT_FASTPATHS_49
5089 handleChanged();
5090 #endif
5091 }
5092
5093
5094 /** 2850 /**
5095 * Sets the maximum number of digits allowed in the integer portion of a 2851 * Sets the maximum number of digits allowed in the integer portion of a
5096 * number. 2852 * number.
5097 * @see NumberFormat#setMaximumIntegerDigits 2853 * @see NumberFormat#setMaximumIntegerDigits
5098 */ 2854 */
5099 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) { 2855 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
5100 NumberFormat::setMaximumIntegerDigits(_min(newValue, gDefaultMaxIntegerDigit s)); 2856 newValue = _min(newValue, gDefaultMaxIntegerDigits);
5101 #if UCONFIG_FORMAT_FASTPATHS_49 2857 NumberFormat::setMaximumIntegerDigits(newValue);
5102 handleChanged(); 2858 fImpl->updatePrecision();
5103 #endif
5104 } 2859 }
5105 2860
5106 /** 2861 /**
5107 * Sets the minimum number of digits allowed in the integer portion of a 2862 * Sets the minimum number of digits allowed in the integer portion of a
5108 * number. This override limits the integer digit count to 309. 2863 * number. This override limits the integer digit count to 309.
5109 * @see NumberFormat#setMinimumIntegerDigits 2864 * @see NumberFormat#setMinimumIntegerDigits
5110 */ 2865 */
5111 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) { 2866 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
5112 NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits)); 2867 newValue = _min(newValue, kDoubleIntegerDigits);
5113 #if UCONFIG_FORMAT_FASTPATHS_49 2868 NumberFormat::setMinimumIntegerDigits(newValue);
5114 handleChanged(); 2869 fImpl->updatePrecision();
5115 #endif
5116 } 2870 }
5117 2871
5118 /** 2872 /**
5119 * Sets the maximum number of digits allowed in the fraction portion of a 2873 * Sets the maximum number of digits allowed in the fraction portion of a
5120 * number. This override limits the fraction digit count to 340. 2874 * number. This override limits the fraction digit count to 340.
5121 * @see NumberFormat#setMaximumFractionDigits 2875 * @see NumberFormat#setMaximumFractionDigits
5122 */ 2876 */
5123 void DecimalFormat::setMaximumFractionDigits(int32_t newValue) { 2877 void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
5124 NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits) ); 2878 newValue = _min(newValue, kDoubleFractionDigits);
5125 #if UCONFIG_FORMAT_FASTPATHS_49 2879 NumberFormat::setMaximumFractionDigits(newValue);
5126 handleChanged(); 2880 fImpl->updatePrecision();
5127 #endif
5128 } 2881 }
5129 2882
5130 /** 2883 /**
5131 * Sets the minimum number of digits allowed in the fraction portion of a 2884 * Sets the minimum number of digits allowed in the fraction portion of a
5132 * number. This override limits the fraction digit count to 340. 2885 * number. This override limits the fraction digit count to 340.
5133 * @see NumberFormat#setMinimumFractionDigits 2886 * @see NumberFormat#setMinimumFractionDigits
5134 */ 2887 */
5135 void DecimalFormat::setMinimumFractionDigits(int32_t newValue) { 2888 void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
5136 NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits) ); 2889 newValue = _min(newValue, kDoubleFractionDigits);
5137 #if UCONFIG_FORMAT_FASTPATHS_49 2890 NumberFormat::setMinimumFractionDigits(newValue);
5138 handleChanged(); 2891 fImpl->updatePrecision();
5139 #endif
5140 } 2892 }
5141 2893
5142 int32_t DecimalFormat::getMinimumSignificantDigits() const { 2894 int32_t DecimalFormat::getMinimumSignificantDigits() const {
5143 return fMinSignificantDigits; 2895 return fImpl->getMinimumSignificantDigits();
5144 } 2896 }
5145 2897
5146 int32_t DecimalFormat::getMaximumSignificantDigits() const { 2898 int32_t DecimalFormat::getMaximumSignificantDigits() const {
5147 return fMaxSignificantDigits; 2899 return fImpl->getMaximumSignificantDigits();
5148 } 2900 }
5149 2901
5150 void DecimalFormat::setMinimumSignificantDigits(int32_t min) { 2902 void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
5151 if (min < 1) { 2903 if (min < 1) {
5152 min = 1; 2904 min = 1;
5153 } 2905 }
5154 // pin max sig dig to >= min 2906 // pin max sig dig to >= min
5155 int32_t max = _max(fMaxSignificantDigits, min); 2907 int32_t max = _max(fImpl->fMaxSigDigits, min);
5156 fMinSignificantDigits = min; 2908 fImpl->setMinMaxSignificantDigits(min, max);
5157 fMaxSignificantDigits = max;
5158 fUseSignificantDigits = TRUE;
5159 #if UCONFIG_FORMAT_FASTPATHS_49
5160 handleChanged();
5161 #endif
5162 } 2909 }
5163 2910
5164 void DecimalFormat::setMaximumSignificantDigits(int32_t max) { 2911 void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
5165 if (max < 1) { 2912 if (max < 1) {
5166 max = 1; 2913 max = 1;
5167 } 2914 }
5168 // pin min sig dig to 1..max 2915 // pin min sig dig to 1..max
5169 U_ASSERT(fMinSignificantDigits >= 1); 2916 U_ASSERT(fImpl->fMinSigDigits >= 1);
5170 int32_t min = _min(fMinSignificantDigits, max); 2917 int32_t min = _min(fImpl->fMinSigDigits, max);
5171 fMinSignificantDigits = min; 2918 fImpl->setMinMaxSignificantDigits(min, max);
5172 fMaxSignificantDigits = max;
5173 fUseSignificantDigits = TRUE;
5174 #if UCONFIG_FORMAT_FASTPATHS_49
5175 handleChanged();
5176 #endif
5177 } 2919 }
5178 2920
5179 UBool DecimalFormat::areSignificantDigitsUsed() const { 2921 UBool DecimalFormat::areSignificantDigitsUsed() const {
5180 return fUseSignificantDigits; 2922 return fImpl->areSignificantDigitsUsed();
5181 } 2923 }
5182 2924
5183 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) { 2925 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
5184 fUseSignificantDigits = useSignificantDigits; 2926 fImpl->setSignificantDigitsUsed(useSignificantDigits);
5185 #if UCONFIG_FORMAT_FASTPATHS_49
5186 handleChanged();
5187 #endif
5188 }
5189
5190 void DecimalFormat::setCurrencyInternally(const UChar* theCurrency,
5191 UErrorCode& ec) {
5192 // If we are a currency format, then modify our affixes to
5193 // encode the currency symbol for the given currency in our
5194 // locale, and adjust the decimal digits and rounding for the
5195 // given currency.
5196
5197 // Note: The code is ordered so that this object is *not changed*
5198 // until we are sure we are going to succeed.
5199
5200 // NULL or empty currency is *legal* and indicates no currency.
5201 UBool isCurr = (theCurrency && *theCurrency);
5202
5203 double rounding = 0.0;
5204 int32_t frac = 0;
5205 if (fCurrencySignCount != fgCurrencySignCountZero && isCurr) {
5206 rounding = ucurr_getRoundingIncrementForUsage(theCurrency, fCurrencyUsag e, &ec);
5207 frac = ucurr_getDefaultFractionDigitsForUsage(theCurrency, fCurrencyUsag e, &ec);
5208 }
5209
5210 NumberFormat::setCurrency(theCurrency, ec);
5211 if (U_FAILURE(ec)) return;
5212
5213 if (fCurrencySignCount != fgCurrencySignCountZero) {
5214 // NULL or empty currency is *legal* and indicates no currency.
5215 if (isCurr) {
5216 setRoundingIncrement(rounding);
5217 setMinimumFractionDigits(frac);
5218 setMaximumFractionDigits(frac);
5219 }
5220 expandAffixes(NULL);
5221 }
5222 #if UCONFIG_FORMAT_FASTPATHS_49
5223 handleChanged();
5224 #endif
5225 } 2927 }
5226 2928
5227 void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { 2929 void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
5228 // set the currency before compute affixes to get the right currency names 2930 // set the currency before compute affixes to get the right currency names
5229 NumberFormat::setCurrency(theCurrency, ec); 2931 NumberFormat::setCurrency(theCurrency, ec);
5230 if (fFormatPattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) { 2932 fImpl->updateCurrency(ec);
5231 UnicodeString savedPtn = fFormatPattern;
5232 setupCurrencyAffixes(fFormatPattern, TRUE, TRUE, ec);
5233 UParseError parseErr;
5234 applyPattern(savedPtn, FALSE, parseErr, ec);
5235 }
5236 // set the currency after apply pattern to get the correct rounding/fraction
5237 setCurrencyInternally(theCurrency, ec);
5238 #if UCONFIG_FORMAT_FASTPATHS_49
5239 handleChanged();
5240 #endif
5241 } 2933 }
5242 2934
5243 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){ 2935 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){
5244 fCurrencyUsage = newContext; 2936 fImpl->setCurrencyUsage(newContext, *ec);
5245
5246 const UChar* theCurrency = getCurrency();
5247
5248 // We set rounding/digit based on currency context
5249 if(theCurrency){
5250 double rounding = ucurr_getRoundingIncrementForUsage(theCurrency, fCurre ncyUsage, ec);
5251 int32_t frac = ucurr_getDefaultFractionDigitsForUsage(theCurrency, fCurr encyUsage, ec);
5252
5253 if (U_SUCCESS(*ec)) {
5254 setRoundingIncrement(rounding);
5255 setMinimumFractionDigits(frac);
5256 setMaximumFractionDigits(frac);
5257 }
5258 }
5259 } 2937 }
5260 2938
5261 UCurrencyUsage DecimalFormat::getCurrencyUsage() const { 2939 UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
5262 return fCurrencyUsage; 2940 return fImpl->getCurrencyUsage();
5263 } 2941 }
5264 2942
5265 // Deprecated variant with no UErrorCode parameter 2943 // Deprecated variant with no UErrorCode parameter
5266 void DecimalFormat::setCurrency(const UChar* theCurrency) { 2944 void DecimalFormat::setCurrency(const UChar* theCurrency) {
5267 UErrorCode ec = U_ZERO_ERROR; 2945 UErrorCode ec = U_ZERO_ERROR;
5268 setCurrency(theCurrency, ec); 2946 setCurrency(theCurrency, ec);
5269 #if UCONFIG_FORMAT_FASTPATHS_49
5270 handleChanged();
5271 #endif
5272 } 2947 }
5273 2948
5274 void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { 2949 void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
5275 if (fSymbols == NULL) { 2950 if (fImpl->fSymbols == NULL) {
5276 ec = U_MEMORY_ALLOCATION_ERROR; 2951 ec = U_MEMORY_ALLOCATION_ERROR;
5277 return; 2952 return;
5278 } 2953 }
5279 ec = U_ZERO_ERROR; 2954 ec = U_ZERO_ERROR;
5280 const UChar* c = getCurrency(); 2955 const UChar* c = getCurrency();
5281 if (*c == 0) { 2956 if (*c == 0) {
5282 const UnicodeString &intl = 2957 const UnicodeString &intl =
5283 fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 2958 fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
5284 c = intl.getBuffer(); // ok for intl to go out of scope 2959 c = intl.getBuffer(); // ok for intl to go out of scope
5285 } 2960 }
5286 u_strncpy(result, c, 3); 2961 u_strncpy(result, c, 3);
5287 result[3] = 0; 2962 result[3] = 0;
5288 } 2963 }
5289 2964
5290 /**
5291 * Return the number of fraction digits to display, or the total
5292 * number of digits for significant digit formats and exponential
5293 * formats.
5294 */
5295 int32_t
5296 DecimalFormat::precision() const {
5297 if (areSignificantDigitsUsed()) {
5298 return getMaximumSignificantDigits();
5299 } else if (fUseExponentialNotation) {
5300 return getMinimumIntegerDigits() + getMaximumFractionDigits();
5301 } else {
5302 return getMaximumFractionDigits();
5303 }
5304 }
5305
5306
5307 // TODO: template algorithm
5308 Hashtable*
5309 DecimalFormat::initHashForAffix(UErrorCode& status) {
5310 if ( U_FAILURE(status) ) {
5311 return NULL;
5312 }
5313 Hashtable* hTable;
5314 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
5315 status = U_MEMORY_ALLOCATION_ERROR;
5316 return NULL;
5317 }
5318 if ( U_FAILURE(status) ) {
5319 delete hTable;
5320 return NULL;
5321 }
5322 hTable->setValueComparator(decimfmtAffixValueComparator);
5323 return hTable;
5324 }
5325
5326 Hashtable* 2965 Hashtable*
5327 DecimalFormat::initHashForAffixPattern(UErrorCode& status) { 2966 DecimalFormat::initHashForAffixPattern(UErrorCode& status) {
5328 if ( U_FAILURE(status) ) { 2967 if ( U_FAILURE(status) ) {
5329 return NULL; 2968 return NULL;
5330 } 2969 }
5331 Hashtable* hTable; 2970 Hashtable* hTable;
5332 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 2971 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
5333 status = U_MEMORY_ALLOCATION_ERROR; 2972 status = U_MEMORY_ALLOCATION_ERROR;
5334 return NULL; 2973 return NULL;
5335 } 2974 }
5336 if ( U_FAILURE(status) ) { 2975 if ( U_FAILURE(status) ) {
5337 delete hTable; 2976 delete hTable;
5338 return NULL; 2977 return NULL;
5339 } 2978 }
5340 hTable->setValueComparator(decimfmtAffixPatternValueComparator); 2979 hTable->setValueComparator(decimfmtAffixPatternValueComparator);
5341 return hTable; 2980 return hTable;
5342 } 2981 }
5343 2982
5344 void 2983 void
5345 DecimalFormat::deleteHashForAffix(Hashtable*& table)
5346 {
5347 if ( table == NULL ) {
5348 return;
5349 }
5350 int32_t pos = -1;
5351 const UHashElement* element = NULL;
5352 while ( (element = table->nextElement(pos)) != NULL ) {
5353 const UHashTok valueTok = element->value;
5354 const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer;
5355 delete value;
5356 }
5357 delete table;
5358 table = NULL;
5359 }
5360
5361
5362
5363 void
5364 DecimalFormat::deleteHashForAffixPattern() 2984 DecimalFormat::deleteHashForAffixPattern()
5365 { 2985 {
5366 if ( fAffixPatternsForCurrency == NULL ) { 2986 if ( fAffixPatternsForCurrency == NULL ) {
5367 return; 2987 return;
5368 } 2988 }
5369 int32_t pos = -1; 2989 int32_t pos = UHASH_FIRST;
5370 const UHashElement* element = NULL; 2990 const UHashElement* element = NULL;
5371 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 2991 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
5372 const UHashTok valueTok = element->value; 2992 const UHashTok valueTok = element->value;
5373 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)value Tok.pointer; 2993 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)value Tok.pointer;
5374 delete value; 2994 delete value;
5375 } 2995 }
5376 delete fAffixPatternsForCurrency; 2996 delete fAffixPatternsForCurrency;
5377 fAffixPatternsForCurrency = NULL; 2997 fAffixPatternsForCurrency = NULL;
5378 } 2998 }
5379 2999
5380 3000
5381 void 3001 void
5382 DecimalFormat::copyHashForAffixPattern(const Hashtable* source, 3002 DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
5383 Hashtable* target, 3003 Hashtable* target,
5384 UErrorCode& status) { 3004 UErrorCode& status) {
5385 if ( U_FAILURE(status) ) { 3005 if ( U_FAILURE(status) ) {
5386 return; 3006 return;
5387 } 3007 }
5388 int32_t pos = -1; 3008 int32_t pos = UHASH_FIRST;
5389 const UHashElement* element = NULL; 3009 const UHashElement* element = NULL;
5390 if ( source ) { 3010 if ( source ) {
5391 while ( (element = source->nextElement(pos)) != NULL ) { 3011 while ( (element = source->nextElement(pos)) != NULL ) {
5392 const UHashTok keyTok = element->key; 3012 const UHashTok keyTok = element->key;
5393 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 3013 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
5394 const UHashTok valueTok = element->value; 3014 const UHashTok valueTok = element->value;
5395 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)v alueTok.pointer; 3015 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)v alueTok.pointer;
5396 AffixPatternsForCurrency* copy = new AffixPatternsForCurrency( 3016 AffixPatternsForCurrency* copy = new AffixPatternsForCurrency(
5397 value->negPrefixPatternForCurrency, 3017 value->negPrefixPatternForCurrency,
5398 value->negSuffixPatternForCurrency, 3018 value->negSuffixPatternForCurrency,
5399 value->posPrefixPatternForCurrency, 3019 value->posPrefixPatternForCurrency,
5400 value->posSuffixPatternForCurrency, 3020 value->posSuffixPatternForCurrency,
5401 value->patternType); 3021 value->patternType);
5402 target->put(UnicodeString(*key), copy, status); 3022 target->put(UnicodeString(*key), copy, status);
5403 if ( U_FAILURE(status) ) { 3023 if ( U_FAILURE(status) ) {
5404 return; 3024 return;
5405 } 3025 }
5406 } 3026 }
5407 } 3027 }
5408 } 3028 }
5409 3029
5410 // this is only overridden to call handleChanged() for fastpath purposes.
5411 void 3030 void
5412 DecimalFormat::setGroupingUsed(UBool newValue) { 3031 DecimalFormat::setGroupingUsed(UBool newValue) {
5413 NumberFormat::setGroupingUsed(newValue); 3032 NumberFormat::setGroupingUsed(newValue);
5414 handleChanged(); 3033 fImpl->updateGrouping();
5415 } 3034 }
5416 3035
5417 // this is only overridden to call handleChanged() for fastpath purposes.
5418 void 3036 void
5419 DecimalFormat::setParseIntegerOnly(UBool newValue) { 3037 DecimalFormat::setParseIntegerOnly(UBool newValue) {
5420 NumberFormat::setParseIntegerOnly(newValue); 3038 NumberFormat::setParseIntegerOnly(newValue);
5421 handleChanged();
5422 } 3039 }
5423 3040
5424 // this is only overridden to call handleChanged() for fastpath purposes.
5425 // setContext doesn't affect the fastPath right now, but this is called for comp leteness
5426 void 3041 void
5427 DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) { 3042 DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {
5428 NumberFormat::setContext(value, status); 3043 NumberFormat::setContext(value, status);
5429 handleChanged();
5430 } 3044 }
5431 3045
5432
5433 DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, 3046 DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
5434 int32_t newValue, 3047 int32_t newValue,
5435 UErrorCode &status) { 3048 UErrorCode &status) {
5436 if(U_FAILURE(status)) return *this; 3049 if(U_FAILURE(status)) return *this;
5437 3050
5438 switch(attr) { 3051 switch(attr) {
5439 case UNUM_LENIENT_PARSE: 3052 case UNUM_LENIENT_PARSE:
5440 setLenient(newValue!=0); 3053 setLenient(newValue!=0);
5441 break; 3054 break;
5442 3055
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
5521 break; 3134 break;
5522 #endif 3135 #endif
5523 3136
5524 /* These are stored in fBoolFlags */ 3137 /* These are stored in fBoolFlags */
5525 case UNUM_PARSE_NO_EXPONENT: 3138 case UNUM_PARSE_NO_EXPONENT:
5526 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 3139 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
5527 case UNUM_PARSE_DECIMAL_MARK_REQUIRED: 3140 case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
5528 if(!fBoolFlags.isValidValue(newValue)) { 3141 if(!fBoolFlags.isValidValue(newValue)) {
5529 status = U_ILLEGAL_ARGUMENT_ERROR; 3142 status = U_ILLEGAL_ARGUMENT_ERROR;
5530 } else { 3143 } else {
3144 if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) {
3145 fImpl->setFailIfMoreThanMaxDigits((UBool) newValue);
3146 }
5531 fBoolFlags.set(attr, newValue); 3147 fBoolFlags.set(attr, newValue);
5532 } 3148 }
5533 break; 3149 break;
5534 3150
5535 case UNUM_SCALE: 3151 case UNUM_SCALE:
5536 fScale = newValue; 3152 fImpl->setScale(newValue);
5537 break; 3153 break;
5538 3154
5539 case UNUM_CURRENCY_USAGE: 3155 case UNUM_CURRENCY_USAGE:
5540 setCurrencyUsage((UCurrencyUsage)newValue, &status); 3156 setCurrencyUsage((UCurrencyUsage)newValue, &status);
3157 break;
3158
3159 case UNUM_MINIMUM_GROUPING_DIGITS:
3160 setMinimumGroupingDigits(newValue);
3161 break;
5541 3162
5542 default: 3163 default:
5543 status = U_UNSUPPORTED_ERROR; 3164 status = U_UNSUPPORTED_ERROR;
5544 break; 3165 break;
5545 } 3166 }
5546 return *this; 3167 return *this;
5547 } 3168 }
5548 3169
5549 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr, 3170 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
5550 UErrorCode &status ) const { 3171 UErrorCode &status ) const {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
5609 case UNUM_SECONDARY_GROUPING_SIZE: 3230 case UNUM_SECONDARY_GROUPING_SIZE:
5610 return getSecondaryGroupingSize(); 3231 return getSecondaryGroupingSize();
5611 3232
5612 /* These are stored in fBoolFlags */ 3233 /* These are stored in fBoolFlags */
5613 case UNUM_PARSE_NO_EXPONENT: 3234 case UNUM_PARSE_NO_EXPONENT:
5614 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 3235 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
5615 case UNUM_PARSE_DECIMAL_MARK_REQUIRED: 3236 case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
5616 return fBoolFlags.get(attr); 3237 return fBoolFlags.get(attr);
5617 3238
5618 case UNUM_SCALE: 3239 case UNUM_SCALE:
5619 return fScale; 3240 return fImpl->fScale;
5620 3241
5621 case UNUM_CURRENCY_USAGE: 3242 case UNUM_CURRENCY_USAGE:
5622 return fCurrencyUsage; 3243 return fImpl->getCurrencyUsage();
3244
3245 case UNUM_MINIMUM_GROUPING_DIGITS:
3246 return getMinimumGroupingDigits();
5623 3247
5624 default: 3248 default:
5625 status = U_UNSUPPORTED_ERROR; 3249 status = U_UNSUPPORTED_ERROR;
5626 break; 3250 break;
5627 } 3251 }
5628 3252
5629 return -1; /* undefined */ 3253 return -1; /* undefined */
5630 } 3254 }
5631 3255
5632 #if UCONFIG_HAVE_PARSEALLINPUT 3256 #if UCONFIG_HAVE_PARSEALLINPUT
5633 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { 3257 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
5634 fParseAllInput = value; 3258 fParseAllInput = value;
5635 #if UCONFIG_FORMAT_FASTPATHS_49
5636 handleChanged();
5637 #endif
5638 } 3259 }
5639 #endif 3260 #endif
5640 3261
5641 void
5642 DecimalFormat::copyHashForAffix(const Hashtable* source,
5643 Hashtable* target,
5644 UErrorCode& status) {
5645 if ( U_FAILURE(status) ) {
5646 return;
5647 }
5648 int32_t pos = -1;
5649 const UHashElement* element = NULL;
5650 if ( source ) {
5651 while ( (element = source->nextElement(pos)) != NULL ) {
5652 const UHashTok keyTok = element->key;
5653 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
5654
5655 const UHashTok valueTok = element->value;
5656 const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.poin ter;
5657 AffixesForCurrency* copy = new AffixesForCurrency(
5658 value->negPrefixForCurrency,
5659 value->negSuffixForCurrency,
5660 value->posPrefixForCurrency,
5661 value->posSuffixForCurrency);
5662 target->put(UnicodeString(*key), copy, status);
5663 if ( U_FAILURE(status) ) {
5664 return;
5665 }
5666 }
5667 }
5668 }
5669
5670 U_NAMESPACE_END 3262 U_NAMESPACE_END
5671 3263
5672 #endif /* #if !UCONFIG_NO_FORMATTING */ 3264 #endif /* #if !UCONFIG_NO_FORMATTING */
5673 3265
5674 //eof 3266 //eof
OLDNEW
« no previous file with comments | « source/i18n/decimalformatpatternimpl.h ('k') | source/i18n/decimfmtimpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698