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