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