]>
Commit | Line | Data |
---|---|---|
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 | 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 | ||
124 | ScientificNumberFormatter::Style *ScientificNumberFormatter::SuperscriptStyle::clone() const { | |
125 | return new ScientificNumberFormatter::SuperscriptStyle(*this); | |
126 | } | |
127 | ||
128 | 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 | 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 | ||
198 | ScientificNumberFormatter::Style *ScientificNumberFormatter::MarkupStyle::clone() const { | |
199 | return new ScientificNumberFormatter::MarkupStyle(*this); | |
200 | } | |
201 | ||
202 | 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 | 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 | ||
242 | ScientificNumberFormatter::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 | ||
264 | ScientificNumberFormatter::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 | ||
276 | ScientificNumberFormatter::~ScientificNumberFormatter() { | |
277 | delete fDecimalFormat; | |
278 | delete fStyle; | |
279 | } | |
280 | ||
281 | UnicodeString &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 | ||
300 | void 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 | ||
308 | U_NAMESPACE_END | |
309 | ||
310 | #endif /* !UCONFIG_NO_FORMATTING */ |