• 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 {
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