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