]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/scientificnumberformatter.cpp
ICU-57149.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / scientificnumberformatter.cpp
CommitLineData
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
19U_NAMESPACE_BEGIN
20
21static const UChar kSuperscriptDigits[] = {
22 0x2070,
23 0xB9,
24 0xB2,
25 0xB3,
26 0x2074,
27 0x2075,
28 0x2076,
29 0x2077,
30 0x2078,
31 0x2079};
32
33static const UChar kSuperscriptPlusSign = 0x207A;
34static const UChar kSuperscriptMinusSign = 0x207B;
35
36static 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
58ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
59 DecimalFormat *fmtToAdopt, UErrorCode &status) {
60 return createInstance(fmtToAdopt, new SuperscriptStyle(), status);
61}
62
63ScientificNumberFormatter *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
72ScientificNumberFormatter *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
83ScientificNumberFormatter *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
95ScientificNumberFormatter *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
122ScientificNumberFormatter::Style *ScientificNumberFormatter::SuperscriptStyle::clone() const {
123 return new ScientificNumberFormatter::SuperscriptStyle(*this);
124}
125
126UnicodeString &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
196ScientificNumberFormatter::Style *ScientificNumberFormatter::MarkupStyle::clone() const {
197 return new ScientificNumberFormatter::MarkupStyle(*this);
198}
199
200UnicodeString &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
240ScientificNumberFormatter::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
262ScientificNumberFormatter::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
274ScientificNumberFormatter::~ScientificNumberFormatter() {
275 delete fDecimalFormat;
276 delete fStyle;
277}
278
279UnicodeString &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
298void 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
306U_NAMESPACE_END
307
308#endif /* !UCONFIG_NO_FORMATTING */