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