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