1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 * Copyright (C) 2015, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 * file name: decimfmtimpl.cpp
8 */
9
10 #include "unicode/utypes.h"
11
12 #if !UCONFIG_NO_FORMATTING
13
14 #include <math.h>
15 #include "unicode/numfmt.h"
16 #include "unicode/plurrule.h"
17 #include "unicode/ustring.h"
18 #include "decimalformatpattern.h"
19 #include "decimalformatpatternimpl.h"
20 #include "decimfmtimpl.h"
21 #include "fphdlimp.h"
22 #include "plurrule_impl.h"
23 #include "valueformatter.h"
24 #include "visibledigits.h"
25
26 U_NAMESPACE_BEGIN
27
28 static const int32_t kMaxScientificIntegerDigits = 8;
29
30 static const int32_t kFormattingPosPrefix = (1 << 0);
31 static const int32_t kFormattingNegPrefix = (1 << 1);
32 static const int32_t kFormattingPosSuffix = (1 << 2);
33 static const int32_t kFormattingNegSuffix = (1 << 3);
34 static const int32_t kFormattingSymbols = (1 << 4);
35 static const int32_t kFormattingCurrency = (1 << 5);
36 static const int32_t kFormattingUsesCurrency = (1 << 6);
37 static const int32_t kFormattingPluralRules = (1 << 7);
38 static const int32_t kFormattingAffixParser = (1 << 8);
39 static const int32_t kFormattingCurrencyAffixInfo = (1 << 9);
40 static const int32_t kFormattingAll = (1 << 10) - 1;
41 static const int32_t kFormattingAffixes =
42 kFormattingPosPrefix | kFormattingPosSuffix |
43 kFormattingNegPrefix | kFormattingNegSuffix;
44 static const int32_t kFormattingAffixParserWithCurrency =
45 kFormattingAffixParser | kFormattingCurrencyAffixInfo;
46
DecimalFormatImpl(NumberFormat * super,const Locale & locale,const UnicodeString & pattern,UErrorCode & status)47 DecimalFormatImpl::DecimalFormatImpl(
48 NumberFormat *super,
49 const Locale &locale,
50 const UnicodeString &pattern,
51 UErrorCode &status)
52 : fSuper(super),
53 fScale(0),
54 fRoundingMode(DecimalFormat::kRoundHalfEven),
55 fSymbols(NULL),
56 fCurrencyUsage(UCURR_USAGE_STANDARD),
57 fRules(NULL),
58 fMonetary(FALSE) {
59 if (U_FAILURE(status)) {
60 return;
61 }
62 fSymbols = new DecimalFormatSymbols(
63 locale, status);
64 if (fSymbols == NULL) {
65 status = U_MEMORY_ALLOCATION_ERROR;
66 return;
67 }
68 UParseError parseError;
69 applyPattern(pattern, FALSE, parseError, status);
70 updateAll(status);
71 }
72
DecimalFormatImpl(NumberFormat * super,const UnicodeString & pattern,DecimalFormatSymbols * symbolsToAdopt,UParseError & parseError,UErrorCode & status)73 DecimalFormatImpl::DecimalFormatImpl(
74 NumberFormat *super,
75 const UnicodeString &pattern,
76 DecimalFormatSymbols *symbolsToAdopt,
77 UParseError &parseError,
78 UErrorCode &status)
79 : fSuper(super),
80 fScale(0),
81 fRoundingMode(DecimalFormat::kRoundHalfEven),
82 fSymbols(symbolsToAdopt),
83 fCurrencyUsage(UCURR_USAGE_STANDARD),
84 fRules(NULL),
85 fMonetary(FALSE) {
86 applyPattern(pattern, FALSE, parseError, status);
87 updateAll(status);
88 }
89
DecimalFormatImpl(NumberFormat * super,const DecimalFormatImpl & other,UErrorCode & status)90 DecimalFormatImpl::DecimalFormatImpl(
91 NumberFormat *super, const DecimalFormatImpl &other, UErrorCode &status) :
92 fSuper(super),
93 fMultiplier(other.fMultiplier),
94 fScale(other.fScale),
95 fRoundingMode(other.fRoundingMode),
96 fMinSigDigits(other.fMinSigDigits),
97 fMaxSigDigits(other.fMaxSigDigits),
98 fUseScientific(other.fUseScientific),
99 fUseSigDigits(other.fUseSigDigits),
100 fGrouping(other.fGrouping),
101 fPositivePrefixPattern(other.fPositivePrefixPattern),
102 fNegativePrefixPattern(other.fNegativePrefixPattern),
103 fPositiveSuffixPattern(other.fPositiveSuffixPattern),
104 fNegativeSuffixPattern(other.fNegativeSuffixPattern),
105 fSymbols(other.fSymbols),
106 fCurrencyUsage(other.fCurrencyUsage),
107 fRules(NULL),
108 fMonetary(other.fMonetary),
109 fAffixParser(other.fAffixParser),
110 fCurrencyAffixInfo(other.fCurrencyAffixInfo),
111 fEffPrecision(other.fEffPrecision),
112 fEffGrouping(other.fEffGrouping),
113 fOptions(other.fOptions),
114 fFormatter(other.fFormatter),
115 fAffixes(other.fAffixes) {
116 fSymbols = new DecimalFormatSymbols(*fSymbols);
117 if (fSymbols == NULL && U_SUCCESS(status)) {
118 status = U_MEMORY_ALLOCATION_ERROR;
119 }
120 if (other.fRules != NULL) {
121 fRules = new PluralRules(*other.fRules);
122 if (fRules == NULL && U_SUCCESS(status)) {
123 status = U_MEMORY_ALLOCATION_ERROR;
124 }
125 }
126 }
127
128
129 DecimalFormatImpl &
assign(const DecimalFormatImpl & other,UErrorCode & status)130 DecimalFormatImpl::assign(const DecimalFormatImpl &other, UErrorCode &status) {
131 if (U_FAILURE(status) || this == &other) {
132 return (*this);
133 }
134 UObject::operator=(other);
135 fMultiplier = other.fMultiplier;
136 fScale = other.fScale;
137 fRoundingMode = other.fRoundingMode;
138 fMinSigDigits = other.fMinSigDigits;
139 fMaxSigDigits = other.fMaxSigDigits;
140 fUseScientific = other.fUseScientific;
141 fUseSigDigits = other.fUseSigDigits;
142 fGrouping = other.fGrouping;
143 fPositivePrefixPattern = other.fPositivePrefixPattern;
144 fNegativePrefixPattern = other.fNegativePrefixPattern;
145 fPositiveSuffixPattern = other.fPositiveSuffixPattern;
146 fNegativeSuffixPattern = other.fNegativeSuffixPattern;
147 fCurrencyUsage = other.fCurrencyUsage;
148 fMonetary = other.fMonetary;
149 fAffixParser = other.fAffixParser;
150 fCurrencyAffixInfo = other.fCurrencyAffixInfo;
151 fEffPrecision = other.fEffPrecision;
152 fEffGrouping = other.fEffGrouping;
153 fOptions = other.fOptions;
154 fFormatter = other.fFormatter;
155 fAffixes = other.fAffixes;
156 *fSymbols = *other.fSymbols;
157 if (fRules != NULL && other.fRules != NULL) {
158 *fRules = *other.fRules;
159 } else {
160 delete fRules;
161 fRules = other.fRules;
162 if (fRules != NULL) {
163 fRules = new PluralRules(*fRules);
164 if (fRules == NULL) {
165 status = U_MEMORY_ALLOCATION_ERROR;
166 return *this;
167 }
168 }
169 }
170 return *this;
171 }
172
173 UBool
operator ==(const DecimalFormatImpl & other) const174 DecimalFormatImpl::operator==(const DecimalFormatImpl &other) const {
175 if (this == &other) {
176 return TRUE;
177 }
178 return (fMultiplier == other.fMultiplier)
179 && (fScale == other.fScale)
180 && (fRoundingMode == other.fRoundingMode)
181 && (fMinSigDigits == other.fMinSigDigits)
182 && (fMaxSigDigits == other.fMaxSigDigits)
183 && (fUseScientific == other.fUseScientific)
184 && (fUseSigDigits == other.fUseSigDigits)
185 && fGrouping.equals(other.fGrouping)
186 && fPositivePrefixPattern.equals(other.fPositivePrefixPattern)
187 && fNegativePrefixPattern.equals(other.fNegativePrefixPattern)
188 && fPositiveSuffixPattern.equals(other.fPositiveSuffixPattern)
189 && fNegativeSuffixPattern.equals(other.fNegativeSuffixPattern)
190 && fCurrencyUsage == other.fCurrencyUsage
191 && fAffixParser.equals(other.fAffixParser)
192 && fCurrencyAffixInfo.equals(other.fCurrencyAffixInfo)
193 && fEffPrecision.equals(other.fEffPrecision)
194 && fEffGrouping.equals(other.fEffGrouping)
195 && fOptions.equals(other.fOptions)
196 && fFormatter.equals(other.fFormatter)
197 && fAffixes.equals(other.fAffixes)
198 && (*fSymbols == *other.fSymbols)
199 && ((fRules == other.fRules) || (
200 (fRules != NULL) && (other.fRules != NULL)
201 && (*fRules == *other.fRules)))
202 && (fMonetary == other.fMonetary);
203 }
204
~DecimalFormatImpl()205 DecimalFormatImpl::~DecimalFormatImpl() {
206 delete fSymbols;
207 delete fRules;
208 }
209
210 ValueFormatter &
prepareValueFormatter(ValueFormatter & vf) const211 DecimalFormatImpl::prepareValueFormatter(ValueFormatter &vf) const {
212 if (fUseScientific) {
213 vf.prepareScientificFormatting(
214 fFormatter, fEffPrecision, fOptions);
215 return vf;
216 }
217 vf.prepareFixedDecimalFormatting(
218 fFormatter, fEffGrouping, fEffPrecision.fMantissa, fOptions.fMantissa);
219 return vf;
220 }
221
222 int32_t
getPatternScale() const223 DecimalFormatImpl::getPatternScale() const {
224 UBool usesPercent = fPositivePrefixPattern.usesPercent() ||
225 fPositiveSuffixPattern.usesPercent() ||
226 fNegativePrefixPattern.usesPercent() ||
227 fNegativeSuffixPattern.usesPercent();
228 if (usesPercent) {
229 return 2;
230 }
231 UBool usesPermill = fPositivePrefixPattern.usesPermill() ||
232 fPositiveSuffixPattern.usesPermill() ||
233 fNegativePrefixPattern.usesPermill() ||
234 fNegativeSuffixPattern.usesPermill();
235 if (usesPermill) {
236 return 3;
237 }
238 return 0;
239 }
240
241 void
setMultiplierScale(int32_t scale)242 DecimalFormatImpl::setMultiplierScale(int32_t scale) {
243 if (scale == 0) {
244 // Needed to preserve equality. fMultiplier == 0 means
245 // multiplier is 1.
246 fMultiplier.set((int32_t)0);
247 } else {
248 fMultiplier.set((int32_t)1);
249 fMultiplier.shiftDecimalRight(scale);
250 }
251 }
252
253 UnicodeString &
format(int32_t number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const254 DecimalFormatImpl::format(
255 int32_t number,
256 UnicodeString &appendTo,
257 FieldPosition &pos,
258 UErrorCode &status) const {
259 FieldPositionOnlyHandler handler(pos);
260 return formatInt32(number, appendTo, handler, status);
261 }
262
263 UnicodeString &
format(int32_t number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const264 DecimalFormatImpl::format(
265 int32_t number,
266 UnicodeString &appendTo,
267 FieldPositionIterator *posIter,
268 UErrorCode &status) const {
269 FieldPositionIteratorHandler handler(posIter, status);
270 return formatInt32(number, appendTo, handler, status);
271 }
272
273 template<class T>
maybeFormatWithDigitList(T number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const274 UBool DecimalFormatImpl::maybeFormatWithDigitList(
275 T number,
276 UnicodeString &appendTo,
277 FieldPositionHandler &handler,
278 UErrorCode &status) const {
279 if (!fMultiplier.isZero()) {
280 DigitList digits;
281 digits.set(number);
282 digits.mult(fMultiplier, status);
283 digits.shiftDecimalRight(fScale);
284 formatAdjustedDigitList(digits, appendTo, handler, status);
285 return TRUE;
286 }
287 if (fScale != 0) {
288 DigitList digits;
289 digits.set(number);
290 digits.shiftDecimalRight(fScale);
291 formatAdjustedDigitList(digits, appendTo, handler, status);
292 return TRUE;
293 }
294 return FALSE;
295 }
296
297 template<class T>
maybeInitVisibleDigitsFromDigitList(T number,VisibleDigitsWithExponent & visibleDigits,UErrorCode & status) const298 UBool DecimalFormatImpl::maybeInitVisibleDigitsFromDigitList(
299 T number,
300 VisibleDigitsWithExponent &visibleDigits,
301 UErrorCode &status) const {
302 if (!fMultiplier.isZero()) {
303 DigitList digits;
304 digits.set(number);
305 digits.mult(fMultiplier, status);
306 digits.shiftDecimalRight(fScale);
307 initVisibleDigitsFromAdjusted(digits, visibleDigits, status);
308 return TRUE;
309 }
310 if (fScale != 0) {
311 DigitList digits;
312 digits.set(number);
313 digits.shiftDecimalRight(fScale);
314 initVisibleDigitsFromAdjusted(digits, visibleDigits, status);
315 return TRUE;
316 }
317 return FALSE;
318 }
319
320 UnicodeString &
formatInt32(int32_t number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const321 DecimalFormatImpl::formatInt32(
322 int32_t number,
323 UnicodeString &appendTo,
324 FieldPositionHandler &handler,
325 UErrorCode &status) const {
326 if (maybeFormatWithDigitList(number, appendTo, handler, status)) {
327 return appendTo;
328 }
329 ValueFormatter vf;
330 return fAffixes.formatInt32(
331 number,
332 prepareValueFormatter(vf),
333 handler,
334 fRules,
335 appendTo,
336 status);
337 }
338
339 UnicodeString &
formatInt64(int64_t number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const340 DecimalFormatImpl::formatInt64(
341 int64_t number,
342 UnicodeString &appendTo,
343 FieldPositionHandler &handler,
344 UErrorCode &status) const {
345 if (number >= INT32_MIN && number <= INT32_MAX) {
346 return formatInt32((int32_t) number, appendTo, handler, status);
347 }
348 VisibleDigitsWithExponent digits;
349 initVisibleDigitsWithExponent(number, digits, status);
350 return formatVisibleDigitsWithExponent(
351 digits, appendTo, handler, status);
352 }
353
354 UnicodeString &
formatDouble(double number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const355 DecimalFormatImpl::formatDouble(
356 double number,
357 UnicodeString &appendTo,
358 FieldPositionHandler &handler,
359 UErrorCode &status) const {
360 VisibleDigitsWithExponent digits;
361 initVisibleDigitsWithExponent(number, digits, status);
362 return formatVisibleDigitsWithExponent(
363 digits, appendTo, handler, status);
364 }
365
366 UnicodeString &
format(double number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const367 DecimalFormatImpl::format(
368 double number,
369 UnicodeString &appendTo,
370 FieldPosition &pos,
371 UErrorCode &status) const {
372 FieldPositionOnlyHandler handler(pos);
373 return formatDouble(number, appendTo, handler, status);
374 }
375
376 UnicodeString &
format(const DigitList & number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const377 DecimalFormatImpl::format(
378 const DigitList &number,
379 UnicodeString &appendTo,
380 FieldPosition &pos,
381 UErrorCode &status) const {
382 DigitList dl(number);
383 FieldPositionOnlyHandler handler(pos);
384 return formatDigitList(dl, appendTo, handler, status);
385 }
386
387 UnicodeString &
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const388 DecimalFormatImpl::format(
389 int64_t number,
390 UnicodeString &appendTo,
391 FieldPosition &pos,
392 UErrorCode &status) const {
393 FieldPositionOnlyHandler handler(pos);
394 return formatInt64(number, appendTo, handler, status);
395 }
396
397 UnicodeString &
format(int64_t number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const398 DecimalFormatImpl::format(
399 int64_t number,
400 UnicodeString &appendTo,
401 FieldPositionIterator *posIter,
402 UErrorCode &status) const {
403 FieldPositionIteratorHandler handler(posIter, status);
404 return formatInt64(number, appendTo, handler, status);
405 }
406
407 UnicodeString &
format(double number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const408 DecimalFormatImpl::format(
409 double number,
410 UnicodeString &appendTo,
411 FieldPositionIterator *posIter,
412 UErrorCode &status) const {
413 FieldPositionIteratorHandler handler(posIter, status);
414 return formatDouble(number, appendTo, handler, status);
415 }
416
417 UnicodeString &
format(const DigitList & number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const418 DecimalFormatImpl::format(
419 const DigitList &number,
420 UnicodeString &appendTo,
421 FieldPositionIterator *posIter,
422 UErrorCode &status) const {
423 DigitList dl(number);
424 FieldPositionIteratorHandler handler(posIter, status);
425 return formatDigitList(dl, appendTo, handler, status);
426 }
427
428 UnicodeString &
format(StringPiece number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const429 DecimalFormatImpl::format(
430 StringPiece number,
431 UnicodeString &appendTo,
432 FieldPositionIterator *posIter,
433 UErrorCode &status) const {
434 DigitList dl;
435 dl.set(number, status);
436 FieldPositionIteratorHandler handler(posIter, status);
437 return formatDigitList(dl, appendTo, handler, status);
438 }
439
440 UnicodeString &
format(const VisibleDigitsWithExponent & digits,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const441 DecimalFormatImpl::format(
442 const VisibleDigitsWithExponent &digits,
443 UnicodeString &appendTo,
444 FieldPosition &pos,
445 UErrorCode &status) const {
446 FieldPositionOnlyHandler handler(pos);
447 return formatVisibleDigitsWithExponent(
448 digits, appendTo, handler, status);
449 }
450
451 UnicodeString &
format(const VisibleDigitsWithExponent & digits,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const452 DecimalFormatImpl::format(
453 const VisibleDigitsWithExponent &digits,
454 UnicodeString &appendTo,
455 FieldPositionIterator *posIter,
456 UErrorCode &status) const {
457 FieldPositionIteratorHandler handler(posIter, status);
458 return formatVisibleDigitsWithExponent(
459 digits, appendTo, handler, status);
460 }
461
462 DigitList &
adjustDigitList(DigitList & number,UErrorCode & status) const463 DecimalFormatImpl::adjustDigitList(
464 DigitList &number, UErrorCode &status) const {
465 number.setRoundingMode(fRoundingMode);
466 if (!fMultiplier.isZero()) {
467 number.mult(fMultiplier, status);
468 }
469 if (fScale != 0) {
470 number.shiftDecimalRight(fScale);
471 }
472 number.reduce();
473 return number;
474 }
475
476 UnicodeString &
formatDigitList(DigitList & number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const477 DecimalFormatImpl::formatDigitList(
478 DigitList &number,
479 UnicodeString &appendTo,
480 FieldPositionHandler &handler,
481 UErrorCode &status) const {
482 VisibleDigitsWithExponent digits;
483 initVisibleDigitsWithExponent(number, digits, status);
484 return formatVisibleDigitsWithExponent(
485 digits, appendTo, handler, status);
486 }
487
488 UnicodeString &
formatAdjustedDigitList(DigitList & number,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const489 DecimalFormatImpl::formatAdjustedDigitList(
490 DigitList &number,
491 UnicodeString &appendTo,
492 FieldPositionHandler &handler,
493 UErrorCode &status) const {
494 ValueFormatter vf;
495 return fAffixes.format(
496 number,
497 prepareValueFormatter(vf),
498 handler,
499 fRules,
500 appendTo,
501 status);
502 }
503
504 UnicodeString &
formatVisibleDigitsWithExponent(const VisibleDigitsWithExponent & digits,UnicodeString & appendTo,FieldPositionHandler & handler,UErrorCode & status) const505 DecimalFormatImpl::formatVisibleDigitsWithExponent(
506 const VisibleDigitsWithExponent &digits,
507 UnicodeString &appendTo,
508 FieldPositionHandler &handler,
509 UErrorCode &status) const {
510 ValueFormatter vf;
511 return fAffixes.format(
512 digits,
513 prepareValueFormatter(vf),
514 handler,
515 fRules,
516 appendTo,
517 status);
518 }
519
initFixedDecimal(const VisibleDigits & digits,FixedDecimal & result)520 static FixedDecimal &initFixedDecimal(
521 const VisibleDigits &digits, FixedDecimal &result) {
522 result.source = 0.0;
523 result.isNegative = digits.isNegative();
524 result._isNaN = digits.isNaN();
525 result._isInfinite = digits.isInfinite();
526 digits.getFixedDecimal(
527 result.source, result.intValue, result.decimalDigits,
528 result.decimalDigitsWithoutTrailingZeros,
529 result.visibleDecimalDigitCount, result.hasIntegerValue);
530 return result;
531 }
532
533 FixedDecimal &
getFixedDecimal(double number,FixedDecimal & result,UErrorCode & status) const534 DecimalFormatImpl::getFixedDecimal(double number, FixedDecimal &result, UErrorCode &status) const {
535 if (U_FAILURE(status)) {
536 return result;
537 }
538 VisibleDigits digits;
539 fEffPrecision.fMantissa.initVisibleDigits(number, digits, status);
540 return initFixedDecimal(digits, result);
541 }
542
543 FixedDecimal &
getFixedDecimal(DigitList & number,FixedDecimal & result,UErrorCode & status) const544 DecimalFormatImpl::getFixedDecimal(
545 DigitList &number, FixedDecimal &result, UErrorCode &status) const {
546 if (U_FAILURE(status)) {
547 return result;
548 }
549 VisibleDigits digits;
550 fEffPrecision.fMantissa.initVisibleDigits(number, digits, status);
551 return initFixedDecimal(digits, result);
552 }
553
554 VisibleDigitsWithExponent &
initVisibleDigitsWithExponent(int64_t number,VisibleDigitsWithExponent & digits,UErrorCode & status) const555 DecimalFormatImpl::initVisibleDigitsWithExponent(
556 int64_t number,
557 VisibleDigitsWithExponent &digits,
558 UErrorCode &status) const {
559 if (maybeInitVisibleDigitsFromDigitList(
560 number, digits, status)) {
561 return digits;
562 }
563 if (fUseScientific) {
564 fEffPrecision.initVisibleDigitsWithExponent(
565 number, digits, status);
566 } else {
567 fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
568 number, digits, status);
569 }
570 return digits;
571 }
572
573 VisibleDigitsWithExponent &
initVisibleDigitsWithExponent(double number,VisibleDigitsWithExponent & digits,UErrorCode & status) const574 DecimalFormatImpl::initVisibleDigitsWithExponent(
575 double number,
576 VisibleDigitsWithExponent &digits,
577 UErrorCode &status) const {
578 if (maybeInitVisibleDigitsFromDigitList(
579 number, digits, status)) {
580 return digits;
581 }
582 if (fUseScientific) {
583 fEffPrecision.initVisibleDigitsWithExponent(
584 number, digits, status);
585 } else {
586 fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
587 number, digits, status);
588 }
589 return digits;
590 }
591
592 VisibleDigitsWithExponent &
initVisibleDigitsWithExponent(DigitList & number,VisibleDigitsWithExponent & digits,UErrorCode & status) const593 DecimalFormatImpl::initVisibleDigitsWithExponent(
594 DigitList &number,
595 VisibleDigitsWithExponent &digits,
596 UErrorCode &status) const {
597 adjustDigitList(number, status);
598 return initVisibleDigitsFromAdjusted(number, digits, status);
599 }
600
601 VisibleDigitsWithExponent &
initVisibleDigitsFromAdjusted(DigitList & number,VisibleDigitsWithExponent & digits,UErrorCode & status) const602 DecimalFormatImpl::initVisibleDigitsFromAdjusted(
603 DigitList &number,
604 VisibleDigitsWithExponent &digits,
605 UErrorCode &status) const {
606 if (fUseScientific) {
607 fEffPrecision.initVisibleDigitsWithExponent(
608 number, digits, status);
609 } else {
610 fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
611 number, digits, status);
612 }
613 return digits;
614 }
615
616 DigitList &
round(DigitList & number,UErrorCode & status) const617 DecimalFormatImpl::round(
618 DigitList &number, UErrorCode &status) const {
619 if (number.isNaN() || number.isInfinite()) {
620 return number;
621 }
622 adjustDigitList(number, status);
623 ValueFormatter vf;
624 prepareValueFormatter(vf);
625 return vf.round(number, status);
626 }
627
628 void
setMinimumSignificantDigits(int32_t newValue)629 DecimalFormatImpl::setMinimumSignificantDigits(int32_t newValue) {
630 fMinSigDigits = newValue;
631 fUseSigDigits = TRUE; // ticket 9936
632 updatePrecision();
633 }
634
635 void
setMaximumSignificantDigits(int32_t newValue)636 DecimalFormatImpl::setMaximumSignificantDigits(int32_t newValue) {
637 fMaxSigDigits = newValue;
638 fUseSigDigits = TRUE; // ticket 9936
639 updatePrecision();
640 }
641
642 void
setMinMaxSignificantDigits(int32_t min,int32_t max)643 DecimalFormatImpl::setMinMaxSignificantDigits(int32_t min, int32_t max) {
644 fMinSigDigits = min;
645 fMaxSigDigits = max;
646 fUseSigDigits = TRUE; // ticket 9936
647 updatePrecision();
648 }
649
650 void
setScientificNotation(UBool newValue)651 DecimalFormatImpl::setScientificNotation(UBool newValue) {
652 fUseScientific = newValue;
653 updatePrecision();
654 }
655
656 void
setSignificantDigitsUsed(UBool newValue)657 DecimalFormatImpl::setSignificantDigitsUsed(UBool newValue) {
658 fUseSigDigits = newValue;
659 updatePrecision();
660 }
661
662 void
setGroupingSize(int32_t newValue)663 DecimalFormatImpl::setGroupingSize(int32_t newValue) {
664 fGrouping.fGrouping = newValue;
665 updateGrouping();
666 }
667
668 void
setSecondaryGroupingSize(int32_t newValue)669 DecimalFormatImpl::setSecondaryGroupingSize(int32_t newValue) {
670 fGrouping.fGrouping2 = newValue;
671 updateGrouping();
672 }
673
674 void
setMinimumGroupingDigits(int32_t newValue)675 DecimalFormatImpl::setMinimumGroupingDigits(int32_t newValue) {
676 fGrouping.fMinGrouping = newValue;
677 updateGrouping();
678 }
679
680 void
setCurrencyUsage(UCurrencyUsage currencyUsage,UErrorCode & status)681 DecimalFormatImpl::setCurrencyUsage(
682 UCurrencyUsage currencyUsage, UErrorCode &status) {
683 fCurrencyUsage = currencyUsage;
684 updateFormatting(kFormattingCurrency, status);
685 }
686
687 void
setRoundingIncrement(double d)688 DecimalFormatImpl::setRoundingIncrement(double d) {
689 if (d > 0.0) {
690 fEffPrecision.fMantissa.fRoundingIncrement.set(d);
691 } else {
692 fEffPrecision.fMantissa.fRoundingIncrement.set(0.0);
693 }
694 }
695
696 double
getRoundingIncrement() const697 DecimalFormatImpl::getRoundingIncrement() const {
698 return fEffPrecision.fMantissa.fRoundingIncrement.getDouble();
699 }
700
701 int32_t
getMultiplier() const702 DecimalFormatImpl::getMultiplier() const {
703 if (fMultiplier.isZero()) {
704 return 1;
705 }
706 return (int32_t) fMultiplier.getDouble();
707 }
708
709 void
setMultiplier(int32_t m)710 DecimalFormatImpl::setMultiplier(int32_t m) {
711 if (m == 0 || m == 1) {
712 fMultiplier.set((int32_t)0);
713 } else {
714 fMultiplier.set(m);
715 }
716 }
717
718 void
setPositivePrefix(const UnicodeString & str)719 DecimalFormatImpl::setPositivePrefix(const UnicodeString &str) {
720 fPositivePrefixPattern.remove();
721 fPositivePrefixPattern.addLiteral(str.getBuffer(), 0, str.length());
722 UErrorCode status = U_ZERO_ERROR;
723 updateFormatting(kFormattingPosPrefix, status);
724 }
725
726 void
setPositiveSuffix(const UnicodeString & str)727 DecimalFormatImpl::setPositiveSuffix(const UnicodeString &str) {
728 fPositiveSuffixPattern.remove();
729 fPositiveSuffixPattern.addLiteral(str.getBuffer(), 0, str.length());
730 UErrorCode status = U_ZERO_ERROR;
731 updateFormatting(kFormattingPosSuffix, status);
732 }
733
734 void
setNegativePrefix(const UnicodeString & str)735 DecimalFormatImpl::setNegativePrefix(const UnicodeString &str) {
736 fNegativePrefixPattern.remove();
737 fNegativePrefixPattern.addLiteral(str.getBuffer(), 0, str.length());
738 UErrorCode status = U_ZERO_ERROR;
739 updateFormatting(kFormattingNegPrefix, status);
740 }
741
742 void
setNegativeSuffix(const UnicodeString & str)743 DecimalFormatImpl::setNegativeSuffix(const UnicodeString &str) {
744 fNegativeSuffixPattern.remove();
745 fNegativeSuffixPattern.addLiteral(str.getBuffer(), 0, str.length());
746 UErrorCode status = U_ZERO_ERROR;
747 updateFormatting(kFormattingNegSuffix, status);
748 }
749
750 UnicodeString &
getPositivePrefix(UnicodeString & result) const751 DecimalFormatImpl::getPositivePrefix(UnicodeString &result) const {
752 result = fAffixes.fPositivePrefix.getOtherVariant().toString();
753 return result;
754 }
755
756 UnicodeString &
getPositiveSuffix(UnicodeString & result) const757 DecimalFormatImpl::getPositiveSuffix(UnicodeString &result) const {
758 result = fAffixes.fPositiveSuffix.getOtherVariant().toString();
759 return result;
760 }
761
762 UnicodeString &
getNegativePrefix(UnicodeString & result) const763 DecimalFormatImpl::getNegativePrefix(UnicodeString &result) const {
764 result = fAffixes.fNegativePrefix.getOtherVariant().toString();
765 return result;
766 }
767
768 UnicodeString &
getNegativeSuffix(UnicodeString & result) const769 DecimalFormatImpl::getNegativeSuffix(UnicodeString &result) const {
770 result = fAffixes.fNegativeSuffix.getOtherVariant().toString();
771 return result;
772 }
773
774 void
adoptDecimalFormatSymbols(DecimalFormatSymbols * symbolsToAdopt)775 DecimalFormatImpl::adoptDecimalFormatSymbols(DecimalFormatSymbols *symbolsToAdopt) {
776 if (symbolsToAdopt == NULL) {
777 return;
778 }
779 delete fSymbols;
780 fSymbols = symbolsToAdopt;
781 UErrorCode status = U_ZERO_ERROR;
782 updateFormatting(kFormattingSymbols, status);
783 }
784
785 void
applyPatternFavorCurrencyPrecision(const UnicodeString & pattern,UErrorCode & status)786 DecimalFormatImpl::applyPatternFavorCurrencyPrecision(
787 const UnicodeString &pattern, UErrorCode &status) {
788 UParseError perror;
789 applyPattern(pattern, FALSE, perror, status);
790 updateForApplyPatternFavorCurrencyPrecision(status);
791 }
792
793 void
applyPattern(const UnicodeString & pattern,UErrorCode & status)794 DecimalFormatImpl::applyPattern(
795 const UnicodeString &pattern, UErrorCode &status) {
796 UParseError perror;
797 applyPattern(pattern, FALSE, perror, status);
798 updateForApplyPattern(status);
799 }
800
801 void
applyPattern(const UnicodeString & pattern,UParseError & perror,UErrorCode & status)802 DecimalFormatImpl::applyPattern(
803 const UnicodeString &pattern,
804 UParseError &perror, UErrorCode &status) {
805 applyPattern(pattern, FALSE, perror, status);
806 updateForApplyPattern(status);
807 }
808
809 void
applyLocalizedPattern(const UnicodeString & pattern,UErrorCode & status)810 DecimalFormatImpl::applyLocalizedPattern(
811 const UnicodeString &pattern, UErrorCode &status) {
812 UParseError perror;
813 applyPattern(pattern, TRUE, perror, status);
814 updateForApplyPattern(status);
815 }
816
817 void
applyLocalizedPattern(const UnicodeString & pattern,UParseError & perror,UErrorCode & status)818 DecimalFormatImpl::applyLocalizedPattern(
819 const UnicodeString &pattern,
820 UParseError &perror, UErrorCode &status) {
821 applyPattern(pattern, TRUE, perror, status);
822 updateForApplyPattern(status);
823 }
824
825 void
applyPattern(const UnicodeString & pattern,UBool localized,UParseError & perror,UErrorCode & status)826 DecimalFormatImpl::applyPattern(
827 const UnicodeString &pattern,
828 UBool localized, UParseError &perror, UErrorCode &status) {
829 if (U_FAILURE(status)) {
830 return;
831 }
832 DecimalFormatPatternParser patternParser;
833 if (localized) {
834 patternParser.useSymbols(*fSymbols);
835 }
836 DecimalFormatPattern out;
837 patternParser.applyPatternWithoutExpandAffix(
838 pattern, out, perror, status);
839 if (U_FAILURE(status)) {
840 return;
841 }
842 fUseScientific = out.fUseExponentialNotation;
843 fUseSigDigits = out.fUseSignificantDigits;
844 fSuper->NumberFormat::setMinimumIntegerDigits(out.fMinimumIntegerDigits);
845 fSuper->NumberFormat::setMaximumIntegerDigits(out.fMaximumIntegerDigits);
846 fSuper->NumberFormat::setMinimumFractionDigits(out.fMinimumFractionDigits);
847 fSuper->NumberFormat::setMaximumFractionDigits(out.fMaximumFractionDigits);
848 fMinSigDigits = out.fMinimumSignificantDigits;
849 fMaxSigDigits = out.fMaximumSignificantDigits;
850 fEffPrecision.fMinExponentDigits = out.fMinExponentDigits;
851 fOptions.fExponent.fAlwaysShowSign = out.fExponentSignAlwaysShown;
852 fSuper->NumberFormat::setGroupingUsed(out.fGroupingUsed);
853 fGrouping.fGrouping = out.fGroupingSize;
854 fGrouping.fGrouping2 = out.fGroupingSize2;
855 fOptions.fMantissa.fAlwaysShowDecimal = out.fDecimalSeparatorAlwaysShown;
856 if (out.fRoundingIncrementUsed) {
857 fEffPrecision.fMantissa.fRoundingIncrement = out.fRoundingIncrement;
858 } else {
859 fEffPrecision.fMantissa.fRoundingIncrement.clear();
860 }
861 fAffixes.fPadChar = out.fPad;
862 fNegativePrefixPattern = out.fNegPrefixAffix;
863 fNegativeSuffixPattern = out.fNegSuffixAffix;
864 fPositivePrefixPattern = out.fPosPrefixAffix;
865 fPositiveSuffixPattern = out.fPosSuffixAffix;
866
867 // Work around. Pattern parsing code and DecimalFormat code don't agree
868 // on the definition of field width, so we have to translate from
869 // pattern field width to decimal format field width here.
870 fAffixes.fWidth = out.fFormatWidth == 0 ? 0 :
871 out.fFormatWidth + fPositivePrefixPattern.countChar32()
872 + fPositiveSuffixPattern.countChar32();
873 switch (out.fPadPosition) {
874 case DecimalFormatPattern::kPadBeforePrefix:
875 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforePrefix;
876 break;
877 case DecimalFormatPattern::kPadAfterPrefix:
878 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterPrefix;
879 break;
880 case DecimalFormatPattern::kPadBeforeSuffix:
881 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforeSuffix;
882 break;
883 case DecimalFormatPattern::kPadAfterSuffix:
884 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterSuffix;
885 break;
886 default:
887 break;
888 }
889 }
890
891 void
updatePrecision()892 DecimalFormatImpl::updatePrecision() {
893 if (fUseScientific) {
894 updatePrecisionForScientific();
895 } else {
896 updatePrecisionForFixed();
897 }
898 }
899
updatePrecisionForScientificMinMax(const DigitInterval & min,const DigitInterval & max,DigitInterval & resultMin,DigitInterval & resultMax,SignificantDigitInterval & resultSignificant)900 static void updatePrecisionForScientificMinMax(
901 const DigitInterval &min,
902 const DigitInterval &max,
903 DigitInterval &resultMin,
904 DigitInterval &resultMax,
905 SignificantDigitInterval &resultSignificant) {
906 resultMin.setIntDigitCount(0);
907 resultMin.setFracDigitCount(0);
908 resultSignificant.clear();
909 resultMax.clear();
910
911 int32_t maxIntDigitCount = max.getIntDigitCount();
912 int32_t minIntDigitCount = min.getIntDigitCount();
913 int32_t maxFracDigitCount = max.getFracDigitCount();
914 int32_t minFracDigitCount = min.getFracDigitCount();
915
916
917 // Not in spec: maxIntDigitCount > 8 assume
918 // maxIntDigitCount = minIntDigitCount. Current DecimalFormat API has
919 // no provision for unsetting maxIntDigitCount which would be useful for
920 // scientific notation. The best we can do is assume that if
921 // maxIntDigitCount is the default of 2000000000 or is "big enough" then
922 // user did not intend to explicitly set it. The 8 was derived emperically
923 // by extensive testing of legacy code.
924 if (maxIntDigitCount > 8) {
925 maxIntDigitCount = minIntDigitCount;
926 }
927
928 // Per the spec, exponent grouping happens if maxIntDigitCount is more
929 // than 1 and more than minIntDigitCount.
930 UBool bExponentGrouping = maxIntDigitCount > 1 && minIntDigitCount < maxIntDigitCount;
931 if (bExponentGrouping) {
932 resultMax.setIntDigitCount(maxIntDigitCount);
933
934 // For exponent grouping minIntDigits is always treated as 1 even
935 // if it wasn't set to 1!
936 resultMin.setIntDigitCount(1);
937 } else {
938 // Fixed digit count left of decimal. minIntDigitCount doesn't have
939 // to equal maxIntDigitCount i.e minIntDigitCount == 0 while
940 // maxIntDigitCount == 1.
941 int32_t fixedIntDigitCount = maxIntDigitCount;
942
943 // If fixedIntDigitCount is 0 but
944 // min or max fraction count is 0 too then use 1. This way we can get
945 // unlimited precision for X.XXXEX
946 if (fixedIntDigitCount == 0 && (minFracDigitCount == 0 || maxFracDigitCount == 0)) {
947 fixedIntDigitCount = 1;
948 }
949 resultMax.setIntDigitCount(fixedIntDigitCount);
950 resultMin.setIntDigitCount(fixedIntDigitCount);
951 }
952 // Spec says this is how we compute significant digits. 0 means
953 // unlimited significant digits.
954 int32_t maxSigDigits = minIntDigitCount + maxFracDigitCount;
955 if (maxSigDigits > 0) {
956 int32_t minSigDigits = minIntDigitCount + minFracDigitCount;
957 resultSignificant.setMin(minSigDigits);
958 resultSignificant.setMax(maxSigDigits);
959 }
960 }
961
962 void
updatePrecisionForScientific()963 DecimalFormatImpl::updatePrecisionForScientific() {
964 FixedPrecision *result = &fEffPrecision.fMantissa;
965 if (fUseSigDigits) {
966 result->fMax.setFracDigitCount(-1);
967 result->fMax.setIntDigitCount(1);
968 result->fMin.setFracDigitCount(0);
969 result->fMin.setIntDigitCount(1);
970 result->fSignificant.clear();
971 extractSigDigits(result->fSignificant);
972 return;
973 }
974 DigitInterval max;
975 DigitInterval min;
976 extractMinMaxDigits(min, max);
977 updatePrecisionForScientificMinMax(
978 min, max,
979 result->fMin, result->fMax, result->fSignificant);
980 }
981
982 void
updatePrecisionForFixed()983 DecimalFormatImpl::updatePrecisionForFixed() {
984 FixedPrecision *result = &fEffPrecision.fMantissa;
985 if (!fUseSigDigits) {
986 extractMinMaxDigits(result->fMin, result->fMax);
987 result->fSignificant.clear();
988 } else {
989 extractSigDigits(result->fSignificant);
990 result->fMin.setIntDigitCount(1);
991 result->fMin.setFracDigitCount(0);
992 result->fMax.clear();
993 }
994 }
995
996 void
extractMinMaxDigits(DigitInterval & min,DigitInterval & max) const997 DecimalFormatImpl::extractMinMaxDigits(
998 DigitInterval &min, DigitInterval &max) const {
999 min.setIntDigitCount(fSuper->getMinimumIntegerDigits());
1000 max.setIntDigitCount(fSuper->getMaximumIntegerDigits());
1001 min.setFracDigitCount(fSuper->getMinimumFractionDigits());
1002 max.setFracDigitCount(fSuper->getMaximumFractionDigits());
1003 }
1004
1005 void
extractSigDigits(SignificantDigitInterval & sig) const1006 DecimalFormatImpl::extractSigDigits(
1007 SignificantDigitInterval &sig) const {
1008 sig.setMin(fMinSigDigits < 0 ? 0 : fMinSigDigits);
1009 sig.setMax(fMaxSigDigits < 0 ? 0 : fMaxSigDigits);
1010 }
1011
1012 void
updateGrouping()1013 DecimalFormatImpl::updateGrouping() {
1014 if (fSuper->isGroupingUsed()) {
1015 fEffGrouping = fGrouping;
1016 } else {
1017 fEffGrouping.clear();
1018 }
1019 }
1020
1021 void
updateCurrency(UErrorCode & status)1022 DecimalFormatImpl::updateCurrency(UErrorCode &status) {
1023 updateFormatting(kFormattingCurrency, TRUE, status);
1024 }
1025
1026 void
updateFormatting(int32_t changedFormattingFields,UErrorCode & status)1027 DecimalFormatImpl::updateFormatting(
1028 int32_t changedFormattingFields,
1029 UErrorCode &status) {
1030 updateFormatting(changedFormattingFields, TRUE, status);
1031 }
1032
1033 void
updateFormatting(int32_t changedFormattingFields,UBool updatePrecisionBasedOnCurrency,UErrorCode & status)1034 DecimalFormatImpl::updateFormatting(
1035 int32_t changedFormattingFields,
1036 UBool updatePrecisionBasedOnCurrency,
1037 UErrorCode &status) {
1038 if (U_FAILURE(status)) {
1039 return;
1040 }
1041 // Each function updates one field. Order matters. For instance,
1042 // updatePluralRules comes before updateCurrencyAffixInfo because the
1043 // fRules field is needed to update the fCurrencyAffixInfo field.
1044 updateFormattingUsesCurrency(changedFormattingFields);
1045 updateFormattingFixedPointFormatter(changedFormattingFields);
1046 updateFormattingAffixParser(changedFormattingFields);
1047 updateFormattingPluralRules(changedFormattingFields, status);
1048 updateFormattingCurrencyAffixInfo(
1049 changedFormattingFields,
1050 updatePrecisionBasedOnCurrency,
1051 status);
1052 updateFormattingLocalizedPositivePrefix(
1053 changedFormattingFields, status);
1054 updateFormattingLocalizedPositiveSuffix(
1055 changedFormattingFields, status);
1056 updateFormattingLocalizedNegativePrefix(
1057 changedFormattingFields, status);
1058 updateFormattingLocalizedNegativeSuffix(
1059 changedFormattingFields, status);
1060 }
1061
1062 void
updateFormattingUsesCurrency(int32_t & changedFormattingFields)1063 DecimalFormatImpl::updateFormattingUsesCurrency(
1064 int32_t &changedFormattingFields) {
1065 if ((changedFormattingFields & kFormattingAffixes) == 0) {
1066 // If no affixes changed, don't need to do any work
1067 return;
1068 }
1069 UBool newUsesCurrency =
1070 fPositivePrefixPattern.usesCurrency() ||
1071 fPositiveSuffixPattern.usesCurrency() ||
1072 fNegativePrefixPattern.usesCurrency() ||
1073 fNegativeSuffixPattern.usesCurrency();
1074 if (fMonetary != newUsesCurrency) {
1075 fMonetary = newUsesCurrency;
1076 changedFormattingFields |= kFormattingUsesCurrency;
1077 }
1078 }
1079
1080 void
updateFormattingPluralRules(int32_t & changedFormattingFields,UErrorCode & status)1081 DecimalFormatImpl::updateFormattingPluralRules(
1082 int32_t &changedFormattingFields, UErrorCode &status) {
1083 if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) {
1084 // No work to do if both fSymbols and fMonetary
1085 // fields are unchanged
1086 return;
1087 }
1088 if (U_FAILURE(status)) {
1089 return;
1090 }
1091 PluralRules *newRules = NULL;
1092 if (fMonetary) {
1093 newRules = PluralRules::forLocale(fSymbols->getLocale(), status);
1094 if (U_FAILURE(status)) {
1095 return;
1096 }
1097 }
1098 // Its ok to say a field has changed when it really hasn't but not
1099 // the other way around. Here we assume the field changed unless it
1100 // was NULL before and is still NULL now
1101 if (fRules != newRules) {
1102 delete fRules;
1103 fRules = newRules;
1104 changedFormattingFields |= kFormattingPluralRules;
1105 }
1106 }
1107
1108 void
updateFormattingCurrencyAffixInfo(int32_t & changedFormattingFields,UBool updatePrecisionBasedOnCurrency,UErrorCode & status)1109 DecimalFormatImpl::updateFormattingCurrencyAffixInfo(
1110 int32_t &changedFormattingFields,
1111 UBool updatePrecisionBasedOnCurrency,
1112 UErrorCode &status) {
1113 if ((changedFormattingFields & (
1114 kFormattingSymbols | kFormattingCurrency |
1115 kFormattingUsesCurrency | kFormattingPluralRules)) == 0) {
1116 // If all these fields are unchanged, no work to do.
1117 return;
1118 }
1119 if (U_FAILURE(status)) {
1120 return;
1121 }
1122 if (!fMonetary) {
1123 if (fCurrencyAffixInfo.isDefault()) {
1124 // In this case don't have to do any work
1125 return;
1126 }
1127 fCurrencyAffixInfo.set(NULL, NULL, NULL, status);
1128 if (U_FAILURE(status)) {
1129 return;
1130 }
1131 changedFormattingFields |= kFormattingCurrencyAffixInfo;
1132 } else {
1133 const UChar *currency = fSuper->getCurrency();
1134 UChar localeCurr[4];
1135 if (currency[0] == 0) {
1136 ucurr_forLocale(fSymbols->getLocale().getName(), localeCurr, UPRV_LENGTHOF(localeCurr), &status);
1137 if (U_SUCCESS(status)) {
1138 currency = localeCurr;
1139 fSuper->NumberFormat::setCurrency(currency, status);
1140 } else {
1141 currency = NULL;
1142 status = U_ZERO_ERROR;
1143 }
1144 }
1145 fCurrencyAffixInfo.set(
1146 fSymbols->getLocale().getName(), fRules, currency, status);
1147 if (U_FAILURE(status)) {
1148 return;
1149 }
1150 UBool customCurrencySymbol = FALSE;
1151 // If DecimalFormatSymbols has custom currency symbol, prefer
1152 // that over what we just read from the resource bundles
1153 if (fSymbols->isCustomCurrencySymbol()) {
1154 fCurrencyAffixInfo.setSymbol(
1155 fSymbols->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
1156 customCurrencySymbol = TRUE;
1157 }
1158 if (fSymbols->isCustomIntlCurrencySymbol()) {
1159 fCurrencyAffixInfo.setISO(
1160 fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1161 customCurrencySymbol = TRUE;
1162 }
1163 changedFormattingFields |= kFormattingCurrencyAffixInfo;
1164 if (currency && !customCurrencySymbol && updatePrecisionBasedOnCurrency) {
1165 FixedPrecision precision;
1166 CurrencyAffixInfo::adjustPrecision(
1167 currency, fCurrencyUsage, precision, status);
1168 if (U_FAILURE(status)) {
1169 return;
1170 }
1171 fSuper->NumberFormat::setMinimumFractionDigits(
1172 precision.fMin.getFracDigitCount());
1173 fSuper->NumberFormat::setMaximumFractionDigits(
1174 precision.fMax.getFracDigitCount());
1175 updatePrecision();
1176 fEffPrecision.fMantissa.fRoundingIncrement =
1177 precision.fRoundingIncrement;
1178 }
1179
1180 }
1181 }
1182
1183 void
updateFormattingFixedPointFormatter(int32_t & changedFormattingFields)1184 DecimalFormatImpl::updateFormattingFixedPointFormatter(
1185 int32_t &changedFormattingFields) {
1186 if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) {
1187 // No work to do if fSymbols is unchanged
1188 return;
1189 }
1190 if (fMonetary) {
1191 fFormatter.setDecimalFormatSymbolsForMonetary(*fSymbols);
1192 } else {
1193 fFormatter.setDecimalFormatSymbols(*fSymbols);
1194 }
1195 }
1196
1197 void
updateFormattingAffixParser(int32_t & changedFormattingFields)1198 DecimalFormatImpl::updateFormattingAffixParser(
1199 int32_t &changedFormattingFields) {
1200 if ((changedFormattingFields & kFormattingSymbols) == 0) {
1201 // No work to do if fSymbols is unchanged
1202 return;
1203 }
1204 fAffixParser.setDecimalFormatSymbols(*fSymbols);
1205 changedFormattingFields |= kFormattingAffixParser;
1206 }
1207
1208 void
updateFormattingLocalizedPositivePrefix(int32_t & changedFormattingFields,UErrorCode & status)1209 DecimalFormatImpl::updateFormattingLocalizedPositivePrefix(
1210 int32_t &changedFormattingFields, UErrorCode &status) {
1211 if (U_FAILURE(status)) {
1212 return;
1213 }
1214 if ((changedFormattingFields & (
1215 kFormattingPosPrefix | kFormattingAffixParserWithCurrency)) == 0) {
1216 // No work to do
1217 return;
1218 }
1219 fAffixes.fPositivePrefix.remove();
1220 fAffixParser.parse(
1221 fPositivePrefixPattern,
1222 fCurrencyAffixInfo,
1223 fAffixes.fPositivePrefix,
1224 status);
1225 }
1226
1227 void
updateFormattingLocalizedPositiveSuffix(int32_t & changedFormattingFields,UErrorCode & status)1228 DecimalFormatImpl::updateFormattingLocalizedPositiveSuffix(
1229 int32_t &changedFormattingFields, UErrorCode &status) {
1230 if (U_FAILURE(status)) {
1231 return;
1232 }
1233 if ((changedFormattingFields & (
1234 kFormattingPosSuffix | kFormattingAffixParserWithCurrency)) == 0) {
1235 // No work to do
1236 return;
1237 }
1238 fAffixes.fPositiveSuffix.remove();
1239 fAffixParser.parse(
1240 fPositiveSuffixPattern,
1241 fCurrencyAffixInfo,
1242 fAffixes.fPositiveSuffix,
1243 status);
1244 }
1245
1246 void
updateFormattingLocalizedNegativePrefix(int32_t & changedFormattingFields,UErrorCode & status)1247 DecimalFormatImpl::updateFormattingLocalizedNegativePrefix(
1248 int32_t &changedFormattingFields, UErrorCode &status) {
1249 if (U_FAILURE(status)) {
1250 return;
1251 }
1252 if ((changedFormattingFields & (
1253 kFormattingNegPrefix | kFormattingAffixParserWithCurrency)) == 0) {
1254 // No work to do
1255 return;
1256 }
1257 fAffixes.fNegativePrefix.remove();
1258 fAffixParser.parse(
1259 fNegativePrefixPattern,
1260 fCurrencyAffixInfo,
1261 fAffixes.fNegativePrefix,
1262 status);
1263 }
1264
1265 void
updateFormattingLocalizedNegativeSuffix(int32_t & changedFormattingFields,UErrorCode & status)1266 DecimalFormatImpl::updateFormattingLocalizedNegativeSuffix(
1267 int32_t &changedFormattingFields, UErrorCode &status) {
1268 if (U_FAILURE(status)) {
1269 return;
1270 }
1271 if ((changedFormattingFields & (
1272 kFormattingNegSuffix | kFormattingAffixParserWithCurrency)) == 0) {
1273 // No work to do
1274 return;
1275 }
1276 fAffixes.fNegativeSuffix.remove();
1277 fAffixParser.parse(
1278 fNegativeSuffixPattern,
1279 fCurrencyAffixInfo,
1280 fAffixes.fNegativeSuffix,
1281 status);
1282 }
1283
1284 void
updateForApplyPatternFavorCurrencyPrecision(UErrorCode & status)1285 DecimalFormatImpl::updateForApplyPatternFavorCurrencyPrecision(
1286 UErrorCode &status) {
1287 updateAll(kFormattingAll & ~kFormattingSymbols, TRUE, status);
1288 }
1289
1290 void
updateForApplyPattern(UErrorCode & status)1291 DecimalFormatImpl::updateForApplyPattern(UErrorCode &status) {
1292 updateAll(kFormattingAll & ~kFormattingSymbols, FALSE, status);
1293 }
1294
1295 void
updateAll(UErrorCode & status)1296 DecimalFormatImpl::updateAll(UErrorCode &status) {
1297 updateAll(kFormattingAll, TRUE, status);
1298 }
1299
1300 void
updateAll(int32_t formattingFlags,UBool updatePrecisionBasedOnCurrency,UErrorCode & status)1301 DecimalFormatImpl::updateAll(
1302 int32_t formattingFlags,
1303 UBool updatePrecisionBasedOnCurrency,
1304 UErrorCode &status) {
1305 if (U_FAILURE(status)) {
1306 return;
1307 }
1308 updatePrecision();
1309 updateGrouping();
1310 updateFormatting(
1311 formattingFlags, updatePrecisionBasedOnCurrency, status);
1312 setMultiplierScale(getPatternScale());
1313 }
1314
1315
1316 static int32_t
getMinimumLengthToDescribeGrouping(const DigitGrouping & grouping)1317 getMinimumLengthToDescribeGrouping(const DigitGrouping &grouping) {
1318 if (grouping.fGrouping <= 0) {
1319 return 0;
1320 }
1321 if (grouping.fGrouping2 <= 0) {
1322 return grouping.fGrouping + 1;
1323 }
1324 return grouping.fGrouping + grouping.fGrouping2 + 1;
1325 }
1326
1327 /**
1328 * Given a grouping policy, calculates how many digits are needed left of
1329 * the decimal point to achieve a desired length left of the
1330 * decimal point.
1331 * @param grouping the grouping policy
1332 * @param desiredLength number of characters needed left of decimal point
1333 * @param minLeftDigits at least this many digits is returned
1334 * @param leftDigits the number of digits needed stored here
1335 * which is >= minLeftDigits.
1336 * @return true if a perfect fit or false if having leftDigits would exceed
1337 * desiredLength
1338 */
1339 static UBool
getLeftDigitsForLeftLength(const DigitGrouping & grouping,int32_t desiredLength,int32_t minLeftDigits,int32_t & leftDigits)1340 getLeftDigitsForLeftLength(
1341 const DigitGrouping &grouping,
1342 int32_t desiredLength,
1343 int32_t minLeftDigits,
1344 int32_t &leftDigits) {
1345 leftDigits = minLeftDigits;
1346 int32_t lengthSoFar = leftDigits + grouping.getSeparatorCount(leftDigits);
1347 while (lengthSoFar < desiredLength) {
1348 lengthSoFar += grouping.isSeparatorAt(leftDigits + 1, leftDigits) ? 2 : 1;
1349 ++leftDigits;
1350 }
1351 return (lengthSoFar == desiredLength);
1352 }
1353
1354 int32_t
computeExponentPatternLength() const1355 DecimalFormatImpl::computeExponentPatternLength() const {
1356 if (fUseScientific) {
1357 return 1 + (fOptions.fExponent.fAlwaysShowSign ? 1 : 0) + fEffPrecision.fMinExponentDigits;
1358 }
1359 return 0;
1360 }
1361
1362 int32_t
countFractionDigitAndDecimalPatternLength(int32_t fracDigitCount) const1363 DecimalFormatImpl::countFractionDigitAndDecimalPatternLength(
1364 int32_t fracDigitCount) const {
1365 if (!fOptions.fMantissa.fAlwaysShowDecimal && fracDigitCount == 0) {
1366 return 0;
1367 }
1368 return fracDigitCount + 1;
1369 }
1370
1371 UnicodeString&
toNumberPattern(UBool hasPadding,int32_t minimumLength,UnicodeString & result) const1372 DecimalFormatImpl::toNumberPattern(
1373 UBool hasPadding, int32_t minimumLength, UnicodeString& result) const {
1374 // Get a grouping policy like the one in this object that does not
1375 // have minimum grouping since toPattern doesn't support it.
1376 DigitGrouping grouping(fEffGrouping);
1377 grouping.fMinGrouping = 0;
1378
1379 // Only for fixed digits, these are the digits that get 0's.
1380 DigitInterval minInterval;
1381
1382 // Only for fixed digits, these are the digits that get #'s.
1383 DigitInterval maxInterval;
1384
1385 // Only for significant digits
1386 int32_t sigMin = 0; /* initialize to avoid compiler warning */
1387 int32_t sigMax = 0; /* initialize to avoid compiler warning */
1388
1389 // These are all the digits to be displayed. For significant digits,
1390 // this interval always starts at the 1's place an extends left.
1391 DigitInterval fullInterval;
1392
1393 // Digit range of rounding increment. If rounding increment is .025.
1394 // then roundingIncrementLowerExp = -3 and roundingIncrementUpperExp = -1
1395 int32_t roundingIncrementLowerExp = 0;
1396 int32_t roundingIncrementUpperExp = 0;
1397
1398 if (fUseSigDigits) {
1399 SignificantDigitInterval sigInterval;
1400 extractSigDigits(sigInterval);
1401 sigMax = sigInterval.getMax();
1402 sigMin = sigInterval.getMin();
1403 fullInterval.setFracDigitCount(0);
1404 fullInterval.setIntDigitCount(sigMax);
1405 } else {
1406 extractMinMaxDigits(minInterval, maxInterval);
1407 if (fUseScientific) {
1408 if (maxInterval.getIntDigitCount() > kMaxScientificIntegerDigits) {
1409 maxInterval.setIntDigitCount(1);
1410 minInterval.shrinkToFitWithin(maxInterval);
1411 }
1412 } else if (hasPadding) {
1413 // Make max int digits match min int digits for now, we
1414 // compute necessary padding later.
1415 maxInterval.setIntDigitCount(minInterval.getIntDigitCount());
1416 } else {
1417 // For some reason toPattern adds at least one leading '#'
1418 maxInterval.setIntDigitCount(minInterval.getIntDigitCount() + 1);
1419 }
1420 if (!fEffPrecision.fMantissa.fRoundingIncrement.isZero()) {
1421 roundingIncrementLowerExp =
1422 fEffPrecision.fMantissa.fRoundingIncrement.getLowerExponent();
1423 roundingIncrementUpperExp =
1424 fEffPrecision.fMantissa.fRoundingIncrement.getUpperExponent();
1425 // We have to include the rounding increment in what we display
1426 maxInterval.expandToContainDigit(roundingIncrementLowerExp);
1427 maxInterval.expandToContainDigit(roundingIncrementUpperExp - 1);
1428 }
1429 fullInterval = maxInterval;
1430 }
1431 // We have to include enough digits to show grouping strategy
1432 int32_t minLengthToDescribeGrouping =
1433 getMinimumLengthToDescribeGrouping(grouping);
1434 if (minLengthToDescribeGrouping > 0) {
1435 fullInterval.expandToContainDigit(
1436 getMinimumLengthToDescribeGrouping(grouping) - 1);
1437 }
1438
1439 // If we have a minimum length, we have to add digits to the left to
1440 // depict padding.
1441 if (hasPadding) {
1442 // For non scientific notation,
1443 // minimumLengthForMantissa = minimumLength
1444 int32_t minimumLengthForMantissa =
1445 minimumLength - computeExponentPatternLength();
1446 int32_t mininumLengthForMantissaIntPart =
1447 minimumLengthForMantissa
1448 - countFractionDigitAndDecimalPatternLength(
1449 fullInterval.getFracDigitCount());
1450 // Because of grouping, we may need fewer than expected digits to
1451 // achieve the length we need.
1452 int32_t digitsNeeded;
1453 if (getLeftDigitsForLeftLength(
1454 grouping,
1455 mininumLengthForMantissaIntPart,
1456 fullInterval.getIntDigitCount(),
1457 digitsNeeded)) {
1458
1459 // In this case, we achieved the exact length that we want.
1460 fullInterval.setIntDigitCount(digitsNeeded);
1461 } else if (digitsNeeded > fullInterval.getIntDigitCount()) {
1462
1463 // Having digitsNeeded digits goes over desired length which
1464 // means that to have desired length would mean starting on a
1465 // grouping sepearator e.g ,###,### so add a '#' and use one
1466 // less digit. This trick gives ####,### but that is the best
1467 // we can do.
1468 result.append(kPatternDigit);
1469 fullInterval.setIntDigitCount(digitsNeeded - 1);
1470 }
1471 }
1472 int32_t maxDigitPos = fullInterval.getMostSignificantExclusive();
1473 int32_t minDigitPos = fullInterval.getLeastSignificantInclusive();
1474 for (int32_t i = maxDigitPos - 1; i >= minDigitPos; --i) {
1475 if (!fOptions.fMantissa.fAlwaysShowDecimal && i == -1) {
1476 result.append(kPatternDecimalSeparator);
1477 }
1478 if (fUseSigDigits) {
1479 // Use digit symbol
1480 if (i >= sigMax || i < sigMax - sigMin) {
1481 result.append(kPatternDigit);
1482 } else {
1483 result.append(kPatternSignificantDigit);
1484 }
1485 } else {
1486 if (i < roundingIncrementUpperExp && i >= roundingIncrementLowerExp) {
1487 result.append((UChar)(fEffPrecision.fMantissa.fRoundingIncrement.getDigitByExponent(i) + kPatternZeroDigit));
1488 } else if (minInterval.contains(i)) {
1489 result.append(kPatternZeroDigit);
1490 } else {
1491 result.append(kPatternDigit);
1492 }
1493 }
1494 if (grouping.isSeparatorAt(i + 1, i)) {
1495 result.append(kPatternGroupingSeparator);
1496 }
1497 if (fOptions.fMantissa.fAlwaysShowDecimal && i == 0) {
1498 result.append(kPatternDecimalSeparator);
1499 }
1500 }
1501 if (fUseScientific) {
1502 result.append(kPatternExponent);
1503 if (fOptions.fExponent.fAlwaysShowSign) {
1504 result.append(kPatternPlus);
1505 }
1506 for (int32_t i = 0; i < 1 || i < fEffPrecision.fMinExponentDigits; ++i) {
1507 result.append(kPatternZeroDigit);
1508 }
1509 }
1510 return result;
1511 }
1512
1513 UnicodeString&
toPattern(UnicodeString & result) const1514 DecimalFormatImpl::toPattern(UnicodeString& result) const {
1515 result.remove();
1516 UnicodeString padSpec;
1517 if (fAffixes.fWidth > 0) {
1518 padSpec.append(kPatternPadEscape);
1519 padSpec.append(fAffixes.fPadChar);
1520 }
1521 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
1522 result.append(padSpec);
1523 }
1524 fPositivePrefixPattern.toUserString(result);
1525 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
1526 result.append(padSpec);
1527 }
1528 toNumberPattern(
1529 fAffixes.fWidth > 0,
1530 fAffixes.fWidth - fPositivePrefixPattern.countChar32() - fPositiveSuffixPattern.countChar32(),
1531 result);
1532 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
1533 result.append(padSpec);
1534 }
1535 fPositiveSuffixPattern.toUserString(result);
1536 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
1537 result.append(padSpec);
1538 }
1539 AffixPattern withNegative;
1540 withNegative.add(AffixPattern::kNegative);
1541 withNegative.append(fPositivePrefixPattern);
1542 if (!fPositiveSuffixPattern.equals(fNegativeSuffixPattern) ||
1543 !withNegative.equals(fNegativePrefixPattern)) {
1544 result.append(kPatternSeparator);
1545 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
1546 result.append(padSpec);
1547 }
1548 fNegativePrefixPattern.toUserString(result);
1549 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
1550 result.append(padSpec);
1551 }
1552 toNumberPattern(
1553 fAffixes.fWidth > 0,
1554 fAffixes.fWidth - fNegativePrefixPattern.countChar32() - fNegativeSuffixPattern.countChar32(),
1555 result);
1556 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
1557 result.append(padSpec);
1558 }
1559 fNegativeSuffixPattern.toUserString(result);
1560 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
1561 result.append(padSpec);
1562 }
1563 }
1564 return result;
1565 }
1566
1567 int32_t
getOldFormatWidth() const1568 DecimalFormatImpl::getOldFormatWidth() const {
1569 if (fAffixes.fWidth == 0) {
1570 return 0;
1571 }
1572 return fAffixes.fWidth - fPositiveSuffixPattern.countChar32() - fPositivePrefixPattern.countChar32();
1573 }
1574
1575 const UnicodeString &
getConstSymbol(DecimalFormatSymbols::ENumberFormatSymbol symbol) const1576 DecimalFormatImpl::getConstSymbol(
1577 DecimalFormatSymbols::ENumberFormatSymbol symbol) const {
1578 return fSymbols->getConstSymbol(symbol);
1579 }
1580
1581 UBool
isParseFastpath() const1582 DecimalFormatImpl::isParseFastpath() const {
1583 AffixPattern negative;
1584 negative.add(AffixPattern::kNegative);
1585
1586 return fAffixes.fWidth == 0 &&
1587 fPositivePrefixPattern.countChar32() == 0 &&
1588 fNegativePrefixPattern.equals(negative) &&
1589 fPositiveSuffixPattern.countChar32() == 0 &&
1590 fNegativeSuffixPattern.countChar32() == 0;
1591 }
1592
1593
1594 U_NAMESPACE_END
1595
1596 #endif /* #if !UCONFIG_NO_FORMATTING */
1597
1598