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 "formattedval_impl.h"
16 #include "number_decnum.h"
17 #include "unicode/numberformatter.h"
18 #include "unicode/unumberformatter.h"
19 #include "unicode/simplenumberformatter.h"
20 #include "unicode/usimplenumberformatter.h"
21
22 using namespace icu;
23 using namespace icu::number;
24 using namespace icu::number::impl;
25
26
27 U_NAMESPACE_BEGIN
28 namespace number::impl {
29
30 /**
31 * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
32 */
33 struct UNumberFormatterData : public UMemory,
34 // Magic number as ASCII == "NFR" (NumberFormatteR)
35 public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> {
36 LocalizedNumberFormatter fFormatter;
37 };
38
39 /**
40 * Implementation class for USimpleNumber. Wraps a SimpleNumberFormatter.
41 */
42 struct USimpleNumberData : public UMemory,
43 // Magic number as ASCII == "SNM" (SimpleNuMber)
44 public IcuCApiHelper<USimpleNumber, USimpleNumberData, 0x534E4D00> {
45 SimpleNumber fNumber;
46 };
47
48 /**
49 * Implementation class for USimpleNumberFormatter. Wraps a SimpleNumberFormatter.
50 */
51 struct USimpleNumberFormatterData : public UMemory,
52 // Magic number as ASCII == "SNF" (SimpleNumberFormatter)
53 public IcuCApiHelper<USimpleNumberFormatter, USimpleNumberFormatterData, 0x534E4600> {
54 SimpleNumberFormatter fFormatter;
55 };
56
57 struct UFormattedNumberImpl;
58
59 // Magic number as ASCII == "FDN" (FormatteDNumber)
60 typedef IcuCApiHelper<UFormattedNumber, UFormattedNumberImpl, 0x46444E00> UFormattedNumberApiHelper;
61
62 struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumberApiHelper {
63 UFormattedNumberImpl();
64 ~UFormattedNumberImpl();
65
66 FormattedNumber fImpl;
67 UFormattedNumberData fData;
68
69 void setTo(FormattedNumber value);
70 };
71
UFormattedNumberImpl()72 UFormattedNumberImpl::UFormattedNumberImpl()
73 : fImpl(&fData) {
74 fFormattedValue = &fImpl;
75 }
76
~UFormattedNumberImpl()77 UFormattedNumberImpl::~UFormattedNumberImpl() {
78 // Disown the data from fImpl so it doesn't get deleted twice
79 fImpl.fData = nullptr;
80 }
81
setTo(FormattedNumber value)82 void UFormattedNumberImpl::setTo(FormattedNumber value) {
83 fData = std::move(*value.fData);
84 }
85
86 } // namespace number::impl
87 U_NAMESPACE_END
88
89
UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(UFormattedNumber,UFormattedNumberImpl,UFormattedNumberApiHelper,unumf) const90 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
91 UFormattedNumber,
92 UFormattedNumberImpl,
93 UFormattedNumberApiHelper,
94 unumf)
95
96
97 const DecimalQuantity* icu::number::impl::validateUFormattedNumberToDecimalQuantity(
98 const UFormattedNumber* uresult, UErrorCode& status) {
99 const auto* result = UFormattedNumberApiHelper::validate(uresult, status);
100 if (U_FAILURE(status)) {
101 return nullptr;
102 }
103 return &result->fData.quantity;
104 }
105
106
107
108 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocale(const char16_t * skeleton,int32_t skeletonLen,const char * locale,UErrorCode * ec)109 unumf_openForSkeletonAndLocale(const char16_t* skeleton, int32_t skeletonLen, const char* locale,
110 UErrorCode* ec) {
111 auto* impl = new UNumberFormatterData();
112 if (impl == nullptr) {
113 *ec = U_MEMORY_ALLOCATION_ERROR;
114 return nullptr;
115 }
116 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
117 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
118 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale);
119 return impl->exportForC();
120 }
121
122 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocaleWithError(const char16_t * skeleton,int32_t skeletonLen,const char * locale,UParseError * perror,UErrorCode * ec)123 unumf_openForSkeletonAndLocaleWithError(const char16_t* skeleton, int32_t skeletonLen, const char* locale,
124 UParseError* perror, UErrorCode* ec) {
125 auto* impl = new UNumberFormatterData();
126 if (impl == nullptr) {
127 *ec = U_MEMORY_ALLOCATION_ERROR;
128 return nullptr;
129 }
130 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
131 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
132 UParseError tempParseError;
133 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, (perror == nullptr) ? tempParseError : *perror, *ec).locale(locale);
134 return impl->exportForC();
135 }
136
137 U_CAPI void U_EXPORT2
unumf_formatInt(const UNumberFormatter * uformatter,int64_t value,UFormattedNumber * uresult,UErrorCode * ec)138 unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
139 UErrorCode* ec) {
140 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
141 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
142 if (U_FAILURE(*ec)) { return; }
143
144 result->fData.resetString();
145 result->fData.quantity.clear();
146 result->fData.quantity.setToLong(value);
147 formatter->fFormatter.formatImpl(&result->fData, *ec);
148 }
149
150 U_CAPI void U_EXPORT2
unumf_formatDouble(const UNumberFormatter * uformatter,double value,UFormattedNumber * uresult,UErrorCode * ec)151 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
152 UErrorCode* ec) {
153 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
154 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
155 if (U_FAILURE(*ec)) { return; }
156
157 result->fData.resetString();
158 result->fData.quantity.clear();
159 result->fData.quantity.setToDouble(value);
160 formatter->fFormatter.formatImpl(&result->fData, *ec);
161 }
162
163 U_CAPI void U_EXPORT2
unumf_formatDecimal(const UNumberFormatter * uformatter,const char * value,int32_t valueLen,UFormattedNumber * uresult,UErrorCode * ec)164 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
165 UFormattedNumber* uresult, UErrorCode* ec) {
166 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
167 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
168 if (U_FAILURE(*ec)) { return; }
169
170 result->fData.resetString();
171 result->fData.quantity.clear();
172 result->fData.quantity.setToDecNumber({value, valueLen}, *ec);
173 if (U_FAILURE(*ec)) { return; }
174 formatter->fFormatter.formatImpl(&result->fData, *ec);
175 }
176
177 U_CAPI int32_t U_EXPORT2
unumf_resultToString(const UFormattedNumber * uresult,char16_t * buffer,int32_t bufferCapacity,UErrorCode * ec)178 unumf_resultToString(const UFormattedNumber* uresult, char16_t* buffer, int32_t bufferCapacity,
179 UErrorCode* ec) {
180 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
181 if (U_FAILURE(*ec)) { return 0; }
182
183 if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
184 *ec = U_ILLEGAL_ARGUMENT_ERROR;
185 return 0;
186 }
187
188 return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
189 }
190
191 U_CAPI UBool U_EXPORT2
unumf_resultNextFieldPosition(const UFormattedNumber * uresult,UFieldPosition * ufpos,UErrorCode * ec)192 unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
193 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
194 if (U_FAILURE(*ec)) { return false; }
195
196 if (ufpos == nullptr) {
197 *ec = U_ILLEGAL_ARGUMENT_ERROR;
198 return false;
199 }
200
201 FieldPosition fp;
202 fp.setField(ufpos->field);
203 fp.setBeginIndex(ufpos->beginIndex);
204 fp.setEndIndex(ufpos->endIndex);
205 bool retval = result->fData.nextFieldPosition(fp, *ec);
206 ufpos->beginIndex = fp.getBeginIndex();
207 ufpos->endIndex = fp.getEndIndex();
208 // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
209 return retval ? true : false;
210 }
211
212 U_CAPI void U_EXPORT2
unumf_resultGetAllFieldPositions(const UFormattedNumber * uresult,UFieldPositionIterator * ufpositer,UErrorCode * ec)213 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
214 UErrorCode* ec) {
215 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
216 if (U_FAILURE(*ec)) { return; }
217
218 if (ufpositer == nullptr) {
219 *ec = U_ILLEGAL_ARGUMENT_ERROR;
220 return;
221 }
222
223 auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
224 FieldPositionIteratorHandler fpih(fpi, *ec);
225 result->fData.getAllFieldPositions(fpih, *ec);
226 }
227
228 U_CAPI int32_t U_EXPORT2
unumf_resultToDecimalNumber(const UFormattedNumber * uresult,char * dest,int32_t destCapacity,UErrorCode * ec)229 unumf_resultToDecimalNumber(
230 const UFormattedNumber* uresult,
231 char* dest,
232 int32_t destCapacity,
233 UErrorCode* ec) {
234 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
235 if (U_FAILURE(*ec)) {
236 return 0;
237 }
238 DecNum decnum;
239 return result->fData.quantity
240 .toDecNum(decnum, *ec)
241 .toCharString(*ec)
242 .extract(dest, destCapacity, *ec);
243 }
244
245 U_CAPI void U_EXPORT2
unumf_close(UNumberFormatter * f)246 unumf_close(UNumberFormatter* f) {
247 UErrorCode localStatus = U_ZERO_ERROR;
248 const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
249 delete impl;
250 }
251
252
253 ///// SIMPLE NUMBER FORMATTER /////
254
255 U_CAPI USimpleNumber* U_EXPORT2
usnum_openForInt64(int64_t value,UErrorCode * ec)256 usnum_openForInt64(int64_t value, UErrorCode* ec) {
257 auto* number = new USimpleNumberData();
258 if (number == nullptr) {
259 *ec = U_MEMORY_ALLOCATION_ERROR;
260 return nullptr;
261 }
262 number->fNumber = SimpleNumber::forInt64(value, *ec);
263 return number->exportForC();
264 }
265
266 U_CAPI void U_EXPORT2
usnum_setToInt64(USimpleNumber * unumber,int64_t value,UErrorCode * ec)267 usnum_setToInt64(USimpleNumber* unumber, int64_t value, UErrorCode* ec) {
268 auto* number = USimpleNumberData::validate(unumber, *ec);
269 if (U_FAILURE(*ec)) {
270 return;
271 }
272 number->fNumber = SimpleNumber::forInt64(value, *ec);
273 }
274
275 U_CAPI void U_EXPORT2
usnum_multiplyByPowerOfTen(USimpleNumber * unumber,int32_t power,UErrorCode * ec)276 usnum_multiplyByPowerOfTen(USimpleNumber* unumber, int32_t power, UErrorCode* ec) {
277 auto* number = USimpleNumberData::validate(unumber, *ec);
278 if (U_FAILURE(*ec)) {
279 return;
280 }
281 number->fNumber.multiplyByPowerOfTen(power, *ec);
282 }
283
284 U_CAPI void U_EXPORT2
usnum_roundTo(USimpleNumber * unumber,int32_t position,UNumberFormatRoundingMode roundingMode,UErrorCode * ec)285 usnum_roundTo(USimpleNumber* unumber, int32_t position, UNumberFormatRoundingMode roundingMode, UErrorCode* ec) {
286 auto* number = USimpleNumberData::validate(unumber, *ec);
287 if (U_FAILURE(*ec)) {
288 return;
289 }
290 number->fNumber.roundTo(position, roundingMode, *ec);
291 }
292
293 U_CAPI void U_EXPORT2
usnum_setMinimumIntegerDigits(USimpleNumber * unumber,int32_t minimumIntegerDigits,UErrorCode * ec)294 usnum_setMinimumIntegerDigits(USimpleNumber* unumber, int32_t minimumIntegerDigits, UErrorCode* ec) {
295 auto* number = USimpleNumberData::validate(unumber, *ec);
296 if (U_FAILURE(*ec)) {
297 return;
298 }
299 number->fNumber.setMinimumIntegerDigits(minimumIntegerDigits, *ec);
300 }
301
302 U_CAPI void U_EXPORT2
usnum_setMinimumFractionDigits(USimpleNumber * unumber,int32_t minimumFractionDigits,UErrorCode * ec)303 usnum_setMinimumFractionDigits(USimpleNumber* unumber, int32_t minimumFractionDigits, UErrorCode* ec) {
304 auto* number = USimpleNumberData::validate(unumber, *ec);
305 if (U_FAILURE(*ec)) {
306 return;
307 }
308 number->fNumber.setMinimumFractionDigits(minimumFractionDigits, *ec);
309 }
310
311 U_CAPI void U_EXPORT2
usnum_setMaximumIntegerDigits(USimpleNumber * unumber,int32_t maximumIntegerDigits,UErrorCode * ec)312 usnum_setMaximumIntegerDigits(USimpleNumber* unumber, int32_t maximumIntegerDigits, UErrorCode* ec) {
313 auto* number = USimpleNumberData::validate(unumber, *ec);
314 if (U_FAILURE(*ec)) {
315 return;
316 }
317 number->fNumber.setMaximumIntegerDigits(maximumIntegerDigits, *ec);
318 }
319
320 U_CAPI void U_EXPORT2
usnum_setSign(USimpleNumber * unumber,USimpleNumberSign sign,UErrorCode * ec)321 usnum_setSign(USimpleNumber* unumber, USimpleNumberSign sign, UErrorCode* ec) {
322 auto* number = USimpleNumberData::validate(unumber, *ec);
323 if (U_FAILURE(*ec)) {
324 return;
325 }
326 number->fNumber.setSign(sign, *ec);
327 }
328
329 U_CAPI USimpleNumberFormatter* U_EXPORT2
usnumf_openForLocale(const char * locale,UErrorCode * ec)330 usnumf_openForLocale(const char* locale, UErrorCode* ec) {
331 auto* impl = new USimpleNumberFormatterData();
332 if (impl == nullptr) {
333 *ec = U_MEMORY_ALLOCATION_ERROR;
334 return nullptr;
335 }
336 impl->fFormatter = SimpleNumberFormatter::forLocale(locale, *ec);
337 return impl->exportForC();
338 }
339
340 U_CAPI USimpleNumberFormatter* U_EXPORT2
usnumf_openForLocaleAndGroupingStrategy(const char * locale,UNumberGroupingStrategy groupingStrategy,UErrorCode * ec)341 usnumf_openForLocaleAndGroupingStrategy(
342 const char* locale, UNumberGroupingStrategy groupingStrategy, UErrorCode* ec) {
343 auto* impl = new USimpleNumberFormatterData();
344 if (impl == nullptr) {
345 *ec = U_MEMORY_ALLOCATION_ERROR;
346 return nullptr;
347 }
348 impl->fFormatter = SimpleNumberFormatter::forLocaleAndGroupingStrategy(locale, groupingStrategy, *ec);
349 return impl->exportForC();
350 }
351
352 U_CAPI void U_EXPORT2
usnumf_format(const USimpleNumberFormatter * uformatter,USimpleNumber * unumber,UFormattedNumber * uresult,UErrorCode * ec)353 usnumf_format(
354 const USimpleNumberFormatter* uformatter,
355 USimpleNumber* unumber,
356 UFormattedNumber* uresult,
357 UErrorCode* ec) {
358 const auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec);
359 auto* number = USimpleNumberData::validate(unumber, *ec);
360 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
361 if (U_FAILURE(*ec)) {
362 return;
363 }
364 auto localResult = formatter->fFormatter.format(std::move(number->fNumber), *ec);
365 if (U_FAILURE(*ec)) {
366 return;
367 }
368 result->setTo(std::move(localResult));
369 }
370
371 U_CAPI void U_EXPORT2
usnumf_formatInt64(const USimpleNumberFormatter * uformatter,int64_t value,UFormattedNumber * uresult,UErrorCode * ec)372 usnumf_formatInt64(
373 const USimpleNumberFormatter* uformatter,
374 int64_t value,
375 UFormattedNumber* uresult,
376 UErrorCode* ec) {
377 const auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec);
378 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
379 if (U_FAILURE(*ec)) {
380 return;
381 }
382 auto localResult = formatter->fFormatter.formatInt64(value, *ec);
383 result->setTo(std::move(localResult));
384 }
385
386 U_CAPI void U_EXPORT2
usnum_close(USimpleNumber * unumber)387 usnum_close(USimpleNumber* unumber) {
388 UErrorCode localStatus = U_ZERO_ERROR;
389 const USimpleNumberData* impl = USimpleNumberData::validate(unumber, localStatus);
390 delete impl;
391 }
392
393 U_CAPI void U_EXPORT2
usnumf_close(USimpleNumberFormatter * uformatter)394 usnumf_close(USimpleNumberFormatter* uformatter) {
395 UErrorCode localStatus = U_ZERO_ERROR;
396 const USimpleNumberFormatterData* impl = USimpleNumberFormatterData::validate(uformatter, localStatus);
397 delete impl;
398 }
399
400
401 #endif /* #if !UCONFIG_NO_FORMATTING */
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429