• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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