]>
Commit | Line | Data |
---|---|---|
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" | |
b331163b | 18 | #include "unicode/decimfmt.h" |
3d1f044b | 19 | #include "static_unicode_sets.h" |
b331163b A |
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 | static 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 | ||
60 | ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance( | |
61 | DecimalFormat *fmtToAdopt, UErrorCode &status) { | |
62 | return createInstance(fmtToAdopt, new SuperscriptStyle(), status); | |
63 | } | |
64 | ||
65 | ScientificNumberFormatter *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 | ||
74 | ScientificNumberFormatter *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 | ||
85 | 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 | DecimalFormat::createScientificInstance(locale, status)), | |
93 | new MarkupStyle(beginMarkup, endMarkup), | |
94 | status); | |
95 | } | |
96 | ||
97 | ScientificNumberFormatter *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 | ||
340931cb | 124 | ScientificNumberFormatter::SuperscriptStyle *ScientificNumberFormatter::SuperscriptStyle::clone() const { |
b331163b A |
125 | return new ScientificNumberFormatter::SuperscriptStyle(*this); |
126 | } | |
127 | ||
128 | UnicodeString &ScientificNumberFormatter::SuperscriptStyle::format( | |
129 | const UnicodeString &original, | |
130 | FieldPositionIterator &fpi, | |
131 | const UnicodeString &preExponent, | |
b331163b A |
132 | UnicodeString &appendTo, |
133 | UErrorCode &status) const { | |
134 | if (U_FAILURE(status)) { | |
135 | return appendTo; | |
136 | } | |
137 | FieldPosition fp; | |
138 | int32_t copyFromOffset = 0; | |
139 | while (fpi.next(fp)) { | |
140 | switch (fp.getField()) { | |
141 | case UNUM_EXPONENT_SYMBOL_FIELD: | |
142 | appendTo.append( | |
143 | original, | |
144 | copyFromOffset, | |
145 | fp.getBeginIndex() - copyFromOffset); | |
146 | copyFromOffset = fp.getEndIndex(); | |
147 | appendTo.append(preExponent); | |
148 | break; | |
149 | case UNUM_EXPONENT_SIGN_FIELD: | |
150 | { | |
3d1f044b | 151 | using namespace icu::numparse::impl; |
b331163b A |
152 | int32_t beginIndex = fp.getBeginIndex(); |
153 | int32_t endIndex = fp.getEndIndex(); | |
154 | UChar32 aChar = original.char32At(beginIndex); | |
3d1f044b | 155 | if (unisets::get(unisets::MINUS_SIGN)->contains(aChar)) { |
b331163b A |
156 | appendTo.append( |
157 | original, | |
158 | copyFromOffset, | |
159 | beginIndex - copyFromOffset); | |
160 | appendTo.append(kSuperscriptMinusSign); | |
3d1f044b | 161 | } else if (unisets::get(unisets::PLUS_SIGN)->contains(aChar)) { |
b331163b A |
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 | ||
340931cb | 198 | ScientificNumberFormatter::MarkupStyle *ScientificNumberFormatter::MarkupStyle::clone() const { |
b331163b A |
199 | return new ScientificNumberFormatter::MarkupStyle(*this); |
200 | } | |
201 | ||
202 | UnicodeString &ScientificNumberFormatter::MarkupStyle::format( | |
203 | const UnicodeString &original, | |
204 | FieldPositionIterator &fpi, | |
205 | const UnicodeString &preExponent, | |
b331163b A |
206 | UnicodeString &appendTo, |
207 | UErrorCode &status) const { | |
208 | if (U_FAILURE(status)) { | |
209 | return appendTo; | |
210 | } | |
211 | FieldPosition fp; | |
212 | int32_t copyFromOffset = 0; | |
213 | while (fpi.next(fp)) { | |
214 | switch (fp.getField()) { | |
215 | case UNUM_EXPONENT_SYMBOL_FIELD: | |
216 | appendTo.append( | |
217 | original, | |
218 | copyFromOffset, | |
219 | fp.getBeginIndex() - copyFromOffset); | |
220 | copyFromOffset = fp.getEndIndex(); | |
221 | appendTo.append(preExponent); | |
222 | appendTo.append(fBeginMarkup); | |
223 | break; | |
224 | case UNUM_EXPONENT_FIELD: | |
225 | appendTo.append( | |
226 | original, | |
227 | copyFromOffset, | |
228 | fp.getEndIndex() - copyFromOffset); | |
229 | copyFromOffset = fp.getEndIndex(); | |
230 | appendTo.append(fEndMarkup); | |
231 | break; | |
232 | default: | |
233 | break; | |
234 | } | |
235 | } | |
236 | appendTo.append( | |
237 | original, copyFromOffset, original.length() - copyFromOffset); | |
238 | return appendTo; | |
239 | } | |
240 | ||
241 | ScientificNumberFormatter::ScientificNumberFormatter( | |
242 | DecimalFormat *fmtToAdopt, Style *styleToAdopt, UErrorCode &status) | |
243 | : fPreExponent(), | |
244 | fDecimalFormat(fmtToAdopt), | |
3d1f044b | 245 | fStyle(styleToAdopt) { |
b331163b A |
246 | if (U_FAILURE(status)) { |
247 | return; | |
248 | } | |
249 | if (fDecimalFormat == NULL || fStyle == NULL) { | |
250 | status = U_ILLEGAL_ARGUMENT_ERROR; | |
251 | return; | |
252 | } | |
253 | const DecimalFormatSymbols *sym = fDecimalFormat->getDecimalFormatSymbols(); | |
254 | if (sym == NULL) { | |
255 | status = U_ILLEGAL_ARGUMENT_ERROR; | |
256 | return; | |
257 | } | |
258 | getPreExponent(*sym, fPreExponent); | |
b331163b A |
259 | } |
260 | ||
261 | ScientificNumberFormatter::ScientificNumberFormatter( | |
262 | const ScientificNumberFormatter &other) | |
263 | : UObject(other), | |
264 | fPreExponent(other.fPreExponent), | |
265 | fDecimalFormat(NULL), | |
3d1f044b | 266 | fStyle(NULL) { |
b331163b A |
267 | fDecimalFormat = static_cast<DecimalFormat *>( |
268 | other.fDecimalFormat->clone()); | |
269 | fStyle = other.fStyle->clone(); | |
270 | } | |
271 | ||
272 | ScientificNumberFormatter::~ScientificNumberFormatter() { | |
273 | delete fDecimalFormat; | |
274 | delete fStyle; | |
275 | } | |
276 | ||
277 | UnicodeString &ScientificNumberFormatter::format( | |
278 | const Formattable &number, | |
279 | UnicodeString &appendTo, | |
280 | UErrorCode &status) const { | |
281 | if (U_FAILURE(status)) { | |
282 | return appendTo; | |
283 | } | |
284 | UnicodeString original; | |
285 | FieldPositionIterator fpi; | |
286 | fDecimalFormat->format(number, original, &fpi, status); | |
287 | return fStyle->format( | |
288 | original, | |
289 | fpi, | |
290 | fPreExponent, | |
b331163b A |
291 | appendTo, |
292 | status); | |
293 | } | |
294 | ||
295 | void ScientificNumberFormatter::getPreExponent( | |
296 | const DecimalFormatSymbols &dfs, UnicodeString &preExponent) { | |
297 | preExponent.append(dfs.getConstSymbol( | |
298 | DecimalFormatSymbols::kExponentMultiplicationSymbol)); | |
299 | preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol)); | |
300 | preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)); | |
301 | } | |
302 | ||
303 | U_NAMESPACE_END | |
304 | ||
305 | #endif /* !UCONFIG_NO_FORMATTING */ |