1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 #include "unicode/utypes.h"
6 #if !UCONFIG_NO_FORMATTING
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
13 #include "number_utypes.h"
14 #include "numparse_types.h"
15 #include "unicode/numberformatter.h"
16 #include "unicode/unumberformatter.h"
19 using namespace icu::number
;
20 using namespace icu::number::impl
;
23 //////////////////////////////////
24 /// C API CONVERSION FUNCTIONS ///
25 //////////////////////////////////
27 UNumberFormatterData
* 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
);
33 const UNumberFormatterData
*
34 UNumberFormatterData::validate(const UNumberFormatter
* input
, UErrorCode
& status
) {
35 if (U_FAILURE(status
)) {
38 if (input
== nullptr) {
39 status
= U_ILLEGAL_ARGUMENT_ERROR
;
42 auto* impl
= reinterpret_cast<const UNumberFormatterData
*>(input
);
43 if (impl
->fMagic
!= UNumberFormatterData::kMagic
) {
44 status
= U_INVALID_FORMAT_ERROR
;
50 UNumberFormatter
* UNumberFormatterData::exportForC() {
51 return reinterpret_cast<UNumberFormatter
*>(this);
54 UFormattedNumberData
* 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
);
60 const UFormattedNumberData
*
61 UFormattedNumberData::validate(const UFormattedNumber
* input
, UErrorCode
& status
) {
62 if (U_FAILURE(status
)) {
65 if (input
== nullptr) {
66 status
= U_ILLEGAL_ARGUMENT_ERROR
;
69 auto* impl
= reinterpret_cast<const UFormattedNumberData
*>(input
);
70 if (impl
->fMagic
!= UFormattedNumberData::kMagic
) {
71 status
= U_INVALID_FORMAT_ERROR
;
77 UFormattedNumber
* UFormattedNumberData::exportForC() {
78 return reinterpret_cast<UFormattedNumber
*>(this);
81 /////////////////////////////////////
82 /// END CAPI CONVERSION FUNCTIONS ///
83 /////////////////////////////////////
86 U_CAPI UNumberFormatter
* U_EXPORT2
87 unumf_openForSkeletonAndLocale(const UChar
* skeleton
, int32_t skeletonLen
, const char* locale
,
89 auto* impl
= new UNumberFormatterData();
90 if (impl
== nullptr) {
91 *ec
= U_MEMORY_ALLOCATION_ERROR
;
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();
100 U_CAPI UFormattedNumber
* U_EXPORT2
101 unumf_openResult(UErrorCode
* ec
) {
102 auto* impl
= new UFormattedNumberData();
103 if (impl
== nullptr) {
104 *ec
= U_MEMORY_ALLOCATION_ERROR
;
107 return impl
->exportForC();
110 U_CAPI
void U_EXPORT2
111 unumf_formatInt(const UNumberFormatter
* uformatter
, int64_t value
, UFormattedNumber
* uresult
,
113 const UNumberFormatterData
* formatter
= UNumberFormatterData::validate(uformatter
, *ec
);
114 UFormattedNumberData
* result
= UFormattedNumberData::validate(uresult
, *ec
);
115 if (U_FAILURE(*ec
)) { return; }
117 result
->string
.clear();
118 result
->quantity
.setToLong(value
);
119 formatter
->fFormatter
.formatImpl(result
, *ec
);
122 U_CAPI
void U_EXPORT2
123 unumf_formatDouble(const UNumberFormatter
* uformatter
, double value
, UFormattedNumber
* uresult
,
125 const UNumberFormatterData
* formatter
= UNumberFormatterData::validate(uformatter
, *ec
);
126 UFormattedNumberData
* result
= UFormattedNumberData::validate(uresult
, *ec
);
127 if (U_FAILURE(*ec
)) { return; }
129 result
->string
.clear();
130 result
->quantity
.setToDouble(value
);
131 formatter
->fFormatter
.formatImpl(result
, *ec
);
134 U_CAPI
void U_EXPORT2
135 unumf_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; }
141 result
->string
.clear();
142 result
->quantity
.setToDecNumber({value
, valueLen
}, *ec
);
143 if (U_FAILURE(*ec
)) { return; }
144 formatter
->fFormatter
.formatImpl(result
, *ec
);
147 U_CAPI
int32_t U_EXPORT2
148 unumf_resultToString(const UFormattedNumber
* uresult
, UChar
* buffer
, int32_t bufferCapacity
,
150 const UFormattedNumberData
* result
= UFormattedNumberData::validate(uresult
, *ec
);
151 if (U_FAILURE(*ec
)) { return 0; }
153 if (buffer
== nullptr ? bufferCapacity
!= 0 : bufferCapacity
< 0) {
154 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
158 return result
->string
.toTempUnicodeString().extract(buffer
, bufferCapacity
, *ec
);
161 U_CAPI UBool U_EXPORT2
162 unumf_resultNextFieldPosition(const UFormattedNumber
* uresult
, UFieldPosition
* ufpos
, UErrorCode
* ec
) {
163 const UFormattedNumberData
* result
= UFormattedNumberData::validate(uresult
, *ec
);
164 if (U_FAILURE(*ec
)) { return FALSE
; }
166 if (ufpos
== nullptr) {
167 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
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
;
182 U_CAPI
void U_EXPORT2
183 unumf_resultGetAllFieldPositions(const UFormattedNumber
* uresult
, UFieldPositionIterator
* ufpositer
,
185 const UFormattedNumberData
* result
= UFormattedNumberData::validate(uresult
, *ec
);
186 if (U_FAILURE(*ec
)) { return; }
188 if (ufpositer
== nullptr) {
189 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
193 auto* fpi
= reinterpret_cast<FieldPositionIterator
*>(ufpositer
);
194 FieldPositionIteratorHandler
fpih(fpi
, *ec
);
195 result
->string
.getAllFieldPositions(fpih
, *ec
);
198 U_CAPI
void U_EXPORT2
199 unumf_closeResult(UFormattedNumber
* uresult
) {
200 UErrorCode localStatus
= U_ZERO_ERROR
;
201 const UFormattedNumberData
* impl
= UFormattedNumberData::validate(uresult
, localStatus
);
205 U_CAPI
void U_EXPORT2
206 unumf_close(UNumberFormatter
* f
) {
207 UErrorCode localStatus
= U_ZERO_ERROR
;
208 const UNumberFormatterData
* impl
= UNumberFormatterData::validate(f
, localStatus
);
213 #endif /* #if !UCONFIG_NO_FORMATTING */