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