1 // Copyright (C) 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.isNanOrInfinity = digits.isNaNOrInfinity();
525 digits.getFixedDecimal(
526 result.source, result.intValue, result.decimalDigits,
527 result.decimalDigitsWithoutTrailingZeros,
528 result.visibleDecimalDigitCount, result.hasIntegerValue);
529 return result;
530 }
531
532 FixedDecimal &
getFixedDecimal(double number,FixedDecimal & result,UErrorCode & status) const533 DecimalFormatImpl::getFixedDecimal(double number, FixedDecimal &result, UErrorCode &status) const {
534 if (U_FAILURE(status)) {
535 return result;
536 }
537 VisibleDigits digits;
538 fEffPrecision.fMantissa.initVisibleDigits(number, digits, status);
539 return initFixedDecimal(digits, result);
540 }
541
542 FixedDecimal &
getFixedDecimal(DigitList & number,FixedDecimal & result,UErrorCode & status) const543 DecimalFormatImpl::getFixedDecimal(
544 DigitList &number, FixedDecimal &result, UErrorCode &status) const {
545 if (U_FAILURE(status)) {
546 return result;
547 }
548 VisibleDigits digits;
549 fEffPrecision.fMantissa.initVisibleDigits(number, digits, status);
550 return initFixedDecimal(digits, result);
551 }
552
553 VisibleDigitsWithExponent &
initVisibleDigitsWithExponent(int64_t number,VisibleDigitsWithExponent & digits,UErrorCode & status) const554 DecimalFormatImpl::initVisibleDigitsWithExponent(
555 int64_t number,
556 VisibleDigitsWithExponent &digits,
557 UErrorCode &status) const {
558 if (maybeInitVisibleDigitsFromDigitList(
559 number, digits, status)) {
560 return digits;
561 }
562 if (fUseScientific) {
563 fEffPrecision.initVisibleDigitsWithExponent(
564 number, digits, status);
565 } else {
566 fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
567 number, digits, status);
568 }
569 return digits;
570 }
571
572 VisibleDigitsWithExponent &
initVisibleDigitsWithExponent(double number,VisibleDigitsWithExponent & digits,UErrorCode & status) const573 DecimalFormatImpl::initVisibleDigitsWithExponent(
574 double number,
575 VisibleDigitsWithExponent &digits,
576 UErrorCode &status) const {
577 if (maybeInitVisibleDigitsFromDigitList(
578 number, digits, status)) {
579 return digits;
580 }
581 if (fUseScientific) {
582 fEffPrecision.initVisibleDigitsWithExponent(
583 number, digits, status);
584 } else {
585 fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
586 number, digits, status);
587 }
588 return digits;
589 }
590
591 VisibleDigitsWithExponent &
initVisibleDigitsWithExponent(DigitList & number,VisibleDigitsWithExponent & digits,UErrorCode & status) const592 DecimalFormatImpl::initVisibleDigitsWithExponent(
593 DigitList &number,
594 VisibleDigitsWithExponent &digits,
595 UErrorCode &status) const {
596 adjustDigitList(number, status);
597 return initVisibleDigitsFromAdjusted(number, digits, status);
598 }
599
600 VisibleDigitsWithExponent &
initVisibleDigitsFromAdjusted(DigitList & number,VisibleDigitsWithExponent & digits,UErrorCode & status) const601 DecimalFormatImpl::initVisibleDigitsFromAdjusted(
602 DigitList &number,
603 VisibleDigitsWithExponent &digits,
604 UErrorCode &status) const {
605 if (fUseScientific) {
606 fEffPrecision.initVisibleDigitsWithExponent(
607 number, digits, status);
608 } else {
609 fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
610 number, digits, status);
611 }
612 return digits;
613 }
614
615 DigitList &
round(DigitList & number,UErrorCode & status) const616 DecimalFormatImpl::round(
617 DigitList &number, UErrorCode &status) const {
618 if (number.isNaN() || number.isInfinite()) {
619 return number;
620 }
621 adjustDigitList(number, status);
622 ValueFormatter vf;
623 prepareValueFormatter(vf);
624 return vf.round(number, status);
625 }
626
627 void
setMinimumSignificantDigits(int32_t newValue)628 DecimalFormatImpl::setMinimumSignificantDigits(int32_t newValue) {
629 fMinSigDigits = newValue;
630 fUseSigDigits = TRUE; // ticket 9936
631 updatePrecision();
632 }
633
634 void
setMaximumSignificantDigits(int32_t newValue)635 DecimalFormatImpl::setMaximumSignificantDigits(int32_t newValue) {
636 fMaxSigDigits = newValue;
637 fUseSigDigits = TRUE; // ticket 9936
638 updatePrecision();
639 }
640
641 void
setMinMaxSignificantDigits(int32_t min,int32_t max)642 DecimalFormatImpl::setMinMaxSignificantDigits(int32_t min, int32_t max) {
643 fMinSigDigits = min;
644 fMaxSigDigits = max;
645 fUseSigDigits = TRUE; // ticket 9936
646 updatePrecision();
647 }
648
649 void
setScientificNotation(UBool newValue)650 DecimalFormatImpl::setScientificNotation(UBool newValue) {
651 fUseScientific = newValue;
652 updatePrecision();
653 }
654
655 void
setSignificantDigitsUsed(UBool newValue)656 DecimalFormatImpl::setSignificantDigitsUsed(UBool newValue) {
657 fUseSigDigits = newValue;
658 updatePrecision();
659 }
660
661 void
setGroupingSize(int32_t newValue)662 DecimalFormatImpl::setGroupingSize(int32_t newValue) {
663 fGrouping.fGrouping = newValue;
664 updateGrouping();
665 }
666
667 void
setSecondaryGroupingSize(int32_t newValue)668 DecimalFormatImpl::setSecondaryGroupingSize(int32_t newValue) {
669 fGrouping.fGrouping2 = newValue;
670 updateGrouping();
671 }
672
673 void
setMinimumGroupingDigits(int32_t newValue)674 DecimalFormatImpl::setMinimumGroupingDigits(int32_t newValue) {
675 fGrouping.fMinGrouping = newValue;
676 updateGrouping();
677 }
678
679 void
setCurrencyUsage(UCurrencyUsage currencyUsage,UErrorCode & status)680 DecimalFormatImpl::setCurrencyUsage(
681 UCurrencyUsage currencyUsage, UErrorCode &status) {
682 fCurrencyUsage = currencyUsage;
683 updateFormatting(kFormattingCurrency, status);
684 }
685
686 void
setRoundingIncrement(double d)687 DecimalFormatImpl::setRoundingIncrement(double d) {
688 if (d > 0.0) {
689 fEffPrecision.fMantissa.fRoundingIncrement.set(d);
690 } else {
691 fEffPrecision.fMantissa.fRoundingIncrement.set(0.0);
692 }
693 }
694
695 double
getRoundingIncrement() const696 DecimalFormatImpl::getRoundingIncrement() const {
697 return fEffPrecision.fMantissa.fRoundingIncrement.getDouble();
698 }
699
700 int32_t
getMultiplier() const701 DecimalFormatImpl::getMultiplier() const {
702 if (fMultiplier.isZero()) {
703 return 1;
704 }
705 return (int32_t) fMultiplier.getDouble();
706 }
707
708 void
setMultiplier(int32_t m)709 DecimalFormatImpl::setMultiplier(int32_t m) {
710 if (m == 0 || m == 1) {
711 fMultiplier.set((int32_t)0);
712 } else {
713 fMultiplier.set(m);
714 }
715 }
716
717 void
setPositivePrefix(const UnicodeString & str)718 DecimalFormatImpl::setPositivePrefix(const UnicodeString &str) {
719 fPositivePrefixPattern.remove();
720 fPositivePrefixPattern.addLiteral(str.getBuffer(), 0, str.length());
721 UErrorCode status = U_ZERO_ERROR;
722 updateFormatting(kFormattingPosPrefix, status);
723 }
724
725 void
setPositiveSuffix(const UnicodeString & str)726 DecimalFormatImpl::setPositiveSuffix(const UnicodeString &str) {
727 fPositiveSuffixPattern.remove();
728 fPositiveSuffixPattern.addLiteral(str.getBuffer(), 0, str.length());
729 UErrorCode status = U_ZERO_ERROR;
730 updateFormatting(kFormattingPosSuffix, status);
731 }
732
733 void
setNegativePrefix(const UnicodeString & str)734 DecimalFormatImpl::setNegativePrefix(const UnicodeString &str) {
735 fNegativePrefixPattern.remove();
736 fNegativePrefixPattern.addLiteral(str.getBuffer(), 0, str.length());
737 UErrorCode status = U_ZERO_ERROR;
738 updateFormatting(kFormattingNegPrefix, status);
739 }
740
741 void
setNegativeSuffix(const UnicodeString & str)742 DecimalFormatImpl::setNegativeSuffix(const UnicodeString &str) {
743 fNegativeSuffixPattern.remove();
744 fNegativeSuffixPattern.addLiteral(str.getBuffer(), 0, str.length());
745 UErrorCode status = U_ZERO_ERROR;
746 updateFormatting(kFormattingNegSuffix, status);
747 }
748
749 UnicodeString &
getPositivePrefix(UnicodeString & result) const750 DecimalFormatImpl::getPositivePrefix(UnicodeString &result) const {
751 result = fAffixes.fPositivePrefix.getOtherVariant().toString();
752 return result;
753 }
754
755 UnicodeString &
getPositiveSuffix(UnicodeString & result) const756 DecimalFormatImpl::getPositiveSuffix(UnicodeString &result) const {
757 result = fAffixes.fPositiveSuffix.getOtherVariant().toString();
758 return result;
759 }
760
761 UnicodeString &
getNegativePrefix(UnicodeString & result) const762 DecimalFormatImpl::getNegativePrefix(UnicodeString &result) const {
763 result = fAffixes.fNegativePrefix.getOtherVariant().toString();
764 return result;
765 }
766
767 UnicodeString &
getNegativeSuffix(UnicodeString & result) const768 DecimalFormatImpl::getNegativeSuffix(UnicodeString &result) const {
769 result = fAffixes.fNegativeSuffix.getOtherVariant().toString();
770 return result;
771 }
772
773 void
adoptDecimalFormatSymbols(DecimalFormatSymbols * symbolsToAdopt)774 DecimalFormatImpl::adoptDecimalFormatSymbols(DecimalFormatSymbols *symbolsToAdopt) {
775 if (symbolsToAdopt == NULL) {
776 return;
777 }
778 delete fSymbols;
779 fSymbols = symbolsToAdopt;
780 UErrorCode status = U_ZERO_ERROR;
781 updateFormatting(kFormattingSymbols, status);
782 }
783
784 void
applyPatternFavorCurrencyPrecision(const UnicodeString & pattern,UErrorCode & status)785 DecimalFormatImpl::applyPatternFavorCurrencyPrecision(
786 const UnicodeString &pattern, UErrorCode &status) {
787 UParseError perror;
788 applyPattern(pattern, FALSE, perror, status);
789 updateForApplyPatternFavorCurrencyPrecision(status);
790 }
791
792 void
applyPattern(const UnicodeString & pattern,UErrorCode & status)793 DecimalFormatImpl::applyPattern(
794 const UnicodeString &pattern, UErrorCode &status) {
795 UParseError perror;
796 applyPattern(pattern, FALSE, perror, status);
797 updateForApplyPattern(status);
798 }
799
800 void
applyPattern(const UnicodeString & pattern,UParseError & perror,UErrorCode & status)801 DecimalFormatImpl::applyPattern(
802 const UnicodeString &pattern,
803 UParseError &perror, UErrorCode &status) {
804 applyPattern(pattern, FALSE, perror, status);
805 updateForApplyPattern(status);
806 }
807
808 void
applyLocalizedPattern(const UnicodeString & pattern,UErrorCode & status)809 DecimalFormatImpl::applyLocalizedPattern(
810 const UnicodeString &pattern, UErrorCode &status) {
811 UParseError perror;
812 applyPattern(pattern, TRUE, perror, status);
813 updateForApplyPattern(status);
814 }
815
816 void
applyLocalizedPattern(const UnicodeString & pattern,UParseError & perror,UErrorCode & status)817 DecimalFormatImpl::applyLocalizedPattern(
818 const UnicodeString &pattern,
819 UParseError &perror, UErrorCode &status) {
820 applyPattern(pattern, TRUE, perror, status);
821 updateForApplyPattern(status);
822 }
823
824 void
applyPattern(const UnicodeString & pattern,UBool localized,UParseError & perror,UErrorCode & status)825 DecimalFormatImpl::applyPattern(
826 const UnicodeString &pattern,
827 UBool localized, UParseError &perror, UErrorCode &status) {
828 if (U_FAILURE(status)) {
829 return;
830 }
831 DecimalFormatPatternParser patternParser;
832 if (localized) {
833 patternParser.useSymbols(*fSymbols);
834 }
835 DecimalFormatPattern out;
836 patternParser.applyPatternWithoutExpandAffix(
837 pattern, out, perror, status);
838 if (U_FAILURE(status)) {
839 return;
840 }
841 fUseScientific = out.fUseExponentialNotation;
842 fUseSigDigits = out.fUseSignificantDigits;
843 fSuper->NumberFormat::setMinimumIntegerDigits(out.fMinimumIntegerDigits);
844 fSuper->NumberFormat::setMaximumIntegerDigits(out.fMaximumIntegerDigits);
845 fSuper->NumberFormat::setMinimumFractionDigits(out.fMinimumFractionDigits);
846 fSuper->NumberFormat::setMaximumFractionDigits(out.fMaximumFractionDigits);
847 fMinSigDigits = out.fMinimumSignificantDigits;
848 fMaxSigDigits = out.fMaximumSignificantDigits;
849 fEffPrecision.fMinExponentDigits = out.fMinExponentDigits;
850 fOptions.fExponent.fAlwaysShowSign = out.fExponentSignAlwaysShown;
851 fSuper->NumberFormat::setGroupingUsed(out.fGroupingUsed);
852 fGrouping.fGrouping = out.fGroupingSize;
853 fGrouping.fGrouping2 = out.fGroupingSize2;
854 fOptions.fMantissa.fAlwaysShowDecimal = out.fDecimalSeparatorAlwaysShown;
855 if (out.fRoundingIncrementUsed) {
856 fEffPrecision.fMantissa.fRoundingIncrement = out.fRoundingIncrement;
857 } else {
858 fEffPrecision.fMantissa.fRoundingIncrement.clear();
859 }
860 fAffixes.fPadChar = out.fPad;
861 fNegativePrefixPattern = out.fNegPrefixAffix;
862 fNegativeSuffixPattern = out.fNegSuffixAffix;
863 fPositivePrefixPattern = out.fPosPrefixAffix;
864 fPositiveSuffixPattern = out.fPosSuffixAffix;
865
866 // Work around. Pattern parsing code and DecimalFormat code don't agree
867 // on the definition of field width, so we have to translate from
868 // pattern field width to decimal format field width here.
869 fAffixes.fWidth = out.fFormatWidth == 0 ? 0 :
870 out.fFormatWidth + fPositivePrefixPattern.countChar32()
871 + fPositiveSuffixPattern.countChar32();
872 switch (out.fPadPosition) {
873 case DecimalFormatPattern::kPadBeforePrefix:
874 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforePrefix;
875 break;
876 case DecimalFormatPattern::kPadAfterPrefix:
877 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterPrefix;
878 break;
879 case DecimalFormatPattern::kPadBeforeSuffix:
880 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforeSuffix;
881 break;
882 case DecimalFormatPattern::kPadAfterSuffix:
883 fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterSuffix;
884 break;
885 default:
886 break;
887 }
888 }
889
890 void
updatePrecision()891 DecimalFormatImpl::updatePrecision() {
892 if (fUseScientific) {
893 updatePrecisionForScientific();
894 } else {
895 updatePrecisionForFixed();
896 }
897 }
898
updatePrecisionForScientificMinMax(const DigitInterval & min,const DigitInterval & max,DigitInterval & resultMin,DigitInterval & resultMax,SignificantDigitInterval & resultSignificant)899 static void updatePrecisionForScientificMinMax(
900 const DigitInterval &min,
901 const DigitInterval &max,
902 DigitInterval &resultMin,
903 DigitInterval &resultMax,
904 SignificantDigitInterval &resultSignificant) {
905 resultMin.setIntDigitCount(0);
906 resultMin.setFracDigitCount(0);
907 resultSignificant.clear();
908 resultMax.clear();
909
910 int32_t maxIntDigitCount = max.getIntDigitCount();
911 int32_t minIntDigitCount = min.getIntDigitCount();
912 int32_t maxFracDigitCount = max.getFracDigitCount();
913 int32_t minFracDigitCount = min.getFracDigitCount();
914
915
916 // Not in spec: maxIntDigitCount > 8 assume
917 // maxIntDigitCount = minIntDigitCount. Current DecimalFormat API has
918 // no provision for unsetting maxIntDigitCount which would be useful for
919 // scientific notation. The best we can do is assume that if
920 // maxIntDigitCount is the default of 2000000000 or is "big enough" then
921 // user did not intend to explicitly set it. The 8 was derived emperically
922 // by extensive testing of legacy code.
923 if (maxIntDigitCount > 8) {
924 maxIntDigitCount = minIntDigitCount;
925 }
926
927 // Per the spec, exponent grouping happens if maxIntDigitCount is more
928 // than 1 and more than minIntDigitCount.
929 UBool bExponentGrouping = maxIntDigitCount > 1 && minIntDigitCount < maxIntDigitCount;
930 if (bExponentGrouping) {
931 resultMax.setIntDigitCount(maxIntDigitCount);
932
933 // For exponent grouping minIntDigits is always treated as 1 even
934 // if it wasn't set to 1!
935 resultMin.setIntDigitCount(1);
936 } else {
937 // Fixed digit count left of decimal. minIntDigitCount doesn't have
938 // to equal maxIntDigitCount i.e minIntDigitCount == 0 while
939 // maxIntDigitCount == 1.
940 int32_t fixedIntDigitCount = maxIntDigitCount;
941
942 // If fixedIntDigitCount is 0 but
943 // min or max fraction count is 0 too then use 1. This way we can get
944 // unlimited precision for X.XXXEX
945 if (fixedIntDigitCount == 0 && (minFracDigitCount == 0 || maxFracDigitCount == 0)) {
946 fixedIntDigitCount = 1;
947 }
948 resultMax.setIntDigitCount(fixedIntDigitCount);
949 resultMin.setIntDigitCount(fixedIntDigitCount);
950 }
951 // Spec says this is how we compute significant digits. 0 means
952 // unlimited significant digits.
953 int32_t maxSigDigits = minIntDigitCount + maxFracDigitCount;
954 if (maxSigDigits > 0) {
955 int32_t minSigDigits = minIntDigitCount + minFracDigitCount;
956 resultSignificant.setMin(minSigDigits);
957 resultSignificant.setMax(maxSigDigits);
958 }
959 }
960
961 void
updatePrecisionForScientific()962 DecimalFormatImpl::updatePrecisionForScientific() {
963 FixedPrecision *result = &fEffPrecision.fMantissa;
964 if (fUseSigDigits) {
965 result->fMax.setFracDigitCount(-1);
966 result->fMax.setIntDigitCount(1);
967 result->fMin.setFracDigitCount(0);
968 result->fMin.setIntDigitCount(1);
969 result->fSignificant.clear();
970 extractSigDigits(result->fSignificant);
971 return;
972 }
973 DigitInterval max;
974 DigitInterval min;
975 extractMinMaxDigits(min, max);
976 updatePrecisionForScientificMinMax(
977 min, max,
978 result->fMin, result->fMax, result->fSignificant);
979 }
980
981 void
updatePrecisionForFixed()982 DecimalFormatImpl::updatePrecisionForFixed() {
983 FixedPrecision *result = &fEffPrecision.fMantissa;
984 if (!fUseSigDigits) {
985 extractMinMaxDigits(result->fMin, result->fMax);
986 result->fSignificant.clear();
987 } else {
988 extractSigDigits(result->fSignificant);
989 result->fMin.setIntDigitCount(1);
990 result->fMin.setFracDigitCount(0);
991 result->fMax.clear();
992 }
993 }
994
995 void
extractMinMaxDigits(DigitInterval & min,DigitInterval & max) const996 DecimalFormatImpl::extractMinMaxDigits(
997 DigitInterval &min, DigitInterval &max) const {
998 min.setIntDigitCount(fSuper->getMinimumIntegerDigits());
999 max.setIntDigitCount(fSuper->getMaximumIntegerDigits());
1000 min.setFracDigitCount(fSuper->getMinimumFractionDigits());
1001 max.setFracDigitCount(fSuper->getMaximumFractionDigits());
1002 }
1003
1004 void
extractSigDigits(SignificantDigitInterval & sig) const1005 DecimalFormatImpl::extractSigDigits(
1006 SignificantDigitInterval &sig) const {
1007 sig.setMin(fMinSigDigits < 0 ? 0 : fMinSigDigits);
1008 sig.setMax(fMaxSigDigits < 0 ? 0 : fMaxSigDigits);
1009 }
1010
1011 void
updateGrouping()1012 DecimalFormatImpl::updateGrouping() {
1013 if (fSuper->isGroupingUsed()) {
1014 fEffGrouping = fGrouping;
1015 } else {
1016 fEffGrouping.clear();
1017 }
1018 }
1019
1020 void
updateCurrency(UErrorCode & status)1021 DecimalFormatImpl::updateCurrency(UErrorCode &status) {
1022 updateFormatting(kFormattingCurrency, TRUE, status);
1023 }
1024
1025 void
updateFormatting(int32_t changedFormattingFields,UErrorCode & status)1026 DecimalFormatImpl::updateFormatting(
1027 int32_t changedFormattingFields,
1028 UErrorCode &status) {
1029 updateFormatting(changedFormattingFields, TRUE, status);
1030 }
1031
1032 void
updateFormatting(int32_t changedFormattingFields,UBool updatePrecisionBasedOnCurrency,UErrorCode & status)1033 DecimalFormatImpl::updateFormatting(
1034 int32_t changedFormattingFields,
1035 UBool updatePrecisionBasedOnCurrency,
1036 UErrorCode &status) {
1037 if (U_FAILURE(status)) {
1038 return;
1039 }
1040 // Each function updates one field. Order matters. For instance,
1041 // updatePluralRules comes before updateCurrencyAffixInfo because the
1042 // fRules field is needed to update the fCurrencyAffixInfo field.
1043 updateFormattingUsesCurrency(changedFormattingFields);
1044 updateFormattingFixedPointFormatter(changedFormattingFields);
1045 updateFormattingAffixParser(changedFormattingFields);
1046 updateFormattingPluralRules(changedFormattingFields, status);
1047 updateFormattingCurrencyAffixInfo(
1048 changedFormattingFields,
1049 updatePrecisionBasedOnCurrency,
1050 status);
1051 updateFormattingLocalizedPositivePrefix(
1052 changedFormattingFields, status);
1053 updateFormattingLocalizedPositiveSuffix(
1054 changedFormattingFields, status);
1055 updateFormattingLocalizedNegativePrefix(
1056 changedFormattingFields, status);
1057 updateFormattingLocalizedNegativeSuffix(
1058 changedFormattingFields, status);
1059 }
1060
1061 void
updateFormattingUsesCurrency(int32_t & changedFormattingFields)1062 DecimalFormatImpl::updateFormattingUsesCurrency(
1063 int32_t &changedFormattingFields) {
1064 if ((changedFormattingFields & kFormattingAffixes) == 0) {
1065 // If no affixes changed, don't need to do any work
1066 return;
1067 }
1068 UBool newUsesCurrency =
1069 fPositivePrefixPattern.usesCurrency() ||
1070 fPositiveSuffixPattern.usesCurrency() ||
1071 fNegativePrefixPattern.usesCurrency() ||
1072 fNegativeSuffixPattern.usesCurrency();
1073 if (fMonetary != newUsesCurrency) {
1074 fMonetary = newUsesCurrency;
1075 changedFormattingFields |= kFormattingUsesCurrency;
1076 }
1077 }
1078
1079 void
updateFormattingPluralRules(int32_t & changedFormattingFields,UErrorCode & status)1080 DecimalFormatImpl::updateFormattingPluralRules(
1081 int32_t &changedFormattingFields, UErrorCode &status) {
1082 if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) {
1083 // No work to do if both fSymbols and fMonetary
1084 // fields are unchanged
1085 return;
1086 }
1087 if (U_FAILURE(status)) {
1088 return;
1089 }
1090 PluralRules *newRules = NULL;
1091 if (fMonetary) {
1092 newRules = PluralRules::forLocale(fSymbols->getLocale(), status);
1093 if (U_FAILURE(status)) {
1094 return;
1095 }
1096 }
1097 // Its ok to say a field has changed when it really hasn't but not
1098 // the other way around. Here we assume the field changed unless it
1099 // was NULL before and is still NULL now
1100 if (fRules != newRules) {
1101 delete fRules;
1102 fRules = newRules;
1103 changedFormattingFields |= kFormattingPluralRules;
1104 }
1105 }
1106
1107 void
updateFormattingCurrencyAffixInfo(int32_t & changedFormattingFields,UBool updatePrecisionBasedOnCurrency,UErrorCode & status)1108 DecimalFormatImpl::updateFormattingCurrencyAffixInfo(
1109 int32_t &changedFormattingFields,
1110 UBool updatePrecisionBasedOnCurrency,
1111 UErrorCode &status) {
1112 if ((changedFormattingFields & (
1113 kFormattingSymbols | kFormattingCurrency |
1114 kFormattingUsesCurrency | kFormattingPluralRules)) == 0) {
1115 // If all these fields are unchanged, no work to do.
1116 return;
1117 }
1118 if (U_FAILURE(status)) {
1119 return;
1120 }
1121 if (!fMonetary) {
1122 if (fCurrencyAffixInfo.isDefault()) {
1123 // In this case don't have to do any work
1124 return;
1125 }
1126 fCurrencyAffixInfo.set(NULL, NULL, NULL, status);
1127 if (U_FAILURE(status)) {
1128 return;
1129 }
1130 changedFormattingFields |= kFormattingCurrencyAffixInfo;
1131 } else {
1132 const UChar *currency = fSuper->getCurrency();
1133 UChar localeCurr[4];
1134 if (currency[0] == 0) {
1135 ucurr_forLocale(fSymbols->getLocale().getName(), localeCurr, UPRV_LENGTHOF(localeCurr), &status);
1136 if (U_SUCCESS(status)) {
1137 currency = localeCurr;
1138 fSuper->NumberFormat::setCurrency(currency, status);
1139 } else {
1140 currency = NULL;
1141 status = U_ZERO_ERROR;
1142 }
1143 }
1144 fCurrencyAffixInfo.set(
1145 fSymbols->getLocale().getName(), fRules, currency, status);
1146 if (U_FAILURE(status)) {
1147 return;
1148 }
1149 UBool customCurrencySymbol = FALSE;
1150 // If DecimalFormatSymbols has custom currency symbol, prefer
1151 // that over what we just read from the resource bundles
1152 if (fSymbols->isCustomCurrencySymbol()) {
1153 fCurrencyAffixInfo.setSymbol(
1154 fSymbols->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
1155 customCurrencySymbol = TRUE;
1156 }
1157 if (fSymbols->isCustomIntlCurrencySymbol()) {
1158 fCurrencyAffixInfo.setISO(
1159 fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1160 customCurrencySymbol = TRUE;
1161 }
1162 changedFormattingFields |= kFormattingCurrencyAffixInfo;
1163 if (currency && !customCurrencySymbol && updatePrecisionBasedOnCurrency) {
1164 FixedPrecision precision;
1165 CurrencyAffixInfo::adjustPrecision(
1166 currency, fCurrencyUsage, precision, status);
1167 if (U_FAILURE(status)) {
1168 return;
1169 }
1170 fSuper->NumberFormat::setMinimumFractionDigits(
1171 precision.fMin.getFracDigitCount());
1172 fSuper->NumberFormat::setMaximumFractionDigits(
1173 precision.fMax.getFracDigitCount());
1174 updatePrecision();
1175 fEffPrecision.fMantissa.fRoundingIncrement =
1176 precision.fRoundingIncrement;
1177 }
1178
1179 }
1180 }
1181
1182 void
updateFormattingFixedPointFormatter(int32_t & changedFormattingFields)1183 DecimalFormatImpl::updateFormattingFixedPointFormatter(
1184 int32_t &changedFormattingFields) {
1185 if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) {
1186 // No work to do if fSymbols is unchanged
1187 return;
1188 }
1189 if (fMonetary) {
1190 fFormatter.setDecimalFormatSymbolsForMonetary(*fSymbols);
1191 } else {
1192 fFormatter.setDecimalFormatSymbols(*fSymbols);
1193 }
1194 }
1195
1196 void
updateFormattingAffixParser(int32_t & changedFormattingFields)1197 DecimalFormatImpl::updateFormattingAffixParser(
1198 int32_t &changedFormattingFields) {
1199 if ((changedFormattingFields & kFormattingSymbols) == 0) {
1200 // No work to do if fSymbols is unchanged
1201 return;
1202 }
1203 fAffixParser.setDecimalFormatSymbols(*fSymbols);
1204 changedFormattingFields |= kFormattingAffixParser;
1205 }
1206
1207 void
updateFormattingLocalizedPositivePrefix(int32_t & changedFormattingFields,UErrorCode & status)1208 DecimalFormatImpl::updateFormattingLocalizedPositivePrefix(
1209 int32_t &changedFormattingFields, UErrorCode &status) {
1210 if (U_FAILURE(status)) {
1211 return;
1212 }
1213 if ((changedFormattingFields & (
1214 kFormattingPosPrefix | kFormattingAffixParserWithCurrency)) == 0) {
1215 // No work to do
1216 return;
1217 }
1218 fAffixes.fPositivePrefix.remove();
1219 fAffixParser.parse(
1220 fPositivePrefixPattern,
1221 fCurrencyAffixInfo,
1222 fAffixes.fPositivePrefix,
1223 status);
1224 }
1225
1226 void
updateFormattingLocalizedPositiveSuffix(int32_t & changedFormattingFields,UErrorCode & status)1227 DecimalFormatImpl::updateFormattingLocalizedPositiveSuffix(
1228 int32_t &changedFormattingFields, UErrorCode &status) {
1229 if (U_FAILURE(status)) {
1230 return;
1231 }
1232 if ((changedFormattingFields & (
1233 kFormattingPosSuffix | kFormattingAffixParserWithCurrency)) == 0) {
1234 // No work to do
1235 return;
1236 }
1237 fAffixes.fPositiveSuffix.remove();
1238 fAffixParser.parse(
1239 fPositiveSuffixPattern,
1240 fCurrencyAffixInfo,
1241 fAffixes.fPositiveSuffix,
1242 status);
1243 }
1244
1245 void
updateFormattingLocalizedNegativePrefix(int32_t & changedFormattingFields,UErrorCode & status)1246 DecimalFormatImpl::updateFormattingLocalizedNegativePrefix(
1247 int32_t &changedFormattingFields, UErrorCode &status) {
1248 if (U_FAILURE(status)) {
1249 return;
1250 }
1251 if ((changedFormattingFields & (
1252 kFormattingNegPrefix | kFormattingAffixParserWithCurrency)) == 0) {
1253 // No work to do
1254 return;
1255 }
1256 fAffixes.fNegativePrefix.remove();
1257 fAffixParser.parse(
1258 fNegativePrefixPattern,
1259 fCurrencyAffixInfo,
1260 fAffixes.fNegativePrefix,
1261 status);
1262 }
1263
1264 void
updateFormattingLocalizedNegativeSuffix(int32_t & changedFormattingFields,UErrorCode & status)1265 DecimalFormatImpl::updateFormattingLocalizedNegativeSuffix(
1266 int32_t &changedFormattingFields, UErrorCode &status) {
1267 if (U_FAILURE(status)) {
1268 return;
1269 }
1270 if ((changedFormattingFields & (
1271 kFormattingNegSuffix | kFormattingAffixParserWithCurrency)) == 0) {
1272 // No work to do
1273 return;
1274 }
1275 fAffixes.fNegativeSuffix.remove();
1276 fAffixParser.parse(
1277 fNegativeSuffixPattern,
1278 fCurrencyAffixInfo,
1279 fAffixes.fNegativeSuffix,
1280 status);
1281 }
1282
1283 void
updateForApplyPatternFavorCurrencyPrecision(UErrorCode & status)1284 DecimalFormatImpl::updateForApplyPatternFavorCurrencyPrecision(
1285 UErrorCode &status) {
1286 updateAll(kFormattingAll & ~kFormattingSymbols, TRUE, status);
1287 }
1288
1289 void
updateForApplyPattern(UErrorCode & status)1290 DecimalFormatImpl::updateForApplyPattern(UErrorCode &status) {
1291 updateAll(kFormattingAll & ~kFormattingSymbols, FALSE, status);
1292 }
1293
1294 void
updateAll(UErrorCode & status)1295 DecimalFormatImpl::updateAll(UErrorCode &status) {
1296 updateAll(kFormattingAll, TRUE, status);
1297 }
1298
1299 void
updateAll(int32_t formattingFlags,UBool updatePrecisionBasedOnCurrency,UErrorCode & status)1300 DecimalFormatImpl::updateAll(
1301 int32_t formattingFlags,
1302 UBool updatePrecisionBasedOnCurrency,
1303 UErrorCode &status) {
1304 if (U_FAILURE(status)) {
1305 return;
1306 }
1307 updatePrecision();
1308 updateGrouping();
1309 updateFormatting(
1310 formattingFlags, updatePrecisionBasedOnCurrency, status);
1311 setMultiplierScale(getPatternScale());
1312 }
1313
1314
1315 static int32_t
getMinimumLengthToDescribeGrouping(const DigitGrouping & grouping)1316 getMinimumLengthToDescribeGrouping(const DigitGrouping &grouping) {
1317 if (grouping.fGrouping <= 0) {
1318 return 0;
1319 }
1320 if (grouping.fGrouping2 <= 0) {
1321 return grouping.fGrouping + 1;
1322 }
1323 return grouping.fGrouping + grouping.fGrouping2 + 1;
1324 }
1325
1326 /**
1327 * Given a grouping policy, calculates how many digits are needed left of
1328 * the decimal point to achieve a desired length left of the
1329 * decimal point.
1330 * @param grouping the grouping policy
1331 * @param desiredLength number of characters needed left of decimal point
1332 * @param minLeftDigits at least this many digits is returned
1333 * @param leftDigits the number of digits needed stored here
1334 * which is >= minLeftDigits.
1335 * @return true if a perfect fit or false if having leftDigits would exceed
1336 * desiredLength
1337 */
1338 static UBool
getLeftDigitsForLeftLength(const DigitGrouping & grouping,int32_t desiredLength,int32_t minLeftDigits,int32_t & leftDigits)1339 getLeftDigitsForLeftLength(
1340 const DigitGrouping &grouping,
1341 int32_t desiredLength,
1342 int32_t minLeftDigits,
1343 int32_t &leftDigits) {
1344 leftDigits = minLeftDigits;
1345 int32_t lengthSoFar = leftDigits + grouping.getSeparatorCount(leftDigits);
1346 while (lengthSoFar < desiredLength) {
1347 lengthSoFar += grouping.isSeparatorAt(leftDigits + 1, leftDigits) ? 2 : 1;
1348 ++leftDigits;
1349 }
1350 return (lengthSoFar == desiredLength);
1351 }
1352
1353 int32_t
computeExponentPatternLength() const1354 DecimalFormatImpl::computeExponentPatternLength() const {
1355 if (fUseScientific) {
1356 return 1 + (fOptions.fExponent.fAlwaysShowSign ? 1 : 0) + fEffPrecision.fMinExponentDigits;
1357 }
1358 return 0;
1359 }
1360
1361 int32_t
countFractionDigitAndDecimalPatternLength(int32_t fracDigitCount) const1362 DecimalFormatImpl::countFractionDigitAndDecimalPatternLength(
1363 int32_t fracDigitCount) const {
1364 if (!fOptions.fMantissa.fAlwaysShowDecimal && fracDigitCount == 0) {
1365 return 0;
1366 }
1367 return fracDigitCount + 1;
1368 }
1369
1370 UnicodeString&
toNumberPattern(UBool hasPadding,int32_t minimumLength,UnicodeString & result) const1371 DecimalFormatImpl::toNumberPattern(
1372 UBool hasPadding, int32_t minimumLength, UnicodeString& result) const {
1373 // Get a grouping policy like the one in this object that does not
1374 // have minimum grouping since toPattern doesn't support it.
1375 DigitGrouping grouping(fEffGrouping);
1376 grouping.fMinGrouping = 0;
1377
1378 // Only for fixed digits, these are the digits that get 0's.
1379 DigitInterval minInterval;
1380
1381 // Only for fixed digits, these are the digits that get #'s.
1382 DigitInterval maxInterval;
1383
1384 // Only for significant digits
1385 int32_t sigMin;
1386 int32_t sigMax;
1387
1388 // These are all the digits to be displayed. For significant digits,
1389 // this interval always starts at the 1's place an extends left.
1390 DigitInterval fullInterval;
1391
1392 // Digit range of rounding increment. If rounding increment is .025.
1393 // then roundingIncrementLowerExp = -3 and roundingIncrementUpperExp = -1
1394 int32_t roundingIncrementLowerExp = 0;
1395 int32_t roundingIncrementUpperExp = 0;
1396
1397 if (fUseSigDigits) {
1398 SignificantDigitInterval sigInterval;
1399 extractSigDigits(sigInterval);
1400 sigMax = sigInterval.getMax();
1401 sigMin = sigInterval.getMin();
1402 fullInterval.setFracDigitCount(0);
1403 fullInterval.setIntDigitCount(sigMax);
1404 } else {
1405 extractMinMaxDigits(minInterval, maxInterval);
1406 if (fUseScientific) {
1407 if (maxInterval.getIntDigitCount() > kMaxScientificIntegerDigits) {
1408 maxInterval.setIntDigitCount(1);
1409 minInterval.shrinkToFitWithin(maxInterval);
1410 }
1411 } else if (hasPadding) {
1412 // Make max int digits match min int digits for now, we
1413 // compute necessary padding later.
1414 maxInterval.setIntDigitCount(minInterval.getIntDigitCount());
1415 } else {
1416 // For some reason toPattern adds at least one leading '#'
1417 maxInterval.setIntDigitCount(minInterval.getIntDigitCount() + 1);
1418 }
1419 if (!fEffPrecision.fMantissa.fRoundingIncrement.isZero()) {
1420 roundingIncrementLowerExp =
1421 fEffPrecision.fMantissa.fRoundingIncrement.getLowerExponent();
1422 roundingIncrementUpperExp =
1423 fEffPrecision.fMantissa.fRoundingIncrement.getUpperExponent();
1424 // We have to include the rounding increment in what we display
1425 maxInterval.expandToContainDigit(roundingIncrementLowerExp);
1426 maxInterval.expandToContainDigit(roundingIncrementUpperExp - 1);
1427 }
1428 fullInterval = maxInterval;
1429 }
1430 // We have to include enough digits to show grouping strategy
1431 int32_t minLengthToDescribeGrouping =
1432 getMinimumLengthToDescribeGrouping(grouping);
1433 if (minLengthToDescribeGrouping > 0) {
1434 fullInterval.expandToContainDigit(
1435 getMinimumLengthToDescribeGrouping(grouping) - 1);
1436 }
1437
1438 // If we have a minimum length, we have to add digits to the left to
1439 // depict padding.
1440 if (hasPadding) {
1441 // For non scientific notation,
1442 // minimumLengthForMantissa = minimumLength
1443 int32_t minimumLengthForMantissa =
1444 minimumLength - computeExponentPatternLength();
1445 int32_t mininumLengthForMantissaIntPart =
1446 minimumLengthForMantissa
1447 - countFractionDigitAndDecimalPatternLength(
1448 fullInterval.getFracDigitCount());
1449 // Because of grouping, we may need fewer than expected digits to
1450 // achieve the length we need.
1451 int32_t digitsNeeded;
1452 if (getLeftDigitsForLeftLength(
1453 grouping,
1454 mininumLengthForMantissaIntPart,
1455 fullInterval.getIntDigitCount(),
1456 digitsNeeded)) {
1457
1458 // In this case, we achieved the exact length that we want.
1459 fullInterval.setIntDigitCount(digitsNeeded);
1460 } else if (digitsNeeded > fullInterval.getIntDigitCount()) {
1461
1462 // Having digitsNeeded digits goes over desired length which
1463 // means that to have desired length would mean starting on a
1464 // grouping sepearator e.g ,###,### so add a '#' and use one
1465 // less digit. This trick gives ####,### but that is the best
1466 // we can do.
1467 result.append(kPatternDigit);
1468 fullInterval.setIntDigitCount(digitsNeeded - 1);
1469 }
1470 }
1471 int32_t maxDigitPos = fullInterval.getMostSignificantExclusive();
1472 int32_t minDigitPos = fullInterval.getLeastSignificantInclusive();
1473 for (int32_t i = maxDigitPos - 1; i >= minDigitPos; --i) {
1474 if (!fOptions.fMantissa.fAlwaysShowDecimal && i == -1) {
1475 result.append(kPatternDecimalSeparator);
1476 }
1477 if (fUseSigDigits) {
1478 // Use digit symbol
1479 if (i >= sigMax || i < sigMax - sigMin) {
1480 result.append(kPatternDigit);
1481 } else {
1482 result.append(kPatternSignificantDigit);
1483 }
1484 } else {
1485 if (i < roundingIncrementUpperExp && i >= roundingIncrementLowerExp) {
1486 result.append((UChar)(fEffPrecision.fMantissa.fRoundingIncrement.getDigitByExponent(i) + kPatternZeroDigit));
1487 } else if (minInterval.contains(i)) {
1488 result.append(kPatternZeroDigit);
1489 } else {
1490 result.append(kPatternDigit);
1491 }
1492 }
1493 if (grouping.isSeparatorAt(i + 1, i)) {
1494 result.append(kPatternGroupingSeparator);
1495 }
1496 if (fOptions.fMantissa.fAlwaysShowDecimal && i == 0) {
1497 result.append(kPatternDecimalSeparator);
1498 }
1499 }
1500 if (fUseScientific) {
1501 result.append(kPatternExponent);
1502 if (fOptions.fExponent.fAlwaysShowSign) {
1503 result.append(kPatternPlus);
1504 }
1505 for (int32_t i = 0; i < 1 || i < fEffPrecision.fMinExponentDigits; ++i) {
1506 result.append(kPatternZeroDigit);
1507 }
1508 }
1509 return result;
1510 }
1511
1512 UnicodeString&
toPattern(UnicodeString & result) const1513 DecimalFormatImpl::toPattern(UnicodeString& result) const {
1514 result.remove();
1515 UnicodeString padSpec;
1516 if (fAffixes.fWidth > 0) {
1517 padSpec.append(kPatternPadEscape);
1518 padSpec.append(fAffixes.fPadChar);
1519 }
1520 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
1521 result.append(padSpec);
1522 }
1523 fPositivePrefixPattern.toUserString(result);
1524 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
1525 result.append(padSpec);
1526 }
1527 toNumberPattern(
1528 fAffixes.fWidth > 0,
1529 fAffixes.fWidth - fPositivePrefixPattern.countChar32() - fPositiveSuffixPattern.countChar32(),
1530 result);
1531 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
1532 result.append(padSpec);
1533 }
1534 fPositiveSuffixPattern.toUserString(result);
1535 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
1536 result.append(padSpec);
1537 }
1538 AffixPattern withNegative;
1539 withNegative.add(AffixPattern::kNegative);
1540 withNegative.append(fPositivePrefixPattern);
1541 if (!fPositiveSuffixPattern.equals(fNegativeSuffixPattern) ||
1542 !withNegative.equals(fNegativePrefixPattern)) {
1543 result.append(kPatternSeparator);
1544 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
1545 result.append(padSpec);
1546 }
1547 fNegativePrefixPattern.toUserString(result);
1548 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
1549 result.append(padSpec);
1550 }
1551 toNumberPattern(
1552 fAffixes.fWidth > 0,
1553 fAffixes.fWidth - fNegativePrefixPattern.countChar32() - fNegativeSuffixPattern.countChar32(),
1554 result);
1555 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
1556 result.append(padSpec);
1557 }
1558 fNegativeSuffixPattern.toUserString(result);
1559 if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
1560 result.append(padSpec);
1561 }
1562 }
1563 return result;
1564 }
1565
1566 int32_t
getOldFormatWidth() const1567 DecimalFormatImpl::getOldFormatWidth() const {
1568 if (fAffixes.fWidth == 0) {
1569 return 0;
1570 }
1571 return fAffixes.fWidth - fPositiveSuffixPattern.countChar32() - fPositivePrefixPattern.countChar32();
1572 }
1573
1574 const UnicodeString &
getConstSymbol(DecimalFormatSymbols::ENumberFormatSymbol symbol) const1575 DecimalFormatImpl::getConstSymbol(
1576 DecimalFormatSymbols::ENumberFormatSymbol symbol) const {
1577 return fSymbols->getConstSymbol(symbol);
1578 }
1579
1580 UBool
isParseFastpath() const1581 DecimalFormatImpl::isParseFastpath() const {
1582 AffixPattern negative;
1583 negative.add(AffixPattern::kNegative);
1584
1585 return fAffixes.fWidth == 0 &&
1586 fPositivePrefixPattern.countChar32() == 0 &&
1587 fNegativePrefixPattern.equals(negative) &&
1588 fPositiveSuffixPattern.countChar32() == 0 &&
1589 fNegativeSuffixPattern.countChar32() == 0;
1590 }
1591
1592
1593 U_NAMESPACE_END
1594
1595 #endif /* #if !UCONFIG_NO_FORMATTING */
1596
1597