]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/decimfmt.cpp
ICU-57166.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / decimfmt.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
b331163b 3* Copyright (C) 1997-2015, International Business Machines Corporation and *
b75a7d8f
A
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().
729e4ab9 35* 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
b75a7d8f
A
36* fPadPosition
37********************************************************************************
38*/
729e4ab9 39
b75a7d8f
A
40#include "unicode/utypes.h"
41
42#if !UCONFIG_NO_FORMATTING
43
46f4442e 44#include "unicode/uniset.h"
729e4ab9
A
45#include "unicode/currpinf.h"
46#include "unicode/plurrule.h"
4388f060
A
47#include "unicode/utf16.h"
48#include "unicode/numsys.h"
49#include "unicode/localpointer.h"
50#include "uresimp.h"
374ca955 51#include "ucurrimp.h"
729e4ab9 52#include "charstr.h"
4388f060 53#include "patternprops.h"
b75a7d8f 54#include "cstring.h"
b75a7d8f 55#include "uassert.h"
729e4ab9 56#include "hash.h"
4388f060 57#include "decfmtst.h"
57a6839d
A
58#include "plurrule_impl.h"
59#include "decimalformatpattern.h"
b331163b 60#include "fmtableimp.h"
2ca993e8
A
61#include "decimfmtimpl.h"
62#include "visibledigits.h"
729e4ab9 63
51004dcb
A
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
b75a7d8f 72
57a6839d 73
b75a7d8f
A
74U_NAMESPACE_BEGIN
75
57a6839d
A
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
729e4ab9
A
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 }
57a6839d
A
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
729e4ab9
A
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 }
57a6839d
A
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
729e4ab9
A
166};
167
168U_CDECL_BEGIN
169
729e4ab9
A
170/**
171 * @internal ICU 4.2
172 */
173static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2);
174
175
729e4ab9
A
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
b75a7d8f 195
4388f060 196
46f4442e 197
b75a7d8f
A
198// *****************************************************************************
199// class DecimalFormat
200// *****************************************************************************
201
374ca955 202UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
b75a7d8f
A
203
204// Constants for characters used in programmatic (unlocalized) patterns.
374ca955
A
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) /* */
b75a7d8f
A
227
228const int32_t DecimalFormat::kDoubleIntegerDigits = 309;
229const int32_t DecimalFormat::kDoubleFractionDigits = 340;
230
374ca955
A
231const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
232
b75a7d8f
A
233/**
234 * These are the tags we expect to see in normal resource bundle files associated
235 * with a locale.
236 */
729e4ab9
A
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";
57a6839d 243
374ca955
A
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; }
b75a7d8f
A
246
247//------------------------------------------------------------------------------
248// Constructs a DecimalFormat instance in the default locale.
729e4ab9
A
249
250DecimalFormat::DecimalFormat(UErrorCode& status) {
57a6839d 251 init();
b75a7d8f
A
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,
729e4ab9 261 UErrorCode& status) {
57a6839d 262 init();
b75a7d8f
A
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,
729e4ab9 274 UErrorCode& status) {
57a6839d 275 init();
b75a7d8f
A
276 UParseError parseError;
277 if (symbolsToAdopt == NULL)
278 status = U_ILLEGAL_ARGUMENT_ERROR;
279 construct(status, parseError, &pattern, symbolsToAdopt);
280}
729e4ab9 281
b75a7d8f
A
282DecimalFormat::DecimalFormat( const UnicodeString& pattern,
283 DecimalFormatSymbols* symbolsToAdopt,
284 UParseError& parseErr,
729e4ab9 285 UErrorCode& status) {
57a6839d 286 init();
b75a7d8f
A
287 if (symbolsToAdopt == NULL)
288 status = U_ILLEGAL_ARGUMENT_ERROR;
289 construct(status,parseErr, &pattern, symbolsToAdopt);
290}
729e4ab9 291
b75a7d8f
A
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.
729e4ab9 296
b75a7d8f
A
297DecimalFormat::DecimalFormat(const UnicodeString& pattern,
298 const DecimalFormatSymbols& symbols,
729e4ab9 299 UErrorCode& status) {
57a6839d 300 init();
b75a7d8f
A
301 UParseError parseError;
302 construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
303}
304
729e4ab9
A
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,
4388f060 312 UNumberFormatStyle style,
729e4ab9 313 UErrorCode& status) {
57a6839d 314 init();
729e4ab9
A
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.
57a6839d
A
324// Can not fail. Leave the object in good enough shape that the destructor
325// or assignment operator can run successfully.
729e4ab9 326void
57a6839d 327DecimalFormat::init() {
51004dcb 328 fBoolFlags.clear();
4388f060 329 fStyle = UNUM_DECIMAL;
729e4ab9 330 fAffixPatternsForCurrency = NULL;
729e4ab9 331 fCurrencyPluralInfo = NULL;
51004dcb
A
332#if UCONFIG_HAVE_PARSEALLINPUT
333 fParseAllInput = UNUM_MAYBE;
334#endif
335
57a6839d 336 fStaticSets = NULL;
2ca993e8 337 fImpl = NULL;
729e4ab9
A
338}
339
b75a7d8f
A
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
57a6839d 346DecimalFormat::construct(UErrorCode& status,
b75a7d8f
A
347 UParseError& parseErr,
348 const UnicodeString* pattern,
349 DecimalFormatSymbols* symbolsToAdopt)
350{
2ca993e8 351 LocalPointer<DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
b75a7d8f
A
352 if (U_FAILURE(status))
353 return;
354
2ca993e8 355 if (adoptedSymbols.isNull())
b75a7d8f 356 {
2ca993e8
A
357 adoptedSymbols.adoptInstead(
358 new DecimalFormatSymbols(Locale::getDefault(), status));
359 if (adoptedSymbols.isNull() && U_SUCCESS(status)) {
b75a7d8f 360 status = U_MEMORY_ALLOCATION_ERROR;
2ca993e8
A
361 }
362 if (U_FAILURE(status)) {
b75a7d8f
A
363 return;
364 }
365 }
57a6839d
A
366 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
367 if (U_FAILURE(status)) {
368 return;
369 }
b75a7d8f
A
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 {
2ca993e8
A
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
374ca955 384 int32_t len = 0;
4388f060
A
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 }
374ca955 398 str.setTo(TRUE, resStr, len);
b75a7d8f 399 pattern = &str;
374ca955 400 ures_close(resource);
4388f060 401 ures_close(top);
b75a7d8f
A
402 }
403
2ca993e8
A
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 }
4388f060 413
b75a7d8f
A
414 if (U_FAILURE(status))
415 {
416 return;
417 }
418
729e4ab9
A
419 const UnicodeString* patternUsed;
420 UnicodeString currencyPluralPatternForOther;
421 // apply pattern
4388f060 422 if (fStyle == UNUM_CURRENCY_PLURAL) {
2ca993e8 423 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
729e4ab9
A
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.
4388f060 435 fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther);
2ca993e8
A
436 // TODO(refactor): Revisit, we are setting the pattern twice.
437 fImpl->applyPatternFavorCurrencyPrecision(
438 currencyPluralPatternForOther, status);
729e4ab9 439 patternUsed = &currencyPluralPatternForOther;
729e4ab9
A
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
2ca993e8 448 handleCurrencySignInPattern(status);
729e4ab9 449 }
2ca993e8 450}
729e4ab9 451
2ca993e8
A
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;
b75a7d8f 458 }
2ca993e8
A
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);
b75a7d8f 468 }
b75a7d8f
A
469}
470
2ca993e8
A
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}
729e4ab9
A
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
2ca993e8 511 NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLocale(),status);
4388f060
A
512 if (U_FAILURE(status)) {
513 return;
514 }
515
729e4ab9
A
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
2ca993e8 522 UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().getName(), &error);
4388f060
A
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);
729e4ab9 526 int32_t patLen = 0;
4388f060
A
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);
729e4ab9 535 ures_close(resource);
4388f060 536 delete ns;
729e4ab9
A
537
538 if (U_SUCCESS(error)) {
2ca993e8
A
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);
729e4ab9 546 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
2ca993e8
A
547 negPrefix,
548 negSuffix,
549 posPrefix,
550 posSuffix,
729e4ab9 551 UCURR_SYMBOL_NAME);
4388f060 552 fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status);
729e4ab9
A
553 }
554
555 // save the unique currency plural patterns of this locale.
556 Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern;
557 const UHashElement* element = NULL;
b331163b 558 int32_t pos = UHASH_FIRST;
729e4ab9
A
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) {
2ca993e8
A
566 UnicodeString negPrefix;
567 UnicodeString negSuffix;
568 UnicodeString posPrefix;
569 UnicodeString posSuffix;
729e4ab9 570 pluralPatternSet.puti(*value, 1, status);
2ca993e8
A
571 applyPatternWithNoSideEffects(
572 *value, parseErr,
573 negPrefix, negSuffix, posPrefix, posSuffix, status);
729e4ab9 574 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
2ca993e8
A
575 negPrefix,
576 negSuffix,
577 posPrefix,
578 posSuffix,
729e4ab9
A
579 UCURR_LONG_NAME);
580 fAffixPatternsForCurrency->put(*key, affixPtn, status);
581 }
582 }
583}
584
585
b75a7d8f
A
586//------------------------------------------------------------------------------
587
588DecimalFormat::~DecimalFormat()
589{
729e4ab9 590 deleteHashForAffixPattern();
729e4ab9 591 delete fCurrencyPluralInfo;
2ca993e8 592 delete fImpl;
b75a7d8f
A
593}
594
595//------------------------------------------------------------------------------
596// copy constructor
597
729e4ab9
A
598DecimalFormat::DecimalFormat(const DecimalFormat &source) :
599 NumberFormat(source) {
57a6839d 600 init();
b75a7d8f
A
601 *this = source;
602}
603
604//------------------------------------------------------------------------------
605// assignment operator
b75a7d8f 606
51004dcb
A
607template <class T>
608static void _clone_ptr(T** pdest, const T* source) {
609 delete *pdest;
610 if (source == NULL) {
611 *pdest = NULL;
b75a7d8f 612 } else {
51004dcb 613 *pdest = static_cast<T*>(source->clone());
b75a7d8f
A
614 }
615}
616
617DecimalFormat&
618DecimalFormat::operator=(const DecimalFormat& rhs)
619{
374ca955 620 if(this != &rhs) {
57a6839d 621 UErrorCode status = U_ZERO_ERROR;
374ca955 622 NumberFormat::operator=(rhs);
2ca993e8
A
623 if (fImpl == NULL) {
624 fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status);
625 } else {
626 fImpl->assign(*rhs.fImpl, status);
627 }
57a6839d 628 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
729e4ab9 629 fStyle = rhs.fStyle;
51004dcb
A
630 _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo);
631 deleteHashForAffixPattern();
729e4ab9
A
632 if (rhs.fAffixPatternsForCurrency) {
633 UErrorCode status = U_ZERO_ERROR;
729e4ab9
A
634 fAffixPatternsForCurrency = initHashForAffixPattern(status);
635 copyHashForAffixPattern(rhs.fAffixPatternsForCurrency,
636 fAffixPatternsForCurrency, status);
637 }
57a6839d 638 }
2ca993e8 639
374ca955 640 return *this;
b75a7d8f
A
641}
642
643//------------------------------------------------------------------------------
644
645UBool
646DecimalFormat::operator==(const Format& that) const
647{
648 if (this == &that)
649 return TRUE;
650
374ca955 651 // NumberFormat::operator== guarantees this cast is safe
b75a7d8f
A
652 const DecimalFormat* other = (DecimalFormat*)&that;
653
57a6839d
A
654 return (
655 NumberFormat::operator==(that) &&
57a6839d 656 fBoolFlags.getAll() == other->fBoolFlags.getAll() &&
2ca993e8 657 *fImpl == *other->fImpl);
57a6839d 658
b75a7d8f
A
659}
660
661//------------------------------------------------------------------------------
662
663Format*
664DecimalFormat::clone() const
665{
666 return new DecimalFormat(*this);
667}
668
57a6839d
A
669
670FixedDecimal
671DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const {
2ca993e8
A
672 VisibleDigitsWithExponent digits;
673 initVisibleDigitsWithExponent(number, digits, status);
57a6839d 674 if (U_FAILURE(status)) {
2ca993e8 675 return FixedDecimal();
57a6839d 676 }
2ca993e8
A
677 return FixedDecimal(digits.getMantissa());
678}
57a6839d 679
2ca993e8
A
680VisibleDigitsWithExponent &
681DecimalFormat::initVisibleDigitsWithExponent(
682 double number,
683 VisibleDigitsWithExponent &digits,
684 UErrorCode &status) const {
685 return fImpl->initVisibleDigitsWithExponent(number, digits, status);
57a6839d
A
686}
687
57a6839d
A
688FixedDecimal
689DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const {
2ca993e8
A
690 VisibleDigitsWithExponent digits;
691 initVisibleDigitsWithExponent(number, digits, status);
57a6839d
A
692 if (U_FAILURE(status)) {
693 return FixedDecimal();
694 }
2ca993e8
A
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 }
57a6839d
A
706 if (!number.isNumeric()) {
707 status = U_ILLEGAL_ARGUMENT_ERROR;
2ca993e8 708 return digits;
57a6839d
A
709 }
710
711 DigitList *dl = number.getDigitList();
712 if (dl != NULL) {
2ca993e8
A
713 DigitList dlCopy(*dl);
714 return fImpl->initVisibleDigitsWithExponent(
715 dlCopy, digits, status);
57a6839d
A
716 }
717
718 Formattable::Type type = number.getType();
719 if (type == Formattable::kDouble || type == Formattable::kLong) {
2ca993e8
A
720 return fImpl->initVisibleDigitsWithExponent(
721 number.getDouble(status), digits, status);
57a6839d 722 }
2ca993e8
A
723 return fImpl->initVisibleDigitsWithExponent(
724 number.getInt64(), digits, status);
57a6839d 725}
57a6839d
A
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 {
2ca993e8
A
733 VisibleDigitsWithExponent digits;
734 initVisibleDigitsWithExponent(number, digits, status);
735 if (U_FAILURE(status)) {
736 return FixedDecimal();
57a6839d 737 }
2ca993e8
A
738 return FixedDecimal(digits.getMantissa());
739}
57a6839d 740
2ca993e8
A
741VisibleDigitsWithExponent &
742DecimalFormat::initVisibleDigitsWithExponent(
743 DigitList &number,
744 VisibleDigitsWithExponent &digits,
745 UErrorCode &status) const {
746 return fImpl->initVisibleDigitsWithExponent(
747 number, digits, status);
57a6839d
A
748}
749
750
b75a7d8f 751//------------------------------------------------------------------------------
729e4ab9 752
b75a7d8f
A
753UnicodeString&
754DecimalFormat::format(int32_t number,
755 UnicodeString& appendTo,
756 FieldPosition& fieldPosition) const
374ca955 757{
2ca993e8
A
758 UErrorCode status = U_ZERO_ERROR;
759 return fImpl->format(number, appendTo, fieldPosition, status);
374ca955
A
760}
761
51004dcb
A
762UnicodeString&
763DecimalFormat::format(int32_t number,
764 UnicodeString& appendTo,
765 FieldPosition& fieldPosition,
766 UErrorCode& status) const
767{
2ca993e8 768 return fImpl->format(number, appendTo, fieldPosition, status);
51004dcb
A
769}
770
729e4ab9
A
771UnicodeString&
772DecimalFormat::format(int32_t number,
773 UnicodeString& appendTo,
774 FieldPositionIterator* posIter,
775 UErrorCode& status) const
776{
2ca993e8 777 return fImpl->format(number, appendTo, posIter, status);
729e4ab9
A
778}
779
51004dcb 780
374ca955 781//------------------------------------------------------------------------------
729e4ab9 782
374ca955
A
783UnicodeString&
784DecimalFormat::format(int64_t number,
785 UnicodeString& appendTo,
786 FieldPosition& fieldPosition) const
51004dcb
A
787{
788 UErrorCode status = U_ZERO_ERROR; /* ignored */
2ca993e8 789 return fImpl->format(number, appendTo, fieldPosition, status);
51004dcb
A
790}
791
792UnicodeString&
793DecimalFormat::format(int64_t number,
794 UnicodeString& appendTo,
795 FieldPosition& fieldPosition,
796 UErrorCode& status) const
b75a7d8f 797{
2ca993e8 798 return fImpl->format(number, appendTo, fieldPosition, status);
729e4ab9 799}
b75a7d8f 800
729e4ab9
A
801UnicodeString&
802DecimalFormat::format(int64_t number,
803 UnicodeString& appendTo,
804 FieldPositionIterator* posIter,
805 UErrorCode& status) const
806{
2ca993e8 807 return fImpl->format(number, appendTo, posIter, status);
b75a7d8f 808}
729e4ab9 809
b75a7d8f
A
810//------------------------------------------------------------------------------
811
812UnicodeString&
813DecimalFormat::format( double number,
814 UnicodeString& appendTo,
815 FieldPosition& fieldPosition) const
816{
51004dcb 817 UErrorCode status = U_ZERO_ERROR; /* ignored */
2ca993e8 818 return fImpl->format(number, appendTo, fieldPosition, status);
51004dcb
A
819}
820
821UnicodeString&
822DecimalFormat::format( double number,
823 UnicodeString& appendTo,
824 FieldPosition& fieldPosition,
825 UErrorCode& status) const
826{
2ca993e8 827 return fImpl->format(number, appendTo, fieldPosition, status);
729e4ab9 828}
b75a7d8f 829
729e4ab9
A
830UnicodeString&
831DecimalFormat::format( double number,
832 UnicodeString& appendTo,
833 FieldPositionIterator* posIter,
834 UErrorCode& status) const
835{
2ca993e8 836 return fImpl->format(number, appendTo, posIter, status);
729e4ab9
A
837}
838
839//------------------------------------------------------------------------------
840
841
842UnicodeString&
843DecimalFormat::format(const StringPiece &number,
844 UnicodeString &toAppendTo,
845 FieldPositionIterator *posIter,
846 UErrorCode &status) const
847{
2ca993e8
A
848 return fImpl->format(number, toAppendTo, posIter, status);
849}
729e4ab9
A
850
851
852UnicodeString&
853DecimalFormat::format(const DigitList &number,
854 UnicodeString &appendTo,
855 FieldPositionIterator *posIter,
856 UErrorCode &status) const {
2ca993e8 857 return fImpl->format(number, appendTo, posIter, status);
729e4ab9
A
858}
859
860
729e4ab9
A
861UnicodeString&
862DecimalFormat::format(const DigitList &number,
863 UnicodeString& appendTo,
864 FieldPosition& pos,
865 UErrorCode &status) const {
2ca993e8 866 return fImpl->format(number, appendTo, pos, status);
b75a7d8f
A
867}
868
51004dcb 869UnicodeString&
2ca993e8
A
870DecimalFormat::format(const VisibleDigitsWithExponent &number,
871 UnicodeString &appendTo,
872 FieldPositionIterator *posIter,
873 UErrorCode &status) const {
874 return fImpl->format(number, appendTo, posIter, status);
b75a7d8f
A
875}
876
b75a7d8f 877
b75a7d8f 878UnicodeString&
2ca993e8
A
879DecimalFormat::format(const VisibleDigitsWithExponent &number,
880 UnicodeString& appendTo,
881 FieldPosition& pos,
882 UErrorCode &status) const {
883 return fImpl->format(number, appendTo, pos, status);
b75a7d8f
A
884}
885
2ca993e8
A
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;
b75a7d8f
A
892}
893
b75a7d8f
A
894void
895DecimalFormat::parse(const UnicodeString& text,
896 Formattable& result,
374ca955 897 ParsePosition& parsePosition) const {
4388f060 898 parse(text, result, parsePosition, NULL);
374ca955
A
899}
900
4388f060
A
901CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
902 ParsePosition& pos) const {
903 Formattable parseResult;
904 int32_t start = pos.getIndex();
51004dcb 905 UChar curbuf[4] = {};
4388f060
A
906 parse(text, parseResult, pos, curbuf);
907 if (pos.getIndex() != start) {
908 UErrorCode ec = U_ZERO_ERROR;
b331163b 909 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec), ec);
4388f060
A
910 if (U_FAILURE(ec)) {
911 pos.setIndex(start); // indicate failure
912 } else {
913 return currAmt.orphan();
914 }
915 }
916 return NULL;
374ca955
A
917}
918
919/**
4388f060 920 * Parses the given text as a number, optionally providing a currency amount.
374ca955 921 * @param text the string to parse
4388f060 922 * @param result output parameter for the numeric result.
374ca955
A
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.
4388f060
A
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.
374ca955
A
932 */
933void DecimalFormat::parse(const UnicodeString& text,
934 Formattable& result,
935 ParsePosition& parsePosition,
4388f060
A
936 UChar* currency) const {
937 int32_t startIdx, backup;
938 int32_t i = startIdx = backup = parsePosition.getIndex();
b75a7d8f 939
729e4ab9
A
940 // clear any old contents in the result. In particular, clears any DigitList
941 // that it may be holding.
942 result.setLong(0);
57a6839d
A
943 if (currency != NULL) {
944 for (int32_t ci=0; ci<4; ci++) {
945 currency[ci] = 0;
946 }
947 }
729e4ab9 948
b75a7d8f 949 // Handle NaN as a special case:
2ca993e8 950 int32_t formatWidth = fImpl->getOldFormatWidth();
729e4ab9 951
b75a7d8f 952 // Skip padding characters, if around prefix
2ca993e8
A
953 if (formatWidth > 0 && (
954 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix ||
955 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix)) {
b75a7d8f
A
956 i = skipPadding(text, i);
957 }
729e4ab9 958
4388f060
A
959 if (isLenient()) {
960 // skip any leading whitespace
961 i = backup = skipUWhiteSpace(text, i);
46f4442e 962 }
729e4ab9 963
b75a7d8f 964 // If the text is composed of the representation of NaN, returns NaN.length
2ca993e8 965 const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
b75a7d8f
A
966 int32_t nanLen = (text.compare(i, nan->length(), *nan)
967 ? 0 : nan->length());
968 if (nanLen) {
969 i += nanLen;
2ca993e8 970 if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix)) {
b75a7d8f
A
971 i = skipPadding(text, i);
972 }
973 parsePosition.setIndex(i);
974 result.setDouble(uprv_getNaN());
975 return;
976 }
729e4ab9 977
b75a7d8f
A
978 // NaN parse failed; start over
979 i = backup;
46f4442e 980 parsePosition.setIndex(i);
b75a7d8f
A
981
982 // status is used to record whether a number is infinite.
983 UBool status[fgStatusLength];
51004dcb
A
984
985 DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
729e4ab9
A
986 if (digits == NULL) {
987 return; // no way to report error from here.
988 }
b75a7d8f 989
2ca993e8 990 if (fImpl->fMonetary) {
729e4ab9
A
991 if (!parseForCurrency(text, parsePosition, *digits,
992 status, currency)) {
51004dcb 993 return;
729e4ab9
A
994 }
995 } else {
996 if (!subparse(text,
2ca993e8
A
997 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
998 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
999 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
1000 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
729e4ab9
A
1001 FALSE, UCURR_SYMBOL_NAME,
1002 parsePosition, *digits, status, currency)) {
51004dcb 1003 debug("!subparse(...) - rewind");
4388f060 1004 parsePosition.setIndex(startIdx);
729e4ab9
A
1005 return;
1006 }
b75a7d8f
A
1007 }
1008
1009 // Handle infinity
1010 if (status[fgStatusInfinite]) {
1011 double inf = uprv_getInfinity();
729e4ab9 1012 result.setDouble(digits->isPositive() ? inf : -inf);
51004dcb 1013 // TODO: set the dl to infinity, and let it fall into the code below.
b75a7d8f
A
1014 }
1015
374ca955 1016 else {
374ca955 1017
2ca993e8 1018 if (!fImpl->fMultiplier.isZero()) {
729e4ab9 1019 UErrorCode ec = U_ZERO_ERROR;
2ca993e8 1020 digits->div(fImpl->fMultiplier, ec);
b75a7d8f 1021 }
729e4ab9 1022
2ca993e8 1023 if (fImpl->fScale != 0) {
51004dcb 1024 DigitList ten;
57a6839d 1025 ten.set((int32_t)10);
2ca993e8
A
1026 if (fImpl->fScale > 0) {
1027 for (int32_t i = fImpl->fScale; i > 0; i--) {
51004dcb
A
1028 UErrorCode ec = U_ZERO_ERROR;
1029 digits->div(ten,ec);
1030 }
1031 } else {
2ca993e8 1032 for (int32_t i = fImpl->fScale; i < 0; i++) {
51004dcb
A
1033 UErrorCode ec = U_ZERO_ERROR;
1034 digits->mult(ten,ec);
1035 }
1036 }
1037 }
1038
729e4ab9
A
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);
b75a7d8f 1044 }
729e4ab9 1045 result.adoptDigitList(digits);
b75a7d8f 1046 }
b75a7d8f
A
1047}
1048
1049
374ca955 1050
729e4ab9
A
1051UBool
1052DecimalFormat::parseForCurrency(const UnicodeString& text,
1053 ParsePosition& parsePosition,
1054 DigitList& digits,
1055 UBool* status,
1056 UChar* currency) const {
2ca993e8
A
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
729e4ab9
A
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;
4388f060 1077 if (fStyle == UNUM_CURRENCY_PLURAL) {
729e4ab9 1078 found = subparse(text,
2ca993e8
A
1079 &negativePrefix, &negativeSuffix,
1080 &positivePrefix, &positiveSuffix,
729e4ab9
A
1081 TRUE, UCURR_LONG_NAME,
1082 tmpPos, tmpDigitList, tmpStatus, currency);
1083 } else {
1084 found = subparse(text,
2ca993e8
A
1085 &negativePrefix, &negativeSuffix,
1086 &positivePrefix, &positiveSuffix,
729e4ab9
A
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.
b331163b 1103 int32_t pos = UHASH_FIRST;
729e4ab9
A
1104 const UHashElement* element = NULL;
1105 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
729e4ab9
A
1106 const UHashTok valueTok = element->value;
1107 const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer;
1108 UBool tmpStatus[fgStatusLength];
1109 ParsePosition tmpPos(origPos);
1110 DigitList tmpDigitList;
57a6839d
A
1111
1112#ifdef FMT_DEBUG
1113 debug("trying affix for currency..");
1114 affixPtn->dump();
1115#endif
1116
729e4ab9
A
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.
57a6839d
A
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
729e4ab9
A
1152 UBool tmpStatus_2[fgStatusLength];
1153 ParsePosition tmpPos_2(origPos);
1154 DigitList tmpDigitList_2;
57a6839d
A
1155
1156 // Disable complex currency parsing and try it again.
729e4ab9 1157 UBool result = subparse(text,
2ca993e8
A
1158 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
1159 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
1160 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
1161 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
57a6839d 1162 FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME,
729e4ab9
A
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
374ca955 1189
b75a7d8f
A
1190/**
1191 * Parse the given text into a number. The text is parsed beginning at
1192 * parsePosition, until an unparseable character is seen.
374ca955 1193 * @param text the string to parse.
729e4ab9
A
1194 * @param negPrefix negative prefix.
1195 * @param negSuffix negative suffix.
1196 * @param posPrefix positive prefix.
1197 * @param posSuffix positive suffix.
57a6839d 1198 * @param complexCurrencyParsing whether it is complex currency parsing or not.
729e4ab9 1199 * @param type the currency type to parse against, LONG_NAME only or not.
b75a7d8f 1200 * @param parsePosition The position at which to being parsing. Upon
374ca955
A
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
b75a7d8f 1204 * whether the value was infinite and whether it was positive.
374ca955
A
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.
b75a7d8f 1209 */
729e4ab9
A
1210UBool DecimalFormat::subparse(const UnicodeString& text,
1211 const UnicodeString* negPrefix,
1212 const UnicodeString* negSuffix,
1213 const UnicodeString* posPrefix,
1214 const UnicodeString* posSuffix,
57a6839d 1215 UBool complexCurrencyParsing,
729e4ab9
A
1216 int8_t type,
1217 ParsePosition& parsePosition,
374ca955
A
1218 DigitList& digits, UBool* status,
1219 UChar* currency) const
b75a7d8f 1220{
729e4ab9
A
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
b75a7d8f
A
1228 int32_t position = parsePosition.getIndex();
1229 int32_t oldStart = position;
51004dcb 1230 int32_t textLength = text.length(); // One less pointer to follow
4388f060 1231 UBool strictParse = !isLenient();
2ca993e8
A
1232 UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
1233 const UnicodeString *groupingString = &fImpl->getConstSymbol(
1234 !fImpl->fMonetary ?
1235 DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
51004dcb
A
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);
51004dcb
A
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. */
2ca993e8 1254 if((fImpl->isParseFastpath()) && !fImpl->fMonetary &&
51004dcb
A
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);
2ca993e8 1266 const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
51004dcb
A
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 }
b75a7d8f 1282
51004dcb
A
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
51004dcb
A
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. ");
51004dcb
A
1349 printf("text.length()=%d ", text.length());
1350 printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
1351
1352 printf("\n");
1353#endif
1354 }
1355
2ca993e8
A
1356 UnicodeString formatPattern;
1357 toPattern(formatPattern);
1358
51004dcb
A
1359 if(!fastParseOk
1360#if UCONFIG_HAVE_PARSEALLINPUT
1361 && fParseAllInput!=UNUM_YES
1362#endif
1363 )
1364 {
2ca993e8 1365 int32_t formatWidth = fImpl->getOldFormatWidth();
b75a7d8f 1366 // Match padding before prefix
2ca993e8 1367 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
b75a7d8f
A
1368 position = skipPadding(text, position);
1369 }
1370
1371 // Match positive and negative prefixes; prefer longest match.
57a6839d
A
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);
b75a7d8f
A
1374 if (posMatch >= 0 && negMatch >= 0) {
1375 if (posMatch > negMatch) {
1376 negMatch = -1;
1377 } else if (negMatch > posMatch) {
1378 posMatch = -1;
729e4ab9 1379 }
b75a7d8f
A
1380 }
1381 if (posMatch >= 0) {
1382 position += posMatch;
729e4ab9 1383 parsedNum.append('+', err);
b75a7d8f
A
1384 } else if (negMatch >= 0) {
1385 position += negMatch;
729e4ab9
A
1386 parsedNum.append('-', err);
1387 } else if (strictParse){
b75a7d8f
A
1388 parsePosition.setErrorIndex(position);
1389 return FALSE;
4388f060
A
1390 } else {
1391 // Temporary set positive. This might be changed after checking suffix
1392 parsedNum.append('+', err);
b75a7d8f
A
1393 }
1394
1395 // Match padding before prefix
2ca993e8 1396 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
b75a7d8f
A
1397 position = skipPadding(text, position);
1398 }
729e4ab9 1399
46f4442e 1400 if (! strictParse) {
4388f060 1401 position = skipUWhiteSpace(text, position);
46f4442e 1402 }
729e4ab9 1403
b75a7d8f 1404 // process digits or Inf, find decimal position
2ca993e8 1405 const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
b75a7d8f
A
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
46f4442e 1409 status[fgStatusInfinite] = infLen != 0;
729e4ab9 1410
4388f060 1411 if (infLen != 0) {
729e4ab9
A
1412 parsedNum.append("Infinity", err);
1413 } else {
b75a7d8f
A
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
b75a7d8f 1421
46f4442e 1422 UBool strictFail = FALSE; // did we exit with a strict parse failure?
46f4442e
A
1423 int32_t lastGroup = -1; // where did we last see a grouping separator?
1424 int32_t digitStart = position;
2ca993e8 1425 int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping.fGrouping : fImpl->fEffGrouping.fGrouping2;
729e4ab9 1426
46f4442e 1427 const UnicodeString *decimalString;
2ca993e8
A
1428 if (fImpl->fMonetary) {
1429 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
b75a7d8f 1430 } else {
2ca993e8 1431 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
b75a7d8f 1432 }
46f4442e 1433 UChar32 decimalChar = decimalString->char32At(0);
51004dcb
A
1434 int32_t decimalStringLength = decimalString->length();
1435 int32_t decimalCharLength = U16_LENGTH(decimalChar);
729e4ab9 1436
b75a7d8f 1437 UBool sawDecimal = FALSE;
4388f060
A
1438 UChar32 sawDecimalChar = 0xFFFF;
1439 UBool sawGrouping = FALSE;
1440 UChar32 sawGroupingChar = 0xFFFF;
b75a7d8f
A
1441 UBool sawDigit = FALSE;
1442 int32_t backup = -1;
1443 int32_t digit;
729e4ab9 1444
46f4442e 1445 // equivalent grouping and decimal support
4388f060
A
1446 const UnicodeSet *decimalSet = NULL;
1447 const UnicodeSet *groupingSet = NULL;
729e4ab9
A
1448
1449 if (decimalCharLength == decimalStringLength) {
4388f060 1450 decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse);
729e4ab9
A
1451 }
1452
1453 if (groupingCharLength == groupingStringLength) {
1454 if (strictParse) {
57a6839d 1455 groupingSet = fStaticSets->fStrictDefaultGroupingSeparators;
729e4ab9 1456 } else {
57a6839d 1457 groupingSet = fStaticSets->fDefaultGroupingSeparators;
46f4442e 1458 }
46f4442e 1459 }
729e4ab9 1460
4388f060
A
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.
729e4ab9 1464
b75a7d8f
A
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;
729e4ab9 1468 int32_t integerDigitCount = 0;
b75a7d8f
A
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
729e4ab9 1482 * calling Character.digit(). If this also fails, digit will
b75a7d8f
A
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 }
729e4ab9
A
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++ ) {
2ca993e8 1499 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
46f4442e
A
1500 break;
1501 }
46f4442e
A
1502 }
1503 }
b75a7d8f 1504 }
b75a7d8f 1505
729e4ab9
A
1506 if (digit >= 0 && digit <= 9)
1507 {
46f4442e
A
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 }
729e4ab9 1519
46f4442e 1520 lastGroup = backup;
b75a7d8f 1521 }
729e4ab9
A
1522
1523 // Cancel out backup setting (see grouping handler below)
46f4442e
A
1524 backup = -1;
1525 sawDigit = TRUE;
729e4ab9
A
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 }
b75a7d8f 1538 }
729e4ab9 1539
b75a7d8f
A
1540 position += U16_LENGTH(ch);
1541 }
4388f060
A
1542 else if (groupingStringLength > 0 &&
1543 matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet,
1544 decimalChar, decimalSet,
51004dcb 1545 ch) && groupingUsed)
b75a7d8f 1546 {
46f4442e
A
1547 if (sawDecimal) {
1548 break;
1549 }
729e4ab9 1550
46f4442e 1551 if (strictParse) {
729e4ab9 1552 if ( (!sawDigit && groupingSet!=NULL && u_isWhitespace(ch)) || backup != -1 ) {
2ca993e8
A
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).
46f4442e
A
1562 strictFail = TRUE;
1563 break;
1564 }
1565 }
729e4ab9 1566
b75a7d8f
A
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;
46f4442e 1571 position += groupingStringLength;
4388f060
A
1572 sawGrouping=TRUE;
1573 // Once we see a grouping character, we only accept that grouping character from then on.
1574 sawGroupingChar=ch;
b75a7d8f 1575 }
4388f060 1576 else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch))
b75a7d8f 1577 {
46f4442e
A
1578 if (strictParse) {
1579 if (backup != -1 ||
2ca993e8 1580 (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1)) {
46f4442e
A
1581 strictFail = TRUE;
1582 break;
1583 }
1584 }
729e4ab9
A
1585
1586 // If we're only parsing integers, or if we ALREADY saw the
b75a7d8f 1587 // decimal, then don't parse this one.
46f4442e 1588 if (isParseIntegerOnly() || sawDecimal) {
4388f060 1589 break;
46f4442e 1590 }
729e4ab9
A
1591
1592 parsedNum.append('.', err);
46f4442e 1593 position += decimalStringLength;
b75a7d8f 1594 sawDecimal = TRUE;
4388f060
A
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)
b75a7d8f 1598 }
4388f060 1599 else {
b75a7d8f 1600
51004dcb 1601 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless..
57a6839d 1602 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
51004dcb 1603 const UnicodeString *tmp;
2ca993e8 1604 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
51004dcb
A
1605 // TODO: CASE
1606 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit
b75a7d8f 1607 {
51004dcb
A
1608 // Parse sign, if present
1609 int32_t pos = position + tmp->length();
1610 char exponentSign = '+';
1611
1612 if (pos < textLength)
b75a7d8f 1613 {
2ca993e8 1614 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
b75a7d8f
A
1615 if (!text.compare(pos, tmp->length(), *tmp))
1616 {
1617 pos += tmp->length();
b75a7d8f 1618 }
51004dcb 1619 else {
2ca993e8 1620 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
51004dcb
A
1621 if (!text.compare(pos, tmp->length(), *tmp))
1622 {
1623 exponentSign = '-';
1624 pos += tmp->length();
1625 }
1626 }
b75a7d8f 1627 }
b75a7d8f 1628
51004dcb
A
1629 UBool sawExponentDigit = FALSE;
1630 while (pos < textLength) {
1631 ch = text[(int32_t)pos];
1632 digit = ch - zero;
b75a7d8f 1633
51004dcb
A
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;
729e4ab9 1647 }
b75a7d8f 1648 }
b75a7d8f 1649
51004dcb
A
1650 if (sawExponentDigit) {
1651 position = pos; // Advance past the exponent
1652 }
b75a7d8f 1653
51004dcb
A
1654 break; // Whether we fail or succeed, we exit this loop
1655 } else {
1656 break;
1657 }
1658 } else { // not parsing exponent
b75a7d8f 1659 break;
51004dcb 1660 }
b75a7d8f
A
1661 }
1662 }
729e4ab9 1663
b331163b
A
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 {
2ca993e8 1667 if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
b331163b
A
1668 {
1669 parsePosition.setIndex(oldStart);
1670 parsePosition.setErrorIndex(position);
1671 debug("decimal point match required fail!");
1672 return FALSE;
1673 }
1674 }
1675
b75a7d8f
A
1676 if (backup != -1)
1677 {
1678 position = backup;
1679 }
1680
46f4442e 1681 if (strictParse && !sawDecimal) {
2ca993e8 1682 if (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1) {
46f4442e
A
1683 strictFail = TRUE;
1684 }
1685 }
46f4442e
A
1686
1687 if (strictFail) {
4388f060 1688 // only set with strictParse and a grouping separator error
729e4ab9 1689
46f4442e
A
1690 parsePosition.setIndex(oldStart);
1691 parsePosition.setErrorIndex(position);
51004dcb 1692 debug("strictFail!");
46f4442e
A
1693 return FALSE;
1694 }
729e4ab9 1695
b75a7d8f 1696 // If there was no decimal point we have an integer
b75a7d8f
A
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) {
51004dcb
A
1703#ifdef FMT_DEBUG
1704 debug("none of text rec");
1705 printf("position=%d\n",position);
1706#endif
b75a7d8f
A
1707 parsePosition.setIndex(oldStart);
1708 parsePosition.setErrorIndex(oldStart);
1709 return FALSE;
1710 }
1711 }
1712
1713 // Match padding before suffix
2ca993e8 1714 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
b75a7d8f
A
1715 position = skipPadding(text, position);
1716 }
1717
46f4442e 1718 int32_t posSuffixMatch = -1, negSuffixMatch = -1;
729e4ab9 1719
b75a7d8f 1720 // Match positive and negative suffixes; prefer longest match.
46f4442e 1721 if (posMatch >= 0 || (!strictParse && negMatch < 0)) {
57a6839d 1722 posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency);
b75a7d8f
A
1723 }
1724 if (negMatch >= 0) {
57a6839d 1725 negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency);
b75a7d8f 1726 }
46f4442e
A
1727 if (posSuffixMatch >= 0 && negSuffixMatch >= 0) {
1728 if (posSuffixMatch > negSuffixMatch) {
4388f060 1729 negSuffixMatch = -1;
46f4442e 1730 } else if (negSuffixMatch > posSuffixMatch) {
4388f060 1731 posSuffixMatch = -1;
729e4ab9 1732 }
b75a7d8f
A
1733 }
1734
1735 // Fail if neither or both
46f4442e 1736 if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) {
b75a7d8f 1737 parsePosition.setErrorIndex(position);
51004dcb 1738 debug("neither or both");
b75a7d8f
A
1739 return FALSE;
1740 }
1741
729e4ab9 1742 position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0));
b75a7d8f
A
1743
1744 // Match padding before suffix
2ca993e8 1745 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
b75a7d8f
A
1746 position = skipPadding(text, position);
1747 }
1748
1749 parsePosition.setIndex(position);
1750
729e4ab9 1751 parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-';
51004dcb
A
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)
b75a7d8f 1766 {
51004dcb
A
1767#ifdef FMT_DEBUG
1768 printf(" PP didnt consume all (UNUM_YES), err\n");
1769#endif
b75a7d8f
A
1770 parsePosition.setErrorIndex(position);
1771 return FALSE;
1772 }
51004dcb
A
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 );
729e4ab9
A
1781
1782 if (U_FAILURE(err)) {
51004dcb
A
1783#ifdef FMT_DEBUG
1784 printf(" err setting %s\n", u_errorName(err));
1785#endif
729e4ab9
A
1786 parsePosition.setErrorIndex(position);
1787 return FALSE;
1788 }
b331163b
A
1789
1790 // check if we missed a required decimal point
1791 if(fastParseOk && isDecimalPatternMatchRequired())
1792 {
2ca993e8 1793 if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
b331163b
A
1794 {
1795 parsePosition.setIndex(oldStart);
1796 parsePosition.setErrorIndex(position);
1797 debug("decimal point match required fail!");
1798 return FALSE;
1799 }
1800 }
1801
1802
b75a7d8f
A
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 {
2ca993e8 1812 int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar);
b75a7d8f 1813 while (position < text.length() &&
2ca993e8 1814 text.char32At(position) == fImpl->fAffixes.fPadChar) {
b75a7d8f
A
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
729e4ab9 1829 * @param affixPat affix pattern used for currency affix comparison.
57a6839d 1830 * @param complexCurrencyParsing whether it is currency parsing or not
729e4ab9 1831 * @param type the currency type to parse against, LONG_NAME only or not.
374ca955
A
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.
b75a7d8f
A
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,
374ca955 1841 UBool isPrefix,
729e4ab9 1842 const UnicodeString* affixPat,
57a6839d 1843 UBool complexCurrencyParsing,
729e4ab9 1844 int8_t type,
46f4442e
A
1845 UChar* currency) const
1846{
1847 const UnicodeString *patternToCompare;
2ca993e8
A
1848 if (currency != NULL ||
1849 (fImpl->fMonetary && complexCurrencyParsing)) {
729e4ab9
A
1850
1851 if (affixPat != NULL) {
1852 return compareComplexAffix(*affixPat, text, pos, type, currency);
46f4442e 1853 }
b75a7d8f 1854 }
729e4ab9 1855
46f4442e
A
1856 if (isNegative) {
1857 if (isPrefix) {
2ca993e8 1858 patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString();
46f4442e
A
1859 }
1860 else {
2ca993e8 1861 patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString();
46f4442e 1862 }
b75a7d8f 1863 }
46f4442e
A
1864 else {
1865 if (isPrefix) {
2ca993e8 1866 patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString();
46f4442e
A
1867 }
1868 else {
2ca993e8 1869 patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString();
46f4442e
A
1870 }
1871 }
4388f060 1872 return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
b75a7d8f
A
1873}
1874
57a6839d
A
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
b75a7d8f
A
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,
46f4442e 1921 int32_t pos,
57a6839d 1922 UBool lenient) const {
b75a7d8f 1923 int32_t start = pos;
57a6839d
A
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();
7393aa2f
A
1930 int32_t inputLength = input.length();
1931 int32_t affixCharLength = U16_LENGTH(affixChar);
1932 UnicodeSet *affixSet;
57a6839d
A
1933 UErrorCode status = U_ZERO_ERROR;
1934
1935 U_ASSERT(fStaticSets != NULL); // should already be loaded
729e4ab9 1936
57a6839d
A
1937 if (U_FAILURE(status)) {
1938 return -1;
1939 }
4388f060 1940 if (!lenient) {
57a6839d
A
1941 affixSet = fStaticSets->fStrictDashEquivalents;
1942
1943 // If the trimmedAffix is exactly one character long and that character
7393aa2f
A
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)) {
57a6839d
A
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;
7393aa2f
A
1952 }
1953 }
729e4ab9 1954
4388f060 1955 for (int32_t i = 0; i < affixLength; ) {
57a6839d 1956 UChar32 c = trimmedAffix.char32At(i);
4388f060
A
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;
57a6839d
A
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 {
4388f060
A
1983 break;
1984 }
1985 }
1986
1987 // Advance over run in pattern
57a6839d 1988 i = skipPatternWhiteSpace(trimmedAffix, i);
4388f060
A
1989
1990 // Advance over run in input text
1991 // Must see at least one white space char in input,
57a6839d 1992 // unless we've already matched some characters literally.
4388f060
A
1993 int32_t s = pos;
1994 pos = skipUWhiteSpace(input, pos);
57a6839d 1995 if (pos == s && !literalMatch) {
4388f060
A
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
57a6839d
A
2001 // is also in the trimmedAffix.
2002 i = skipUWhiteSpace(trimmedAffix, i);
4388f060 2003 } else {
57a6839d
A
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) {
4388f060
A
2018 return -1;
2019 }
2020 }
2021 }
729e4ab9 2022 } else {
4388f060 2023 UBool match = FALSE;
57a6839d
A
2024
2025 affixSet = fStaticSets->fDashEquivalents;
729e4ab9 2026
7393aa2f 2027 if (affixCharLength == affixLength && affixSet->contains(affixChar)) {
57a6839d
A
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;
7393aa2f
A
2035 }
2036 }
729e4ab9 2037
4388f060
A
2038 for (int32_t i = 0; i < affixLength; )
2039 {
57a6839d
A
2040 //i = skipRuleWhiteSpace(trimmedAffix, i);
2041 i = skipUWhiteSpace(trimmedAffix, i);
2042 pos = skipUWhiteSpaceAndMarks(input, pos);
729e4ab9 2043
4388f060
A
2044 if (i >= affixLength || pos >= inputLength) {
2045 break;
2046 }
729e4ab9 2047
57a6839d
A
2048 UChar32 c = trimmedAffix.char32At(i);
2049 UChar32 ic = input.char32At(pos);
729e4ab9 2050
57a6839d 2051 if (!equalWithSignCompatibility(ic, c)) {
4388f060
A
2052 return -1;
2053 }
729e4ab9 2054
4388f060 2055 match = TRUE;
57a6839d
A
2056 i += U16_LENGTH(c);
2057 pos += U16_LENGTH(ic);
2058 pos = skipBidiMarks(input, pos);
4388f060 2059 }
729e4ab9 2060
4388f060
A
2061 if (affixLength > 0 && ! match) {
2062 return -1;
2063 }
729e4ab9 2064 }
b75a7d8f
A
2065 return pos - start;
2066}
2067
2068/**
4388f060 2069 * Skip over a run of zero or more Pattern_White_Space characters at
b75a7d8f
A
2070 * pos in text.
2071 */
4388f060
A
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);
b75a7d8f
A
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);
57a6839d 2084 if (!u_isUWhiteSpace(c)) {
b75a7d8f
A
2085 break;
2086 }
2087 pos += U16_LENGTH(c);
2088 }
2089 return pos;
2090}
2091
57a6839d
A
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
b75a7d8f
A
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
729e4ab9 2126 * @param type the currency type to parse against, LONG_NAME only or not.
374ca955
A
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.
b75a7d8f
A
2131 * @return length of input that matches, or -1 if match failure
2132 */
2133int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
2134 const UnicodeString& text,
374ca955 2135 int32_t pos,
729e4ab9 2136 int8_t type,
73c04bcf
A
2137 UChar* currency) const
2138{
2139 int32_t start = pos;
2ca993e8 2140 U_ASSERT(currency != NULL || fImpl->fMonetary);
b75a7d8f 2141
729e4ab9
A
2142 for (int32_t i=0;
2143 i<affixPat.length() && pos >= 0; ) {
b75a7d8f
A
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: {
729e4ab9
A
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.
b75a7d8f
A
2161 UBool intl = i<affixPat.length() &&
2162 affixPat.char32At(i) == kCurrencySign;
729e4ab9
A
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 }
374ca955
A
2172 // Parse generic currency -- anything for which we
2173 // have a display name, or any 3-letter ISO code.
729e4ab9
A
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) {
374ca955 2186 u_strcpy(currency, curr);
4388f060 2187 } else {
729e4ab9
A
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);
4388f060 2193 if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) {
57a6839d
A
2194 pos = -1;
2195 continue;
729e4ab9 2196 }
374ca955 2197 }
729e4ab9 2198 pos = ppos.getIndex();
4388f060 2199 } else if (!isLenient()){
729e4ab9 2200 pos = -1;
b75a7d8f
A
2201 }
2202 continue;
2203 }
2204 case kPatternPercent:
2ca993e8 2205 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
b75a7d8f
A
2206 break;
2207 case kPatternPerMill:
2ca993e8 2208 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
b75a7d8f
A
2209 break;
2210 case kPatternPlus:
2ca993e8 2211 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
b75a7d8f
A
2212 break;
2213 case kPatternMinus:
2ca993e8 2214 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
b75a7d8f
A
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);
4388f060
A
2228 if (PatternProps::isWhiteSpace(c)) {
2229 i = skipPatternWhiteSpace(affixPat, i);
b75a7d8f
A
2230 }
2231 }
73c04bcf 2232 return pos - start;
b75a7d8f
A
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
4388f060 2238 * ch is a Pattern_White_Space then match a run of white space in text.
b75a7d8f
A
2239 */
2240int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) {
4388f060 2241 if (PatternProps::isWhiteSpace(ch)) {
b75a7d8f
A
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;
4388f060 2245 pos = skipPatternWhiteSpace(text, pos);
b75a7d8f
A
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);
4388f060
A
2264 if (PatternProps::isWhiteSpace(ch)) {
2265 i = skipPatternWhiteSpace(str, i);
b75a7d8f
A
2266 }
2267 pos = match(text, pos, ch);
2268 }
2269 return pos;
2270}
2271
46f4442e 2272UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol,
729e4ab9 2273 UnicodeSet *sset, UChar32 schar)
46f4442e 2274{
4388f060
A
2275 if (sset != NULL) {
2276 return sset->contains(schar);
2277 }
729e4ab9 2278
4388f060 2279 return text.compare(position, length, symbol) == 0;
46f4442e
A
2280}
2281
4388f060
A
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
729e4ab9 2314
b75a7d8f
A
2315//------------------------------------------------------------------------------
2316// Gets the pointer to the localized decimal format symbols
2317
2318const DecimalFormatSymbols*
2319DecimalFormat::getDecimalFormatSymbols() const
2320{
2ca993e8 2321 return &fImpl->getDecimalFormatSymbols();
b75a7d8f
A
2322}
2323
2324//------------------------------------------------------------------------------
2325// De-owning the current localized symbols and adopt the new symbols.
2326
2327void
2328DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
2329{
374ca955
A
2330 if (symbolsToAdopt == NULL) {
2331 return; // do not allow caller to set fSymbols to NULL
2332 }
2ca993e8 2333 fImpl->adoptDecimalFormatSymbols(symbolsToAdopt);
b75a7d8f
A
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}
729e4ab9 2344
4388f060 2345
729e4ab9
A
2346const CurrencyPluralInfo*
2347DecimalFormat::getCurrencyPluralInfo(void) const
2348{
2349 return fCurrencyPluralInfo;
2350}
2351
4388f060 2352
729e4ab9
A
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.
2ca993e8 2360 if (fImpl->fMonetary) {
729e4ab9
A
2361 UErrorCode status = U_ZERO_ERROR;
2362 if (fAffixPatternsForCurrency) {
2363 deleteHashForAffixPattern();
2364 }
2365 setupCurrencyAffixPatterns(status);
729e4ab9
A
2366 }
2367 }
2368}
2369
2370void
2371DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
2372{
2373 adoptCurrencyPluralInfo(info.clone());
b75a7d8f
A
2374}
2375
2376
2377//------------------------------------------------------------------------------
2378// Gets the positive prefix of the number pattern.
729e4ab9 2379
b75a7d8f
A
2380UnicodeString&
2381DecimalFormat::getPositivePrefix(UnicodeString& result) const
2382{
2ca993e8 2383 return fImpl->getPositivePrefix(result);
b75a7d8f 2384}
729e4ab9 2385
b75a7d8f
A
2386//------------------------------------------------------------------------------
2387// Sets the positive prefix of the number pattern.
729e4ab9 2388
b75a7d8f
A
2389void
2390DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
2391{
2ca993e8 2392 fImpl->setPositivePrefix(newValue);
b75a7d8f
A
2393}
2394
2395//------------------------------------------------------------------------------
2396// Gets the negative prefix of the number pattern.
2397
2398UnicodeString&
2399DecimalFormat::getNegativePrefix(UnicodeString& result) const
2400{
2ca993e8 2401 return fImpl->getNegativePrefix(result);
b75a7d8f
A
2402}
2403
2404//------------------------------------------------------------------------------
2405// Gets the negative prefix of the number pattern.
2406
2407void
2408DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
2409{
2ca993e8 2410 fImpl->setNegativePrefix(newValue);
b75a7d8f
A
2411}
2412
2413//------------------------------------------------------------------------------
2414// Gets the positive suffix of the number pattern.
2415
2416UnicodeString&
2417DecimalFormat::getPositiveSuffix(UnicodeString& result) const
2418{
2ca993e8 2419 return fImpl->getPositiveSuffix(result);
b75a7d8f
A
2420}
2421
2422//------------------------------------------------------------------------------
2423// Sets the positive suffix of the number pattern.
2424
2425void
2426DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
2427{
2ca993e8 2428 fImpl->setPositiveSuffix(newValue);
b75a7d8f
A
2429}
2430
2431//------------------------------------------------------------------------------
2432// Gets the negative suffix of the number pattern.
2433
2434UnicodeString&
2435DecimalFormat::getNegativeSuffix(UnicodeString& result) const
2436{
2ca993e8 2437 return fImpl->getNegativeSuffix(result);
b75a7d8f
A
2438}
2439
2440//------------------------------------------------------------------------------
2441// Sets the negative suffix of the number pattern.
2442
2443void
2444DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
2445{
2ca993e8 2446 fImpl->setNegativeSuffix(newValue);
b75a7d8f
A
2447}
2448
2449//------------------------------------------------------------------------------
2450// Gets the multiplier of the number pattern.
729e4ab9
A
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.
b75a7d8f 2454
729e4ab9
A
2455int32_t
2456DecimalFormat::getMultiplier() const
b75a7d8f 2457{
2ca993e8 2458 return fImpl->getMultiplier();
b75a7d8f
A
2459}
2460
2461//------------------------------------------------------------------------------
2462// Sets the multiplier of the number pattern.
2463void
2464DecimalFormat::setMultiplier(int32_t newValue)
2465{
2ca993e8 2466 fImpl->setMultiplier(newValue);
b75a7d8f
A
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 */
374ca955 2477double DecimalFormat::getRoundingIncrement() const {
2ca993e8 2478 return fImpl->getRoundingIncrement();
b75a7d8f
A
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) {
2ca993e8 2491 fImpl->setRoundingIncrement(newValue);
b75a7d8f
A
2492}
2493
2494/**
2495 * Get the rounding mode.
2496 * @return A rounding mode
2497 * @see #setRoundingIncrement
2498 * @see #getRoundingIncrement
2499 * @see #setRoundingMode
2500 */
374ca955 2501DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
2ca993e8 2502 return fImpl->getRoundingMode();
b75a7d8f
A
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) {
2ca993e8 2514 fImpl->setRoundingMode(roundingMode);
b75a7d8f
A
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 */
374ca955 2526int32_t DecimalFormat::getFormatWidth() const {
2ca993e8 2527 return fImpl->getFormatWidth();
b75a7d8f
A
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) {
2ca993e8
A
2543 int32_t formatWidth = (width > 0) ? width : 0;
2544 fImpl->setFormatWidth(formatWidth);
b75a7d8f
A
2545}
2546
374ca955 2547UnicodeString DecimalFormat::getPadCharacterString() const {
2ca993e8 2548 return UnicodeString(fImpl->getPadCharacter());
b75a7d8f
A
2549}
2550
b75a7d8f 2551void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
2ca993e8 2552 UChar pad;
b75a7d8f 2553 if (padChar.length() > 0) {
2ca993e8 2554 pad = padChar.char32At(0);
b75a7d8f
A
2555 }
2556 else {
2ca993e8 2557 pad = kDefaultPad;
b75a7d8f 2558 }
2ca993e8
A
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;
b75a7d8f
A
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 */
374ca955 2596DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
2ca993e8
A
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;
b75a7d8f
A
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) {
2ca993e8 2637 fImpl->setPadPosition(toPadPosition(padPos));
b75a7d8f
A
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 */
57a6839d 2649UBool DecimalFormat::isScientificNotation() const {
2ca993e8 2650 return fImpl->isScientificNotation();
b75a7d8f
A
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) {
2ca993e8 2664 fImpl->setScientificNotation(useScientific);
b75a7d8f
A
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 */
374ca955 2676int8_t DecimalFormat::getMinimumExponentDigits() const {
2ca993e8 2677 return fImpl->getMinimumExponentDigits();
b75a7d8f
A
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) {
2ca993e8
A
2692 int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
2693 fImpl->setMinimumExponentDigits(minExponentDigits);
b75a7d8f
A
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 */
57a6839d 2707UBool DecimalFormat::isExponentSignAlwaysShown() const {
2ca993e8 2708 return fImpl->isExponentSignAlwaysShown();
b75a7d8f
A
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) {
2ca993e8 2724 fImpl->setExponentSignAlwaysShown(expSignAlways);
b75a7d8f
A
2725}
2726
2727//------------------------------------------------------------------------------
2728// Gets the grouping size of the number pattern. For example, thousand or 10
2729// thousand groupings.
729e4ab9 2730
b75a7d8f
A
2731int32_t
2732DecimalFormat::getGroupingSize() const
2733{
2ca993e8 2734 return fImpl->getGroupingSize();
b75a7d8f 2735}
729e4ab9 2736
b75a7d8f
A
2737//------------------------------------------------------------------------------
2738// Gets the grouping size of the number pattern.
729e4ab9 2739
b75a7d8f
A
2740void
2741DecimalFormat::setGroupingSize(int32_t newValue)
2742{
2ca993e8 2743 fImpl->setGroupingSize(newValue);
b75a7d8f
A
2744}
2745
2746//------------------------------------------------------------------------------
2747
2748int32_t
2749DecimalFormat::getSecondaryGroupingSize() const
2750{
2ca993e8 2751 return fImpl->getSecondaryGroupingSize();
b75a7d8f
A
2752}
2753
2754//------------------------------------------------------------------------------
2755
2756void
2757DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
2758{
2ca993e8
A
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);
b75a7d8f
A
2776}
2777
2778//------------------------------------------------------------------------------
2779// Checks if to show the decimal separator.
2780
2781UBool
2782DecimalFormat::isDecimalSeparatorAlwaysShown() const
2783{
2ca993e8 2784 return fImpl->isDecimalSeparatorAlwaysShown();
b75a7d8f
A
2785}
2786
2787//------------------------------------------------------------------------------
2788// Sets to always show the decimal separator.
2789
2790void
2791DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
2792{
2ca993e8 2793 fImpl->setDecimalSeparatorAlwaysShown(newValue);
b75a7d8f
A
2794}
2795
b331163b
A
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
b75a7d8f
A
2814//------------------------------------------------------------------------------
2815// Emits the pattern of this DecimalFormat instance.
2816
2817UnicodeString&
2818DecimalFormat::toPattern(UnicodeString& result) const
2819{
2ca993e8 2820 return fImpl->toPattern(result);
b75a7d8f
A
2821}
2822
2823//------------------------------------------------------------------------------
2824// Emits the localized pattern this DecimalFormat instance.
2825
2826UnicodeString&
2827DecimalFormat::toLocalizedPattern(UnicodeString& result) const
2828{
2ca993e8
A
2829 // toLocalizedPattern is deprecated, so we just make it the same as
2830 // toPattern.
2831 return fImpl->toPattern(result);
b75a7d8f
A
2832}
2833
2834//------------------------------------------------------------------------------
2835
2836void
2837DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
2838{
2ca993e8
A
2839 if (pattern.indexOf(kCurrencySign) != -1) {
2840 handleCurrencySignInPattern(status);
2841 }
2842 fImpl->applyPattern(pattern, status);
b75a7d8f
A
2843}
2844
2845//------------------------------------------------------------------------------
2846
2847void
2848DecimalFormat::applyPattern(const UnicodeString& pattern,
729e4ab9 2849 UParseError& parseError,
b75a7d8f
A
2850 UErrorCode& status)
2851{
2ca993e8
A
2852 if (pattern.indexOf(kCurrencySign) != -1) {
2853 handleCurrencySignInPattern(status);
2854 }
2855 fImpl->applyPattern(pattern, parseError, status);
b75a7d8f
A
2856}
2857//------------------------------------------------------------------------------
2858
2859void
2860DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
2861{
2ca993e8
A
2862 if (pattern.indexOf(kCurrencySign) != -1) {
2863 handleCurrencySignInPattern(status);
2864 }
2865 fImpl->applyLocalizedPattern(pattern, status);
b75a7d8f
A
2866}
2867
2868//------------------------------------------------------------------------------
2869
2870void
2871DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
2872 UParseError& parseError,
2873 UErrorCode& status)
2874{
729e4ab9 2875 if (pattern.indexOf(kCurrencySign) != -1) {
2ca993e8 2876 handleCurrencySignInPattern(status);
b75a7d8f 2877 }
2ca993e8 2878 fImpl->applyLocalizedPattern(pattern, parseError, status);
b75a7d8f
A
2879}
2880
2ca993e8 2881//------------------------------------------------------------------------------
729e4ab9 2882
b75a7d8f
A
2883/**
2884 * Sets the maximum number of digits allowed in the integer portion of a
57a6839d 2885 * number.
b75a7d8f
A
2886 * @see NumberFormat#setMaximumIntegerDigits
2887 */
2888void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
2ca993e8
A
2889 newValue = _min(newValue, gDefaultMaxIntegerDigits);
2890 NumberFormat::setMaximumIntegerDigits(newValue);
2891 fImpl->updatePrecision();
b75a7d8f
A
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) {
2ca993e8
A
2900 newValue = _min(newValue, kDoubleIntegerDigits);
2901 NumberFormat::setMinimumIntegerDigits(newValue);
2902 fImpl->updatePrecision();
b75a7d8f
A
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) {
2ca993e8
A
2911 newValue = _min(newValue, kDoubleFractionDigits);
2912 NumberFormat::setMaximumFractionDigits(newValue);
2913 fImpl->updatePrecision();
b75a7d8f
A
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) {
2ca993e8
A
2922 newValue = _min(newValue, kDoubleFractionDigits);
2923 NumberFormat::setMinimumFractionDigits(newValue);
2924 fImpl->updatePrecision();
b75a7d8f
A
2925}
2926
374ca955 2927int32_t DecimalFormat::getMinimumSignificantDigits() const {
2ca993e8 2928 return fImpl->getMinimumSignificantDigits();
374ca955
A
2929}
2930
2931int32_t DecimalFormat::getMaximumSignificantDigits() const {
2ca993e8 2932 return fImpl->getMaximumSignificantDigits();
374ca955
A
2933}
2934
2935void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
2936 if (min < 1) {
729e4ab9 2937 min = 1;
374ca955
A
2938 }
2939 // pin max sig dig to >= min
2ca993e8
A
2940 int32_t max = _max(fImpl->fMaxSigDigits, min);
2941 fImpl->setMinMaxSignificantDigits(min, max);
374ca955
A
2942}
2943
2944void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
2945 if (max < 1) {
2946 max = 1;
2947 }
2948 // pin min sig dig to 1..max
2ca993e8
A
2949 U_ASSERT(fImpl->fMinSigDigits >= 1);
2950 int32_t min = _min(fImpl->fMinSigDigits, max);
2951 fImpl->setMinMaxSignificantDigits(min, max);
374ca955
A
2952}
2953
2954UBool DecimalFormat::areSignificantDigitsUsed() const {
2ca993e8 2955 return fImpl->areSignificantDigitsUsed();
374ca955
A
2956}
2957
2958void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
2ca993e8 2959 fImpl->setSignificantDigitsUsed(useSignificantDigits);
729e4ab9
A
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);
2ca993e8 2965 fImpl->updateCurrency(ec);
b75a7d8f
A
2966}
2967
b331163b 2968void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){
2ca993e8 2969 fImpl->setCurrencyUsage(newContext, *ec);
b331163b
A
2970}
2971
2972UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
2ca993e8 2973 return fImpl->getCurrencyUsage();
b331163b
A
2974}
2975
374ca955
A
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
46f4442e 2982void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
2ca993e8 2983 if (fImpl->fSymbols == NULL) {
46f4442e
A
2984 ec = U_MEMORY_ALLOCATION_ERROR;
2985 return;
2986 }
2987 ec = U_ZERO_ERROR;
374ca955
A
2988 const UChar* c = getCurrency();
2989 if (*c == 0) {
2990 const UnicodeString &intl =
2ca993e8 2991 fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
374ca955
A
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
729e4ab9
A
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
729e4ab9
A
3016void
3017DecimalFormat::deleteHashForAffixPattern()
3018{
3019 if ( fAffixPatternsForCurrency == NULL ) {
3020 return;
3021 }
b331163b 3022 int32_t pos = UHASH_FIRST;
729e4ab9
A
3023 const UHashElement* element = NULL;
3024 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
729e4ab9
A
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 }
b331163b 3041 int32_t pos = UHASH_FIRST;
729e4ab9
A
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
57a6839d
A
3063void
3064DecimalFormat::setGroupingUsed(UBool newValue) {
3065 NumberFormat::setGroupingUsed(newValue);
2ca993e8 3066 fImpl->updateGrouping();
57a6839d
A
3067}
3068
57a6839d
A
3069void
3070DecimalFormat::setParseIntegerOnly(UBool newValue) {
3071 NumberFormat::setParseIntegerOnly(newValue);
57a6839d
A
3072}
3073
57a6839d
A
3074void
3075DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {
3076 NumberFormat::setContext(value, status);
57a6839d
A
3077}
3078
51004dcb
A
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:
b331163b 3173 case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
51004dcb
A
3174 if(!fBoolFlags.isValidValue(newValue)) {
3175 status = U_ILLEGAL_ARGUMENT_ERROR;
3176 } else {
2ca993e8
A
3177 if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) {
3178 fImpl->setFailIfMoreThanMaxDigits((UBool) newValue);
3179 }
51004dcb
A
3180 fBoolFlags.set(attr, newValue);
3181 }
3182 break;
3183
3184 case UNUM_SCALE:
2ca993e8 3185 fImpl->setScale(newValue);
51004dcb
A
3186 break;
3187
b331163b
A
3188 case UNUM_CURRENCY_USAGE:
3189 setCurrencyUsage((UCurrencyUsage)newValue, &status);
2ca993e8
A
3190 break;
3191
3192 case UNUM_MINIMUM_GROUPING_DIGITS:
3193 setMinimumGroupingDigits(newValue);
3194 break;
b331163b 3195
51004dcb
A
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:
b331163b 3269 case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
51004dcb
A
3270 return fBoolFlags.get(attr);
3271
3272 case UNUM_SCALE:
2ca993e8 3273 return fImpl->fScale;
51004dcb 3274
b331163b 3275 case UNUM_CURRENCY_USAGE:
2ca993e8
A
3276 return fImpl->getCurrencyUsage();
3277
3278 case UNUM_MINIMUM_GROUPING_DIGITS:
3279 return getMinimumGroupingDigits();
b331163b 3280
51004dcb
A
3281 default:
3282 status = U_UNSUPPORTED_ERROR;
3283 break;
3284 }
729e4ab9 3285
51004dcb
A
3286 return -1; /* undefined */
3287}
3288
3289#if UCONFIG_HAVE_PARSEALLINPUT
3290void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
3291 fParseAllInput = value;
51004dcb
A
3292}
3293#endif
729e4ab9 3294
b75a7d8f
A
3295U_NAMESPACE_END
3296
3297#endif /* #if !UCONFIG_NO_FORMATTING */
3298
3299//eof