1 /*
2 *******************************************************************************
3 * Copyright (C) 1996-2007, 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
unum_open(UNumberFormatStyle style,const UChar * pattern,int32_t patternLength,const char * locale,UParseError * parseErr,UErrorCode * status)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
unum_close(UNumberFormat * fmt)148 unum_close(UNumberFormat* fmt)
149 {
150 delete (NumberFormat*) fmt;
151 }
152
153 U_CAPI UNumberFormat* U_EXPORT2
unum_clone(const UNumberFormat * fmt,UErrorCode * status)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
unum_format(const UNumberFormat * fmt,int32_t number,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)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
unum_formatInt64(const UNumberFormat * fmt,int64_t number,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)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
unum_formatDouble(const UNumberFormat * fmt,double number,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)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
unum_formatDoubleCurrency(const UNumberFormat * fmt,double number,UChar * currency,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)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
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
286 static void
parseRes(Formattable & res,const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UBool parseCurrency,UErrorCode * status)287 parseRes(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
321 U_CAPI int32_t U_EXPORT2
unum_parse(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)322 unum_parse( const UNumberFormat* fmt,
323 const UChar* text,
324 int32_t textLength,
325 int32_t *parsePos /* 0 = start */,
326 UErrorCode *status)
327 {
328 Formattable res;
329 parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
330 return res.getLong(*status);
331 }
332
333 U_CAPI int64_t U_EXPORT2
unum_parseInt64(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)334 unum_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);
343 }
344
345 U_CAPI double U_EXPORT2
unum_parseDouble(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)346 unum_parseDouble( const UNumberFormat* fmt,
347 const UChar* text,
348 int32_t textLength,
349 int32_t *parsePos /* 0 = start */,
350 UErrorCode *status)
351 {
352 Formattable res;
353 parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
354 return res.getDouble(*status);
355 }
356
357 U_CAPI double U_EXPORT2
unum_parseDoubleCurrency(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UChar * currency,UErrorCode * status)358 unum_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());
371 }
372 return res.getDouble(*status);
373 }
374
375 U_CAPI const char* U_EXPORT2
unum_getAvailable(int32_t index)376 unum_getAvailable(int32_t index)
377 {
378 return uloc_getAvailable(index);
379 }
380
381 U_CAPI int32_t U_EXPORT2
unum_countAvailable()382 unum_countAvailable()
383 {
384 return uloc_countAvailable();
385 }
386
387 U_CAPI int32_t U_EXPORT2
unum_getAttribute(const UNumberFormat * fmt,UNumberFormatAttribute attr)388 unum_getAttribute(const UNumberFormat* fmt,
389 UNumberFormatAttribute attr)
390 {
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 }
461 }
462
463 return -1;
464 }
465
466 U_CAPI void U_EXPORT2
unum_setAttribute(UNumberFormat * fmt,UNumberFormatAttribute attr,int32_t newValue)467 unum_setAttribute( UNumberFormat* fmt,
468 UNumberFormatAttribute attr,
469 int32_t newValue)
470 {
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 }
560 }
561 }
562
563 U_CAPI double U_EXPORT2
unum_getDoubleAttribute(const UNumberFormat * fmt,UNumberFormatAttribute attr)564 unum_getDoubleAttribute(const UNumberFormat* fmt,
565 UNumberFormatAttribute attr)
566 {
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 }
573 }
574
575 U_CAPI void U_EXPORT2
unum_setDoubleAttribute(UNumberFormat * fmt,UNumberFormatAttribute attr,double newValue)576 unum_setDoubleAttribute( UNumberFormat* fmt,
577 UNumberFormatAttribute attr,
578 double newValue)
579 {
580 if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID() &&
581 attr == UNUM_ROUNDING_INCREMENT) {
582 ((DecimalFormat*)fmt)->setRoundingIncrement(newValue);
583 }
584 }
585
586 U_CAPI int32_t U_EXPORT2
unum_getTextAttribute(const UNumberFormat * fmt,UNumberFormatTextAttribute tag,UChar * result,int32_t resultLength,UErrorCode * status)587 unum_getTextAttribute(const UNumberFormat* fmt,
588 UNumberFormatTextAttribute tag,
589 UChar* result,
590 int32_t resultLength,
591 UErrorCode* status)
592 {
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 }
602
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 }
650
651 return res.extract(result, resultLength, *status);
652 }
653
654 U_CAPI void U_EXPORT2
unum_setTextAttribute(UNumberFormat * fmt,UNumberFormatTextAttribute tag,const UChar * newValue,int32_t newValueLength,UErrorCode * status)655 unum_setTextAttribute( UNumberFormat* fmt,
656 UNumberFormatTextAttribute tag,
657 const UChar* newValue,
658 int32_t newValueLength,
659 UErrorCode *status)
660 {
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 {
703 *status = U_UNSUPPORTED_ERROR;
704 }
705 }
706 }
707
708 U_CAPI int32_t U_EXPORT2
unum_toPattern(const UNumberFormat * fmt,UBool isPatternLocalized,UChar * result,int32_t resultLength,UErrorCode * status)709 unum_toPattern( const UNumberFormat* fmt,
710 UBool isPatternLocalized,
711 UChar* result,
712 int32_t resultLength,
713 UErrorCode* status)
714 {
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 }
724
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);
736 }
737
738 U_CAPI int32_t U_EXPORT2
unum_getSymbol(const UNumberFormat * fmt,UNumberFormatSymbol symbol,UChar * buffer,int32_t size,UErrorCode * status)739 unum_getSymbol(const UNumberFormat *fmt,
740 UNumberFormatSymbol symbol,
741 UChar *buffer,
742 int32_t size,
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 }
753
754 if (((const NumberFormat*)fmt)->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
755 *status = U_UNSUPPORTED_ERROR;
756 return 0;
757 }
758
759 return ((const DecimalFormat *)fmt)->
760 getDecimalFormatSymbols()->
761 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
762 extract(buffer, size, *status);
763 }
764
765 U_CAPI void U_EXPORT2
unum_setSymbol(UNumberFormat * fmt,UNumberFormatSymbol symbol,const UChar * value,int32_t length,UErrorCode * status)766 unum_setSymbol(UNumberFormat *fmt,
767 UNumberFormatSymbol symbol,
768 const UChar *value,
769 int32_t length,
770 UErrorCode *status)
771 {
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);
790 }
791
792 U_CAPI void U_EXPORT2
unum_applyPattern(UNumberFormat * format,UBool localized,const UChar * pattern,int32_t patternLength,UParseError * parseError,UErrorCode * status)793 unum_applyPattern( UNumberFormat *format,
794 UBool localized,
795 const UChar *pattern,
796 int32_t patternLength,
797 UParseError *parseError,
798 UErrorCode* status)
799 {
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;
823 return;
824 }
825 }
826
827 U_CAPI const char* U_EXPORT2
unum_getLocaleByType(const UNumberFormat * fmt,ULocDataLocaleType type,UErrorCode * status)828 unum_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);
839 }
840
841 #endif /* #if !UCONFIG_NO_FORMATTING */
842