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