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