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 "unicode/numberformatter.h"
17 #include "unicode/unumberformatter.h"
18 
19 using namespace icu;
20 using namespace icu::number;
21 using namespace icu::number::impl;
22 
23 
24 U_NAMESPACE_BEGIN
25 namespace number {
26 namespace impl {
27 
28 /**
29  * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
30  */
31 struct UNumberFormatterData : public UMemory,
32         // Magic number as ASCII == "NFR" (NumberFormatteR)
33         public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> {
34     LocalizedNumberFormatter fFormatter;
35 };
36 
37 struct UFormattedNumberImpl;
38 
39 // Magic number as ASCII == "FDN" (FormatteDNumber)
40 typedef IcuCApiHelper<UFormattedNumber, UFormattedNumberImpl, 0x46444E00> UFormattedNumberApiHelper;
41 
42 struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumberApiHelper {
43     UFormattedNumberImpl();
44     ~UFormattedNumberImpl();
45 
46     FormattedNumber fImpl;
47     UFormattedNumberData fData;
48 };
49 
UFormattedNumberImpl()50 UFormattedNumberImpl::UFormattedNumberImpl()
51         : fImpl(&fData) {
52     fFormattedValue = &fImpl;
53 }
54 
~UFormattedNumberImpl()55 UFormattedNumberImpl::~UFormattedNumberImpl() {
56     // Disown the data from fImpl so it doesn't get deleted twice
57     fImpl.fData = nullptr;
58 }
59 
60 }
61 }
62 U_NAMESPACE_END
63 
64 
UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(UFormattedNumber,UFormattedNumberImpl,UFormattedNumberApiHelper,unumf) const65 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
66     UFormattedNumber,
67     UFormattedNumberImpl,
68     UFormattedNumberApiHelper,
69     unumf)
70 
71 
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)) {
76         return nullptr;
77     }
78     return &result->fData.quantity;
79 }
80 
81 
82 
83 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocale(const UChar * skeleton,int32_t skeletonLen,const char * locale,UErrorCode * ec)84 unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale,
85                                UErrorCode* ec) {
86     auto* impl = new UNumberFormatterData();
87     if (impl == nullptr) {
88         *ec = U_MEMORY_ALLOCATION_ERROR;
89         return nullptr;
90     }
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();
95 }
96 
97 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocaleWithError(const UChar * skeleton,int32_t skeletonLen,const char * locale,UParseError * perror,UErrorCode * ec)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;
103         return nullptr;
104     }
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();
109 }
110 
111 U_CAPI void U_EXPORT2
unumf_formatInt(const UNumberFormatter * uformatter,int64_t value,UFormattedNumber * uresult,UErrorCode * ec)112 unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
113                 UErrorCode* ec) {
114     const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
115     auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
116     if (U_FAILURE(*ec)) { return; }
117 
118     result->fData.getStringRef().clear();
119     result->fData.quantity.setToLong(value);
120     formatter->fFormatter.formatImpl(&result->fData, *ec);
121 }
122 
123 U_CAPI void U_EXPORT2
unumf_formatDouble(const UNumberFormatter * uformatter,double value,UFormattedNumber * uresult,UErrorCode * ec)124 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
125                    UErrorCode* ec) {
126     const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
127     auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
128     if (U_FAILURE(*ec)) { return; }
129 
130     result->fData.getStringRef().clear();
131     result->fData.quantity.setToDouble(value);
132     formatter->fFormatter.formatImpl(&result->fData, *ec);
133 }
134 
135 U_CAPI void U_EXPORT2
unumf_formatDecimal(const UNumberFormatter * uformatter,const char * value,int32_t valueLen,UFormattedNumber * uresult,UErrorCode * ec)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; }
141 
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);
146 }
147 
148 U_CAPI int32_t U_EXPORT2
unumf_resultToString(const UFormattedNumber * uresult,UChar * buffer,int32_t bufferCapacity,UErrorCode * ec)149 unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
150                      UErrorCode* ec) {
151     const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
152     if (U_FAILURE(*ec)) { return 0; }
153 
154     if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
155         *ec = U_ILLEGAL_ARGUMENT_ERROR;
156         return 0;
157     }
158 
159     return result->fImpl.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
160 }
161 
162 U_CAPI UBool U_EXPORT2
unumf_resultNextFieldPosition(const UFormattedNumber * uresult,UFieldPosition * ufpos,UErrorCode * ec)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; }
166 
167     if (ufpos == nullptr) {
168         *ec = U_ILLEGAL_ARGUMENT_ERROR;
169         return FALSE;
170     }
171 
172     FieldPosition fp;
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;
181 }
182 
183 U_CAPI void U_EXPORT2
unumf_resultGetAllFieldPositions(const UFormattedNumber * uresult,UFieldPositionIterator * ufpositer,UErrorCode * ec)184 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
185                                  UErrorCode* ec) {
186     const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
187     if (U_FAILURE(*ec)) { return; }
188 
189     if (ufpositer == nullptr) {
190         *ec = U_ILLEGAL_ARGUMENT_ERROR;
191         return;
192     }
193 
194     auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
195     result->fImpl.getAllFieldPositions(*fpi, *ec);
196 }
197 
198 U_CAPI void U_EXPORT2
unumf_close(UNumberFormatter * f)199 unumf_close(UNumberFormatter* f) {
200     UErrorCode localStatus = U_ZERO_ERROR;
201     const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
202     delete impl;
203 }
204 
205 
206 #endif /* #if !UCONFIG_NO_FORMATTING */
207 
208 
209 
210 
211 
212 
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
224 
225 
226 
227 
228 
229 
230 
231 
232 
233 
234