2 **********************************************************************
3 * Copyright (c) 2014, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
7 #include "unicode/utypes.h"
9 #if !UCONFIG_NO_FORMATTING
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"
17 #include "unicode/decimfmt.h"
21 static const UChar kSuperscriptDigits
[] = {
33 static const UChar kSuperscriptPlusSign
= 0x207A;
34 static const UChar kSuperscriptMinusSign
= 0x207B;
36 static UBool
copyAsSuperscript(
37 const UnicodeString
&s
,
40 UnicodeString
&result
,
42 if (U_FAILURE(status
)) {
45 for (int32_t i
= beginIndex
; i
< endIndex
;) {
46 UChar32 c
= s
.char32At(i
);
47 int32_t digit
= u_charDigitValue(c
);
49 status
= U_INVALID_CHAR_FOUND
;
52 result
.append(kSuperscriptDigits
[digit
]);
58 ScientificNumberFormatter
*ScientificNumberFormatter::createSuperscriptInstance(
59 DecimalFormat
*fmtToAdopt
, UErrorCode
&status
) {
60 return createInstance(fmtToAdopt
, new SuperscriptStyle(), status
);
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(),
72 ScientificNumberFormatter
*ScientificNumberFormatter::createMarkupInstance(
73 DecimalFormat
*fmtToAdopt
,
74 const UnicodeString
&beginMarkup
,
75 const UnicodeString
&endMarkup
,
77 return createInstance(
79 new MarkupStyle(beginMarkup
, endMarkup
),
83 ScientificNumberFormatter
*ScientificNumberFormatter::createMarkupInstance(
85 const UnicodeString
&beginMarkup
,
86 const UnicodeString
&endMarkup
,
88 return createInstance(
89 static_cast<DecimalFormat
*>(
90 DecimalFormat::createScientificInstance(locale
, status
)),
91 new MarkupStyle(beginMarkup
, endMarkup
),
95 ScientificNumberFormatter
*ScientificNumberFormatter::createInstance(
96 DecimalFormat
*fmtToAdopt
,
99 LocalPointer
<DecimalFormat
> fmt(fmtToAdopt
);
100 LocalPointer
<Style
> style(styleToAdopt
);
101 if (U_FAILURE(status
)) {
104 ScientificNumberFormatter
*result
=
105 new ScientificNumberFormatter(
109 if (result
== NULL
) {
110 status
= U_MEMORY_ALLOCATION_ERROR
;
115 if (U_FAILURE(status
)) {
122 ScientificNumberFormatter::Style
*ScientificNumberFormatter::SuperscriptStyle::clone() const {
123 return new ScientificNumberFormatter::SuperscriptStyle(*this);
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
)) {
137 int32_t copyFromOffset
= 0;
138 while (fpi
.next(fp
)) {
139 switch (fp
.getField()) {
140 case UNUM_EXPONENT_SYMBOL_FIELD
:
144 fp
.getBeginIndex() - copyFromOffset
);
145 copyFromOffset
= fp
.getEndIndex();
146 appendTo
.append(preExponent
);
148 case UNUM_EXPONENT_SIGN_FIELD
:
150 int32_t beginIndex
= fp
.getBeginIndex();
151 int32_t endIndex
= fp
.getEndIndex();
152 UChar32 aChar
= original
.char32At(beginIndex
);
153 if (staticSets
.fMinusSigns
->contains(aChar
)) {
157 beginIndex
- copyFromOffset
);
158 appendTo
.append(kSuperscriptMinusSign
);
159 } else if (staticSets
.fPlusSigns
->contains(aChar
)) {
163 beginIndex
- copyFromOffset
);
164 appendTo
.append(kSuperscriptPlusSign
);
166 status
= U_INVALID_CHAR_FOUND
;
169 copyFromOffset
= endIndex
;
172 case UNUM_EXPONENT_FIELD
:
176 fp
.getBeginIndex() - copyFromOffset
);
177 if (!copyAsSuperscript(
185 copyFromOffset
= fp
.getEndIndex();
192 original
, copyFromOffset
, original
.length() - copyFromOffset
);
196 ScientificNumberFormatter::Style
*ScientificNumberFormatter::MarkupStyle::clone() const {
197 return new ScientificNumberFormatter::MarkupStyle(*this);
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
)) {
211 int32_t copyFromOffset
= 0;
212 while (fpi
.next(fp
)) {
213 switch (fp
.getField()) {
214 case UNUM_EXPONENT_SYMBOL_FIELD
:
218 fp
.getBeginIndex() - copyFromOffset
);
219 copyFromOffset
= fp
.getEndIndex();
220 appendTo
.append(preExponent
);
221 appendTo
.append(fBeginMarkup
);
223 case UNUM_EXPONENT_FIELD
:
227 fp
.getEndIndex() - copyFromOffset
);
228 copyFromOffset
= fp
.getEndIndex();
229 appendTo
.append(fEndMarkup
);
236 original
, copyFromOffset
, original
.length() - copyFromOffset
);
240 ScientificNumberFormatter::ScientificNumberFormatter(
241 DecimalFormat
*fmtToAdopt
, Style
*styleToAdopt
, UErrorCode
&status
)
243 fDecimalFormat(fmtToAdopt
),
244 fStyle(styleToAdopt
),
246 if (U_FAILURE(status
)) {
249 if (fDecimalFormat
== NULL
|| fStyle
== NULL
) {
250 status
= U_ILLEGAL_ARGUMENT_ERROR
;
253 const DecimalFormatSymbols
*sym
= fDecimalFormat
->getDecimalFormatSymbols();
255 status
= U_ILLEGAL_ARGUMENT_ERROR
;
258 getPreExponent(*sym
, fPreExponent
);
259 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
262 ScientificNumberFormatter::ScientificNumberFormatter(
263 const ScientificNumberFormatter
&other
)
265 fPreExponent(other
.fPreExponent
),
266 fDecimalFormat(NULL
),
268 fStaticSets(other
.fStaticSets
) {
269 fDecimalFormat
= static_cast<DecimalFormat
*>(
270 other
.fDecimalFormat
->clone());
271 fStyle
= other
.fStyle
->clone();
274 ScientificNumberFormatter::~ScientificNumberFormatter() {
275 delete fDecimalFormat
;
279 UnicodeString
&ScientificNumberFormatter::format(
280 const Formattable
&number
,
281 UnicodeString
&appendTo
,
282 UErrorCode
&status
) const {
283 if (U_FAILURE(status
)) {
286 UnicodeString original
;
287 FieldPositionIterator fpi
;
288 fDecimalFormat
->format(number
, original
, &fpi
, status
);
289 return fStyle
->format(
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
));
308 #endif /* !UCONFIG_NO_FORMATTING */