]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/unum.cpp
ICU-8.11.4.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
374ca955 3* Copyright (C) 1996-2004, 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"
23#include "unicode/ustring.h"
24#include "unicode/fmtable.h"
25#include "unicode/dcfmtsym.h"
374ca955
A
26#include "unicode/curramt.h"
27#include "uassert.h"
b75a7d8f 28#include "cpputils.h"
b75a7d8f 29
b75a7d8f 30
374ca955 31U_NAMESPACE_USE
b75a7d8f
A
32
33
34U_CAPI UNumberFormat* U_EXPORT2
35unum_open( UNumberFormatStyle style,
36 const UChar* pattern,
37 int32_t patternLength,
38 const char* locale,
39 UParseError* parseErr,
40 UErrorCode* status)
41{
42
374ca955
A
43 if(U_FAILURE(*status))
44 {
45 return 0;
46 }
47
48 UNumberFormat *retVal = 0;
49
50 switch(style) {
51 case UNUM_DECIMAL:
b75a7d8f 52 if(locale == 0)
374ca955 53 retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
b75a7d8f 54 else
374ca955
A
55 retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
56 *status);
b75a7d8f
A
57 break;
58
374ca955 59 case UNUM_CURRENCY:
b75a7d8f 60 if(locale == 0)
374ca955 61 retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
b75a7d8f 62 else
374ca955
A
63 retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
64 *status);
b75a7d8f
A
65 break;
66
374ca955 67 case UNUM_PERCENT:
b75a7d8f 68 if(locale == 0)
374ca955 69 retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
b75a7d8f 70 else
374ca955
A
71 retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
72 *status);
b75a7d8f
A
73 break;
74
374ca955 75 case UNUM_SCIENTIFIC:
b75a7d8f 76 if(locale == 0)
374ca955 77 retVal = (UNumberFormat*)NumberFormat::createScientificInstance(*status);
b75a7d8f 78 else
374ca955
A
79 retVal = (UNumberFormat*)NumberFormat::createScientificInstance(Locale(locale),
80 *status);
b75a7d8f
A
81 break;
82
374ca955
A
83 case UNUM_PATTERN_DECIMAL: {
84 UParseError tErr;
85 /* UnicodeString can handle the case when patternLength = -1. */
86 const UnicodeString pat(pattern, patternLength);
87 DecimalFormatSymbols *syms = 0;
88
89 if(parseErr==NULL){
90 parseErr = &tErr;
91 }
92
93 if(locale == 0)
94 syms = new DecimalFormatSymbols(*status);
95 else
96 syms = new DecimalFormatSymbols(Locale(locale), *status);
97
98 if(syms == 0) {
99 *status = U_MEMORY_ALLOCATION_ERROR;
100 return 0;
101 }
102
103 retVal = (UNumberFormat*)new DecimalFormat(pat, syms, *parseErr, *status);
104 if(retVal == 0) {
105 delete syms;
106 }
107 } break;
108
b75a7d8f 109#if U_HAVE_RBNF
374ca955
A
110 case UNUM_PATTERN_RULEBASED: {
111 UParseError tErr;
112 /* UnicodeString can handle the case when patternLength = -1. */
113 const UnicodeString pat(pattern, patternLength);
114
115 if(parseErr==NULL){
116 parseErr = &tErr;
117 }
118
119 retVal = (UNumberFormat*)new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
120 } break;
121
122 case UNUM_SPELLOUT:
123 retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
124 break;
b75a7d8f 125
374ca955
A
126 case UNUM_ORDINAL:
127 retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
128 break;
b75a7d8f 129
374ca955
A
130 case UNUM_DURATION:
131 retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
132 break;
133#endif
134
135 default:
136 *status = U_UNSUPPORTED_ERROR;
b75a7d8f 137 return 0;
374ca955 138 }
b75a7d8f 139
374ca955 140 if(retVal == 0 && U_SUCCESS(*status)) {
b75a7d8f 141 *status = U_MEMORY_ALLOCATION_ERROR;
374ca955 142 }
b75a7d8f 143
374ca955 144 return retVal;
b75a7d8f
A
145}
146
147U_CAPI void U_EXPORT2
148unum_close(UNumberFormat* fmt)
149{
374ca955 150 delete (NumberFormat*) fmt;
b75a7d8f
A
151}
152
153U_CAPI UNumberFormat* U_EXPORT2
154unum_clone(const UNumberFormat *fmt,
155 UErrorCode *status)
156{
374ca955
A
157 if(U_FAILURE(*status))
158 return 0;
159
160 Format *res = 0;
161 if (((const NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
162 res = ((const DecimalFormat*)fmt)->clone();
163 } else {
164 U_ASSERT(((const NumberFormat*)fmt)->getDynamicClassID() == RuleBasedNumberFormat::getStaticClassID());
165 res = ((const RuleBasedNumberFormat*)fmt)->clone();
166 }
b75a7d8f 167
374ca955
A
168 if(res == 0) {
169 *status = U_MEMORY_ALLOCATION_ERROR;
170 return 0;
171 }
172
173 return (UNumberFormat*) res;
b75a7d8f
A
174}
175
176U_CAPI int32_t U_EXPORT2
177unum_format( const UNumberFormat* fmt,
374ca955 178 int32_t number,
b75a7d8f 179 UChar* result,
374ca955 180 int32_t resultLength,
b75a7d8f 181 UFieldPosition *pos,
374ca955 182 UErrorCode* status)
b75a7d8f 183{
374ca955
A
184 return unum_formatInt64(fmt, number, result, resultLength, pos, status);
185}
b75a7d8f 186
374ca955
A
187U_CAPI int32_t U_EXPORT2
188unum_formatInt64(const UNumberFormat* fmt,
189 int64_t number,
190 UChar* result,
191 int32_t resultLength,
192 UFieldPosition *pos,
193 UErrorCode* status)
194{
195 if(U_FAILURE(*status))
196 return -1;
197
198 UnicodeString res;
199 if(!(result==NULL && resultLength==0)) {
200 // NULL destination for pure preflighting: empty dummy string
201 // otherwise, alias the destination buffer
202 res.setTo(result, 0, resultLength);
203 }
204
205 FieldPosition fp;
206
207 if(pos != 0)
208 fp.setField(pos->field);
209
210 ((const NumberFormat*)fmt)->format(number, res, fp);
211
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
374ca955 243 ((const NumberFormat*)fmt)->format(number, res, fp);
b75a7d8f
A
244
245 if(pos != 0) {
246 pos->beginIndex = fp.getBeginIndex();
247 pos->endIndex = fp.getEndIndex();
248 }
249
250 return res.extract(result, resultLength, *status);
251}
252
374ca955
A
253U_DRAFT int32_t U_EXPORT2
254unum_formatDoubleCurrency(const UNumberFormat* fmt,
255 double number,
256 UChar* currency,
257 UChar* result,
258 int32_t resultLength,
259 UFieldPosition* pos, /* ignored if 0 */
260 UErrorCode* status) {
261 if (U_FAILURE(*status)) return -1;
262
263 UnicodeString res;
264 if (!(result==NULL && resultLength==0)) {
265 // NULL destination for pure preflighting: empty dummy string
266 // otherwise, alias the destination buffer
267 res.setTo(result, 0, resultLength);
268 }
269
270 FieldPosition fp;
271 if (pos != 0) {
272 fp.setField(pos->field);
273 }
274
275 Formattable n(new CurrencyAmount(number, currency, *status));
276 ((const NumberFormat*)fmt)->format(n, res, fp, *status);
277
278 if (pos != 0) {
279 pos->beginIndex = fp.getBeginIndex();
280 pos->endIndex = fp.getEndIndex();
281 }
282
283 return res.extract(result, resultLength, *status);
284}
285
286static void
287parseRes(Formattable& res,
288 const UNumberFormat* fmt,
289 const UChar* text,
290 int32_t textLength,
291 int32_t *parsePos /* 0 = start */,
292 UBool parseCurrency,
293 UErrorCode *status)
294{
295 if(U_FAILURE(*status))
296 return;
297
298 int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
299 const UnicodeString src((UChar*)text, len, len);
300 ParsePosition pp;
301
302 if(parsePos != 0)
303 pp.setIndex(*parsePos);
304
305 if (parseCurrency) {
306 ((const NumberFormat*)fmt)->parseCurrency(src, res, pp);
307 } else {
308 ((const NumberFormat*)fmt)->parse(src, res, pp);
309 }
310
311 if(parsePos != 0) {
312 if(pp.getErrorIndex() == -1)
313 *parsePos = pp.getIndex();
314 else {
315 *parsePos = pp.getErrorIndex();
316 *status = U_PARSE_ERROR;
317 }
318 }
319}
320
b75a7d8f
A
321U_CAPI int32_t U_EXPORT2
322unum_parse( const UNumberFormat* fmt,
323 const UChar* text,
324 int32_t textLength,
325 int32_t *parsePos /* 0 = start */,
326 UErrorCode *status)
327{
374ca955
A
328 Formattable res;
329 parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
330 return res.getLong(*status);
331}
b75a7d8f 332
374ca955
A
333U_CAPI int64_t U_EXPORT2
334unum_parseInt64( const UNumberFormat* fmt,
335 const UChar* text,
336 int32_t textLength,
337 int32_t *parsePos /* 0 = start */,
338 UErrorCode *status)
339{
340 Formattable res;
341 parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
342 return res.getInt64(*status);
b75a7d8f
A
343}
344
345U_CAPI double U_EXPORT2
346unum_parseDouble( const UNumberFormat* fmt,
347 const UChar* text,
348 int32_t textLength,
349 int32_t *parsePos /* 0 = start */,
350 UErrorCode *status)
351{
374ca955
A
352 Formattable res;
353 parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
354 return res.getDouble(*status);
355}
b75a7d8f 356
374ca955
A
357U_DRAFT double U_EXPORT2
358unum_parseDoubleCurrency(const UNumberFormat* fmt,
359 const UChar* text,
360 int32_t textLength,
361 int32_t* parsePos, /* 0 = start */
362 UChar* currency,
363 UErrorCode* status) {
364 Formattable res;
365 parseRes(res, fmt, text, textLength, parsePos, TRUE, status);
366 currency[0] = 0;
367 if (res.getType() == Formattable::kObject &&
368 res.getObject()->getDynamicClassID() == CurrencyAmount::getStaticClassID()) {
369 const CurrencyAmount* c = (const CurrencyAmount*) res.getObject();
370 u_strcpy(currency, c->getISOCurrency());
b75a7d8f 371 }
374ca955 372 return res.getDouble(*status);
b75a7d8f
A
373}
374
375U_CAPI const char* U_EXPORT2
376unum_getAvailable(int32_t index)
377{
374ca955 378 return uloc_getAvailable(index);
b75a7d8f
A
379}
380
381U_CAPI int32_t U_EXPORT2
382unum_countAvailable()
383{
374ca955 384 return uloc_countAvailable();
b75a7d8f
A
385}
386
387U_CAPI int32_t U_EXPORT2
388unum_getAttribute(const UNumberFormat* fmt,
389 UNumberFormatAttribute attr)
390{
374ca955
A
391 if (((const NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
392 const DecimalFormat* df = (const DecimalFormat*) fmt;
393 switch(attr) {
394 case UNUM_PARSE_INT_ONLY:
395 return df->isParseIntegerOnly();
396
397 case UNUM_GROUPING_USED:
398 return df->isGroupingUsed();
399
400 case UNUM_DECIMAL_ALWAYS_SHOWN:
401 return df->isDecimalSeparatorAlwaysShown();
402
403 case UNUM_MAX_INTEGER_DIGITS:
404 return df->getMaximumIntegerDigits();
405
406 case UNUM_MIN_INTEGER_DIGITS:
407 return df->getMinimumIntegerDigits();
408
409 case UNUM_INTEGER_DIGITS:
410 // TBD: what should this return?
411 return df->getMinimumIntegerDigits();
412
413 case UNUM_MAX_FRACTION_DIGITS:
414 return df->getMaximumFractionDigits();
415
416 case UNUM_MIN_FRACTION_DIGITS:
417 return df->getMinimumFractionDigits();
418
419 case UNUM_FRACTION_DIGITS:
420 // TBD: what should this return?
421 return df->getMinimumFractionDigits();
422
423 case UNUM_SIGNIFICANT_DIGITS_USED:
424 return df->areSignificantDigitsUsed();
425
426 case UNUM_MAX_SIGNIFICANT_DIGITS:
427 return df->getMaximumSignificantDigits();
428
429 case UNUM_MIN_SIGNIFICANT_DIGITS:
430 return df->getMinimumSignificantDigits();
431
432 case UNUM_MULTIPLIER:
433 return df->getMultiplier();
434
435 case UNUM_GROUPING_SIZE:
436 return df->getGroupingSize();
437
438 case UNUM_ROUNDING_MODE:
439 return df->getRoundingMode();
440
441 case UNUM_FORMAT_WIDTH:
442 return df->getFormatWidth();
443
444 case UNUM_PADDING_POSITION:
445 return df->getPadPosition();
446
447 case UNUM_SECONDARY_GROUPING_SIZE:
448 return df->getSecondaryGroupingSize();
449
450 default:
451 /* enums out of sync? unsupported enum? */
452 break;
453 }
454 } else {
455 U_ASSERT(((const NumberFormat*)fmt)->getDynamicClassID() == RuleBasedNumberFormat::getStaticClassID());
456 if (attr == UNUM_LENIENT_PARSE) {
457#if !UCONFIG_NO_COLLATION
458 return ((const RuleBasedNumberFormat*)fmt)->isLenient();
459#endif
460 }
b75a7d8f 461 }
374ca955 462
b75a7d8f
A
463 return -1;
464}
465
466U_CAPI void U_EXPORT2
467unum_setAttribute( UNumberFormat* fmt,
468 UNumberFormatAttribute attr,
469 int32_t newValue)
470{
374ca955
A
471 if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
472 DecimalFormat* df = (DecimalFormat*) fmt;
473 switch(attr) {
474 case UNUM_PARSE_INT_ONLY:
475 df->setParseIntegerOnly(newValue!=0);
476 break;
477
478 case UNUM_GROUPING_USED:
479 df->setGroupingUsed(newValue!=0);
480 break;
481
482 case UNUM_DECIMAL_ALWAYS_SHOWN:
483 df->setDecimalSeparatorAlwaysShown(newValue!=0);
484 break;
485
486 case UNUM_MAX_INTEGER_DIGITS:
487 df->setMaximumIntegerDigits(newValue);
488 break;
489
490 case UNUM_MIN_INTEGER_DIGITS:
491 df->setMinimumIntegerDigits(newValue);
492 break;
493
494 case UNUM_INTEGER_DIGITS:
495 df->setMinimumIntegerDigits(newValue);
496 df->setMaximumIntegerDigits(newValue);
497 break;
498
499 case UNUM_MAX_FRACTION_DIGITS:
500 df->setMaximumFractionDigits(newValue);
501 break;
502
503 case UNUM_MIN_FRACTION_DIGITS:
504 df->setMinimumFractionDigits(newValue);
505 break;
506
507 case UNUM_FRACTION_DIGITS:
508 df->setMinimumFractionDigits(newValue);
509 df->setMaximumFractionDigits(newValue);
510 break;
511
512 case UNUM_SIGNIFICANT_DIGITS_USED:
513 df->setSignificantDigitsUsed(newValue!=0);
514 break;
515
516 case UNUM_MAX_SIGNIFICANT_DIGITS:
517 df->setMaximumSignificantDigits(newValue);
518 break;
519
520 case UNUM_MIN_SIGNIFICANT_DIGITS:
521 df->setMinimumSignificantDigits(newValue);
522 break;
523
524 case UNUM_MULTIPLIER:
525 df->setMultiplier(newValue);
526 break;
527
528 case UNUM_GROUPING_SIZE:
529 df->setGroupingSize(newValue);
530 break;
531
532 case UNUM_ROUNDING_MODE:
533 df->setRoundingMode((DecimalFormat::ERoundingMode)newValue);
534 break;
535
536 case UNUM_FORMAT_WIDTH:
537 df->setFormatWidth(newValue);
538 break;
539
540 case UNUM_PADDING_POSITION:
541 /** The position at which padding will take place. */
542 df->setPadPosition((DecimalFormat::EPadPosition)newValue);
543 break;
544
545 case UNUM_SECONDARY_GROUPING_SIZE:
546 df->setSecondaryGroupingSize(newValue);
547 break;
548
549 default:
550 /* Shouldn't get here anyway */
551 break;
552 }
553 } else {
554 U_ASSERT(((NumberFormat*)fmt)->getDynamicClassID() == RuleBasedNumberFormat::getStaticClassID());
555 if (attr == UNUM_LENIENT_PARSE) {
556#if !UCONFIG_NO_COLLATION
557 ((RuleBasedNumberFormat*)fmt)->setLenient((UBool)newValue);
558#endif
559 }
b75a7d8f
A
560 }
561}
562
563U_CAPI double U_EXPORT2
564unum_getDoubleAttribute(const UNumberFormat* fmt,
565 UNumberFormatAttribute attr)
566{
374ca955
A
567 if (((const NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID() &&
568 attr == UNUM_ROUNDING_INCREMENT) {
569 return ((const DecimalFormat*)fmt)->getRoundingIncrement();
570 } else {
571 return -1.0;
572 }
b75a7d8f
A
573}
574
575U_CAPI void U_EXPORT2
576unum_setDoubleAttribute( UNumberFormat* fmt,
577 UNumberFormatAttribute attr,
578 double newValue)
579{
374ca955
A
580 if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID() &&
581 attr == UNUM_ROUNDING_INCREMENT) {
582 ((DecimalFormat*)fmt)->setRoundingIncrement(newValue);
583 }
b75a7d8f
A
584}
585
586U_CAPI int32_t U_EXPORT2
587unum_getTextAttribute(const UNumberFormat* fmt,
588 UNumberFormatTextAttribute tag,
589 UChar* result,
590 int32_t resultLength,
591 UErrorCode* status)
592{
374ca955
A
593 if(U_FAILURE(*status))
594 return -1;
595
596 UnicodeString res;
597 if(!(result==NULL && resultLength==0)) {
598 // NULL destination for pure preflighting: empty dummy string
599 // otherwise, alias the destination buffer
600 res.setTo(result, 0, resultLength);
601 }
b75a7d8f 602
374ca955
A
603 if (((const NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
604 const DecimalFormat* df = (const DecimalFormat*) fmt;
605 switch(tag) {
606 case UNUM_POSITIVE_PREFIX:
607 df->getPositivePrefix(res);
608 break;
609
610 case UNUM_POSITIVE_SUFFIX:
611 df->getPositiveSuffix(res);
612 break;
613
614 case UNUM_NEGATIVE_PREFIX:
615 df->getNegativePrefix(res);
616 break;
617
618 case UNUM_NEGATIVE_SUFFIX:
619 df->getNegativeSuffix(res);
620 break;
621
622 case UNUM_PADDING_CHARACTER:
623 res = df->getPadCharacterString();
624 break;
625
626 case UNUM_CURRENCY_CODE:
627 res = UnicodeString(df->getCurrency());
628 break;
629
630 default:
631 *status = U_UNSUPPORTED_ERROR;
632 return -1;
633 }
634 } else {
635 U_ASSERT(((const NumberFormat*)fmt)->getDynamicClassID() == RuleBasedNumberFormat::getStaticClassID());
636 const RuleBasedNumberFormat* rbnf = (const RuleBasedNumberFormat*)fmt;
637 if (tag == UNUM_DEFAULT_RULESET) {
638 res = rbnf->getDefaultRuleSetName();
639 } else if (tag == UNUM_PUBLIC_RULESETS) {
640 int32_t count = rbnf->getNumberOfRuleSetNames();
641 for (int i = 0; i < count; ++i) {
642 res += rbnf->getRuleSetName(i);
643 res += (UChar)0x003b; // semicolon
644 }
645 } else {
646 *status = U_UNSUPPORTED_ERROR;
647 return -1;
648 }
649 }
b75a7d8f 650
374ca955 651 return res.extract(result, resultLength, *status);
b75a7d8f
A
652}
653
654U_CAPI void U_EXPORT2
655unum_setTextAttribute( UNumberFormat* fmt,
656 UNumberFormatTextAttribute tag,
657 const UChar* newValue,
658 int32_t newValueLength,
659 UErrorCode *status)
660{
374ca955
A
661 if(U_FAILURE(*status))
662 return;
663
664 int32_t len = (newValueLength == -1 ? u_strlen(newValue) : newValueLength);
665 const UnicodeString val((UChar*)newValue, len, len);
666
667 if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
668 DecimalFormat* df = (DecimalFormat*) fmt;
669 switch(tag) {
670 case UNUM_POSITIVE_PREFIX:
671 df->setPositivePrefix(val);
672 break;
673
674 case UNUM_POSITIVE_SUFFIX:
675 df->setPositiveSuffix(val);
676 break;
677
678 case UNUM_NEGATIVE_PREFIX:
679 df->setNegativePrefix(val);
680 break;
681
682 case UNUM_NEGATIVE_SUFFIX:
683 df->setNegativeSuffix(val);
684 break;
685
686 case UNUM_PADDING_CHARACTER:
687 df->setPadCharacter(*newValue);
688 break;
689
690 case UNUM_CURRENCY_CODE:
691 df->setCurrency(newValue, *status);
692 break;
693
694 default:
695 *status = U_UNSUPPORTED_ERROR;
696 break;
697 }
698 } else {
699 U_ASSERT(((NumberFormat*)fmt)->getDynamicClassID() == RuleBasedNumberFormat::getStaticClassID());
700 if (tag == UNUM_DEFAULT_RULESET) {
701 ((RuleBasedNumberFormat*)fmt)->setDefaultRuleSet(newValue, *status);
702 } else {
b75a7d8f 703 *status = U_UNSUPPORTED_ERROR;
374ca955
A
704 }
705 }
b75a7d8f
A
706}
707
708U_CAPI int32_t U_EXPORT2
709unum_toPattern( const UNumberFormat* fmt,
710 UBool isPatternLocalized,
711 UChar* result,
712 int32_t resultLength,
713 UErrorCode* status)
714{
374ca955
A
715 if(U_FAILURE(*status))
716 return -1;
717
718 UnicodeString pat;
719 if(!(result==NULL && resultLength==0)) {
720 // NULL destination for pure preflighting: empty dummy string
721 // otherwise, alias the destination buffer
722 pat.setTo(result, 0, resultLength);
723 }
b75a7d8f 724
374ca955
A
725 if (((const NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
726 const DecimalFormat* df = (const DecimalFormat*) fmt;
727 if(isPatternLocalized)
728 df->toLocalizedPattern(pat);
729 else
730 df->toPattern(pat);
731 } else {
732 U_ASSERT(((const NumberFormat*)fmt)->getDynamicClassID() == RuleBasedNumberFormat::getStaticClassID());
733 pat = ((const RuleBasedNumberFormat*)fmt)->getRules();
734 }
735 return pat.extract(result, resultLength, *status);
b75a7d8f
A
736}
737
738U_CAPI int32_t U_EXPORT2
374ca955 739unum_getSymbol(const UNumberFormat *fmt,
b75a7d8f
A
740 UNumberFormatSymbol symbol,
741 UChar *buffer,
742 int32_t size,
374ca955
A
743 UErrorCode *status)
744{
745 if(status==NULL || U_FAILURE(*status)) {
746 return 0;
747 }
748
749 if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
750 *status=U_ILLEGAL_ARGUMENT_ERROR;
751 return 0;
752 }
b75a7d8f 753
374ca955
A
754 if (((const NumberFormat*)fmt)->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
755 *status = U_UNSUPPORTED_ERROR;
756 return 0;
757 }
b75a7d8f 758
374ca955 759 return ((const DecimalFormat *)fmt)->
b75a7d8f
A
760 getDecimalFormatSymbols()->
761 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
762 extract(buffer, size, *status);
763}
764
765U_CAPI void U_EXPORT2
766unum_setSymbol(UNumberFormat *fmt,
767 UNumberFormatSymbol symbol,
768 const UChar *value,
769 int32_t length,
374ca955 770 UErrorCode *status)
b75a7d8f 771{
374ca955
A
772 if(status==NULL || U_FAILURE(*status)) {
773 return;
774 }
775
776 if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
777 *status=U_ILLEGAL_ARGUMENT_ERROR;
778 return;
779 }
780
781 if (((NumberFormat*)fmt)->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
782 *status = U_UNSUPPORTED_ERROR;
783 return;
784 }
785
786 DecimalFormatSymbols symbols(*((DecimalFormat *)fmt)->getDecimalFormatSymbols());
787 symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
788 UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */
789 ((DecimalFormat *)fmt)->setDecimalFormatSymbols(symbols);
b75a7d8f 790}
b75a7d8f
A
791
792U_CAPI void U_EXPORT2
793unum_applyPattern( UNumberFormat *format,
794 UBool localized,
795 const UChar *pattern,
796 int32_t patternLength,
797 UParseError *parseError,
798 UErrorCode* status)
799{
374ca955
A
800 UErrorCode tStatus = U_ZERO_ERROR;
801 UParseError tParseError;
802
803 if(parseError == NULL){
804 parseError = &tParseError;
805 }
806
807 if(status==NULL){
808 status = &tStatus;
809 }
810
811 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
812 const UnicodeString pat((UChar*)pattern, len, len);
813
814 // Verify if the object passed is a DecimalFormat object
815 if (((NumberFormat*)format)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
816 if(localized) {
817 ((DecimalFormat*)format)->applyLocalizedPattern(pat,*parseError, *status);
818 } else {
819 ((DecimalFormat*)format)->applyPattern(pat,*parseError, *status);
820 }
821 } else {
822 *status = U_UNSUPPORTED_ERROR;
b75a7d8f 823 return;
374ca955
A
824 }
825}
826
827U_CAPI const char* U_EXPORT2
828unum_getLocaleByType(const UNumberFormat *fmt,
829 ULocDataLocaleType type,
830 UErrorCode* status)
831{
832 if (fmt == NULL) {
833 if (U_SUCCESS(*status)) {
834 *status = U_ILLEGAL_ARGUMENT_ERROR;
835 }
836 return NULL;
837 }
838 return ((const Format*)fmt)->getLocaleID(type, *status);
b75a7d8f
A
839}
840
841#endif /* #if !UCONFIG_NO_FORMATTING */