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