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