]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
57a6839d | 3 | * Copyright (C) 1996-2014, International Business Machines |
b75a7d8f A |
4 | * Corporation and others. All Rights Reserved. |
5 | ******************************************************************************* | |
6 | * Modification History: | |
7 | * | |
8 | * Date Name Description | |
9 | * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes | |
10 | ******************************************************************************* | |
11 | */ | |
12 | ||
13 | #include "unicode/utypes.h" | |
14 | ||
15 | #if !UCONFIG_NO_FORMATTING | |
16 | ||
17 | #include "unicode/unum.h" | |
18 | ||
19 | #include "unicode/uloc.h" | |
20 | #include "unicode/numfmt.h" | |
21 | #include "unicode/decimfmt.h" | |
22 | #include "unicode/rbnf.h" | |
b331163b | 23 | #include "unicode/compactdecimalformat.h" |
b75a7d8f A |
24 | #include "unicode/ustring.h" |
25 | #include "unicode/fmtable.h" | |
26 | #include "unicode/dcfmtsym.h" | |
374ca955 | 27 | #include "unicode/curramt.h" |
4388f060 | 28 | #include "unicode/localpointer.h" |
57a6839d | 29 | #include "unicode/udisplaycontext.h" |
374ca955 | 30 | #include "uassert.h" |
b75a7d8f | 31 | #include "cpputils.h" |
729e4ab9 | 32 | #include "cstring.h" |
b75a7d8f | 33 | |
b75a7d8f | 34 | |
374ca955 | 35 | U_NAMESPACE_USE |
b75a7d8f A |
36 | |
37 | ||
38 | U_CAPI UNumberFormat* U_EXPORT2 | |
39 | unum_open( UNumberFormatStyle style, | |
40 | const UChar* pattern, | |
41 | int32_t patternLength, | |
42 | const char* locale, | |
43 | UParseError* parseErr, | |
4388f060 A |
44 | UErrorCode* status) { |
45 | if(U_FAILURE(*status)) { | |
46 | return NULL; | |
374ca955 A |
47 | } |
48 | ||
4388f060 | 49 | NumberFormat *retVal = NULL; |
374ca955 A |
50 | |
51 | switch(style) { | |
52 | case UNUM_DECIMAL: | |
374ca955 | 53 | case UNUM_CURRENCY: |
374ca955 | 54 | case UNUM_PERCENT: |
374ca955 | 55 | case UNUM_SCIENTIFIC: |
57a6839d A |
56 | case UNUM_CURRENCY_ISO: |
57 | case UNUM_CURRENCY_PLURAL: | |
58 | case UNUM_CURRENCY_ACCOUNTING: | |
b331163b | 59 | case UNUM_CASH_CURRENCY: |
4388f060 | 60 | retVal = NumberFormat::createInstance(Locale(locale), style, *status); |
b75a7d8f A |
61 | break; |
62 | ||
374ca955 A |
63 | case UNUM_PATTERN_DECIMAL: { |
64 | UParseError tErr; | |
65 | /* UnicodeString can handle the case when patternLength = -1. */ | |
66 | const UnicodeString pat(pattern, patternLength); | |
374ca955 A |
67 | |
68 | if(parseErr==NULL){ | |
69 | parseErr = &tErr; | |
70 | } | |
71 | ||
4388f060 A |
72 | DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); |
73 | if(syms == NULL) { | |
374ca955 | 74 | *status = U_MEMORY_ALLOCATION_ERROR; |
4388f060 | 75 | return NULL; |
374ca955 | 76 | } |
729e4ab9 A |
77 | if (U_FAILURE(*status)) { |
78 | delete syms; | |
4388f060 | 79 | return NULL; |
729e4ab9 | 80 | } |
374ca955 | 81 | |
4388f060 A |
82 | retVal = new DecimalFormat(pat, syms, *parseErr, *status); |
83 | if(retVal == NULL) { | |
374ca955 A |
84 | delete syms; |
85 | } | |
4388f060 | 86 | } break; |
374ca955 | 87 | |
b75a7d8f | 88 | #if U_HAVE_RBNF |
374ca955 A |
89 | case UNUM_PATTERN_RULEBASED: { |
90 | UParseError tErr; | |
91 | /* UnicodeString can handle the case when patternLength = -1. */ | |
92 | const UnicodeString pat(pattern, patternLength); | |
93 | ||
94 | if(parseErr==NULL){ | |
95 | parseErr = &tErr; | |
96 | } | |
97 | ||
4388f060 | 98 | retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); |
374ca955 A |
99 | } break; |
100 | ||
101 | case UNUM_SPELLOUT: | |
4388f060 | 102 | retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); |
374ca955 | 103 | break; |
b75a7d8f | 104 | |
374ca955 | 105 | case UNUM_ORDINAL: |
4388f060 | 106 | retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); |
374ca955 | 107 | break; |
b75a7d8f | 108 | |
374ca955 | 109 | case UNUM_DURATION: |
4388f060 | 110 | retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); |
374ca955 | 111 | break; |
729e4ab9 A |
112 | |
113 | case UNUM_NUMBERING_SYSTEM: | |
4388f060 | 114 | retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status); |
729e4ab9 | 115 | break; |
374ca955 A |
116 | #endif |
117 | ||
b331163b A |
118 | case UNUM_DECIMAL_COMPACT_SHORT: |
119 | retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status); | |
120 | break; | |
121 | ||
122 | case UNUM_DECIMAL_COMPACT_LONG: | |
123 | retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status); | |
124 | break; | |
125 | ||
374ca955 A |
126 | default: |
127 | *status = U_UNSUPPORTED_ERROR; | |
4388f060 | 128 | return NULL; |
374ca955 | 129 | } |
b75a7d8f | 130 | |
4388f060 | 131 | if(retVal == NULL && U_SUCCESS(*status)) { |
b75a7d8f | 132 | *status = U_MEMORY_ALLOCATION_ERROR; |
374ca955 | 133 | } |
b75a7d8f | 134 | |
4388f060 | 135 | return reinterpret_cast<UNumberFormat *>(retVal); |
b75a7d8f A |
136 | } |
137 | ||
138 | U_CAPI void U_EXPORT2 | |
139 | unum_close(UNumberFormat* fmt) | |
140 | { | |
374ca955 | 141 | delete (NumberFormat*) fmt; |
b75a7d8f A |
142 | } |
143 | ||
144 | U_CAPI UNumberFormat* U_EXPORT2 | |
145 | unum_clone(const UNumberFormat *fmt, | |
146 | UErrorCode *status) | |
147 | { | |
374ca955 A |
148 | if(U_FAILURE(*status)) |
149 | return 0; | |
150 | ||
151 | Format *res = 0; | |
729e4ab9 A |
152 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
153 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
154 | if (df != NULL) { | |
155 | res = df->clone(); | |
374ca955 | 156 | } else { |
729e4ab9 A |
157 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
158 | U_ASSERT(rbnf != NULL); | |
159 | res = rbnf->clone(); | |
374ca955 | 160 | } |
b75a7d8f | 161 | |
374ca955 A |
162 | if(res == 0) { |
163 | *status = U_MEMORY_ALLOCATION_ERROR; | |
164 | return 0; | |
165 | } | |
166 | ||
167 | return (UNumberFormat*) res; | |
b75a7d8f A |
168 | } |
169 | ||
170 | U_CAPI int32_t U_EXPORT2 | |
171 | unum_format( const UNumberFormat* fmt, | |
374ca955 | 172 | int32_t number, |
b75a7d8f | 173 | UChar* result, |
374ca955 | 174 | int32_t resultLength, |
b75a7d8f | 175 | UFieldPosition *pos, |
374ca955 | 176 | UErrorCode* status) |
b75a7d8f | 177 | { |
374ca955 A |
178 | return unum_formatInt64(fmt, number, result, resultLength, pos, status); |
179 | } | |
b75a7d8f | 180 | |
374ca955 A |
181 | U_CAPI int32_t U_EXPORT2 |
182 | unum_formatInt64(const UNumberFormat* fmt, | |
183 | int64_t number, | |
184 | UChar* result, | |
185 | int32_t resultLength, | |
186 | UFieldPosition *pos, | |
187 | UErrorCode* status) | |
188 | { | |
189 | if(U_FAILURE(*status)) | |
190 | return -1; | |
191 | ||
192 | UnicodeString res; | |
193 | if(!(result==NULL && resultLength==0)) { | |
194 | // NULL destination for pure preflighting: empty dummy string | |
195 | // otherwise, alias the destination buffer | |
196 | res.setTo(result, 0, resultLength); | |
197 | } | |
198 | ||
199 | FieldPosition fp; | |
200 | ||
201 | if(pos != 0) | |
202 | fp.setField(pos->field); | |
203 | ||
b331163b A |
204 | const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt); |
205 | if (cdf != NULL) { | |
206 | cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !! | |
207 | } else { | |
208 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); | |
209 | } | |
51004dcb | 210 | |
374ca955 A |
211 | if(pos != 0) { |
212 | pos->beginIndex = fp.getBeginIndex(); | |
213 | pos->endIndex = fp.getEndIndex(); | |
214 | } | |
215 | ||
216 | return res.extract(result, resultLength, *status); | |
b75a7d8f A |
217 | } |
218 | ||
219 | U_CAPI int32_t U_EXPORT2 | |
220 | unum_formatDouble( const UNumberFormat* fmt, | |
221 | double number, | |
222 | UChar* result, | |
223 | int32_t resultLength, | |
224 | UFieldPosition *pos, /* 0 if ignore */ | |
225 | UErrorCode* status) | |
226 | { | |
227 | ||
228 | if(U_FAILURE(*status)) return -1; | |
229 | ||
230 | UnicodeString res; | |
231 | if(!(result==NULL && resultLength==0)) { | |
232 | // NULL destination for pure preflighting: empty dummy string | |
233 | // otherwise, alias the destination buffer | |
234 | res.setTo(result, 0, resultLength); | |
235 | } | |
236 | ||
237 | FieldPosition fp; | |
238 | ||
239 | if(pos != 0) | |
240 | fp.setField(pos->field); | |
241 | ||
b331163b A |
242 | const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt); |
243 | if (cdf != NULL) { | |
244 | cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !! | |
245 | } else { | |
246 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); | |
247 | } | |
b75a7d8f A |
248 | |
249 | if(pos != 0) { | |
250 | pos->beginIndex = fp.getBeginIndex(); | |
251 | pos->endIndex = fp.getEndIndex(); | |
252 | } | |
253 | ||
254 | return res.extract(result, resultLength, *status); | |
255 | } | |
256 | ||
729e4ab9 | 257 | |
51004dcb | 258 | U_CAPI int32_t U_EXPORT2 |
729e4ab9 A |
259 | unum_formatDecimal(const UNumberFormat* fmt, |
260 | const char * number, | |
261 | int32_t length, | |
262 | UChar* result, | |
263 | int32_t resultLength, | |
264 | UFieldPosition *pos, /* 0 if ignore */ | |
265 | UErrorCode* status) { | |
266 | ||
267 | if(U_FAILURE(*status)) { | |
268 | return -1; | |
269 | } | |
270 | if ((result == NULL && resultLength != 0) || resultLength < 0) { | |
271 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
272 | return -1; | |
273 | } | |
274 | ||
275 | FieldPosition fp; | |
276 | if(pos != 0) { | |
277 | fp.setField(pos->field); | |
278 | } | |
279 | ||
280 | if (length < 0) { | |
281 | length = uprv_strlen(number); | |
282 | } | |
283 | StringPiece numSP(number, length); | |
284 | Formattable numFmtbl(numSP, *status); | |
285 | ||
286 | UnicodeString resultStr; | |
287 | if (resultLength > 0) { | |
288 | // Alias the destination buffer. | |
289 | resultStr.setTo(result, 0, resultLength); | |
290 | } | |
291 | ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); | |
292 | if(pos != 0) { | |
293 | pos->beginIndex = fp.getBeginIndex(); | |
294 | pos->endIndex = fp.getEndIndex(); | |
295 | } | |
296 | return resultStr.extract(result, resultLength, *status); | |
297 | } | |
298 | ||
299 | ||
300 | ||
301 | ||
46f4442e | 302 | U_CAPI int32_t U_EXPORT2 |
374ca955 A |
303 | unum_formatDoubleCurrency(const UNumberFormat* fmt, |
304 | double number, | |
305 | UChar* currency, | |
306 | UChar* result, | |
307 | int32_t resultLength, | |
308 | UFieldPosition* pos, /* ignored if 0 */ | |
309 | UErrorCode* status) { | |
310 | if (U_FAILURE(*status)) return -1; | |
311 | ||
312 | UnicodeString res; | |
313 | if (!(result==NULL && resultLength==0)) { | |
314 | // NULL destination for pure preflighting: empty dummy string | |
315 | // otherwise, alias the destination buffer | |
316 | res.setTo(result, 0, resultLength); | |
317 | } | |
318 | ||
319 | FieldPosition fp; | |
320 | if (pos != 0) { | |
321 | fp.setField(pos->field); | |
322 | } | |
46f4442e A |
323 | CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); |
324 | // Check for null pointer. | |
325 | if (tempCurrAmnt == NULL) { | |
326 | *status = U_MEMORY_ALLOCATION_ERROR; | |
327 | return -1; | |
328 | } | |
329 | Formattable n(tempCurrAmnt); | |
374ca955 A |
330 | ((const NumberFormat*)fmt)->format(n, res, fp, *status); |
331 | ||
332 | if (pos != 0) { | |
333 | pos->beginIndex = fp.getBeginIndex(); | |
334 | pos->endIndex = fp.getEndIndex(); | |
335 | } | |
336 | ||
337 | return res.extract(result, resultLength, *status); | |
338 | } | |
339 | ||
340 | static void | |
341 | parseRes(Formattable& res, | |
342 | const UNumberFormat* fmt, | |
343 | const UChar* text, | |
344 | int32_t textLength, | |
345 | int32_t *parsePos /* 0 = start */, | |
374ca955 A |
346 | UErrorCode *status) |
347 | { | |
348 | if(U_FAILURE(*status)) | |
349 | return; | |
350 | ||
4388f060 | 351 | const UnicodeString src((UBool)(textLength == -1), text, textLength); |
374ca955 A |
352 | ParsePosition pp; |
353 | ||
354 | if(parsePos != 0) | |
355 | pp.setIndex(*parsePos); | |
356 | ||
4388f060 | 357 | ((const NumberFormat*)fmt)->parse(src, res, pp); |
374ca955 | 358 | |
46f4442e A |
359 | if(pp.getErrorIndex() != -1) { |
360 | *status = U_PARSE_ERROR; | |
361 | if(parsePos != 0) { | |
374ca955 | 362 | *parsePos = pp.getErrorIndex(); |
374ca955 | 363 | } |
46f4442e A |
364 | } else if(parsePos != 0) { |
365 | *parsePos = pp.getIndex(); | |
374ca955 A |
366 | } |
367 | } | |
368 | ||
b75a7d8f A |
369 | U_CAPI int32_t U_EXPORT2 |
370 | unum_parse( const UNumberFormat* fmt, | |
371 | const UChar* text, | |
372 | int32_t textLength, | |
373 | int32_t *parsePos /* 0 = start */, | |
374 | UErrorCode *status) | |
375 | { | |
374ca955 | 376 | Formattable res; |
4388f060 | 377 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 A |
378 | return res.getLong(*status); |
379 | } | |
b75a7d8f | 380 | |
374ca955 A |
381 | U_CAPI int64_t U_EXPORT2 |
382 | unum_parseInt64( const UNumberFormat* fmt, | |
383 | const UChar* text, | |
384 | int32_t textLength, | |
385 | int32_t *parsePos /* 0 = start */, | |
386 | UErrorCode *status) | |
387 | { | |
388 | Formattable res; | |
4388f060 | 389 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 | 390 | return res.getInt64(*status); |
b75a7d8f A |
391 | } |
392 | ||
393 | U_CAPI double U_EXPORT2 | |
394 | unum_parseDouble( const UNumberFormat* fmt, | |
395 | const UChar* text, | |
396 | int32_t textLength, | |
397 | int32_t *parsePos /* 0 = start */, | |
398 | UErrorCode *status) | |
399 | { | |
374ca955 | 400 | Formattable res; |
4388f060 | 401 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 A |
402 | return res.getDouble(*status); |
403 | } | |
b75a7d8f | 404 | |
729e4ab9 A |
405 | U_CAPI int32_t U_EXPORT2 |
406 | unum_parseDecimal(const UNumberFormat* fmt, | |
407 | const UChar* text, | |
408 | int32_t textLength, | |
409 | int32_t *parsePos /* 0 = start */, | |
410 | char *outBuf, | |
411 | int32_t outBufLength, | |
412 | UErrorCode *status) | |
413 | { | |
414 | if (U_FAILURE(*status)) { | |
415 | return -1; | |
416 | } | |
417 | if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) { | |
418 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
419 | return -1; | |
420 | } | |
421 | Formattable res; | |
4388f060 | 422 | parseRes(res, fmt, text, textLength, parsePos, status); |
729e4ab9 A |
423 | StringPiece sp = res.getDecimalNumber(*status); |
424 | if (U_FAILURE(*status)) { | |
425 | return -1; | |
426 | } else if (sp.size() > outBufLength) { | |
427 | *status = U_BUFFER_OVERFLOW_ERROR; | |
428 | } else if (sp.size() == outBufLength) { | |
429 | uprv_strncpy(outBuf, sp.data(), sp.size()); | |
430 | *status = U_STRING_NOT_TERMINATED_WARNING; | |
431 | } else { | |
4388f060 | 432 | U_ASSERT(outBufLength > 0); |
729e4ab9 A |
433 | uprv_strcpy(outBuf, sp.data()); |
434 | } | |
435 | return sp.size(); | |
436 | } | |
437 | ||
46f4442e | 438 | U_CAPI double U_EXPORT2 |
374ca955 A |
439 | unum_parseDoubleCurrency(const UNumberFormat* fmt, |
440 | const UChar* text, | |
441 | int32_t textLength, | |
442 | int32_t* parsePos, /* 0 = start */ | |
443 | UChar* currency, | |
444 | UErrorCode* status) { | |
4388f060 | 445 | double doubleVal = 0.0; |
374ca955 | 446 | currency[0] = 0; |
4388f060 A |
447 | if (U_FAILURE(*status)) { |
448 | return doubleVal; | |
b75a7d8f | 449 | } |
4388f060 A |
450 | const UnicodeString src((UBool)(textLength == -1), text, textLength); |
451 | ParsePosition pp; | |
452 | if (parsePos != NULL) { | |
453 | pp.setIndex(*parsePos); | |
454 | } | |
455 | *status = U_PARSE_ERROR; // assume failure, reset if succeed | |
456 | LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); | |
457 | if (pp.getErrorIndex() != -1) { | |
458 | if (parsePos != NULL) { | |
459 | *parsePos = pp.getErrorIndex(); | |
460 | } | |
461 | } else { | |
462 | if (parsePos != NULL) { | |
463 | *parsePos = pp.getIndex(); | |
464 | } | |
465 | if (pp.getIndex() > 0) { | |
466 | *status = U_ZERO_ERROR; | |
467 | u_strcpy(currency, currAmt->getISOCurrency()); | |
468 | doubleVal = currAmt->getNumber().getDouble(*status); | |
469 | } | |
470 | } | |
471 | return doubleVal; | |
b75a7d8f A |
472 | } |
473 | ||
474 | U_CAPI const char* U_EXPORT2 | |
475 | unum_getAvailable(int32_t index) | |
476 | { | |
374ca955 | 477 | return uloc_getAvailable(index); |
b75a7d8f A |
478 | } |
479 | ||
480 | U_CAPI int32_t U_EXPORT2 | |
481 | unum_countAvailable() | |
482 | { | |
374ca955 | 483 | return uloc_countAvailable(); |
b75a7d8f A |
484 | } |
485 | ||
486 | U_CAPI int32_t U_EXPORT2 | |
487 | unum_getAttribute(const UNumberFormat* fmt, | |
488 | UNumberFormatAttribute attr) | |
489 | { | |
729e4ab9 | 490 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
4388f060 A |
491 | if ( attr == UNUM_LENIENT_PARSE ) { |
492 | // Supported for all subclasses | |
493 | return nf->isLenient(); | |
494 | } | |
51004dcb | 495 | |
4388f060 | 496 | // The remaining attributea are only supported for DecimalFormat |
729e4ab9 A |
497 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); |
498 | if (df != NULL) { | |
51004dcb A |
499 | UErrorCode ignoredStatus = U_ZERO_ERROR; |
500 | return df->getAttribute( attr, ignoredStatus ); | |
b75a7d8f | 501 | } |
374ca955 | 502 | |
b75a7d8f A |
503 | return -1; |
504 | } | |
505 | ||
506 | U_CAPI void U_EXPORT2 | |
507 | unum_setAttribute( UNumberFormat* fmt, | |
508 | UNumberFormatAttribute attr, | |
509 | int32_t newValue) | |
510 | { | |
729e4ab9 | 511 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
4388f060 A |
512 | if ( attr == UNUM_LENIENT_PARSE ) { |
513 | // Supported for all subclasses | |
51004dcb | 514 | // keep this here as the class may not be a DecimalFormat |
4388f060 A |
515 | return nf->setLenient(newValue != 0); |
516 | } | |
517 | // The remaining attributea are only supported for DecimalFormat | |
729e4ab9 A |
518 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); |
519 | if (df != NULL) { | |
51004dcb A |
520 | UErrorCode ignoredStatus = U_ZERO_ERROR; |
521 | df->setAttribute(attr, newValue, ignoredStatus); | |
b75a7d8f A |
522 | } |
523 | } | |
524 | ||
525 | U_CAPI double U_EXPORT2 | |
526 | unum_getDoubleAttribute(const UNumberFormat* fmt, | |
527 | UNumberFormatAttribute attr) | |
528 | { | |
729e4ab9 A |
529 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
530 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
531 | if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { | |
532 | return df->getRoundingIncrement(); | |
374ca955 A |
533 | } else { |
534 | return -1.0; | |
535 | } | |
b75a7d8f A |
536 | } |
537 | ||
538 | U_CAPI void U_EXPORT2 | |
539 | unum_setDoubleAttribute( UNumberFormat* fmt, | |
540 | UNumberFormatAttribute attr, | |
541 | double newValue) | |
542 | { | |
729e4ab9 A |
543 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
544 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
545 | if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { | |
546 | df->setRoundingIncrement(newValue); | |
374ca955 | 547 | } |
b75a7d8f A |
548 | } |
549 | ||
550 | U_CAPI int32_t U_EXPORT2 | |
551 | unum_getTextAttribute(const UNumberFormat* fmt, | |
552 | UNumberFormatTextAttribute tag, | |
553 | UChar* result, | |
554 | int32_t resultLength, | |
555 | UErrorCode* status) | |
556 | { | |
374ca955 A |
557 | if(U_FAILURE(*status)) |
558 | return -1; | |
559 | ||
560 | UnicodeString res; | |
561 | if(!(result==NULL && resultLength==0)) { | |
562 | // NULL destination for pure preflighting: empty dummy string | |
563 | // otherwise, alias the destination buffer | |
564 | res.setTo(result, 0, resultLength); | |
565 | } | |
b75a7d8f | 566 | |
729e4ab9 A |
567 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
568 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
569 | if (df != NULL) { | |
374ca955 A |
570 | switch(tag) { |
571 | case UNUM_POSITIVE_PREFIX: | |
572 | df->getPositivePrefix(res); | |
573 | break; | |
574 | ||
575 | case UNUM_POSITIVE_SUFFIX: | |
576 | df->getPositiveSuffix(res); | |
577 | break; | |
578 | ||
579 | case UNUM_NEGATIVE_PREFIX: | |
580 | df->getNegativePrefix(res); | |
581 | break; | |
582 | ||
583 | case UNUM_NEGATIVE_SUFFIX: | |
584 | df->getNegativeSuffix(res); | |
585 | break; | |
586 | ||
587 | case UNUM_PADDING_CHARACTER: | |
588 | res = df->getPadCharacterString(); | |
589 | break; | |
590 | ||
591 | case UNUM_CURRENCY_CODE: | |
592 | res = UnicodeString(df->getCurrency()); | |
593 | break; | |
594 | ||
595 | default: | |
596 | *status = U_UNSUPPORTED_ERROR; | |
597 | return -1; | |
598 | } | |
599 | } else { | |
729e4ab9 A |
600 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
601 | U_ASSERT(rbnf != NULL); | |
374ca955 A |
602 | if (tag == UNUM_DEFAULT_RULESET) { |
603 | res = rbnf->getDefaultRuleSetName(); | |
604 | } else if (tag == UNUM_PUBLIC_RULESETS) { | |
605 | int32_t count = rbnf->getNumberOfRuleSetNames(); | |
606 | for (int i = 0; i < count; ++i) { | |
607 | res += rbnf->getRuleSetName(i); | |
608 | res += (UChar)0x003b; // semicolon | |
609 | } | |
610 | } else { | |
611 | *status = U_UNSUPPORTED_ERROR; | |
612 | return -1; | |
613 | } | |
614 | } | |
b75a7d8f | 615 | |
374ca955 | 616 | return res.extract(result, resultLength, *status); |
b75a7d8f A |
617 | } |
618 | ||
619 | U_CAPI void U_EXPORT2 | |
620 | unum_setTextAttribute( UNumberFormat* fmt, | |
621 | UNumberFormatTextAttribute tag, | |
622 | const UChar* newValue, | |
623 | int32_t newValueLength, | |
624 | UErrorCode *status) | |
625 | { | |
374ca955 A |
626 | if(U_FAILURE(*status)) |
627 | return; | |
729e4ab9 | 628 | |
4388f060 | 629 | UnicodeString val(newValue, newValueLength); |
729e4ab9 A |
630 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
631 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
632 | if (df != NULL) { | |
374ca955 A |
633 | switch(tag) { |
634 | case UNUM_POSITIVE_PREFIX: | |
635 | df->setPositivePrefix(val); | |
636 | break; | |
637 | ||
638 | case UNUM_POSITIVE_SUFFIX: | |
639 | df->setPositiveSuffix(val); | |
640 | break; | |
641 | ||
642 | case UNUM_NEGATIVE_PREFIX: | |
643 | df->setNegativePrefix(val); | |
644 | break; | |
645 | ||
646 | case UNUM_NEGATIVE_SUFFIX: | |
647 | df->setNegativeSuffix(val); | |
648 | break; | |
649 | ||
650 | case UNUM_PADDING_CHARACTER: | |
4388f060 | 651 | df->setPadCharacter(val); |
374ca955 A |
652 | break; |
653 | ||
654 | case UNUM_CURRENCY_CODE: | |
4388f060 | 655 | df->setCurrency(val.getTerminatedBuffer(), *status); |
374ca955 A |
656 | break; |
657 | ||
658 | default: | |
659 | *status = U_UNSUPPORTED_ERROR; | |
660 | break; | |
661 | } | |
662 | } else { | |
729e4ab9 A |
663 | RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); |
664 | U_ASSERT(rbnf != NULL); | |
374ca955 | 665 | if (tag == UNUM_DEFAULT_RULESET) { |
4388f060 | 666 | rbnf->setDefaultRuleSet(val, *status); |
374ca955 | 667 | } else { |
729e4ab9 | 668 | *status = U_UNSUPPORTED_ERROR; |
374ca955 A |
669 | } |
670 | } | |
b75a7d8f A |
671 | } |
672 | ||
673 | U_CAPI int32_t U_EXPORT2 | |
674 | unum_toPattern( const UNumberFormat* fmt, | |
675 | UBool isPatternLocalized, | |
676 | UChar* result, | |
677 | int32_t resultLength, | |
678 | UErrorCode* status) | |
679 | { | |
374ca955 A |
680 | if(U_FAILURE(*status)) |
681 | return -1; | |
682 | ||
683 | UnicodeString pat; | |
684 | if(!(result==NULL && resultLength==0)) { | |
685 | // NULL destination for pure preflighting: empty dummy string | |
686 | // otherwise, alias the destination buffer | |
687 | pat.setTo(result, 0, resultLength); | |
688 | } | |
b75a7d8f | 689 | |
729e4ab9 A |
690 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
691 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
692 | if (df != NULL) { | |
374ca955 A |
693 | if(isPatternLocalized) |
694 | df->toLocalizedPattern(pat); | |
695 | else | |
696 | df->toPattern(pat); | |
697 | } else { | |
729e4ab9 A |
698 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
699 | U_ASSERT(rbnf != NULL); | |
700 | pat = rbnf->getRules(); | |
374ca955 A |
701 | } |
702 | return pat.extract(result, resultLength, *status); | |
b75a7d8f A |
703 | } |
704 | ||
705 | U_CAPI int32_t U_EXPORT2 | |
374ca955 | 706 | unum_getSymbol(const UNumberFormat *fmt, |
b75a7d8f A |
707 | UNumberFormatSymbol symbol, |
708 | UChar *buffer, | |
709 | int32_t size, | |
374ca955 A |
710 | UErrorCode *status) |
711 | { | |
712 | if(status==NULL || U_FAILURE(*status)) { | |
713 | return 0; | |
714 | } | |
4388f060 | 715 | if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { |
374ca955 A |
716 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
717 | return 0; | |
718 | } | |
729e4ab9 A |
719 | const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); |
720 | const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); | |
721 | if (dcf == NULL) { | |
374ca955 A |
722 | *status = U_UNSUPPORTED_ERROR; |
723 | return 0; | |
724 | } | |
b75a7d8f | 725 | |
729e4ab9 | 726 | return dcf-> |
b75a7d8f A |
727 | getDecimalFormatSymbols()-> |
728 | getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). | |
729 | extract(buffer, size, *status); | |
730 | } | |
731 | ||
732 | U_CAPI void U_EXPORT2 | |
733 | unum_setSymbol(UNumberFormat *fmt, | |
734 | UNumberFormatSymbol symbol, | |
735 | const UChar *value, | |
736 | int32_t length, | |
374ca955 | 737 | UErrorCode *status) |
b75a7d8f | 738 | { |
374ca955 A |
739 | if(status==NULL || U_FAILURE(*status)) { |
740 | return; | |
741 | } | |
4388f060 | 742 | if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { |
374ca955 A |
743 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
744 | return; | |
745 | } | |
729e4ab9 A |
746 | NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); |
747 | DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); | |
748 | if (dcf == NULL) { | |
374ca955 A |
749 | *status = U_UNSUPPORTED_ERROR; |
750 | return; | |
751 | } | |
752 | ||
729e4ab9 | 753 | DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); |
374ca955 A |
754 | symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, |
755 | UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ | |
729e4ab9 | 756 | dcf->setDecimalFormatSymbols(symbols); |
b75a7d8f | 757 | } |
b75a7d8f A |
758 | |
759 | U_CAPI void U_EXPORT2 | |
729e4ab9 | 760 | unum_applyPattern( UNumberFormat *fmt, |
b75a7d8f A |
761 | UBool localized, |
762 | const UChar *pattern, | |
763 | int32_t patternLength, | |
764 | UParseError *parseError, | |
765 | UErrorCode* status) | |
766 | { | |
374ca955 A |
767 | UErrorCode tStatus = U_ZERO_ERROR; |
768 | UParseError tParseError; | |
769 | ||
770 | if(parseError == NULL){ | |
771 | parseError = &tParseError; | |
772 | } | |
773 | ||
774 | if(status==NULL){ | |
775 | status = &tStatus; | |
776 | } | |
777 | ||
778 | int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); | |
779 | const UnicodeString pat((UChar*)pattern, len, len); | |
729e4ab9 | 780 | |
374ca955 | 781 | // Verify if the object passed is a DecimalFormat object |
729e4ab9 A |
782 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
783 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
784 | if (df != NULL) { | |
374ca955 | 785 | if(localized) { |
729e4ab9 | 786 | df->applyLocalizedPattern(pat,*parseError, *status); |
374ca955 | 787 | } else { |
729e4ab9 | 788 | df->applyPattern(pat,*parseError, *status); |
374ca955 A |
789 | } |
790 | } else { | |
791 | *status = U_UNSUPPORTED_ERROR; | |
b75a7d8f | 792 | return; |
374ca955 A |
793 | } |
794 | } | |
795 | ||
796 | U_CAPI const char* U_EXPORT2 | |
797 | unum_getLocaleByType(const UNumberFormat *fmt, | |
798 | ULocDataLocaleType type, | |
799 | UErrorCode* status) | |
800 | { | |
801 | if (fmt == NULL) { | |
802 | if (U_SUCCESS(*status)) { | |
803 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
804 | } | |
805 | return NULL; | |
806 | } | |
807 | return ((const Format*)fmt)->getLocaleID(type, *status); | |
b75a7d8f A |
808 | } |
809 | ||
57a6839d A |
810 | U_CAPI void U_EXPORT2 |
811 | unum_setContext(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status) | |
812 | { | |
813 | if (U_FAILURE(*status)) { | |
814 | return; | |
815 | } | |
816 | ((NumberFormat*)fmt)->setContext(value, *status); | |
817 | return; | |
818 | } | |
819 | ||
820 | U_CAPI UDisplayContext U_EXPORT2 | |
821 | unum_getContext(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status) | |
822 | { | |
823 | if (U_FAILURE(*status)) { | |
824 | return (UDisplayContext)0; | |
825 | } | |
826 | return ((const NumberFormat*)fmt)->getContext(type, *status); | |
827 | } | |
828 | ||
829 | U_INTERNAL UFormattable * U_EXPORT2 | |
830 | unum_parseToUFormattable(const UNumberFormat* fmt, | |
831 | UFormattable *result, | |
832 | const UChar* text, | |
833 | int32_t textLength, | |
834 | int32_t* parsePos, /* 0 = start */ | |
835 | UErrorCode* status) { | |
836 | UFormattable *newFormattable = NULL; | |
837 | if (U_FAILURE(*status)) return result; | |
838 | if (fmt == NULL || (text==NULL && textLength!=0)) { | |
839 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
840 | return result; | |
841 | } | |
842 | if (result == NULL) { // allocate if not allocated. | |
843 | newFormattable = result = ufmt_open(status); | |
844 | } | |
845 | parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); | |
846 | if (U_FAILURE(*status) && newFormattable != NULL) { | |
847 | ufmt_close(newFormattable); | |
848 | result = NULL; // deallocate if there was a parse error | |
849 | } | |
850 | return result; | |
851 | } | |
852 | ||
853 | U_INTERNAL int32_t U_EXPORT2 | |
854 | unum_formatUFormattable(const UNumberFormat* fmt, | |
855 | const UFormattable *number, | |
856 | UChar *result, | |
857 | int32_t resultLength, | |
858 | UFieldPosition *pos, /* ignored if 0 */ | |
859 | UErrorCode *status) { | |
860 | if (U_FAILURE(*status)) { | |
861 | return 0; | |
862 | } | |
863 | if (fmt == NULL || number==NULL || | |
864 | (result==NULL ? resultLength!=0 : resultLength<0)) { | |
865 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
866 | return 0; | |
867 | } | |
868 | UnicodeString res(result, 0, resultLength); | |
869 | ||
870 | FieldPosition fp; | |
871 | ||
872 | if(pos != 0) | |
873 | fp.setField(pos->field); | |
874 | ||
875 | ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); | |
876 | ||
877 | if(pos != 0) { | |
878 | pos->beginIndex = fp.getBeginIndex(); | |
879 | pos->endIndex = fp.getEndIndex(); | |
880 | } | |
881 | ||
882 | return res.extract(result, resultLength, *status); | |
883 | } | |
884 | ||
b75a7d8f | 885 | #endif /* #if !UCONFIG_NO_FORMATTING */ |