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 "formattedval_impl.h"
16 #include "unicode/numberformatter.h"
17 #include "unicode/unumberformatter.h"
20 using namespace icu::number
;
21 using namespace icu::number::impl
;
29 * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
31 struct UNumberFormatterData
: public UMemory
,
32 // Magic number as ASCII == "NFR" (NumberFormatteR)
33 public IcuCApiHelper
<UNumberFormatter
, UNumberFormatterData
, 0x4E465200> {
34 LocalizedNumberFormatter fFormatter
;
37 struct UFormattedNumberImpl
;
39 // Magic number as ASCII == "FDN" (FormatteDNumber)
40 typedef IcuCApiHelper
<UFormattedNumber
, UFormattedNumberImpl
, 0x46444E00> UFormattedNumberApiHelper
;
42 struct UFormattedNumberImpl
: public UFormattedValueImpl
, public UFormattedNumberApiHelper
{
43 UFormattedNumberImpl();
44 ~UFormattedNumberImpl();
46 FormattedNumber fImpl
;
47 UFormattedNumberData fData
;
50 UFormattedNumberImpl::UFormattedNumberImpl()
52 fFormattedValue
= &fImpl
;
55 UFormattedNumberImpl::~UFormattedNumberImpl() {
56 // Disown the data from fImpl so it doesn't get deleted twice
57 fImpl
.fData
= nullptr;
65 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
68 UFormattedNumberApiHelper
,
72 const DecimalQuantity
* icu::number::impl::validateUFormattedNumberToDecimalQuantity(
73 const UFormattedNumber
* uresult
, UErrorCode
& status
) {
74 auto* result
= UFormattedNumberApiHelper::validate(uresult
, status
);
75 if (U_FAILURE(status
)) {
78 return &result
->fData
.quantity
;
83 U_CAPI UNumberFormatter
* U_EXPORT2
84 unumf_openForSkeletonAndLocale(const UChar
* skeleton
, int32_t skeletonLen
, const char* locale
,
86 auto* impl
= new UNumberFormatterData();
87 if (impl
== nullptr) {
88 *ec
= U_MEMORY_ALLOCATION_ERROR
;
91 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
92 UnicodeString
skeletonString(skeletonLen
== -1, skeleton
, skeletonLen
);
93 impl
->fFormatter
= NumberFormatter::forSkeleton(skeletonString
, *ec
).locale(locale
);
94 return impl
->exportForC();
97 U_CAPI UNumberFormatter
* U_EXPORT2
98 unumf_openForSkeletonAndLocaleWithError(const UChar
* skeleton
, int32_t skeletonLen
, const char* locale
,
99 UParseError
* perror
, UErrorCode
* ec
) {
100 auto* impl
= new UNumberFormatterData();
101 if (impl
== nullptr) {
102 *ec
= U_MEMORY_ALLOCATION_ERROR
;
105 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
106 UnicodeString
skeletonString(skeletonLen
== -1, skeleton
, skeletonLen
);
107 impl
->fFormatter
= NumberFormatter::forSkeleton(skeletonString
, *perror
, *ec
).locale(locale
);
108 return impl
->exportForC();
111 U_CAPI
void U_EXPORT2
112 unumf_formatInt(const UNumberFormatter
* uformatter
, int64_t value
, UFormattedNumber
* uresult
,
114 const UNumberFormatterData
* formatter
= UNumberFormatterData::validate(uformatter
, *ec
);
115 auto* result
= UFormattedNumberApiHelper::validate(uresult
, *ec
);
116 if (U_FAILURE(*ec
)) { return; }
118 result
->fData
.getStringRef().clear();
119 result
->fData
.quantity
.setToLong(value
);
120 formatter
->fFormatter
.formatImpl(&result
->fData
, *ec
);
123 U_CAPI
void U_EXPORT2
124 unumf_formatDouble(const UNumberFormatter
* uformatter
, double value
, UFormattedNumber
* uresult
,
126 const UNumberFormatterData
* formatter
= UNumberFormatterData::validate(uformatter
, *ec
);
127 auto* result
= UFormattedNumberApiHelper::validate(uresult
, *ec
);
128 if (U_FAILURE(*ec
)) { return; }
130 result
->fData
.getStringRef().clear();
131 result
->fData
.quantity
.setToDouble(value
);
132 formatter
->fFormatter
.formatImpl(&result
->fData
, *ec
);
135 U_CAPI
void U_EXPORT2
136 unumf_formatDecimal(const UNumberFormatter
* uformatter
, const char* value
, int32_t valueLen
,
137 UFormattedNumber
* uresult
, UErrorCode
* ec
) {
138 const UNumberFormatterData
* formatter
= UNumberFormatterData::validate(uformatter
, *ec
);
139 auto* result
= UFormattedNumberApiHelper::validate(uresult
, *ec
);
140 if (U_FAILURE(*ec
)) { return; }
142 result
->fData
.getStringRef().clear();
143 result
->fData
.quantity
.setToDecNumber({value
, valueLen
}, *ec
);
144 if (U_FAILURE(*ec
)) { return; }
145 formatter
->fFormatter
.formatImpl(&result
->fData
, *ec
);
148 U_CAPI
int32_t U_EXPORT2
149 unumf_resultToString(const UFormattedNumber
* uresult
, UChar
* buffer
, int32_t bufferCapacity
,
151 const auto* result
= UFormattedNumberApiHelper::validate(uresult
, *ec
);
152 if (U_FAILURE(*ec
)) { return 0; }
154 if (buffer
== nullptr ? bufferCapacity
!= 0 : bufferCapacity
< 0) {
155 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
159 return result
->fImpl
.toTempString(*ec
).extract(buffer
, bufferCapacity
, *ec
);
162 U_CAPI UBool U_EXPORT2
163 unumf_resultNextFieldPosition(const UFormattedNumber
* uresult
, UFieldPosition
* ufpos
, UErrorCode
* ec
) {
164 const auto* result
= UFormattedNumberApiHelper::validate(uresult
, *ec
);
165 if (U_FAILURE(*ec
)) { return FALSE
; }
167 if (ufpos
== nullptr) {
168 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
173 fp
.setField(ufpos
->field
);
174 fp
.setBeginIndex(ufpos
->beginIndex
);
175 fp
.setEndIndex(ufpos
->endIndex
);
176 bool retval
= result
->fImpl
.nextFieldPosition(fp
, *ec
);
177 ufpos
->beginIndex
= fp
.getBeginIndex();
178 ufpos
->endIndex
= fp
.getEndIndex();
179 // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
180 return retval
? TRUE
: FALSE
;
183 U_CAPI
void U_EXPORT2
184 unumf_resultGetAllFieldPositions(const UFormattedNumber
* uresult
, UFieldPositionIterator
* ufpositer
,
186 const auto* result
= UFormattedNumberApiHelper::validate(uresult
, *ec
);
187 if (U_FAILURE(*ec
)) { return; }
189 if (ufpositer
== nullptr) {
190 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
194 auto* fpi
= reinterpret_cast<FieldPositionIterator
*>(ufpositer
);
195 result
->fImpl
.getAllFieldPositions(*fpi
, *ec
);
198 U_CAPI
void U_EXPORT2
199 unumf_close(UNumberFormatter
* f
) {
200 UErrorCode localStatus
= U_ZERO_ERROR
;
201 const UNumberFormatterData
* impl
= UNumberFormatterData::validate(f
, localStatus
);
206 #endif /* #if !UCONFIG_NO_FORMATTING */