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