Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(774)

Side by Side Diff: source/i18n/digitformatter.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/i18n/digitformatter.h ('k') | source/i18n/digitgrouping.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2015, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *
5 * file name: digitformatter.cpp
6 */
7
8 #include "unicode/utypes.h"
9
10 #if !UCONFIG_NO_FORMATTING
11
12 #include "unicode/dcfmtsym.h"
13 #include "unicode/unum.h"
14
15 #include "digitformatter.h"
16 #include "digitgrouping.h"
17 #include "digitinterval.h"
18 #include "digitlst.h"
19 #include "fphdlimp.h"
20 #include "smallintformatter.h"
21 #include "unistrappender.h"
22 #include "visibledigits.h"
23
24 U_NAMESPACE_BEGIN
25
26 DigitFormatter::DigitFormatter()
27 : fGroupingSeparator(",", -1, US_INV), fDecimal(".", -1, US_INV),
28 fNegativeSign("-", -1, US_INV), fPositiveSign("+", -1, US_INV),
29 fIsStandardDigits(TRUE), fExponent("E", -1, US_INV) {
30 for (int32_t i = 0; i < 10; ++i) {
31 fLocalizedDigits[i] = (UChar32) (0x30 + i);
32 }
33 fInfinity.setTo(UnicodeString("Inf", -1, US_INV), UNUM_INTEGER_FIELD);
34 fNan.setTo(UnicodeString("Nan", -1, US_INV), UNUM_INTEGER_FIELD);
35 }
36
37 DigitFormatter::DigitFormatter(const DecimalFormatSymbols &symbols) {
38 setDecimalFormatSymbols(symbols);
39 }
40
41 void
42 DigitFormatter::setOtherDecimalFormatSymbols(
43 const DecimalFormatSymbols &symbols) {
44 fLocalizedDigits[0] = symbols.getConstSymbol(DecimalFormatSymbols::kZeroDigi tSymbol).char32At(0);
45 fLocalizedDigits[1] = symbols.getConstSymbol(DecimalFormatSymbols::kOneDigit Symbol).char32At(0);
46 fLocalizedDigits[2] = symbols.getConstSymbol(DecimalFormatSymbols::kTwoDigit Symbol).char32At(0);
47 fLocalizedDigits[3] = symbols.getConstSymbol(DecimalFormatSymbols::kThreeDig itSymbol).char32At(0);
48 fLocalizedDigits[4] = symbols.getConstSymbol(DecimalFormatSymbols::kFourDigi tSymbol).char32At(0);
49 fLocalizedDigits[5] = symbols.getConstSymbol(DecimalFormatSymbols::kFiveDigi tSymbol).char32At(0);
50 fLocalizedDigits[6] = symbols.getConstSymbol(DecimalFormatSymbols::kSixDigit Symbol).char32At(0);
51 fLocalizedDigits[7] = symbols.getConstSymbol(DecimalFormatSymbols::kSevenDig itSymbol).char32At(0);
52 fLocalizedDigits[8] = symbols.getConstSymbol(DecimalFormatSymbols::kEightDig itSymbol).char32At(0);
53 fLocalizedDigits[9] = symbols.getConstSymbol(DecimalFormatSymbols::kNineDigi tSymbol).char32At(0);
54 fIsStandardDigits = isStandardDigits();
55 fNegativeSign = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbo l);
56 fPositiveSign = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol );
57 fInfinity.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol ), UNUM_INTEGER_FIELD);
58 fNan.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), UNUM_IN TEGER_FIELD);
59 fExponent = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol) ;
60 }
61
62 void
63 DigitFormatter::setDecimalFormatSymbolsForMonetary(
64 const DecimalFormatSymbols &symbols) {
65 setOtherDecimalFormatSymbols(symbols);
66 fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetaryG roupingSeparatorSymbol);
67 fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSy mbol);
68 }
69
70 void
71 DigitFormatter::setDecimalFormatSymbols(
72 const DecimalFormatSymbols &symbols) {
73 setOtherDecimalFormatSymbols(symbols);
74 fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingS eparatorSymbol);
75 fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSym bol);
76 }
77
78 static void appendField(
79 int32_t fieldId,
80 const UnicodeString &value,
81 FieldPositionHandler &handler,
82 UnicodeString &appendTo) {
83 int32_t currentLength = appendTo.length();
84 appendTo.append(value);
85 handler.addAttribute(
86 fieldId,
87 currentLength,
88 appendTo.length());
89 }
90
91 int32_t DigitFormatter::countChar32(
92 const DigitGrouping &grouping,
93 const DigitInterval &interval,
94 const DigitFormatterOptions &options) const {
95 int32_t result = interval.length();
96
97 // We always emit '0' in lieu of no digits.
98 if (result == 0) {
99 result = 1;
100 }
101 if (options.fAlwaysShowDecimal || interval.getLeastSignificantInclusive() < 0) {
102 result += fDecimal.countChar32();
103 }
104 result += grouping.getSeparatorCount(interval.getIntDigitCount()) * fGroupin gSeparator.countChar32();
105 return result;
106 }
107
108 int32_t
109 DigitFormatter::countChar32(
110 const VisibleDigits &digits,
111 const DigitGrouping &grouping,
112 const DigitFormatterOptions &options) const {
113 if (digits.isNaN()) {
114 return countChar32ForNaN();
115 }
116 if (digits.isInfinite()) {
117 return countChar32ForInfinity();
118 }
119 return countChar32(
120 grouping,
121 digits.getInterval(),
122 options);
123 }
124
125 int32_t
126 DigitFormatter::countChar32(
127 const VisibleDigitsWithExponent &digits,
128 const SciFormatterOptions &options) const {
129 if (digits.isNaN()) {
130 return countChar32ForNaN();
131 }
132 if (digits.isInfinite()) {
133 return countChar32ForInfinity();
134 }
135 const VisibleDigits *exponent = digits.getExponent();
136 if (exponent == NULL) {
137 DigitGrouping grouping;
138 return countChar32(
139 grouping,
140 digits.getMantissa().getInterval(),
141 options.fMantissa);
142 }
143 return countChar32(
144 *exponent, digits.getMantissa().getInterval(), options);
145 }
146
147 int32_t
148 DigitFormatter::countChar32(
149 const VisibleDigits &exponent,
150 const DigitInterval &mantissaInterval,
151 const SciFormatterOptions &options) const {
152 DigitGrouping grouping;
153 int32_t count = countChar32(
154 grouping, mantissaInterval, options.fMantissa);
155 count += fExponent.countChar32();
156 count += countChar32ForExponent(
157 exponent, options.fExponent);
158 return count;
159 }
160
161 UnicodeString &DigitFormatter::format(
162 const VisibleDigits &digits,
163 const DigitGrouping &grouping,
164 const DigitFormatterOptions &options,
165 FieldPositionHandler &handler,
166 UnicodeString &appendTo) const {
167 if (digits.isNaN()) {
168 return formatNaN(handler, appendTo);
169 }
170 if (digits.isInfinite()) {
171 return formatInfinity(handler, appendTo);
172 }
173
174 const DigitInterval &interval = digits.getInterval();
175 int32_t digitsLeftOfDecimal = interval.getMostSignificantExclusive();
176 int32_t lastDigitPos = interval.getLeastSignificantInclusive();
177 int32_t intBegin = appendTo.length();
178 int32_t fracBegin;
179
180 // Emit "0" instead of empty string.
181 if (digitsLeftOfDecimal == 0 && lastDigitPos == 0) {
182 appendTo.append(fLocalizedDigits[0]);
183 handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
184 if (options.fAlwaysShowDecimal) {
185 appendField(
186 UNUM_DECIMAL_SEPARATOR_FIELD,
187 fDecimal,
188 handler,
189 appendTo);
190 }
191 return appendTo;
192 }
193 {
194 UnicodeStringAppender appender(appendTo);
195 for (int32_t i = interval.getMostSignificantExclusive() - 1;
196 i >= interval.getLeastSignificantInclusive(); --i) {
197 if (i == -1) {
198 appender.flush();
199 appendField(
200 UNUM_DECIMAL_SEPARATOR_FIELD,
201 fDecimal,
202 handler,
203 appendTo);
204 fracBegin = appendTo.length();
205 }
206 appender.append(fLocalizedDigits[digits.getDigitByExponent(i)]);
207 if (grouping.isSeparatorAt(digitsLeftOfDecimal, i)) {
208 appender.flush();
209 appendField(
210 UNUM_GROUPING_SEPARATOR_FIELD,
211 fGroupingSeparator,
212 handler,
213 appendTo);
214 }
215 if (i == 0) {
216 appender.flush();
217 if (digitsLeftOfDecimal > 0) {
218 handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo. length());
219 }
220 }
221 }
222 if (options.fAlwaysShowDecimal && lastDigitPos == 0) {
223 appender.flush();
224 appendField(
225 UNUM_DECIMAL_SEPARATOR_FIELD,
226 fDecimal,
227 handler,
228 appendTo);
229 }
230 }
231 // lastDigitPos is never > 0 so we are guaranteed that kIntegerField
232 // is already added.
233 if (lastDigitPos < 0) {
234 handler.addAttribute(UNUM_FRACTION_FIELD, fracBegin, appendTo.length());
235 }
236 return appendTo;
237 }
238
239 UnicodeString &
240 DigitFormatter::format(
241 const VisibleDigitsWithExponent &digits,
242 const SciFormatterOptions &options,
243 FieldPositionHandler &handler,
244 UnicodeString &appendTo) const {
245 DigitGrouping grouping;
246 format(
247 digits.getMantissa(),
248 grouping,
249 options.fMantissa,
250 handler,
251 appendTo);
252 const VisibleDigits *exponent = digits.getExponent();
253 if (exponent == NULL) {
254 return appendTo;
255 }
256 int32_t expBegin = appendTo.length();
257 appendTo.append(fExponent);
258 handler.addAttribute(
259 UNUM_EXPONENT_SYMBOL_FIELD, expBegin, appendTo.length());
260 return formatExponent(
261 *exponent,
262 options.fExponent,
263 UNUM_EXPONENT_SIGN_FIELD,
264 UNUM_EXPONENT_FIELD,
265 handler,
266 appendTo);
267 }
268
269 static int32_t formatInt(
270 int32_t value, uint8_t *digits) {
271 int32_t idx = 0;
272 while (value > 0) {
273 digits[idx++] = (uint8_t) (value % 10);
274 value /= 10;
275 }
276 return idx;
277 }
278
279 UnicodeString &
280 DigitFormatter::formatDigits(
281 const uint8_t *digits,
282 int32_t count,
283 const IntDigitCountRange &range,
284 int32_t intField,
285 FieldPositionHandler &handler,
286 UnicodeString &appendTo) const {
287 int32_t i = range.pin(count) - 1;
288 int32_t begin = appendTo.length();
289
290 // Always emit '0' as placeholder for empty string.
291 if (i == -1) {
292 appendTo.append(fLocalizedDigits[0]);
293 handler.addAttribute(intField, begin, appendTo.length());
294 return appendTo;
295 }
296 {
297 UnicodeStringAppender appender(appendTo);
298 for (; i >= count; --i) {
299 appender.append(fLocalizedDigits[0]);
300 }
301 for (; i >= 0; --i) {
302 appender.append(fLocalizedDigits[digits[i]]);
303 }
304 }
305 handler.addAttribute(intField, begin, appendTo.length());
306 return appendTo;
307 }
308
309 UnicodeString &
310 DigitFormatter::formatExponent(
311 const VisibleDigits &digits,
312 const DigitFormatterIntOptions &options,
313 int32_t signField,
314 int32_t intField,
315 FieldPositionHandler &handler,
316 UnicodeString &appendTo) const {
317 UBool neg = digits.isNegative();
318 if (neg || options.fAlwaysShowSign) {
319 appendField(
320 signField,
321 neg ? fNegativeSign : fPositiveSign,
322 handler,
323 appendTo);
324 }
325 int32_t begin = appendTo.length();
326 DigitGrouping grouping;
327 DigitFormatterOptions expOptions;
328 FieldPosition fpos(FieldPosition::DONT_CARE);
329 FieldPositionOnlyHandler noHandler(fpos);
330 format(
331 digits,
332 grouping,
333 expOptions,
334 noHandler,
335 appendTo);
336 handler.addAttribute(intField, begin, appendTo.length());
337 return appendTo;
338 }
339
340 int32_t
341 DigitFormatter::countChar32ForExponent(
342 const VisibleDigits &exponent,
343 const DigitFormatterIntOptions &options) const {
344 int32_t result = 0;
345 UBool neg = exponent.isNegative();
346 if (neg || options.fAlwaysShowSign) {
347 result += neg ? fNegativeSign.countChar32() : fPositiveSign.countChar32( );
348 }
349 DigitGrouping grouping;
350 DigitFormatterOptions expOptions;
351 result += countChar32(grouping, exponent.getInterval(), expOptions);
352 return result;
353 }
354
355 UnicodeString &
356 DigitFormatter::formatPositiveInt32(
357 int32_t positiveValue,
358 const IntDigitCountRange &range,
359 FieldPositionHandler &handler,
360 UnicodeString &appendTo) const {
361 // super fast path
362 if (fIsStandardDigits && SmallIntFormatter::canFormat(positiveValue, range)) {
363 int32_t begin = appendTo.length();
364 SmallIntFormatter::format(positiveValue, range, appendTo);
365 handler.addAttribute(UNUM_INTEGER_FIELD, begin, appendTo.length());
366 return appendTo;
367 }
368 uint8_t digits[10];
369 int32_t count = formatInt(positiveValue, digits);
370 return formatDigits(
371 digits,
372 count,
373 range,
374 UNUM_INTEGER_FIELD,
375 handler,
376 appendTo);
377 }
378
379 UBool DigitFormatter::isStandardDigits() const {
380 UChar32 cdigit = 0x30;
381 for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
382 if (fLocalizedDigits[i] != cdigit) {
383 return FALSE;
384 }
385 ++cdigit;
386 }
387 return TRUE;
388 }
389
390 UBool
391 DigitFormatter::equals(const DigitFormatter &rhs) const {
392 UBool result = (fGroupingSeparator == rhs.fGroupingSeparator) &&
393 (fDecimal == rhs.fDecimal) &&
394 (fNegativeSign == rhs.fNegativeSign) &&
395 (fPositiveSign == rhs.fPositiveSign) &&
396 (fInfinity.equals(rhs.fInfinity)) &&
397 (fNan.equals(rhs.fNan)) &&
398 (fIsStandardDigits == rhs.fIsStandardDigits) &&
399 (fExponent == rhs.fExponent);
400
401 if (!result) {
402 return FALSE;
403 }
404 for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
405 if (fLocalizedDigits[i] != rhs.fLocalizedDigits[i]) {
406 return FALSE;
407 }
408 }
409 return TRUE;
410 }
411
412
413 U_NAMESPACE_END
414
415 #endif /* #if !UCONFIG_NO_FORMATTING */
OLDNEW
« no previous file with comments | « source/i18n/digitformatter.h ('k') | source/i18n/digitgrouping.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698