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