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