File: | root/firefox-clang/intl/icu/source/i18n/unum.cpp |
Warning: | line 467, column 9 Null pointer passed as 1st argument to string copy function |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // © 2016 and later: Unicode, Inc. and others. | |||
2 | // License & terms of use: http://www.unicode.org/copyright.html | |||
3 | /* | |||
4 | ******************************************************************************* | |||
5 | * Copyright (C) 1996-2015, International Business Machines | |||
6 | * Corporation and others. All Rights Reserved. | |||
7 | ******************************************************************************* | |||
8 | * Modification History: | |||
9 | * | |||
10 | * Date Name Description | |||
11 | * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes | |||
12 | ******************************************************************************* | |||
13 | */ | |||
14 | ||||
15 | #include "unicode/utypes.h" | |||
16 | ||||
17 | #if !UCONFIG_NO_FORMATTING0 | |||
18 | ||||
19 | #include "unicode/unum.h" | |||
20 | ||||
21 | #include "unicode/uloc.h" | |||
22 | #include "unicode/numfmt.h" | |||
23 | #include "unicode/decimfmt.h" | |||
24 | #include "unicode/rbnf.h" | |||
25 | #include "unicode/compactdecimalformat.h" | |||
26 | #include "unicode/ustring.h" | |||
27 | #include "unicode/fmtable.h" | |||
28 | #include "unicode/dcfmtsym.h" | |||
29 | #include "unicode/curramt.h" | |||
30 | #include "unicode/localpointer.h" | |||
31 | #include "unicode/measfmt.h" | |||
32 | #include "unicode/udisplaycontext.h" | |||
33 | #include "uassert.h" | |||
34 | #include "cpputils.h" | |||
35 | #include "cstring.h" | |||
36 | #include "putilimp.h" | |||
37 | ||||
38 | ||||
39 | U_NAMESPACE_USEusing namespace icu_77; | |||
40 | ||||
41 | ||||
42 | U_CAPIextern "C" UNumberFormat* U_EXPORT2 | |||
43 | unum_openunum_open_77( UNumberFormatStyle style, | |||
44 | const char16_t* pattern, | |||
45 | int32_t patternLength, | |||
46 | const char* locale, | |||
47 | UParseError* parseErr, | |||
48 | UErrorCode* status) { | |||
49 | if(U_FAILURE(*status)) { | |||
50 | return nullptr; | |||
51 | } | |||
52 | ||||
53 | NumberFormat *retVal = nullptr; | |||
54 | ||||
55 | switch(style) { | |||
56 | case UNUM_DECIMAL: | |||
57 | case UNUM_CURRENCY: | |||
58 | case UNUM_PERCENT: | |||
59 | case UNUM_SCIENTIFIC: | |||
60 | case UNUM_CURRENCY_ISO: | |||
61 | case UNUM_CURRENCY_PLURAL: | |||
62 | case UNUM_CURRENCY_ACCOUNTING: | |||
63 | case UNUM_CASH_CURRENCY: | |||
64 | case UNUM_CURRENCY_STANDARD: | |||
65 | retVal = NumberFormat::createInstance(Locale(locale), style, *status); | |||
66 | break; | |||
67 | ||||
68 | case UNUM_PATTERN_DECIMAL: { | |||
69 | UParseError tErr; | |||
70 | /* UnicodeString can handle the case when patternLength = -1. */ | |||
71 | const UnicodeString pat(pattern, patternLength); | |||
72 | ||||
73 | if(parseErr==nullptr){ | |||
74 | parseErr = &tErr; | |||
75 | } | |||
76 | ||||
77 | DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); | |||
78 | if(syms == nullptr) { | |||
79 | *status = U_MEMORY_ALLOCATION_ERROR; | |||
80 | return nullptr; | |||
81 | } | |||
82 | if (U_FAILURE(*status)) { | |||
83 | delete syms; | |||
84 | return nullptr; | |||
85 | } | |||
86 | ||||
87 | retVal = new DecimalFormat(pat, syms, *parseErr, *status); | |||
88 | if(retVal == nullptr) { | |||
89 | delete syms; | |||
90 | } | |||
91 | } break; | |||
92 | ||||
93 | #if U_HAVE_RBNF1 | |||
94 | case UNUM_PATTERN_RULEBASED: { | |||
95 | UParseError tErr; | |||
96 | /* UnicodeString can handle the case when patternLength = -1. */ | |||
97 | const UnicodeString pat(pattern, patternLength); | |||
98 | ||||
99 | if(parseErr==nullptr){ | |||
100 | parseErr = &tErr; | |||
101 | } | |||
102 | ||||
103 | retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); | |||
104 | } break; | |||
105 | ||||
106 | case UNUM_SPELLOUT: | |||
107 | retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); | |||
108 | break; | |||
109 | ||||
110 | case UNUM_ORDINAL: | |||
111 | retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); | |||
112 | break; | |||
113 | ||||
114 | case UNUM_DURATION: | |||
115 | retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); | |||
116 | break; | |||
117 | ||||
118 | case UNUM_NUMBERING_SYSTEM: { | |||
119 | // if the locale ID specifies a numbering system, go through NumberFormat::createInstance() | |||
120 | // to handle it properly (we have to specify UNUM_DEFAULT to get it to handle the numbering | |||
121 | // system, but we'll always get a RuleBasedNumberFormat back); otherwise, just go ahead and | |||
122 | // create a RuleBasedNumberFormat ourselves | |||
123 | UErrorCode localErr = U_ZERO_ERROR; | |||
124 | Locale localeObj(locale); | |||
125 | int32_t keywordLength = localeObj.getKeywordValue("numbers", nullptr, 0, localErr); | |||
126 | if (keywordLength > 0) { | |||
127 | retVal = NumberFormat::createInstance(localeObj, UNUM_DEFAULT, *status); | |||
128 | } else { | |||
129 | retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, localeObj, *status); | |||
130 | } | |||
131 | } break; | |||
132 | #endif | |||
133 | ||||
134 | case UNUM_DECIMAL_COMPACT_SHORT: | |||
135 | retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status); | |||
136 | break; | |||
137 | ||||
138 | case UNUM_DECIMAL_COMPACT_LONG: | |||
139 | retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status); | |||
140 | break; | |||
141 | ||||
142 | default: | |||
143 | *status = U_UNSUPPORTED_ERROR; | |||
144 | return nullptr; | |||
145 | } | |||
146 | ||||
147 | if(retVal == nullptr && U_SUCCESS(*status)) { | |||
148 | *status = U_MEMORY_ALLOCATION_ERROR; | |||
149 | } | |||
150 | ||||
151 | if (U_FAILURE(*status) && retVal != nullptr) { | |||
152 | delete retVal; | |||
153 | retVal = nullptr; | |||
154 | } | |||
155 | ||||
156 | return reinterpret_cast<UNumberFormat *>(retVal); | |||
157 | } | |||
158 | ||||
159 | U_CAPIextern "C" void U_EXPORT2 | |||
160 | unum_closeunum_close_77(UNumberFormat* fmt) | |||
161 | { | |||
162 | delete (NumberFormat*) fmt; | |||
163 | } | |||
164 | ||||
165 | U_CAPIextern "C" UNumberFormat* U_EXPORT2 | |||
166 | unum_cloneunum_clone_77(const UNumberFormat *fmt, | |||
167 | UErrorCode *status) | |||
168 | { | |||
169 | if(U_FAILURE(*status)) | |||
170 | return nullptr; | |||
171 | ||||
172 | Format* res = nullptr; | |||
173 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); | |||
174 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |||
175 | if (df != nullptr) { | |||
176 | res = df->clone(); | |||
177 | } else { | |||
178 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); | |||
179 | U_ASSERT(rbnf != nullptr)(static_cast <bool> (rbnf != nullptr) ? void (0) : __assert_fail ("rbnf != nullptr", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | |||
180 | res = rbnf->clone(); | |||
181 | } | |||
182 | ||||
183 | if (res == nullptr) { | |||
184 | *status = U_MEMORY_ALLOCATION_ERROR; | |||
185 | return nullptr; | |||
186 | } | |||
187 | ||||
188 | return (UNumberFormat*) res; | |||
189 | } | |||
190 | ||||
191 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
192 | unum_formatunum_format_77( const UNumberFormat* fmt, | |||
193 | int32_t number, | |||
194 | char16_t* result, | |||
195 | int32_t resultLength, | |||
196 | UFieldPosition *pos, | |||
197 | UErrorCode* status) | |||
198 | { | |||
199 | return unum_formatInt64unum_formatInt64_77(fmt, number, result, resultLength, pos, status); | |||
200 | } | |||
201 | ||||
202 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
203 | unum_formatInt64unum_formatInt64_77(const UNumberFormat* fmt, | |||
204 | int64_t number, | |||
205 | char16_t* result, | |||
206 | int32_t resultLength, | |||
207 | UFieldPosition *pos, | |||
208 | UErrorCode* status) | |||
209 | { | |||
210 | if(U_FAILURE(*status)) | |||
211 | return -1; | |||
212 | ||||
213 | UnicodeString res; | |||
214 | if(!(result==nullptr && resultLength==0)) { | |||
215 | // nullptr destination for pure preflighting: empty dummy string | |||
216 | // otherwise, alias the destination buffer | |||
217 | res.setTo(result, 0, resultLength); | |||
218 | } | |||
219 | ||||
220 | FieldPosition fp; | |||
221 | ||||
222 | if (pos != nullptr) | |||
223 | fp.setField(pos->field); | |||
224 | ||||
225 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); | |||
226 | ||||
227 | if (pos != nullptr) { | |||
228 | pos->beginIndex = fp.getBeginIndex(); | |||
229 | pos->endIndex = fp.getEndIndex(); | |||
230 | } | |||
231 | ||||
232 | return res.extract(result, resultLength, *status); | |||
233 | } | |||
234 | ||||
235 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
236 | unum_formatDoubleunum_formatDouble_77( const UNumberFormat* fmt, | |||
237 | double number, | |||
238 | char16_t* result, | |||
239 | int32_t resultLength, | |||
240 | UFieldPosition *pos, /* 0 if ignore */ | |||
241 | UErrorCode* status) | |||
242 | { | |||
243 | ||||
244 | if(U_FAILURE(*status)) return -1; | |||
245 | ||||
246 | UnicodeString res; | |||
247 | if(!(result==nullptr && resultLength==0)) { | |||
248 | // nullptr destination for pure preflighting: empty dummy string | |||
249 | // otherwise, alias the destination buffer | |||
250 | res.setTo(result, 0, resultLength); | |||
251 | } | |||
252 | ||||
253 | FieldPosition fp; | |||
254 | ||||
255 | if (pos != nullptr) | |||
256 | fp.setField(pos->field); | |||
257 | ||||
258 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); | |||
259 | ||||
260 | if (pos != nullptr) { | |||
261 | pos->beginIndex = fp.getBeginIndex(); | |||
262 | pos->endIndex = fp.getEndIndex(); | |||
263 | } | |||
264 | ||||
265 | return res.extract(result, resultLength, *status); | |||
266 | } | |||
267 | ||||
268 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
269 | unum_formatDoubleForFieldsunum_formatDoubleForFields_77(const UNumberFormat* format, | |||
270 | double number, | |||
271 | char16_t* result, | |||
272 | int32_t resultLength, | |||
273 | UFieldPositionIterator* fpositer, | |||
274 | UErrorCode* status) | |||
275 | { | |||
276 | if (U_FAILURE(*status)) | |||
277 | return -1; | |||
278 | ||||
279 | if (result == nullptr ? resultLength != 0 : resultLength < 0) { | |||
280 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |||
281 | return -1; | |||
282 | } | |||
283 | ||||
284 | UnicodeString res; | |||
285 | if (result != nullptr) { | |||
286 | // nullptr destination for pure preflighting: empty dummy string | |||
287 | // otherwise, alias the destination buffer | |||
288 | res.setTo(result, 0, resultLength); | |||
289 | } | |||
290 | ||||
291 | ((const NumberFormat*)format)->format(number, res, (FieldPositionIterator*)fpositer, *status); | |||
292 | ||||
293 | return res.extract(result, resultLength, *status); | |||
294 | } | |||
295 | ||||
296 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
297 | unum_formatDecimalunum_formatDecimal_77(const UNumberFormat* fmt, | |||
298 | const char * number, | |||
299 | int32_t length, | |||
300 | char16_t* result, | |||
301 | int32_t resultLength, | |||
302 | UFieldPosition *pos, /* 0 if ignore */ | |||
303 | UErrorCode* status) { | |||
304 | ||||
305 | if(U_FAILURE(*status)) { | |||
306 | return -1; | |||
307 | } | |||
308 | if ((result == nullptr && resultLength != 0) || resultLength < 0) { | |||
309 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |||
310 | return -1; | |||
311 | } | |||
312 | ||||
313 | FieldPosition fp; | |||
314 | if (pos != nullptr) { | |||
315 | fp.setField(pos->field); | |||
316 | } | |||
317 | ||||
318 | if (length < 0) { | |||
319 | length = static_cast<int32_t>(uprv_strlen(number):: strlen(number)); | |||
320 | } | |||
321 | StringPiece numSP(number, length); | |||
322 | Formattable numFmtbl(numSP, *status); | |||
323 | ||||
324 | UnicodeString resultStr; | |||
325 | if (resultLength > 0) { | |||
326 | // Alias the destination buffer. | |||
327 | resultStr.setTo(result, 0, resultLength); | |||
328 | } | |||
329 | ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); | |||
330 | if (pos != nullptr) { | |||
331 | pos->beginIndex = fp.getBeginIndex(); | |||
332 | pos->endIndex = fp.getEndIndex(); | |||
333 | } | |||
334 | return resultStr.extract(result, resultLength, *status); | |||
335 | } | |||
336 | ||||
337 | ||||
338 | ||||
339 | ||||
340 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
341 | unum_formatDoubleCurrencyunum_formatDoubleCurrency_77(const UNumberFormat* fmt, | |||
342 | double number, | |||
343 | char16_t* currency, | |||
344 | char16_t* result, | |||
345 | int32_t resultLength, | |||
346 | UFieldPosition* pos, /* ignored if 0 */ | |||
347 | UErrorCode* status) { | |||
348 | if (U_FAILURE(*status)) return -1; | |||
349 | ||||
350 | UnicodeString res; | |||
351 | if (!(result==nullptr && resultLength==0)) { | |||
352 | // nullptr destination for pure preflighting: empty dummy string | |||
353 | // otherwise, alias the destination buffer | |||
354 | res.setTo(result, 0, resultLength); | |||
355 | } | |||
356 | ||||
357 | FieldPosition fp; | |||
358 | if (pos != nullptr) { | |||
359 | fp.setField(pos->field); | |||
360 | } | |||
361 | CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); | |||
362 | // Check for null pointer. | |||
363 | if (tempCurrAmnt == nullptr) { | |||
364 | *status = U_MEMORY_ALLOCATION_ERROR; | |||
365 | return -1; | |||
366 | } | |||
367 | Formattable n(tempCurrAmnt); | |||
368 | ((const NumberFormat*)fmt)->format(n, res, fp, *status); | |||
369 | ||||
370 | if (pos != nullptr) { | |||
371 | pos->beginIndex = fp.getBeginIndex(); | |||
372 | pos->endIndex = fp.getEndIndex(); | |||
373 | } | |||
374 | ||||
375 | return res.extract(result, resultLength, *status); | |||
376 | } | |||
377 | ||||
378 | static void | |||
379 | parseRes(Formattable& res, | |||
380 | const UNumberFormat* fmt, | |||
381 | const char16_t* text, | |||
382 | int32_t textLength, | |||
383 | int32_t *parsePos /* 0 = start */, | |||
384 | UErrorCode *status) | |||
385 | { | |||
386 | if(U_FAILURE(*status)) | |||
387 | return; | |||
388 | ||||
389 | const UnicodeString src(static_cast<UBool>(textLength == -1), text, textLength); | |||
390 | ParsePosition pp; | |||
391 | ||||
392 | if (parsePos != nullptr) | |||
393 | pp.setIndex(*parsePos); | |||
394 | ||||
395 | reinterpret_cast<const NumberFormat*>(fmt)->parse(src, res, pp); | |||
396 | ||||
397 | if(pp.getErrorIndex() != -1) { | |||
398 | *status = U_PARSE_ERROR; | |||
399 | if (parsePos != nullptr) { | |||
400 | *parsePos = pp.getErrorIndex(); | |||
401 | } | |||
402 | } else if (parsePos != nullptr) { | |||
403 | *parsePos = pp.getIndex(); | |||
404 | } | |||
405 | } | |||
406 | ||||
407 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
408 | unum_parseunum_parse_77( const UNumberFormat* fmt, | |||
409 | const char16_t* text, | |||
410 | int32_t textLength, | |||
411 | int32_t *parsePos /* 0 = start */, | |||
412 | UErrorCode *status) | |||
413 | { | |||
414 | Formattable res; | |||
415 | parseRes(res, fmt, text, textLength, parsePos, status); | |||
416 | return res.getLong(*status); | |||
417 | } | |||
418 | ||||
419 | U_CAPIextern "C" int64_t U_EXPORT2 | |||
420 | unum_parseInt64unum_parseInt64_77( const UNumberFormat* fmt, | |||
421 | const char16_t* text, | |||
422 | int32_t textLength, | |||
423 | int32_t *parsePos /* 0 = start */, | |||
424 | UErrorCode *status) | |||
425 | { | |||
426 | Formattable res; | |||
427 | parseRes(res, fmt, text, textLength, parsePos, status); | |||
428 | return res.getInt64(*status); | |||
429 | } | |||
430 | ||||
431 | U_CAPIextern "C" double U_EXPORT2 | |||
432 | unum_parseDoubleunum_parseDouble_77( const UNumberFormat* fmt, | |||
433 | const char16_t* text, | |||
434 | int32_t textLength, | |||
435 | int32_t *parsePos /* 0 = start */, | |||
436 | UErrorCode *status) | |||
437 | { | |||
438 | Formattable res; | |||
439 | parseRes(res, fmt, text, textLength, parsePos, status); | |||
440 | return res.getDouble(*status); | |||
441 | } | |||
442 | ||||
443 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
444 | unum_parseDecimalunum_parseDecimal_77(const UNumberFormat* fmt, | |||
445 | const char16_t* text, | |||
446 | int32_t textLength, | |||
447 | int32_t *parsePos /* 0 = start */, | |||
448 | char *outBuf, | |||
449 | int32_t outBufLength, | |||
450 | UErrorCode *status) | |||
451 | { | |||
452 | if (U_FAILURE(*status)) { | |||
453 | return -1; | |||
454 | } | |||
455 | if ((outBuf == nullptr && outBufLength != 0) || outBufLength
| |||
| ||||
456 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |||
457 | return -1; | |||
458 | } | |||
459 | Formattable res; | |||
460 | parseRes(res, fmt, text, textLength, parsePos, status); | |||
461 | StringPiece sp = res.getDecimalNumber(*status); | |||
462 | if (U_FAILURE(*status)) { | |||
463 | return -1; | |||
464 | } else if (sp.size() > outBufLength) { | |||
465 | *status = U_BUFFER_OVERFLOW_ERROR; | |||
466 | } else if (sp.size() == outBufLength) { | |||
467 | uprv_strncpy(outBuf, sp.data(), sp.size()):: strncpy(outBuf, sp.data(), sp.size()); | |||
| ||||
468 | *status = U_STRING_NOT_TERMINATED_WARNING; | |||
469 | } else { | |||
470 | U_ASSERT(outBufLength > 0)(static_cast <bool> (outBufLength > 0) ? void (0) : __assert_fail ("outBufLength > 0", __builtin_FILE (), __builtin_LINE () , __extension__ __PRETTY_FUNCTION__)); | |||
471 | uprv_strcpy(outBuf, sp.data()):: strcpy(outBuf, sp.data()); | |||
472 | } | |||
473 | return sp.size(); | |||
474 | } | |||
475 | ||||
476 | U_CAPIextern "C" double U_EXPORT2 | |||
477 | unum_parseDoubleCurrencyunum_parseDoubleCurrency_77(const UNumberFormat* fmt, | |||
478 | const char16_t* text, | |||
479 | int32_t textLength, | |||
480 | int32_t* parsePos, /* 0 = start */ | |||
481 | char16_t* currency, | |||
482 | UErrorCode* status) { | |||
483 | double doubleVal = 0.0; | |||
484 | currency[0] = 0; | |||
485 | if (U_FAILURE(*status)) { | |||
486 | return doubleVal; | |||
487 | } | |||
488 | const UnicodeString src(textLength == -1, text, textLength); | |||
489 | ParsePosition pp; | |||
490 | if (parsePos != nullptr) { | |||
491 | pp.setIndex(*parsePos); | |||
492 | } | |||
493 | *status = U_PARSE_ERROR; // assume failure, reset if succeed | |||
494 | LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); | |||
495 | if (pp.getErrorIndex() != -1) { | |||
496 | if (parsePos != nullptr) { | |||
497 | *parsePos = pp.getErrorIndex(); | |||
498 | } | |||
499 | } else { | |||
500 | if (parsePos != nullptr) { | |||
501 | *parsePos = pp.getIndex(); | |||
502 | } | |||
503 | if (pp.getIndex() > 0) { | |||
504 | *status = U_ZERO_ERROR; | |||
505 | u_strcpyu_strcpy_77(currency, currAmt->getISOCurrency()); | |||
506 | doubleVal = currAmt->getNumber().getDouble(*status); | |||
507 | } | |||
508 | } | |||
509 | return doubleVal; | |||
510 | } | |||
511 | ||||
512 | U_CAPIextern "C" const char* U_EXPORT2 | |||
513 | unum_getAvailableunum_getAvailable_77(int32_t index) | |||
514 | { | |||
515 | return uloc_getAvailableuloc_getAvailable_77(index); | |||
516 | } | |||
517 | ||||
518 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
519 | unum_countAvailableunum_countAvailable_77() | |||
520 | { | |||
521 | return uloc_countAvailableuloc_countAvailable_77(); | |||
522 | } | |||
523 | ||||
524 | U_CAPIextern "C" bool U_EXPORT2 | |||
525 | unum_hasAttributeunum_hasAttribute_77(const UNumberFormat* fmt, | |||
526 | UNumberFormatAttribute attr) | |||
527 | { | |||
528 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); | |||
529 | bool isDecimalFormat = dynamic_cast<const DecimalFormat*>(nf) != nullptr; | |||
530 | ||||
531 | switch (attr) { | |||
532 | case UNUM_LENIENT_PARSE: | |||
533 | case UNUM_MAX_INTEGER_DIGITS: | |||
534 | case UNUM_MIN_INTEGER_DIGITS: | |||
535 | case UNUM_INTEGER_DIGITS: | |||
536 | case UNUM_MAX_FRACTION_DIGITS: | |||
537 | case UNUM_MIN_FRACTION_DIGITS: | |||
538 | case UNUM_FRACTION_DIGITS: | |||
539 | case UNUM_ROUNDING_MODE: | |||
540 | return true; | |||
541 | default: | |||
542 | return isDecimalFormat; | |||
543 | } | |||
544 | } | |||
545 | ||||
546 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
547 | unum_getAttributeunum_getAttribute_77(const UNumberFormat* fmt, | |||
548 | UNumberFormatAttribute attr) | |||
549 | { | |||
550 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); | |||
551 | if (attr == UNUM_LENIENT_PARSE) { | |||
552 | // Supported for all subclasses | |||
553 | return nf->isLenient(); | |||
554 | } | |||
555 | else if (attr == UNUM_MAX_INTEGER_DIGITS) { | |||
556 | return nf->getMaximumIntegerDigits(); | |||
557 | } | |||
558 | else if (attr == UNUM_MIN_INTEGER_DIGITS) { | |||
559 | return nf->getMinimumIntegerDigits(); | |||
560 | } | |||
561 | else if (attr == UNUM_INTEGER_DIGITS) { | |||
562 | // TODO: what should this return? | |||
563 | return nf->getMinimumIntegerDigits(); | |||
564 | } | |||
565 | else if (attr == UNUM_MAX_FRACTION_DIGITS) { | |||
566 | return nf->getMaximumFractionDigits(); | |||
567 | } | |||
568 | else if (attr == UNUM_MIN_FRACTION_DIGITS) { | |||
569 | return nf->getMinimumFractionDigits(); | |||
570 | } | |||
571 | else if (attr == UNUM_FRACTION_DIGITS) { | |||
572 | // TODO: what should this return? | |||
573 | return nf->getMinimumFractionDigits(); | |||
574 | } | |||
575 | else if (attr == UNUM_ROUNDING_MODE) { | |||
576 | return nf->getRoundingMode(); | |||
577 | } | |||
578 | ||||
579 | // The remaining attributes are only supported for DecimalFormat | |||
580 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |||
581 | if (df != nullptr) { | |||
582 | UErrorCode ignoredStatus = U_ZERO_ERROR; | |||
583 | return df->getAttribute(attr, ignoredStatus); | |||
584 | } | |||
585 | ||||
586 | return -1; | |||
587 | } | |||
588 | ||||
589 | U_CAPIextern "C" void U_EXPORT2 | |||
590 | unum_setAttributeunum_setAttribute_77( UNumberFormat* fmt, | |||
591 | UNumberFormatAttribute attr, | |||
592 | int32_t newValue) | |||
593 | { | |||
594 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); | |||
595 | if (attr == UNUM_LENIENT_PARSE) { | |||
596 | // Supported for all subclasses | |||
597 | // keep this here as the class may not be a DecimalFormat | |||
598 | return nf->setLenient(newValue != 0); | |||
599 | } | |||
600 | else if (attr == UNUM_MAX_INTEGER_DIGITS) { | |||
601 | return nf->setMaximumIntegerDigits(newValue); | |||
602 | } | |||
603 | else if (attr == UNUM_MIN_INTEGER_DIGITS) { | |||
604 | return nf->setMinimumIntegerDigits(newValue); | |||
605 | } | |||
606 | else if (attr == UNUM_INTEGER_DIGITS) { | |||
607 | nf->setMinimumIntegerDigits(newValue); | |||
608 | return nf->setMaximumIntegerDigits(newValue); | |||
609 | } | |||
610 | else if (attr == UNUM_MAX_FRACTION_DIGITS) { | |||
611 | return nf->setMaximumFractionDigits(newValue); | |||
612 | } | |||
613 | else if (attr == UNUM_MIN_FRACTION_DIGITS) { | |||
614 | return nf->setMinimumFractionDigits(newValue); | |||
615 | } | |||
616 | else if (attr == UNUM_FRACTION_DIGITS) { | |||
617 | nf->setMinimumFractionDigits(newValue); | |||
618 | return nf->setMaximumFractionDigits(newValue); | |||
619 | } | |||
620 | else if (attr == UNUM_ROUNDING_MODE) { | |||
621 | return nf->setRoundingMode((NumberFormat::ERoundingMode)newValue); | |||
622 | } | |||
623 | ||||
624 | // The remaining attributes are only supported for DecimalFormat | |||
625 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |||
626 | if (df != nullptr) { | |||
627 | UErrorCode ignoredStatus = U_ZERO_ERROR; | |||
628 | df->setAttribute(attr, newValue, ignoredStatus); | |||
629 | } | |||
630 | } | |||
631 | ||||
632 | U_CAPIextern "C" double U_EXPORT2 | |||
633 | unum_getDoubleAttributeunum_getDoubleAttribute_77(const UNumberFormat* fmt, | |||
634 | UNumberFormatAttribute attr) | |||
635 | { | |||
636 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); | |||
637 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |||
638 | if (df != nullptr && attr == UNUM_ROUNDING_INCREMENT) { | |||
639 | return df->getRoundingIncrement(); | |||
640 | } else { | |||
641 | return -1.0; | |||
642 | } | |||
643 | } | |||
644 | ||||
645 | U_CAPIextern "C" void U_EXPORT2 | |||
646 | unum_setDoubleAttributeunum_setDoubleAttribute_77( UNumberFormat* fmt, | |||
647 | UNumberFormatAttribute attr, | |||
648 | double newValue) | |||
649 | { | |||
650 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); | |||
651 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |||
652 | if (df != nullptr && attr == UNUM_ROUNDING_INCREMENT) { | |||
653 | df->setRoundingIncrement(newValue); | |||
654 | } | |||
655 | } | |||
656 | ||||
657 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
658 | unum_getTextAttributeunum_getTextAttribute_77(const UNumberFormat* fmt, | |||
659 | UNumberFormatTextAttribute tag, | |||
660 | char16_t* result, | |||
661 | int32_t resultLength, | |||
662 | UErrorCode* status) | |||
663 | { | |||
664 | if(U_FAILURE(*status)) | |||
665 | return -1; | |||
666 | ||||
667 | UnicodeString res; | |||
668 | if(!(result==nullptr && resultLength==0)) { | |||
669 | // nullptr destination for pure preflighting: empty dummy string | |||
670 | // otherwise, alias the destination buffer | |||
671 | res.setTo(result, 0, resultLength); | |||
672 | } | |||
673 | ||||
674 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); | |||
675 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |||
676 | const RuleBasedNumberFormat* rbnf = nullptr; // cast is below for performance | |||
677 | if (df != nullptr) { | |||
678 | switch(tag) { | |||
679 | case UNUM_POSITIVE_PREFIX: | |||
680 | df->getPositivePrefix(res); | |||
681 | break; | |||
682 | ||||
683 | case UNUM_POSITIVE_SUFFIX: | |||
684 | df->getPositiveSuffix(res); | |||
685 | break; | |||
686 | ||||
687 | case UNUM_NEGATIVE_PREFIX: | |||
688 | df->getNegativePrefix(res); | |||
689 | break; | |||
690 | ||||
691 | case UNUM_NEGATIVE_SUFFIX: | |||
692 | df->getNegativeSuffix(res); | |||
693 | break; | |||
694 | ||||
695 | case UNUM_PADDING_CHARACTER: | |||
696 | res = df->getPadCharacterString(); | |||
697 | break; | |||
698 | ||||
699 | case UNUM_CURRENCY_CODE: | |||
700 | res = UnicodeString(df->getCurrency()); | |||
701 | break; | |||
702 | ||||
703 | default: | |||
704 | *status = U_UNSUPPORTED_ERROR; | |||
705 | return -1; | |||
706 | } | |||
707 | } else if ((rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf)) != nullptr) { | |||
708 | U_ASSERT(rbnf != nullptr)(static_cast <bool> (rbnf != nullptr) ? void (0) : __assert_fail ("rbnf != nullptr", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | |||
709 | if (tag == UNUM_DEFAULT_RULESET) { | |||
710 | res = rbnf->getDefaultRuleSetName(); | |||
711 | } else if (tag == UNUM_PUBLIC_RULESETS) { | |||
712 | int32_t count = rbnf->getNumberOfRuleSetNames(); | |||
713 | for (int i = 0; i < count; ++i) { | |||
714 | res += rbnf->getRuleSetName(i); | |||
715 | res += (char16_t)0x003b; // semicolon | |||
716 | } | |||
717 | } else { | |||
718 | *status = U_UNSUPPORTED_ERROR; | |||
719 | return -1; | |||
720 | } | |||
721 | } else { | |||
722 | *status = U_UNSUPPORTED_ERROR; | |||
723 | return -1; | |||
724 | } | |||
725 | ||||
726 | return res.extract(result, resultLength, *status); | |||
727 | } | |||
728 | ||||
729 | U_CAPIextern "C" void U_EXPORT2 | |||
730 | unum_setTextAttributeunum_setTextAttribute_77( UNumberFormat* fmt, | |||
731 | UNumberFormatTextAttribute tag, | |||
732 | const char16_t* newValue, | |||
733 | int32_t newValueLength, | |||
734 | UErrorCode *status) | |||
735 | { | |||
736 | if(U_FAILURE(*status)) | |||
737 | return; | |||
738 | ||||
739 | UnicodeString val(newValue, newValueLength); | |||
740 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); | |||
741 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |||
742 | if (df != nullptr) { | |||
743 | switch(tag) { | |||
744 | case UNUM_POSITIVE_PREFIX: | |||
745 | df->setPositivePrefix(val); | |||
746 | break; | |||
747 | ||||
748 | case UNUM_POSITIVE_SUFFIX: | |||
749 | df->setPositiveSuffix(val); | |||
750 | break; | |||
751 | ||||
752 | case UNUM_NEGATIVE_PREFIX: | |||
753 | df->setNegativePrefix(val); | |||
754 | break; | |||
755 | ||||
756 | case UNUM_NEGATIVE_SUFFIX: | |||
757 | df->setNegativeSuffix(val); | |||
758 | break; | |||
759 | ||||
760 | case UNUM_PADDING_CHARACTER: | |||
761 | df->setPadCharacter(val); | |||
762 | break; | |||
763 | ||||
764 | case UNUM_CURRENCY_CODE: | |||
765 | df->setCurrency(val.getTerminatedBuffer(), *status); | |||
766 | break; | |||
767 | ||||
768 | default: | |||
769 | *status = U_UNSUPPORTED_ERROR; | |||
770 | break; | |||
771 | } | |||
772 | } else { | |||
773 | RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); | |||
774 | U_ASSERT(rbnf != nullptr)(static_cast <bool> (rbnf != nullptr) ? void (0) : __assert_fail ("rbnf != nullptr", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | |||
775 | if (tag == UNUM_DEFAULT_RULESET) { | |||
776 | rbnf->setDefaultRuleSet(val, *status); | |||
777 | } else { | |||
778 | *status = U_UNSUPPORTED_ERROR; | |||
779 | } | |||
780 | } | |||
781 | } | |||
782 | ||||
783 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
784 | unum_toPatternunum_toPattern_77( const UNumberFormat* fmt, | |||
785 | UBool isPatternLocalized, | |||
786 | char16_t* result, | |||
787 | int32_t resultLength, | |||
788 | UErrorCode* status) | |||
789 | { | |||
790 | if(U_FAILURE(*status)) | |||
791 | return -1; | |||
792 | ||||
793 | UnicodeString pat; | |||
794 | if(!(result==nullptr && resultLength==0)) { | |||
795 | // nullptr destination for pure preflighting: empty dummy string | |||
796 | // otherwise, alias the destination buffer | |||
797 | pat.setTo(result, 0, resultLength); | |||
798 | } | |||
799 | ||||
800 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); | |||
801 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |||
802 | const RuleBasedNumberFormat* rbnf = nullptr; // cast is below for performance | |||
803 | if (df != nullptr) { | |||
804 | if(isPatternLocalized) | |||
805 | df->toLocalizedPattern(pat); | |||
806 | else | |||
807 | df->toPattern(pat); | |||
808 | } else if ((rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf)) != nullptr) { | |||
809 | pat = rbnf->getRules(); | |||
810 | } else { | |||
811 | // leave `pat` empty | |||
812 | } | |||
813 | return pat.extract(result, resultLength, *status); | |||
814 | } | |||
815 | ||||
816 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
817 | unum_getSymbolunum_getSymbol_77(const UNumberFormat *fmt, | |||
818 | UNumberFormatSymbol symbol, | |||
819 | char16_t *buffer, | |||
820 | int32_t size, | |||
821 | UErrorCode *status) UPRV_NO_SANITIZE_UNDEFINED__attribute__((no_sanitize("undefined"))) { | |||
822 | if(status==nullptr || U_FAILURE(*status)) { | |||
823 | return 0; | |||
824 | } | |||
825 | if(fmt==nullptr || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { | |||
826 | *status=U_ILLEGAL_ARGUMENT_ERROR; | |||
827 | return 0; | |||
828 | } | |||
829 | const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); | |||
830 | const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); | |||
831 | if (dcf == nullptr) { | |||
832 | *status = U_UNSUPPORTED_ERROR; | |||
833 | return 0; | |||
834 | } | |||
835 | ||||
836 | return dcf-> | |||
837 | getDecimalFormatSymbols()-> | |||
838 | getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). | |||
839 | extract(buffer, size, *status); | |||
840 | } | |||
841 | ||||
842 | U_CAPIextern "C" void U_EXPORT2 | |||
843 | unum_setSymbolunum_setSymbol_77(UNumberFormat *fmt, | |||
844 | UNumberFormatSymbol symbol, | |||
845 | const char16_t *value, | |||
846 | int32_t length, | |||
847 | UErrorCode *status) UPRV_NO_SANITIZE_UNDEFINED__attribute__((no_sanitize("undefined"))) { | |||
848 | if(status==nullptr || U_FAILURE(*status)) { | |||
849 | return; | |||
850 | } | |||
851 | if(fmt==nullptr || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==nullptr || length<-1) { | |||
852 | *status=U_ILLEGAL_ARGUMENT_ERROR; | |||
853 | return; | |||
854 | } | |||
855 | NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); | |||
856 | DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); | |||
857 | if (dcf == nullptr) { | |||
858 | *status = U_UNSUPPORTED_ERROR; | |||
859 | return; | |||
860 | } | |||
861 | ||||
862 | DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); | |||
863 | symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, | |||
864 | UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ | |||
865 | dcf->setDecimalFormatSymbols(symbols); | |||
866 | } | |||
867 | ||||
868 | U_CAPIextern "C" void U_EXPORT2 | |||
869 | unum_applyPatternunum_applyPattern_77( UNumberFormat *fmt, | |||
870 | UBool localized, | |||
871 | const char16_t *pattern, | |||
872 | int32_t patternLength, | |||
873 | UParseError *parseError, | |||
874 | UErrorCode* status) | |||
875 | { | |||
876 | UErrorCode tStatus = U_ZERO_ERROR; | |||
877 | UParseError tParseError; | |||
878 | ||||
879 | if(parseError == nullptr){ | |||
880 | parseError = &tParseError; | |||
881 | } | |||
882 | ||||
883 | if(status==nullptr){ | |||
884 | status = &tStatus; | |||
885 | } | |||
886 | ||||
887 | int32_t len = (patternLength == -1 ? u_strlenu_strlen_77(pattern) : patternLength); | |||
888 | const UnicodeString pat((char16_t*)pattern, len, len); | |||
889 | ||||
890 | // Verify if the object passed is a DecimalFormat object | |||
891 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); | |||
892 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |||
893 | if (df != nullptr) { | |||
894 | if(localized) { | |||
895 | df->applyLocalizedPattern(pat,*parseError, *status); | |||
896 | } else { | |||
897 | df->applyPattern(pat,*parseError, *status); | |||
898 | } | |||
899 | } else { | |||
900 | *status = U_UNSUPPORTED_ERROR; | |||
901 | return; | |||
902 | } | |||
903 | } | |||
904 | ||||
905 | U_CAPIextern "C" const char* U_EXPORT2 | |||
906 | unum_getLocaleByTypeunum_getLocaleByType_77(const UNumberFormat *fmt, | |||
907 | ULocDataLocaleType type, | |||
908 | UErrorCode* status) | |||
909 | { | |||
910 | if (fmt == nullptr) { | |||
911 | if (U_SUCCESS(*status)) { | |||
912 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |||
913 | } | |||
914 | return nullptr; | |||
915 | } | |||
916 | return ((const Format*)fmt)->getLocaleID(type, *status); | |||
917 | } | |||
918 | ||||
919 | U_CAPIextern "C" void U_EXPORT2 | |||
920 | unum_setContextunum_setContext_77(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status) | |||
921 | { | |||
922 | if (U_FAILURE(*status)) { | |||
923 | return; | |||
924 | } | |||
925 | ((NumberFormat*)fmt)->setContext(value, *status); | |||
926 | } | |||
927 | ||||
928 | U_CAPIextern "C" UDisplayContext U_EXPORT2 | |||
929 | unum_getContextunum_getContext_77(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status) | |||
930 | { | |||
931 | if (U_FAILURE(*status)) { | |||
932 | return (UDisplayContext)0; | |||
933 | } | |||
934 | return ((const NumberFormat*)fmt)->getContext(type, *status); | |||
935 | } | |||
936 | ||||
937 | U_CAPIextern "C" UFormattable * U_EXPORT2 | |||
938 | unum_parseToUFormattableunum_parseToUFormattable_77(const UNumberFormat* fmt, | |||
939 | UFormattable *result, | |||
940 | const char16_t* text, | |||
941 | int32_t textLength, | |||
942 | int32_t* parsePos, /* 0 = start */ | |||
943 | UErrorCode* status) { | |||
944 | UFormattable *newFormattable = nullptr; | |||
945 | if (U_FAILURE(*status)) return result; | |||
946 | if (fmt == nullptr || (text==nullptr && textLength!=0)) { | |||
947 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |||
948 | return result; | |||
949 | } | |||
950 | if (result == nullptr) { // allocate if not allocated. | |||
951 | newFormattable = result = ufmt_openufmt_open_77(status); | |||
952 | } | |||
953 | parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); | |||
954 | if (U_FAILURE(*status) && newFormattable != nullptr) { | |||
955 | ufmt_closeufmt_close_77(newFormattable); | |||
956 | result = nullptr; // deallocate if there was a parse error | |||
957 | } | |||
958 | return result; | |||
959 | } | |||
960 | ||||
961 | U_CAPIextern "C" int32_t U_EXPORT2 | |||
962 | unum_formatUFormattableunum_formatUFormattable_77(const UNumberFormat* fmt, | |||
963 | const UFormattable *number, | |||
964 | char16_t *result, | |||
965 | int32_t resultLength, | |||
966 | UFieldPosition *pos, /* ignored if 0 */ | |||
967 | UErrorCode *status) { | |||
968 | if (U_FAILURE(*status)) { | |||
969 | return 0; | |||
970 | } | |||
971 | if (fmt == nullptr || number==nullptr || | |||
972 | (result==nullptr ? resultLength!=0 : resultLength<0)) { | |||
973 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |||
974 | return 0; | |||
975 | } | |||
976 | UnicodeString res(result, 0, resultLength); | |||
977 | ||||
978 | FieldPosition fp; | |||
979 | ||||
980 | if (pos != nullptr) | |||
981 | fp.setField(pos->field); | |||
982 | ||||
983 | ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); | |||
984 | ||||
985 | if (pos != nullptr) { | |||
986 | pos->beginIndex = fp.getBeginIndex(); | |||
987 | pos->endIndex = fp.getEndIndex(); | |||
988 | } | |||
989 | ||||
990 | return res.extract(result, resultLength, *status); | |||
991 | } | |||
992 | ||||
993 | #endif /* #if !UCONFIG_NO_FORMATTING */ |