OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 = ¤cyPluralPatternForOther; | 439 patternUsed = ¤cyPluralPatternForOther; |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |