Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/i18n/number_capi.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2018 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
4
#include "unicode/utypes.h"
5
6
#if !UCONFIG_NO_FORMATTING
7
8
// Allow implicit conversion from char16_t* to UnicodeString for this file:
9
// Helpful in toString methods and elsewhere.
10
#define UNISTR_FROM_STRING_EXPLICIT
11
12
#include "fphdlimp.h"
13
#include "number_utypes.h"
14
#include "numparse_types.h"
15
#include "unicode/numberformatter.h"
16
#include "unicode/unumberformatter.h"
17
18
using namespace icu;
19
using namespace icu::number;
20
using namespace icu::number::impl;
21
22
23
//////////////////////////////////
24
/// C API CONVERSION FUNCTIONS ///
25
//////////////////////////////////
26
27
0
UNumberFormatterData* UNumberFormatterData::validate(UNumberFormatter* input, UErrorCode& status) {
28
0
    auto* constInput = static_cast<const UNumberFormatter*>(input);
29
0
    auto* validated = validate(constInput, status);
30
0
    return const_cast<UNumberFormatterData*>(validated);
31
0
}
32
33
const UNumberFormatterData*
34
0
UNumberFormatterData::validate(const UNumberFormatter* input, UErrorCode& status) {
35
0
    if (U_FAILURE(status)) {
36
0
        return nullptr;
37
0
    }
38
0
    if (input == nullptr) {
39
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
40
0
        return nullptr;
41
0
    }
42
0
    auto* impl = reinterpret_cast<const UNumberFormatterData*>(input);
43
0
    if (impl->fMagic != UNumberFormatterData::kMagic) {
44
0
        status = U_INVALID_FORMAT_ERROR;
45
0
        return nullptr;
46
0
    }
47
0
    return impl;
48
0
}
49
50
0
UNumberFormatter* UNumberFormatterData::exportForC() {
51
0
    return reinterpret_cast<UNumberFormatter*>(this);
52
0
}
53
54
0
UFormattedNumberData* UFormattedNumberData::validate(UFormattedNumber* input, UErrorCode& status) {
55
0
    auto* constInput = static_cast<const UFormattedNumber*>(input);
56
0
    auto* validated = validate(constInput, status);
57
0
    return const_cast<UFormattedNumberData*>(validated);
58
0
}
59
60
const UFormattedNumberData*
61
0
UFormattedNumberData::validate(const UFormattedNumber* input, UErrorCode& status) {
62
0
    if (U_FAILURE(status)) {
63
0
        return nullptr;
64
0
    }
65
0
    if (input == nullptr) {
66
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
67
0
        return nullptr;
68
0
    }
69
0
    auto* impl = reinterpret_cast<const UFormattedNumberData*>(input);
70
0
    if (impl->fMagic != UFormattedNumberData::kMagic) {
71
0
        status = U_INVALID_FORMAT_ERROR;
72
0
        return nullptr;
73
0
    }
74
0
    return impl;
75
0
}
76
77
0
UFormattedNumber* UFormattedNumberData::exportForC() {
78
0
    return reinterpret_cast<UFormattedNumber*>(this);
79
0
}
80
81
/////////////////////////////////////
82
/// END CAPI CONVERSION FUNCTIONS ///
83
/////////////////////////////////////
84
85
86
U_CAPI UNumberFormatter* U_EXPORT2
87
unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale,
88
0
                               UErrorCode* ec) {
89
0
    auto* impl = new UNumberFormatterData();
90
0
    if (impl == nullptr) {
91
0
        *ec = U_MEMORY_ALLOCATION_ERROR;
92
0
        return nullptr;
93
0
    }
94
0
    // Readonly-alias constructor (first argument is whether we are NUL-terminated)
95
0
    UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
96
0
    impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale);
97
0
    return impl->exportForC();
98
0
}
99
100
U_CAPI UFormattedNumber* U_EXPORT2
101
0
unumf_openResult(UErrorCode* ec) {
102
0
    auto* impl = new UFormattedNumberData();
103
0
    if (impl == nullptr) {
104
0
        *ec = U_MEMORY_ALLOCATION_ERROR;
105
0
        return nullptr;
106
0
    }
107
0
    return impl->exportForC();
108
0
}
109
110
U_CAPI void U_EXPORT2
111
unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
112
0
                UErrorCode* ec) {
113
0
    const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
114
0
    UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
115
0
    if (U_FAILURE(*ec)) { return; }
116
0
117
0
    result->string.clear();
118
0
    result->quantity.setToLong(value);
119
0
    formatter->fFormatter.formatImpl(result, *ec);
120
0
}
121
122
U_CAPI void U_EXPORT2
123
unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
124
0
                   UErrorCode* ec) {
125
0
    const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
126
0
    UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
127
0
    if (U_FAILURE(*ec)) { return; }
128
0
129
0
    result->string.clear();
130
0
    result->quantity.setToDouble(value);
131
0
    formatter->fFormatter.formatImpl(result, *ec);
132
0
}
133
134
U_CAPI void U_EXPORT2
135
unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
136
0
                    UFormattedNumber* uresult, UErrorCode* ec) {
137
0
    const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
138
0
    UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
139
0
    if (U_FAILURE(*ec)) { return; }
140
0
141
0
    result->string.clear();
142
0
    result->quantity.setToDecNumber({value, valueLen}, *ec);
143
0
    if (U_FAILURE(*ec)) { return; }
144
0
    formatter->fFormatter.formatImpl(result, *ec);
145
0
}
146
147
U_CAPI int32_t U_EXPORT2
148
unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
149
0
                     UErrorCode* ec) {
150
0
    const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
151
0
    if (U_FAILURE(*ec)) { return 0; }
152
0
153
0
    if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
154
0
        *ec = U_ILLEGAL_ARGUMENT_ERROR;
155
0
        return 0;
156
0
    }
157
0
158
0
    return result->string.toTempUnicodeString().extract(buffer, bufferCapacity, *ec);
159
0
}
160
161
U_CAPI UBool U_EXPORT2
162
0
unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
163
0
    const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
164
0
    if (U_FAILURE(*ec)) { return FALSE; }
165
0
166
0
    if (ufpos == nullptr) {
167
0
        *ec = U_ILLEGAL_ARGUMENT_ERROR;
168
0
        return FALSE;
169
0
    }
170
0
171
0
    FieldPosition fp;
172
0
    fp.setField(ufpos->field);
173
0
    fp.setBeginIndex(ufpos->beginIndex);
174
0
    fp.setEndIndex(ufpos->endIndex);
175
0
    bool retval = result->string.nextFieldPosition(fp, *ec);
176
0
    ufpos->beginIndex = fp.getBeginIndex();
177
0
    ufpos->endIndex = fp.getEndIndex();
178
0
    // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
179
0
    return retval ? TRUE : FALSE;
180
0
}
181
182
U_CAPI void U_EXPORT2
183
unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
184
0
                                 UErrorCode* ec) {
185
0
    const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
186
0
    if (U_FAILURE(*ec)) { return; }
187
0
188
0
    if (ufpositer == nullptr) {
189
0
        *ec = U_ILLEGAL_ARGUMENT_ERROR;
190
0
        return;
191
0
    }
192
0
193
0
    auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
194
0
    FieldPositionIteratorHandler fpih(fpi, *ec);
195
0
    result->string.getAllFieldPositions(fpih, *ec);
196
0
}
197
198
U_CAPI void U_EXPORT2
199
0
unumf_closeResult(UFormattedNumber* uresult) {
200
0
    UErrorCode localStatus = U_ZERO_ERROR;
201
0
    const UFormattedNumberData* impl = UFormattedNumberData::validate(uresult, localStatus);
202
0
    delete impl;
203
0
}
204
205
U_CAPI void U_EXPORT2
206
0
unumf_close(UNumberFormatter* f) {
207
0
    UErrorCode localStatus = U_ZERO_ERROR;
208
0
    const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
209
0
    delete impl;
210
0
}
211
212
213
#endif /* #if !UCONFIG_NO_FORMATTING */
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240