• 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 "unicode/numberformatter.h"
16 #include "unicode/unumberformatter.h"
17 
18 using namespace icu;
19 using namespace icu::number;
20 using namespace icu::number::impl;
21 
22 
23 //////////////////////////////////
24 /// C API CONVERSION FUNCTIONS ///
25 //////////////////////////////////
26 
validate(UNumberFormatter * input,UErrorCode & status)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);
31 }
32 
33 const UNumberFormatterData*
validate(const UNumberFormatter * input,UErrorCode & status)34 UNumberFormatterData::validate(const UNumberFormatter* input, UErrorCode& status) {
35     if (U_FAILURE(status)) {
36         return nullptr;
37     }
38     if (input == nullptr) {
39         status = U_ILLEGAL_ARGUMENT_ERROR;
40         return nullptr;
41     }
42     auto* impl = reinterpret_cast<const UNumberFormatterData*>(input);
43     if (impl->fMagic != UNumberFormatterData::kMagic) {
44         status = U_INVALID_FORMAT_ERROR;
45         return nullptr;
46     }
47     return impl;
48 }
49 
exportForC()50 UNumberFormatter* UNumberFormatterData::exportForC() {
51     return reinterpret_cast<UNumberFormatter*>(this);
52 }
53 
validate(UFormattedNumber * input,UErrorCode & status)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);
58 }
59 
60 const UFormattedNumberData*
validate(const UFormattedNumber * input,UErrorCode & status)61 UFormattedNumberData::validate(const UFormattedNumber* input, UErrorCode& status) {
62     if (U_FAILURE(status)) {
63         return nullptr;
64     }
65     if (input == nullptr) {
66         status = U_ILLEGAL_ARGUMENT_ERROR;
67         return nullptr;
68     }
69     auto* impl = reinterpret_cast<const UFormattedNumberData*>(input);
70     if (impl->fMagic != UFormattedNumberData::kMagic) {
71         status = U_INVALID_FORMAT_ERROR;
72         return nullptr;
73     }
74     return impl;
75 }
76 
exportForC()77 UFormattedNumber* UFormattedNumberData::exportForC() {
78     return reinterpret_cast<UFormattedNumber*>(this);
79 }
80 
81 /////////////////////////////////////
82 /// END CAPI CONVERSION FUNCTIONS ///
83 /////////////////////////////////////
84 
85 
86 U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocale(const UChar * skeleton,int32_t skeletonLen,const char * locale,UErrorCode * ec)87 unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale,
88                                UErrorCode* ec) {
89     auto* impl = new UNumberFormatterData();
90     if (impl == nullptr) {
91         *ec = U_MEMORY_ALLOCATION_ERROR;
92         return nullptr;
93     }
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();
98 }
99 
100 U_CAPI UFormattedNumber* U_EXPORT2
unumf_openResult(UErrorCode * ec)101 unumf_openResult(UErrorCode* ec) {
102     auto* impl = new UFormattedNumberData();
103     if (impl == nullptr) {
104         *ec = U_MEMORY_ALLOCATION_ERROR;
105         return nullptr;
106     }
107     return impl->exportForC();
108 }
109 
110 U_CAPI void U_EXPORT2
unumf_formatInt(const UNumberFormatter * uformatter,int64_t value,UFormattedNumber * uresult,UErrorCode * ec)111 unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
112                 UErrorCode* ec) {
113     const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
114     UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
115     if (U_FAILURE(*ec)) { return; }
116 
117     result->string.clear();
118     result->quantity.setToLong(value);
119     formatter->fFormatter.formatImpl(result, *ec);
120 }
121 
122 U_CAPI void U_EXPORT2
unumf_formatDouble(const UNumberFormatter * uformatter,double value,UFormattedNumber * uresult,UErrorCode * ec)123 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
124                    UErrorCode* ec) {
125     const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
126     UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
127     if (U_FAILURE(*ec)) { return; }
128 
129     result->string.clear();
130     result->quantity.setToDouble(value);
131     formatter->fFormatter.formatImpl(result, *ec);
132 }
133 
134 U_CAPI void U_EXPORT2
unumf_formatDecimal(const UNumberFormatter * uformatter,const char * value,int32_t valueLen,UFormattedNumber * uresult,UErrorCode * ec)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; }
140 
141     result->string.clear();
142     result->quantity.setToDecNumber({value, valueLen}, *ec);
143     if (U_FAILURE(*ec)) { return; }
144     formatter->fFormatter.formatImpl(result, *ec);
145 }
146 
147 U_CAPI int32_t U_EXPORT2
unumf_resultToString(const UFormattedNumber * uresult,UChar * buffer,int32_t bufferCapacity,UErrorCode * ec)148 unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
149                      UErrorCode* ec) {
150     const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
151     if (U_FAILURE(*ec)) { return 0; }
152 
153     if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
154         *ec = U_ILLEGAL_ARGUMENT_ERROR;
155         return 0;
156     }
157 
158     return result->string.toTempUnicodeString().extract(buffer, bufferCapacity, *ec);
159 }
160 
161 U_CAPI UBool U_EXPORT2
unumf_resultNextFieldPosition(const UFormattedNumber * uresult,UFieldPosition * ufpos,UErrorCode * ec)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; }
165 
166     if (ufpos == nullptr) {
167         *ec = U_ILLEGAL_ARGUMENT_ERROR;
168         return FALSE;
169     }
170 
171     FieldPosition fp;
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;
180 }
181 
182 U_CAPI void U_EXPORT2
unumf_resultGetAllFieldPositions(const UFormattedNumber * uresult,UFieldPositionIterator * ufpositer,UErrorCode * ec)183 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
184                                  UErrorCode* ec) {
185     const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec);
186     if (U_FAILURE(*ec)) { return; }
187 
188     if (ufpositer == nullptr) {
189         *ec = U_ILLEGAL_ARGUMENT_ERROR;
190         return;
191     }
192 
193     auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
194     FieldPositionIteratorHandler fpih(fpi, *ec);
195     result->string.getAllFieldPositions(fpih, *ec);
196 }
197 
198 U_CAPI void U_EXPORT2
unumf_closeResult(UFormattedNumber * uresult)199 unumf_closeResult(UFormattedNumber* uresult) {
200     UErrorCode localStatus = U_ZERO_ERROR;
201     const UFormattedNumberData* impl = UFormattedNumberData::validate(uresult, localStatus);
202     delete impl;
203 }
204 
205 U_CAPI void U_EXPORT2
unumf_close(UNumberFormatter * f)206 unumf_close(UNumberFormatter* f) {
207     UErrorCode localStatus = U_ZERO_ERROR;
208     const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
209     delete impl;
210 }
211 
212 
213 #endif /* #if !UCONFIG_NO_FORMATTING */
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
224 
225 
226 
227 
228 
229 
230 
231 
232 
233 
234 
235 
236 
237 
238 
239 
240 
241