]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/unum.cpp
ICU-551.51.4.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
CommitLineData
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 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:
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
138U_CAPI void U_EXPORT2
139unum_close(UNumberFormat* fmt)
140{
374ca955 141 delete (NumberFormat*) fmt;
b75a7d8f
A
142}
143
144U_CAPI UNumberFormat* U_EXPORT2
145unum_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
170U_CAPI int32_t U_EXPORT2
171unum_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
181U_CAPI int32_t U_EXPORT2
182unum_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
219U_CAPI int32_t U_EXPORT2
220unum_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 258U_CAPI int32_t U_EXPORT2
729e4ab9
A
259unum_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 302U_CAPI int32_t U_EXPORT2
374ca955
A
303unum_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
340static void
341parseRes(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
369U_CAPI int32_t U_EXPORT2
370unum_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
381U_CAPI int64_t U_EXPORT2
382unum_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
393U_CAPI double U_EXPORT2
394unum_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
405U_CAPI int32_t U_EXPORT2
406unum_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 438U_CAPI double U_EXPORT2
374ca955
A
439unum_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
474U_CAPI const char* U_EXPORT2
475unum_getAvailable(int32_t index)
476{
374ca955 477 return uloc_getAvailable(index);
b75a7d8f
A
478}
479
480U_CAPI int32_t U_EXPORT2
481unum_countAvailable()
482{
374ca955 483 return uloc_countAvailable();
b75a7d8f
A
484}
485
486U_CAPI int32_t U_EXPORT2
487unum_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
506U_CAPI void U_EXPORT2
507unum_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
525U_CAPI double U_EXPORT2
526unum_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
538U_CAPI void U_EXPORT2
539unum_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
550U_CAPI int32_t U_EXPORT2
551unum_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
619U_CAPI void U_EXPORT2
620unum_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
673U_CAPI int32_t U_EXPORT2
674unum_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
705U_CAPI int32_t U_EXPORT2
374ca955 706unum_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
732U_CAPI void U_EXPORT2
733unum_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
759U_CAPI void U_EXPORT2
729e4ab9 760unum_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
796U_CAPI const char* U_EXPORT2
797unum_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
810U_CAPI void U_EXPORT2
811unum_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
820U_CAPI UDisplayContext U_EXPORT2
821unum_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
829U_INTERNAL UFormattable * U_EXPORT2
830unum_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
853U_INTERNAL int32_t U_EXPORT2
854unum_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 */