Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/i18n/scientificnumberformatter.cpp
Line
Count
Source (jump to first uncovered line)
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 "unicode/decimfmt.h"
19
#include "static_unicode_sets.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
0
        UErrorCode &status) {
44
0
    if (U_FAILURE(status)) {
45
0
        return FALSE;
46
0
    }
47
0
    for (int32_t i = beginIndex; i < endIndex;) {
48
0
        UChar32 c = s.char32At(i);
49
0
        int32_t digit = u_charDigitValue(c);
50
0
        if (digit < 0) {
51
0
            status = U_INVALID_CHAR_FOUND;
52
0
            return FALSE;
53
0
        }
54
0
        result.append(kSuperscriptDigits[digit]);
55
0
        i += U16_LENGTH(c);
56
0
    }
57
0
    return TRUE;
58
0
}
59
60
ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
61
0
            DecimalFormat *fmtToAdopt, UErrorCode &status) {
62
0
    return createInstance(fmtToAdopt, new SuperscriptStyle(), status);
63
0
}
64
65
ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
66
0
            const Locale &locale, UErrorCode &status) {
67
0
    return createInstance(
68
0
            static_cast<DecimalFormat *>(
69
0
                    DecimalFormat::createScientificInstance(locale, status)),
70
0
            new SuperscriptStyle(),
71
0
            status);
72
0
}
73
74
ScientificNumberFormatter *ScientificNumberFormatter::createMarkupInstance(
75
        DecimalFormat *fmtToAdopt,
76
        const UnicodeString &beginMarkup,
77
        const UnicodeString &endMarkup,
78
0
        UErrorCode &status) {
79
0
    return createInstance(
80
0
            fmtToAdopt,
81
0
            new MarkupStyle(beginMarkup, endMarkup),
82
0
            status);
83
0
}
84
85
ScientificNumberFormatter *ScientificNumberFormatter::createMarkupInstance(
86
        const Locale &locale,
87
        const UnicodeString &beginMarkup,
88
        const UnicodeString &endMarkup,
89
0
        UErrorCode &status) {
90
0
    return createInstance(
91
0
            static_cast<DecimalFormat *>(
92
0
                    DecimalFormat::createScientificInstance(locale, status)),
93
0
            new MarkupStyle(beginMarkup, endMarkup),
94
0
            status);
95
0
}
96
97
ScientificNumberFormatter *ScientificNumberFormatter::createInstance(
98
            DecimalFormat *fmtToAdopt,
99
            Style *styleToAdopt,
100
0
            UErrorCode &status) {
101
0
    LocalPointer<DecimalFormat> fmt(fmtToAdopt);
102
0
    LocalPointer<Style> style(styleToAdopt);
103
0
    if (U_FAILURE(status)) {
104
0
        return NULL;
105
0
    }
106
0
    ScientificNumberFormatter *result =
107
0
            new ScientificNumberFormatter(
108
0
                    fmt.getAlias(),
109
0
                    style.getAlias(),
110
0
                    status);
111
0
    if (result == NULL) {
112
0
        status = U_MEMORY_ALLOCATION_ERROR;
113
0
        return NULL;
114
0
    }
115
0
    fmt.orphan();
116
0
    style.orphan();
117
0
    if (U_FAILURE(status)) {
118
0
        delete result;
119
0
        return NULL;
120
0
    }
121
0
    return result;
122
0
}
123
124
0
ScientificNumberFormatter::Style *ScientificNumberFormatter::SuperscriptStyle::clone() const {
125
0
    return new ScientificNumberFormatter::SuperscriptStyle(*this);
126
0
}
127
128
UnicodeString &ScientificNumberFormatter::SuperscriptStyle::format(
129
        const UnicodeString &original,
130
        FieldPositionIterator &fpi,
131
        const UnicodeString &preExponent,
132
        UnicodeString &appendTo,
133
0
        UErrorCode &status) const {
134
0
    if (U_FAILURE(status)) {
135
0
        return appendTo;
136
0
    }
137
0
    FieldPosition fp;
138
0
    int32_t copyFromOffset = 0;
139
0
    while (fpi.next(fp)) {
140
0
        switch (fp.getField()) {
141
0
        case UNUM_EXPONENT_SYMBOL_FIELD:
142
0
            appendTo.append(
143
0
                    original,
144
0
                    copyFromOffset,
145
0
                    fp.getBeginIndex() - copyFromOffset);
146
0
            copyFromOffset = fp.getEndIndex();
147
0
            appendTo.append(preExponent);
148
0
            break;
149
0
        case UNUM_EXPONENT_SIGN_FIELD:
150
0
            {
151
0
                using namespace icu::numparse::impl;
152
0
                int32_t beginIndex = fp.getBeginIndex();
153
0
                int32_t endIndex = fp.getEndIndex();
154
0
                UChar32 aChar = original.char32At(beginIndex);
155
0
                if (unisets::get(unisets::MINUS_SIGN)->contains(aChar)) {
156
0
                    appendTo.append(
157
0
                            original,
158
0
                            copyFromOffset,
159
0
                            beginIndex - copyFromOffset);
160
0
                    appendTo.append(kSuperscriptMinusSign);
161
0
                } else if (unisets::get(unisets::PLUS_SIGN)->contains(aChar)) {
162
0
                    appendTo.append(
163
0
                           original,
164
0
                           copyFromOffset,
165
0
                           beginIndex - copyFromOffset);
166
0
                    appendTo.append(kSuperscriptPlusSign);
167
0
                } else {
168
0
                    status = U_INVALID_CHAR_FOUND;
169
0
                    return appendTo;
170
0
                }
171
0
                copyFromOffset = endIndex;
172
0
            }
173
0
            break;
174
0
        case UNUM_EXPONENT_FIELD:
175
0
            appendTo.append(
176
0
                    original,
177
0
                    copyFromOffset,
178
0
                    fp.getBeginIndex() - copyFromOffset);
179
0
            if (!copyAsSuperscript(
180
0
                    original,
181
0
                    fp.getBeginIndex(),
182
0
                    fp.getEndIndex(),
183
0
                    appendTo,
184
0
                    status)) {
185
0
              return appendTo;
186
0
            }
187
0
            copyFromOffset = fp.getEndIndex();
188
0
            break;
189
0
        default:
190
0
            break;
191
0
        }
192
0
    }
193
0
    appendTo.append(
194
0
            original, copyFromOffset, original.length() - copyFromOffset);
195
0
    return appendTo;
196
0
}
197
198
0
ScientificNumberFormatter::Style *ScientificNumberFormatter::MarkupStyle::clone() const {
199
0
    return new ScientificNumberFormatter::MarkupStyle(*this);
200
0
}
201
202
UnicodeString &ScientificNumberFormatter::MarkupStyle::format(
203
        const UnicodeString &original,
204
        FieldPositionIterator &fpi,
205
        const UnicodeString &preExponent,
206
        UnicodeString &appendTo,
207
0
        UErrorCode &status) const {
208
0
    if (U_FAILURE(status)) {
209
0
        return appendTo;
210
0
    }
211
0
    FieldPosition fp;
212
0
    int32_t copyFromOffset = 0;
213
0
    while (fpi.next(fp)) {
214
0
        switch (fp.getField()) {
215
0
        case UNUM_EXPONENT_SYMBOL_FIELD:
216
0
            appendTo.append(
217
0
                    original,
218
0
                    copyFromOffset,
219
0
                    fp.getBeginIndex() - copyFromOffset);
220
0
            copyFromOffset = fp.getEndIndex();
221
0
            appendTo.append(preExponent);
222
0
            appendTo.append(fBeginMarkup);
223
0
            break;
224
0
        case UNUM_EXPONENT_FIELD:
225
0
            appendTo.append(
226
0
                    original,
227
0
                    copyFromOffset,
228
0
                    fp.getEndIndex() - copyFromOffset);
229
0
            copyFromOffset = fp.getEndIndex();
230
0
            appendTo.append(fEndMarkup);
231
0
            break;
232
0
        default:
233
0
            break;
234
0
        }
235
0
    }
236
0
    appendTo.append(
237
0
            original, copyFromOffset, original.length() - copyFromOffset);
238
0
    return appendTo;
239
0
}
240
241
ScientificNumberFormatter::ScientificNumberFormatter(
242
        DecimalFormat *fmtToAdopt, Style *styleToAdopt, UErrorCode &status)
243
        : fPreExponent(),
244
          fDecimalFormat(fmtToAdopt),
245
0
          fStyle(styleToAdopt) {
246
0
    if (U_FAILURE(status)) {
247
0
        return;
248
0
    }
249
0
    if (fDecimalFormat == NULL || fStyle == NULL) {
250
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
251
0
        return;
252
0
    }
253
0
    const DecimalFormatSymbols *sym = fDecimalFormat->getDecimalFormatSymbols();
254
0
    if (sym == NULL) {
255
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
256
0
        return;
257
0
    }
258
0
    getPreExponent(*sym, fPreExponent);
259
0
}
260
261
ScientificNumberFormatter::ScientificNumberFormatter(
262
        const ScientificNumberFormatter &other)
263
        : UObject(other),
264
          fPreExponent(other.fPreExponent),
265
          fDecimalFormat(NULL),
266
0
          fStyle(NULL) {
267
0
    fDecimalFormat = static_cast<DecimalFormat *>(
268
0
            other.fDecimalFormat->clone());
269
0
    fStyle = other.fStyle->clone();
270
0
}
271
272
0
ScientificNumberFormatter::~ScientificNumberFormatter() {
273
0
    delete fDecimalFormat;
274
0
    delete fStyle;
275
0
}
276
277
UnicodeString &ScientificNumberFormatter::format(
278
        const Formattable &number,
279
        UnicodeString &appendTo,
280
0
        UErrorCode &status) const {
281
0
    if (U_FAILURE(status)) {
282
0
        return appendTo;
283
0
    }
284
0
    UnicodeString original;
285
0
    FieldPositionIterator fpi;
286
0
    fDecimalFormat->format(number, original, &fpi, status);
287
0
    return fStyle->format(
288
0
            original,
289
0
            fpi,
290
0
            fPreExponent,
291
0
            appendTo,
292
0
            status);
293
0
}
294
295
void ScientificNumberFormatter::getPreExponent(
296
0
        const DecimalFormatSymbols &dfs, UnicodeString &preExponent) {
297
0
    preExponent.append(dfs.getConstSymbol(
298
0
            DecimalFormatSymbols::kExponentMultiplicationSymbol));
299
0
    preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol));
300
0
    preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol));
301
0
}
302
303
U_NAMESPACE_END
304
305
#endif /* !UCONFIG_NO_FORMATTING */