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
20 using namespace icu;
21 using namespace icu::number;
22 using namespace icu::number::impl;
23
24
25 U_NAMESPACE_BEGIN
26 namespace number {
27 namespace impl {
28
29 /**
30 * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
31 */
32 struct UNumberFormatterData : public UMemory,
33 // Magic number as ASCII == "NFR" (NumberFormatteR)
34 public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> {
35 LocalizedNumberFormatter fFormatter;
36 };
37
38 struct UFormattedNumberImpl;
39
40 // Magic number as ASCII == "FDN" (FormatteDNumber)
41 typedef IcuCApiHelper<UFormattedNumber, UFormattedNumberImpl, 0x46444E00> UFormattedNumberApiHelper;
42
43 struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumberApiHelper {
44 UFormattedNumberImpl();
45 ~UFormattedNumberImpl();
46
47 FormattedNumber fImpl;
48 UFormattedNumberData fData;
49 };
50
UFormattedNumberImpl()51 UFormattedNumberImpl::UFormattedNumberImpl()
52 : fImpl(&fData) {
53 fFormattedValue = &fImpl;
54 }
55
~UFormattedNumberImpl()56 UFormattedNumberImpl::~UFormattedNumberImpl() {
57 // Disown the data from fImpl so it doesn't get deleted twice
58 fImpl.fData = nullptr;
59 }
60
61 }
62 }
63 U_NAMESPACE_END
64
65
UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(UFormattedNumber,UFormattedNumberImpl,UFormattedNumberApiHelper,unumf) const66 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
67 UFormattedNumber,
68 UFormattedNumberImpl,
69 UFormattedNumberApiHelper,
70 unumf)
71
72
73 const DecimalQuantity* icu::number::impl::validateUFormattedNumberToDecimalQuantity(
74 const UFormattedNumber* uresult, UErrorCode& status) {
75 auto* result = UFormattedNumberApiHelper::validate(uresult, status);
76 if (U_FAILURE(status)) {
77 return nullptr;
78 }
79 return &result->fData.quantity;
80 }
81
82
83
84 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocale(const UChar * skeleton,int32_t skeletonLen,const char * locale,UErrorCode * ec)85 unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale,
86 UErrorCode* ec) {
87 auto* impl = new UNumberFormatterData();
88 if (impl == nullptr) {
89 *ec = U_MEMORY_ALLOCATION_ERROR;
90 return nullptr;
91 }
92 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
93 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
94 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale);
95 return impl->exportForC();
96 }
97
98 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocaleWithError(const UChar * skeleton,int32_t skeletonLen,const char * locale,UParseError * perror,UErrorCode * ec)99 unumf_openForSkeletonAndLocaleWithError(const UChar* skeleton, int32_t skeletonLen, const char* locale,
100 UParseError* perror, UErrorCode* ec) {
101 auto* impl = new UNumberFormatterData();
102 if (impl == nullptr) {
103 *ec = U_MEMORY_ALLOCATION_ERROR;
104 return nullptr;
105 }
106 // Readonly-alias constructor (first argument is whether we are NUL-terminated)
107 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
108 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *perror, *ec).locale(locale);
109 return impl->exportForC();
110 }
111
112 U_CAPI void U_EXPORT2
unumf_formatInt(const UNumberFormatter * uformatter,int64_t value,UFormattedNumber * uresult,UErrorCode * ec)113 unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
114 UErrorCode* ec) {
115 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
116 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
117 if (U_FAILURE(*ec)) { return; }
118
119 result->fData.getStringRef().clear();
120 result->fData.quantity.setToLong(value);
121 formatter->fFormatter.formatImpl(&result->fData, *ec);
122 }
123
124 U_CAPI void U_EXPORT2
unumf_formatDouble(const UNumberFormatter * uformatter,double value,UFormattedNumber * uresult,UErrorCode * ec)125 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
126 UErrorCode* ec) {
127 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
128 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
129 if (U_FAILURE(*ec)) { return; }
130
131 result->fData.getStringRef().clear();
132 result->fData.quantity.setToDouble(value);
133 formatter->fFormatter.formatImpl(&result->fData, *ec);
134 }
135
136 U_CAPI void U_EXPORT2
unumf_formatDecimal(const UNumberFormatter * uformatter,const char * value,int32_t valueLen,UFormattedNumber * uresult,UErrorCode * ec)137 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
138 UFormattedNumber* uresult, UErrorCode* ec) {
139 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
140 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
141 if (U_FAILURE(*ec)) { return; }
142
143 result->fData.getStringRef().clear();
144 result->fData.quantity.setToDecNumber({value, valueLen}, *ec);
145 if (U_FAILURE(*ec)) { return; }
146 formatter->fFormatter.formatImpl(&result->fData, *ec);
147 }
148
149 U_CAPI int32_t U_EXPORT2
unumf_resultToString(const UFormattedNumber * uresult,UChar * buffer,int32_t bufferCapacity,UErrorCode * ec)150 unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
151 UErrorCode* ec) {
152 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
153 if (U_FAILURE(*ec)) { return 0; }
154
155 if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
156 *ec = U_ILLEGAL_ARGUMENT_ERROR;
157 return 0;
158 }
159
160 return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
161 }
162
163 U_CAPI UBool U_EXPORT2
unumf_resultNextFieldPosition(const UFormattedNumber * uresult,UFieldPosition * ufpos,UErrorCode * ec)164 unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
165 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
166 if (U_FAILURE(*ec)) { return FALSE; }
167
168 if (ufpos == nullptr) {
169 *ec = U_ILLEGAL_ARGUMENT_ERROR;
170 return FALSE;
171 }
172
173 FieldPosition fp;
174 fp.setField(ufpos->field);
175 fp.setBeginIndex(ufpos->beginIndex);
176 fp.setEndIndex(ufpos->endIndex);
177 bool retval = result->fData.nextFieldPosition(fp, *ec);
178 ufpos->beginIndex = fp.getBeginIndex();
179 ufpos->endIndex = fp.getEndIndex();
180 // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
181 return retval ? TRUE : FALSE;
182 }
183
184 U_CAPI void U_EXPORT2
unumf_resultGetAllFieldPositions(const UFormattedNumber * uresult,UFieldPositionIterator * ufpositer,UErrorCode * ec)185 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
186 UErrorCode* ec) {
187 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
188 if (U_FAILURE(*ec)) { return; }
189
190 if (ufpositer == nullptr) {
191 *ec = U_ILLEGAL_ARGUMENT_ERROR;
192 return;
193 }
194
195 auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
196 FieldPositionIteratorHandler fpih(fpi, *ec);
197 result->fData.getAllFieldPositions(fpih, *ec);
198 }
199
200 U_CAPI int32_t U_EXPORT2
unumf_resultToDecimalNumber(const UFormattedNumber * uresult,char * dest,int32_t destCapacity,UErrorCode * ec)201 unumf_resultToDecimalNumber(
202 const UFormattedNumber* uresult,
203 char* dest,
204 int32_t destCapacity,
205 UErrorCode* ec) {
206 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
207 if (U_FAILURE(*ec)) {
208 return 0;
209 }
210 DecNum decnum;
211 return result->fData.quantity
212 .toDecNum(decnum, *ec)
213 .toCharString(*ec)
214 .extract(dest, destCapacity, *ec);
215 }
216
217 U_CAPI void U_EXPORT2
unumf_close(UNumberFormatter * f)218 unumf_close(UNumberFormatter* f) {
219 UErrorCode localStatus = U_ZERO_ERROR;
220 const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
221 delete impl;
222 }
223
224
225 #endif /* #if !UCONFIG_NO_FORMATTING */
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253