]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/number_capi.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / number_capi.cpp
CommitLineData
0f5d89e8
A
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
18using namespace icu;
19using namespace icu::number;
20using namespace icu::number::impl;
21
22
23//////////////////////////////////
24/// C API CONVERSION FUNCTIONS ///
25//////////////////////////////////
26
27UNumberFormatterData* UNumberFormatterData::validate(UNumberFormatter* input, UErrorCode& status) {
28 auto* constInput = static_cast<const UNumberFormatter*>(input);
29 auto* validated = validate(constInput, status);
30 return const_cast<UNumberFormatterData*>(validated);
31}
32
33const UNumberFormatterData*
34UNumberFormatterData::validate(const UNumberFormatter* input, UErrorCode& status) {
35 if (U_FAILURE(status)) {
36 return nullptr;
37 }
38 if (input == nullptr) {
39 status = U_ILLEGAL_ARGUMENT_ERROR;
40 return nullptr;
41 }
42 auto* impl = reinterpret_cast<const UNumberFormatterData*>(input);
43 if (impl->fMagic != UNumberFormatterData::kMagic) {
44 status = U_INVALID_FORMAT_ERROR;
45 return nullptr;
46 }
47 return impl;
48}
49
50UNumberFormatter* UNumberFormatterData::exportForC() {
51 return reinterpret_cast<UNumberFormatter*>(this);
52}
53
54UFormattedNumberData* UFormattedNumberData::validate(UFormattedNumber* input, UErrorCode& status) {
55 auto* constInput = static_cast<const UFormattedNumber*>(input);
56 auto* validated = validate(constInput, status);
57 return const_cast<UFormattedNumberData*>(validated);
58}
59
60const UFormattedNumberData*
61UFormattedNumberData::validate(const UFormattedNumber* input, UErrorCode& status) {
62 if (U_FAILURE(status)) {
63 return nullptr;
64 }
65 if (input == nullptr) {
66 status = U_ILLEGAL_ARGUMENT_ERROR;
67 return nullptr;
68 }
69 auto* impl = reinterpret_cast<const UFormattedNumberData*>(input);
70 if (impl->fMagic != UFormattedNumberData::kMagic) {
71 status = U_INVALID_FORMAT_ERROR;
72 return nullptr;
73 }
74 return impl;
75}
76
77UFormattedNumber* UFormattedNumberData::exportForC() {
78 return reinterpret_cast<UFormattedNumber*>(this);
79}
80
81/////////////////////////////////////
82/// END CAPI CONVERSION FUNCTIONS ///
83/////////////////////////////////////
84
85
86U_CAPI UNumberFormatter* U_EXPORT2
87unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale,
88 UErrorCode* ec) {
89 auto* impl = new UNumberFormatterData();
90 if (impl == nullptr) {
91 *ec = U_MEMORY_ALLOCATION_ERROR;
92 return nullptr;
93 }
94 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
95 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
96 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale);
97 return impl->exportForC();
98}
99
100U_CAPI UFormattedNumber* U_EXPORT2
101unumf_openResult(UErrorCode* ec) {
102 auto* impl = new UFormattedNumberData();
103 if (impl == nullptr) {
104 *ec = U_MEMORY_ALLOCATION_ERROR;
105 return nullptr;
106 }
107 return impl->exportForC();
108}
109
110U_CAPI void U_EXPORT2
111unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
112 UErrorCode* ec) {
113 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
114 UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
115 if (U_FAILURE(*ec)) { return; }
116
117 result->string.clear();
118 result->quantity.setToLong(value);
119 formatter->fFormatter.formatImpl(result, *ec);
120}
121
122U_CAPI void U_EXPORT2
123unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
124 UErrorCode* ec) {
125 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
126 UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
127 if (U_FAILURE(*ec)) { return; }
128
129 result->string.clear();
130 result->quantity.setToDouble(value);
131 formatter->fFormatter.formatImpl(result, *ec);
132}
133
134U_CAPI void U_EXPORT2
135unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
136 UFormattedNumber* uresult, UErrorCode* ec) {
137 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
138 UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
139 if (U_FAILURE(*ec)) { return; }
140
141 result->string.clear();
142 result->quantity.setToDecNumber({value, valueLen}, *ec);
143 if (U_FAILURE(*ec)) { return; }
144 formatter->fFormatter.formatImpl(result, *ec);
145}
146
147U_CAPI int32_t U_EXPORT2
148unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
149 UErrorCode* ec) {
150 const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
151 if (U_FAILURE(*ec)) { return 0; }
152
153 if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
154 *ec = U_ILLEGAL_ARGUMENT_ERROR;
155 return 0;
156 }
157
158 return result->string.toTempUnicodeString().extract(buffer, bufferCapacity, *ec);
159}
160
161U_CAPI UBool U_EXPORT2
162unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
163 const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
164 if (U_FAILURE(*ec)) { return FALSE; }
165
166 if (ufpos == nullptr) {
167 *ec = U_ILLEGAL_ARGUMENT_ERROR;
168 return FALSE;
169 }
170
171 FieldPosition fp;
172 fp.setField(ufpos->field);
173 fp.setBeginIndex(ufpos->beginIndex);
174 fp.setEndIndex(ufpos->endIndex);
175 bool retval = result->string.nextFieldPosition(fp, *ec);
176 ufpos->beginIndex = fp.getBeginIndex();
177 ufpos->endIndex = fp.getEndIndex();
178 // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
179 return retval ? TRUE : FALSE;
180}
181
182U_CAPI void U_EXPORT2
183unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
184 UErrorCode* ec) {
185 const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
186 if (U_FAILURE(*ec)) { return; }
187
188 if (ufpositer == nullptr) {
189 *ec = U_ILLEGAL_ARGUMENT_ERROR;
190 return;
191 }
192
193 auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
194 FieldPositionIteratorHandler fpih(fpi, *ec);
195 result->string.getAllFieldPositions(fpih, *ec);
196}
197
198U_CAPI void U_EXPORT2
199unumf_closeResult(UFormattedNumber* uresult) {
200 UErrorCode localStatus = U_ZERO_ERROR;
201 const UFormattedNumberData* impl = UFormattedNumberData::validate(uresult, localStatus);
202 delete impl;
203}
204
205U_CAPI void U_EXPORT2
206unumf_close(UNumberFormatter* f) {
207 UErrorCode localStatus = U_ZERO_ERROR;
208 const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
209 delete impl;
210}
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