]>
Commit | Line | Data |
---|---|---|
2ca993e8 A |
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 | ||
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 | ||
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 | ||
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 & | |
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 | |
172 | 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 | ||
203 | DecimalFormatImpl::~DecimalFormatImpl() { | |
204 | delete fSymbols; | |
205 | delete fRules; | |
206 | } | |
207 | ||
208 | ValueFormatter & | |
209 | 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 | |
221 | 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 | |
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 & | |
252 | 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 & | |
262 | 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> | |
272 | 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> | |
296 | 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 & | |
319 | 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 & | |
338 | 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 & | |
353 | 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 & | |
365 | 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 & | |
375 | 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 & | |
386 | 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 & | |
396 | 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 & | |
406 | 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 & | |
416 | 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 & | |
427 | 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 & | |
439 | 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 & | |
450 | 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 & | |
461 | 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 & | |
475 | 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 & | |
487 | 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 & | |
503 | 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 | ||
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 & | |
531 | 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 & | |
541 | 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 & | |
552 | 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 & | |
571 | 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 & | |
590 | 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 & | |
599 | 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 & | |
614 | 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 | |
626 | DecimalFormatImpl::setMinimumSignificantDigits(int32_t newValue) { | |
627 | fMinSigDigits = newValue; | |
628 | fUseSigDigits = TRUE; // ticket 9936 | |
629 | updatePrecision(); | |
630 | } | |
631 | ||
632 | void | |
633 | DecimalFormatImpl::setMaximumSignificantDigits(int32_t newValue) { | |
634 | fMaxSigDigits = newValue; | |
635 | fUseSigDigits = TRUE; // ticket 9936 | |
636 | updatePrecision(); | |
637 | } | |
638 | ||
639 | void | |
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 | |
648 | DecimalFormatImpl::setScientificNotation(UBool newValue) { | |
649 | fUseScientific = newValue; | |
650 | updatePrecision(); | |
651 | } | |
652 | ||
653 | void | |
654 | DecimalFormatImpl::setSignificantDigitsUsed(UBool newValue) { | |
655 | fUseSigDigits = newValue; | |
656 | updatePrecision(); | |
657 | } | |
658 | ||
659 | void | |
660 | DecimalFormatImpl::setGroupingSize(int32_t newValue) { | |
661 | fGrouping.fGrouping = newValue; | |
662 | updateGrouping(); | |
663 | } | |
664 | ||
665 | void | |
666 | DecimalFormatImpl::setSecondaryGroupingSize(int32_t newValue) { | |
667 | fGrouping.fGrouping2 = newValue; | |
668 | updateGrouping(); | |
669 | } | |
670 | ||
671 | void | |
672 | DecimalFormatImpl::setMinimumGroupingDigits(int32_t newValue) { | |
673 | fGrouping.fMinGrouping = newValue; | |
674 | updateGrouping(); | |
675 | } | |
676 | ||
677 | void | |
678 | DecimalFormatImpl::setCurrencyUsage( | |
679 | UCurrencyUsage currencyUsage, UErrorCode &status) { | |
680 | fCurrencyUsage = currencyUsage; | |
681 | updateFormatting(kFormattingCurrency, status); | |
682 | } | |
683 | ||
684 | void | |
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 | |
694 | DecimalFormatImpl::getRoundingIncrement() const { | |
695 | return fEffPrecision.fMantissa.fRoundingIncrement.getDouble(); | |
696 | } | |
697 | ||
698 | int32_t | |
699 | DecimalFormatImpl::getMultiplier() const { | |
700 | if (fMultiplier.isZero()) { | |
701 | return 1; | |
702 | } | |
703 | return (int32_t) fMultiplier.getDouble(); | |
704 | } | |
705 | ||
706 | void | |
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 | |
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 | |
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 | |
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 | |
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 & | |
748 | DecimalFormatImpl::getPositivePrefix(UnicodeString &result) const { | |
749 | result = fAffixes.fPositivePrefix.getOtherVariant().toString(); | |
750 | return result; | |
751 | } | |
752 | ||
753 | UnicodeString & | |
754 | DecimalFormatImpl::getPositiveSuffix(UnicodeString &result) const { | |
755 | result = fAffixes.fPositiveSuffix.getOtherVariant().toString(); | |
756 | return result; | |
757 | } | |
758 | ||
759 | UnicodeString & | |
760 | DecimalFormatImpl::getNegativePrefix(UnicodeString &result) const { | |
761 | result = fAffixes.fNegativePrefix.getOtherVariant().toString(); | |
762 | return result; | |
763 | } | |
764 | ||
765 | UnicodeString & | |
766 | DecimalFormatImpl::getNegativeSuffix(UnicodeString &result) const { | |
767 | result = fAffixes.fNegativeSuffix.getOtherVariant().toString(); | |
768 | return result; | |
769 | } | |
770 | ||
771 | void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
889 | DecimalFormatImpl::updatePrecision() { | |
890 | if (fUseScientific) { | |
891 | updatePrecisionForScientific(); | |
892 | } else { | |
893 | updatePrecisionForFixed(); | |
894 | } | |
895 | } | |
896 | ||
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 | |
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 | |
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 | |
994 | 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 | |
1003 | DecimalFormatImpl::extractSigDigits( | |
1004 | SignificantDigitInterval &sig) const { | |
1005 | sig.setMin(fMinSigDigits < 0 ? 0 : fMinSigDigits); | |
1006 | sig.setMax(fMaxSigDigits < 0 ? 0 : fMaxSigDigits); | |
1007 | } | |
1008 | ||
1009 | void | |
1010 | DecimalFormatImpl::updateGrouping() { | |
1011 | if (fSuper->isGroupingUsed()) { | |
1012 | fEffGrouping = fGrouping; | |
1013 | } else { | |
1014 | fEffGrouping.clear(); | |
1015 | } | |
1016 | } | |
1017 | ||
1018 | void | |
1019 | DecimalFormatImpl::updateCurrency(UErrorCode &status) { | |
1020 | updateFormatting(kFormattingCurrency, TRUE, status); | |
1021 | } | |
1022 | ||
1023 | void | |
1024 | DecimalFormatImpl::updateFormatting( | |
1025 | int32_t changedFormattingFields, | |
1026 | UErrorCode &status) { | |
1027 | updateFormatting(changedFormattingFields, TRUE, status); | |
1028 | } | |
1029 | ||
1030 | void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
1282 | DecimalFormatImpl::updateForApplyPatternFavorCurrencyPrecision( | |
1283 | UErrorCode &status) { | |
1284 | updateAll(kFormattingAll & ~kFormattingSymbols, TRUE, status); | |
1285 | } | |
1286 | ||
1287 | void | |
1288 | DecimalFormatImpl::updateForApplyPattern(UErrorCode &status) { | |
1289 | updateAll(kFormattingAll & ~kFormattingSymbols, FALSE, status); | |
1290 | } | |
1291 | ||
1292 | void | |
1293 | DecimalFormatImpl::updateAll(UErrorCode &status) { | |
1294 | updateAll(kFormattingAll, TRUE, status); | |
1295 | } | |
1296 | ||
1297 | void | |
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 | |
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 | |
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 | |
1352 | 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 | |
1360 | 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& | |
1369 | 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& | |
1511 | 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 | |
1565 | 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 & | |
1573 | DecimalFormatImpl::getConstSymbol( | |
1574 | DecimalFormatSymbols::ENumberFormatSymbol symbol) const { | |
1575 | return fSymbols->getConstSymbol(symbol); | |
1576 | } | |
1577 | ||
1578 | UBool | |
1579 | 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 |