1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 * Copyright (C) 2015, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 * file name: digitformatter.cpp
10 #include "unicode/utypes.h"
12 #if !UCONFIG_NO_FORMATTING
14 #include "unicode/dcfmtsym.h"
15 #include "unicode/unum.h"
17 #include "digitformatter.h"
18 #include "digitgrouping.h"
19 #include "digitinterval.h"
22 #include "smallintformatter.h"
23 #include "unistrappender.h"
24 #include "visibledigits.h"
28 DigitFormatter::DigitFormatter()
29 : fGroupingSeparator(",", -1, US_INV), fDecimal(".", -1, US_INV),
30 fNegativeSign("-", -1, US_INV), fPositiveSign("+", -1, US_INV),
31 fIsStandardDigits(TRUE), fExponent("E", -1, US_INV) {
32 for (int32_t i = 0; i < 10; ++i) {
33 fLocalizedDigits[i] = (UChar32) (0x30 + i);
35 fInfinity.setTo(UnicodeString("Inf", -1, US_INV), UNUM_INTEGER_FIELD);
36 fNan.setTo(UnicodeString("Nan", -1, US_INV), UNUM_INTEGER_FIELD);
39 DigitFormatter::DigitFormatter(const DecimalFormatSymbols &symbols) {
40 setDecimalFormatSymbols(symbols);
44 DigitFormatter::setOtherDecimalFormatSymbols(
45 const DecimalFormatSymbols &symbols) {
46 fLocalizedDigits[0] = symbols.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
47 fLocalizedDigits[1] = symbols.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0);
48 fLocalizedDigits[2] = symbols.getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0);
49 fLocalizedDigits[3] = symbols.getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0);
50 fLocalizedDigits[4] = symbols.getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0);
51 fLocalizedDigits[5] = symbols.getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0);
52 fLocalizedDigits[6] = symbols.getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0);
53 fLocalizedDigits[7] = symbols.getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0);
54 fLocalizedDigits[8] = symbols.getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0);
55 fLocalizedDigits[9] = symbols.getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0);
56 fIsStandardDigits = isStandardDigits();
57 fNegativeSign = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
58 fPositiveSign = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
59 fInfinity.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), UNUM_INTEGER_FIELD);
60 fNan.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), UNUM_INTEGER_FIELD);
61 fExponent = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
65 DigitFormatter::setDecimalFormatSymbolsForMonetary(
66 const DecimalFormatSymbols &symbols) {
67 setOtherDecimalFormatSymbols(symbols);
68 fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
69 fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
73 DigitFormatter::setDecimalFormatSymbols(
74 const DecimalFormatSymbols &symbols) {
75 setOtherDecimalFormatSymbols(symbols);
76 fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
77 fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
80 static void appendField(
82 const UnicodeString &value,
83 FieldPositionHandler &handler,
84 UnicodeString &appendTo) {
85 int32_t currentLength = appendTo.length();
86 appendTo.append(value);
93 int32_t DigitFormatter::countChar32(
94 const DigitGrouping &grouping,
95 const DigitInterval &interval,
96 const DigitFormatterOptions &options) const {
97 int32_t result = interval.length();
99 // We always emit '0' in lieu of no digits.
103 if (options.fAlwaysShowDecimal || interval.getLeastSignificantInclusive() < 0) {
104 result += fDecimal.countChar32();
106 result += grouping.getSeparatorCount(interval.getIntDigitCount()) * fGroupingSeparator.countChar32();
111 DigitFormatter::countChar32(
112 const VisibleDigits &digits,
113 const DigitGrouping &grouping,
114 const DigitFormatterOptions &options) const {
115 if (digits.isNaN()) {
116 return countChar32ForNaN();
118 if (digits.isInfinite()) {
119 return countChar32ForInfinity();
123 digits.getInterval(),
128 DigitFormatter::countChar32(
129 const VisibleDigitsWithExponent &digits,
130 const SciFormatterOptions &options) const {
131 if (digits.isNaN()) {
132 return countChar32ForNaN();
134 if (digits.isInfinite()) {
135 return countChar32ForInfinity();
137 const VisibleDigits *exponent = digits.getExponent();
138 if (exponent == NULL) {
139 DigitGrouping grouping;
142 digits.getMantissa().getInterval(),
146 *exponent, digits.getMantissa().getInterval(), options);
150 DigitFormatter::countChar32(
151 const VisibleDigits &exponent,
152 const DigitInterval &mantissaInterval,
153 const SciFormatterOptions &options) const {
154 DigitGrouping grouping;
155 int32_t count = countChar32(
156 grouping, mantissaInterval, options.fMantissa);
157 count += fExponent.countChar32();
158 count += countChar32ForExponent(
159 exponent, options.fExponent);
163 UnicodeString &DigitFormatter::format(
164 const VisibleDigits &digits,
165 const DigitGrouping &grouping,
166 const DigitFormatterOptions &options,
167 FieldPositionHandler &handler,
168 UnicodeString &appendTo) const {
169 if (digits.isNaN()) {
170 return formatNaN(handler, appendTo);
172 if (digits.isInfinite()) {
173 return formatInfinity(handler, appendTo);
176 const DigitInterval &interval = digits.getInterval();
177 int32_t digitsLeftOfDecimal = interval.getMostSignificantExclusive();
178 int32_t lastDigitPos = interval.getLeastSignificantInclusive();
179 int32_t intBegin = appendTo.length();
182 // Emit "0" instead of empty string.
183 if (digitsLeftOfDecimal == 0 && lastDigitPos == 0) {
184 appendTo.append(fLocalizedDigits[0]);
185 handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
186 if (options.fAlwaysShowDecimal) {
188 UNUM_DECIMAL_SEPARATOR_FIELD,
196 UnicodeStringAppender appender(appendTo);
197 for (int32_t i = interval.getMostSignificantExclusive() - 1;
198 i >= interval.getLeastSignificantInclusive(); --i) {
202 UNUM_DECIMAL_SEPARATOR_FIELD,
206 fracBegin = appendTo.length();
208 appender.append(fLocalizedDigits[digits.getDigitByExponent(i)]);
209 if (grouping.isSeparatorAt(digitsLeftOfDecimal, i)) {
212 UNUM_GROUPING_SEPARATOR_FIELD,
219 if (digitsLeftOfDecimal > 0) {
220 handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
224 if (options.fAlwaysShowDecimal && lastDigitPos == 0) {
227 UNUM_DECIMAL_SEPARATOR_FIELD,
233 // lastDigitPos is never > 0 so we are guaranteed that kIntegerField
235 if (lastDigitPos < 0) {
236 handler.addAttribute(UNUM_FRACTION_FIELD, fracBegin, appendTo.length());
242 DigitFormatter::format(
243 const VisibleDigitsWithExponent &digits,
244 const SciFormatterOptions &options,
245 FieldPositionHandler &handler,
246 UnicodeString &appendTo) const {
247 DigitGrouping grouping;
249 digits.getMantissa(),
254 const VisibleDigits *exponent = digits.getExponent();
255 if (exponent == NULL) {
258 int32_t expBegin = appendTo.length();
259 appendTo.append(fExponent);
260 handler.addAttribute(
261 UNUM_EXPONENT_SYMBOL_FIELD, expBegin, appendTo.length());
262 return formatExponent(
265 UNUM_EXPONENT_SIGN_FIELD,
271 static int32_t formatInt(
272 int32_t value, uint8_t *digits) {
275 digits[idx++] = (uint8_t) (value % 10);
282 DigitFormatter::formatDigits(
283 const uint8_t *digits,
285 const IntDigitCountRange &range,
287 FieldPositionHandler &handler,
288 UnicodeString &appendTo) const {
289 int32_t i = range.pin(count) - 1;
290 int32_t begin = appendTo.length();
292 // Always emit '0' as placeholder for empty string.
294 appendTo.append(fLocalizedDigits[0]);
295 handler.addAttribute(intField, begin, appendTo.length());
299 UnicodeStringAppender appender(appendTo);
300 for (; i >= count; --i) {
301 appender.append(fLocalizedDigits[0]);
303 for (; i >= 0; --i) {
304 appender.append(fLocalizedDigits[digits[i]]);
307 handler.addAttribute(intField, begin, appendTo.length());
312 DigitFormatter::formatExponent(
313 const VisibleDigits &digits,
314 const DigitFormatterIntOptions &options,
317 FieldPositionHandler &handler,
318 UnicodeString &appendTo) const {
319 UBool neg = digits.isNegative();
320 if (neg || options.fAlwaysShowSign) {
323 neg ? fNegativeSign : fPositiveSign,
327 int32_t begin = appendTo.length();
328 DigitGrouping grouping;
329 DigitFormatterOptions expOptions;
330 FieldPosition fpos(FieldPosition::DONT_CARE);
331 FieldPositionOnlyHandler noHandler(fpos);
338 handler.addAttribute(intField, begin, appendTo.length());
343 DigitFormatter::countChar32ForExponent(
344 const VisibleDigits &exponent,
345 const DigitFormatterIntOptions &options) const {
347 UBool neg = exponent.isNegative();
348 if (neg || options.fAlwaysShowSign) {
349 result += neg ? fNegativeSign.countChar32() : fPositiveSign.countChar32();
351 DigitGrouping grouping;
352 DigitFormatterOptions expOptions;
353 result += countChar32(grouping, exponent.getInterval(), expOptions);
358 DigitFormatter::formatPositiveInt32(
359 int32_t positiveValue,
360 const IntDigitCountRange &range,
361 FieldPositionHandler &handler,
362 UnicodeString &appendTo) const {
364 if (fIsStandardDigits && SmallIntFormatter::canFormat(positiveValue, range)) {
365 int32_t begin = appendTo.length();
366 SmallIntFormatter::format(positiveValue, range, appendTo);
367 handler.addAttribute(UNUM_INTEGER_FIELD, begin, appendTo.length());
371 int32_t count = formatInt(positiveValue, digits);
381 UBool DigitFormatter::isStandardDigits() const {
382 UChar32 cdigit = 0x30;
383 for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
384 if (fLocalizedDigits[i] != cdigit) {
393 DigitFormatter::equals(const DigitFormatter &rhs) const {
394 UBool result = (fGroupingSeparator == rhs.fGroupingSeparator) &&
395 (fDecimal == rhs.fDecimal) &&
396 (fNegativeSign == rhs.fNegativeSign) &&
397 (fPositiveSign == rhs.fPositiveSign) &&
398 (fInfinity.equals(rhs.fInfinity)) &&
399 (fNan.equals(rhs.fNan)) &&
400 (fIsStandardDigits == rhs.fIsStandardDigits) &&
401 (fExponent == rhs.fExponent);
406 for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
407 if (fLocalizedDigits[i] != rhs.fLocalizedDigits[i]) {
417 #endif /* #if !UCONFIG_NO_FORMATTING */