• 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 
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.resetString();
120     result->fData.quantity.clear();
121     result->fData.quantity.setToLong(value);
122     formatter->fFormatter.formatImpl(&result->fData, *ec);
123 }
124 
125 U_CAPI void U_EXPORT2
unumf_formatDouble(const UNumberFormatter * uformatter,double value,UFormattedNumber * uresult,UErrorCode * ec)126 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
127                    UErrorCode* ec) {
128     const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
129     auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
130     if (U_FAILURE(*ec)) { return; }
131 
132     result->fData.resetString();
133     result->fData.quantity.clear();
134     result->fData.quantity.setToDouble(value);
135     formatter->fFormatter.formatImpl(&result->fData, *ec);
136 }
137 
138 U_CAPI void U_EXPORT2
unumf_formatDecimal(const UNumberFormatter * uformatter,const char * value,int32_t valueLen,UFormattedNumber * uresult,UErrorCode * ec)139 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
140                     UFormattedNumber* uresult, UErrorCode* ec) {
141     const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
142     auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
143     if (U_FAILURE(*ec)) { return; }
144 
145     result->fData.resetString();
146     result->fData.quantity.clear();
147     result->fData.quantity.setToDecNumber({value, valueLen}, *ec);
148     if (U_FAILURE(*ec)) { return; }
149     formatter->fFormatter.formatImpl(&result->fData, *ec);
150 }
151 
152 U_CAPI int32_t U_EXPORT2
unumf_resultToString(const UFormattedNumber * uresult,UChar * buffer,int32_t bufferCapacity,UErrorCode * ec)153 unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
154                      UErrorCode* ec) {
155     const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
156     if (U_FAILURE(*ec)) { return 0; }
157 
158     if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
159         *ec = U_ILLEGAL_ARGUMENT_ERROR;
160         return 0;
161     }
162 
163     return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
164 }
165 
166 U_CAPI UBool U_EXPORT2
unumf_resultNextFieldPosition(const UFormattedNumber * uresult,UFieldPosition * ufpos,UErrorCode * ec)167 unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
168     const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
169     if (U_FAILURE(*ec)) { return false; }
170 
171     if (ufpos == nullptr) {
172         *ec = U_ILLEGAL_ARGUMENT_ERROR;
173         return false;
174     }
175 
176     FieldPosition fp;
177     fp.setField(ufpos->field);
178     fp.setBeginIndex(ufpos->beginIndex);
179     fp.setEndIndex(ufpos->endIndex);
180     bool retval = result->fData.nextFieldPosition(fp, *ec);
181     ufpos->beginIndex = fp.getBeginIndex();
182     ufpos->endIndex = fp.getEndIndex();
183     // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
184     return retval ? true : false;
185 }
186 
187 U_CAPI void U_EXPORT2
unumf_resultGetAllFieldPositions(const UFormattedNumber * uresult,UFieldPositionIterator * ufpositer,UErrorCode * ec)188 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
189                                  UErrorCode* ec) {
190     const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
191     if (U_FAILURE(*ec)) { return; }
192 
193     if (ufpositer == nullptr) {
194         *ec = U_ILLEGAL_ARGUMENT_ERROR;
195         return;
196     }
197 
198     auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
199     FieldPositionIteratorHandler fpih(fpi, *ec);
200     result->fData.getAllFieldPositions(fpih, *ec);
201 }
202 
203 U_CAPI int32_t U_EXPORT2
unumf_resultToDecimalNumber(const UFormattedNumber * uresult,char * dest,int32_t destCapacity,UErrorCode * ec)204 unumf_resultToDecimalNumber(
205         const UFormattedNumber* uresult,
206         char* dest,
207         int32_t destCapacity,
208         UErrorCode* ec) {
209     const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
210     if (U_FAILURE(*ec)) {
211         return 0;
212     }
213     DecNum decnum;
214     return result->fData.quantity
215         .toDecNum(decnum, *ec)
216         .toCharString(*ec)
217         .extract(dest, destCapacity, *ec);
218 }
219 
220 U_CAPI void U_EXPORT2
unumf_close(UNumberFormatter * f)221 unumf_close(UNumberFormatter* f) {
222     UErrorCode localStatus = U_ZERO_ERROR;
223     const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
224     delete impl;
225 }
226 
227 
228 #endif /* #if !UCONFIG_NO_FORMATTING */
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 
254 
255 
256