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