]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/scientificnumberformatter.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / scientificnumberformatter.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
b331163b
A
3/*
4**********************************************************************
5* Copyright (c) 2014, International Business Machines
6* Corporation and others. All Rights Reserved.
7**********************************************************************
8*/
9#include "unicode/utypes.h"
10
11#if !UCONFIG_NO_FORMATTING
12
13#include "unicode/scientificnumberformatter.h"
14#include "unicode/dcfmtsym.h"
15#include "unicode/fpositer.h"
16#include "unicode/utf16.h"
17#include "unicode/uniset.h"
18#include "decfmtst.h"
19#include "unicode/decimfmt.h"
20
21U_NAMESPACE_BEGIN
22
23static const UChar kSuperscriptDigits[] = {
24 0x2070,
25 0xB9,
26 0xB2,
27 0xB3,
28 0x2074,
29 0x2075,
30 0x2076,
31 0x2077,
32 0x2078,
33 0x2079};
34
35static const UChar kSuperscriptPlusSign = 0x207A;
36static const UChar kSuperscriptMinusSign = 0x207B;
37
38static UBool copyAsSuperscript(
39 const UnicodeString &s,
40 int32_t beginIndex,
41 int32_t endIndex,
42 UnicodeString &result,
43 UErrorCode &status) {
44 if (U_FAILURE(status)) {
45 return FALSE;
46 }
47 for (int32_t i = beginIndex; i < endIndex;) {
48 UChar32 c = s.char32At(i);
49 int32_t digit = u_charDigitValue(c);
50 if (digit < 0) {
51 status = U_INVALID_CHAR_FOUND;
52 return FALSE;
53 }
54 result.append(kSuperscriptDigits[digit]);
55 i += U16_LENGTH(c);
56 }
57 return TRUE;
58}
59
60ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
61 DecimalFormat *fmtToAdopt, UErrorCode &status) {
62 return createInstance(fmtToAdopt, new SuperscriptStyle(), status);
63}
64
65ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
66 const Locale &locale, UErrorCode &status) {
67 return createInstance(
68 static_cast<DecimalFormat *>(
69 DecimalFormat::createScientificInstance(locale, status)),
70 new SuperscriptStyle(),
71 status);
72}
73
74ScientificNumberFormatter *ScientificNumberFormatter::createMarkupInstance(
75 DecimalFormat *fmtToAdopt,
76 const UnicodeString &beginMarkup,
77 const UnicodeString &endMarkup,
78 UErrorCode &status) {
79 return createInstance(
80 fmtToAdopt,
81 new MarkupStyle(beginMarkup, endMarkup),
82 status);
83}
84
85ScientificNumberFormatter *ScientificNumberFormatter::createMarkupInstance(
86 const Locale &locale,
87 const UnicodeString &beginMarkup,
88 const UnicodeString &endMarkup,
89 UErrorCode &status) {
90 return createInstance(
91 static_cast<DecimalFormat *>(
92 DecimalFormat::createScientificInstance(locale, status)),
93 new MarkupStyle(beginMarkup, endMarkup),
94 status);
95}
96
97ScientificNumberFormatter *ScientificNumberFormatter::createInstance(
98 DecimalFormat *fmtToAdopt,
99 Style *styleToAdopt,
100 UErrorCode &status) {
101 LocalPointer<DecimalFormat> fmt(fmtToAdopt);
102 LocalPointer<Style> style(styleToAdopt);
103 if (U_FAILURE(status)) {
104 return NULL;
105 }
106 ScientificNumberFormatter *result =
107 new ScientificNumberFormatter(
108 fmt.getAlias(),
109 style.getAlias(),
110 status);
111 if (result == NULL) {
112 status = U_MEMORY_ALLOCATION_ERROR;
113 return NULL;
114 }
115 fmt.orphan();
116 style.orphan();
117 if (U_FAILURE(status)) {
118 delete result;
119 return NULL;
120 }
121 return result;
122}
123
124ScientificNumberFormatter::Style *ScientificNumberFormatter::SuperscriptStyle::clone() const {
125 return new ScientificNumberFormatter::SuperscriptStyle(*this);
126}
127
128UnicodeString &ScientificNumberFormatter::SuperscriptStyle::format(
129 const UnicodeString &original,
130 FieldPositionIterator &fpi,
131 const UnicodeString &preExponent,
132 const DecimalFormatStaticSets &staticSets,
133 UnicodeString &appendTo,
134 UErrorCode &status) const {
135 if (U_FAILURE(status)) {
136 return appendTo;
137 }
138 FieldPosition fp;
139 int32_t copyFromOffset = 0;
140 while (fpi.next(fp)) {
141 switch (fp.getField()) {
142 case UNUM_EXPONENT_SYMBOL_FIELD:
143 appendTo.append(
144 original,
145 copyFromOffset,
146 fp.getBeginIndex() - copyFromOffset);
147 copyFromOffset = fp.getEndIndex();
148 appendTo.append(preExponent);
149 break;
150 case UNUM_EXPONENT_SIGN_FIELD:
151 {
152 int32_t beginIndex = fp.getBeginIndex();
153 int32_t endIndex = fp.getEndIndex();
154 UChar32 aChar = original.char32At(beginIndex);
155 if (staticSets.fMinusSigns->contains(aChar)) {
156 appendTo.append(
157 original,
158 copyFromOffset,
159 beginIndex - copyFromOffset);
160 appendTo.append(kSuperscriptMinusSign);
161 } else if (staticSets.fPlusSigns->contains(aChar)) {
162 appendTo.append(
163 original,
164 copyFromOffset,
165 beginIndex - copyFromOffset);
166 appendTo.append(kSuperscriptPlusSign);
167 } else {
168 status = U_INVALID_CHAR_FOUND;
169 return appendTo;
170 }
171 copyFromOffset = endIndex;
172 }
173 break;
174 case UNUM_EXPONENT_FIELD:
175 appendTo.append(
176 original,
177 copyFromOffset,
178 fp.getBeginIndex() - copyFromOffset);
179 if (!copyAsSuperscript(
180 original,
181 fp.getBeginIndex(),
182 fp.getEndIndex(),
183 appendTo,
184 status)) {
185 return appendTo;
186 }
187 copyFromOffset = fp.getEndIndex();
188 break;
189 default:
190 break;
191 }
192 }
193 appendTo.append(
194 original, copyFromOffset, original.length() - copyFromOffset);
195 return appendTo;
196}
197
198ScientificNumberFormatter::Style *ScientificNumberFormatter::MarkupStyle::clone() const {
199 return new ScientificNumberFormatter::MarkupStyle(*this);
200}
201
202UnicodeString &ScientificNumberFormatter::MarkupStyle::format(
203 const UnicodeString &original,
204 FieldPositionIterator &fpi,
205 const UnicodeString &preExponent,
206 const DecimalFormatStaticSets & /*unusedDecimalFormatSets*/,
207 UnicodeString &appendTo,
208 UErrorCode &status) const {
209 if (U_FAILURE(status)) {
210 return appendTo;
211 }
212 FieldPosition fp;
213 int32_t copyFromOffset = 0;
214 while (fpi.next(fp)) {
215 switch (fp.getField()) {
216 case UNUM_EXPONENT_SYMBOL_FIELD:
217 appendTo.append(
218 original,
219 copyFromOffset,
220 fp.getBeginIndex() - copyFromOffset);
221 copyFromOffset = fp.getEndIndex();
222 appendTo.append(preExponent);
223 appendTo.append(fBeginMarkup);
224 break;
225 case UNUM_EXPONENT_FIELD:
226 appendTo.append(
227 original,
228 copyFromOffset,
229 fp.getEndIndex() - copyFromOffset);
230 copyFromOffset = fp.getEndIndex();
231 appendTo.append(fEndMarkup);
232 break;
233 default:
234 break;
235 }
236 }
237 appendTo.append(
238 original, copyFromOffset, original.length() - copyFromOffset);
239 return appendTo;
240}
241
242ScientificNumberFormatter::ScientificNumberFormatter(
243 DecimalFormat *fmtToAdopt, Style *styleToAdopt, UErrorCode &status)
244 : fPreExponent(),
245 fDecimalFormat(fmtToAdopt),
246 fStyle(styleToAdopt),
247 fStaticSets(NULL) {
248 if (U_FAILURE(status)) {
249 return;
250 }
251 if (fDecimalFormat == NULL || fStyle == NULL) {
252 status = U_ILLEGAL_ARGUMENT_ERROR;
253 return;
254 }
255 const DecimalFormatSymbols *sym = fDecimalFormat->getDecimalFormatSymbols();
256 if (sym == NULL) {
257 status = U_ILLEGAL_ARGUMENT_ERROR;
258 return;
259 }
260 getPreExponent(*sym, fPreExponent);
261 fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
262}
263
264ScientificNumberFormatter::ScientificNumberFormatter(
265 const ScientificNumberFormatter &other)
266 : UObject(other),
267 fPreExponent(other.fPreExponent),
268 fDecimalFormat(NULL),
269 fStyle(NULL),
270 fStaticSets(other.fStaticSets) {
271 fDecimalFormat = static_cast<DecimalFormat *>(
272 other.fDecimalFormat->clone());
273 fStyle = other.fStyle->clone();
274}
275
276ScientificNumberFormatter::~ScientificNumberFormatter() {
277 delete fDecimalFormat;
278 delete fStyle;
279}
280
281UnicodeString &ScientificNumberFormatter::format(
282 const Formattable &number,
283 UnicodeString &appendTo,
284 UErrorCode &status) const {
285 if (U_FAILURE(status)) {
286 return appendTo;
287 }
288 UnicodeString original;
289 FieldPositionIterator fpi;
290 fDecimalFormat->format(number, original, &fpi, status);
291 return fStyle->format(
292 original,
293 fpi,
294 fPreExponent,
295 *fStaticSets,
296 appendTo,
297 status);
298}
299
300void ScientificNumberFormatter::getPreExponent(
301 const DecimalFormatSymbols &dfs, UnicodeString &preExponent) {
302 preExponent.append(dfs.getConstSymbol(
303 DecimalFormatSymbols::kExponentMultiplicationSymbol));
304 preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol));
305 preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol));
306}
307
308U_NAMESPACE_END
309
310#endif /* !UCONFIG_NO_FORMATTING */