1 /*
2 *******************************************************************************
3 * Copyright (C) 1996-2012, 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 "unicode/localpointer.h"
28 #include "uassert.h"
29 #include "cpputils.h"
30 #include "cstring.h"
31
32
33 U_NAMESPACE_USE
34
35
36 U_CAPI UNumberFormat* U_EXPORT2
unum_open(UNumberFormatStyle style,const UChar * pattern,int32_t patternLength,const char * locale,UParseError * parseErr,UErrorCode * status)37 unum_open( UNumberFormatStyle style,
38 const UChar* pattern,
39 int32_t patternLength,
40 const char* locale,
41 UParseError* parseErr,
42 UErrorCode* status) {
43 if(U_FAILURE(*status)) {
44 return NULL;
45 }
46
47 NumberFormat *retVal = NULL;
48
49 switch(style) {
50 case UNUM_DECIMAL:
51 case UNUM_CURRENCY:
52 case UNUM_PERCENT:
53 case UNUM_SCIENTIFIC:
54 retVal = NumberFormat::createInstance(Locale(locale), style, *status);
55 break;
56
57 case UNUM_PATTERN_DECIMAL: {
58 UParseError tErr;
59 /* UnicodeString can handle the case when patternLength = -1. */
60 const UnicodeString pat(pattern, patternLength);
61
62 if(parseErr==NULL){
63 parseErr = &tErr;
64 }
65
66 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
67 if(syms == NULL) {
68 *status = U_MEMORY_ALLOCATION_ERROR;
69 return NULL;
70 }
71 if (U_FAILURE(*status)) {
72 delete syms;
73 return NULL;
74 }
75
76 retVal = new DecimalFormat(pat, syms, *parseErr, *status);
77 if(retVal == NULL) {
78 delete syms;
79 }
80 } break;
81
82 #if U_HAVE_RBNF
83 case UNUM_PATTERN_RULEBASED: {
84 UParseError tErr;
85 /* UnicodeString can handle the case when patternLength = -1. */
86 const UnicodeString pat(pattern, patternLength);
87
88 if(parseErr==NULL){
89 parseErr = &tErr;
90 }
91
92 retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
93 } break;
94
95 case UNUM_SPELLOUT:
96 retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
97 break;
98
99 case UNUM_ORDINAL:
100 retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
101 break;
102
103 case UNUM_DURATION:
104 retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
105 break;
106
107 case UNUM_NUMBERING_SYSTEM:
108 retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
109 break;
110 #endif
111
112 default:
113 *status = U_UNSUPPORTED_ERROR;
114 return NULL;
115 }
116
117 if(retVal == NULL && U_SUCCESS(*status)) {
118 *status = U_MEMORY_ALLOCATION_ERROR;
119 }
120
121 return reinterpret_cast<UNumberFormat *>(retVal);
122 }
123
124 U_CAPI void U_EXPORT2
unum_close(UNumberFormat * fmt)125 unum_close(UNumberFormat* fmt)
126 {
127 delete (NumberFormat*) fmt;
128 }
129
130 U_CAPI UNumberFormat* U_EXPORT2
unum_clone(const UNumberFormat * fmt,UErrorCode * status)131 unum_clone(const UNumberFormat *fmt,
132 UErrorCode *status)
133 {
134 if(U_FAILURE(*status))
135 return 0;
136
137 Format *res = 0;
138 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
139 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
140 if (df != NULL) {
141 res = df->clone();
142 } else {
143 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
144 U_ASSERT(rbnf != NULL);
145 res = rbnf->clone();
146 }
147
148 if(res == 0) {
149 *status = U_MEMORY_ALLOCATION_ERROR;
150 return 0;
151 }
152
153 return (UNumberFormat*) res;
154 }
155
156 U_CAPI int32_t U_EXPORT2
unum_format(const UNumberFormat * fmt,int32_t number,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)157 unum_format( const UNumberFormat* fmt,
158 int32_t number,
159 UChar* result,
160 int32_t resultLength,
161 UFieldPosition *pos,
162 UErrorCode* status)
163 {
164 return unum_formatInt64(fmt, number, result, resultLength, pos, status);
165 }
166
167 U_CAPI int32_t U_EXPORT2
unum_formatInt64(const UNumberFormat * fmt,int64_t number,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)168 unum_formatInt64(const UNumberFormat* fmt,
169 int64_t number,
170 UChar* result,
171 int32_t resultLength,
172 UFieldPosition *pos,
173 UErrorCode* status)
174 {
175 if(U_FAILURE(*status))
176 return -1;
177
178 UnicodeString res;
179 if(!(result==NULL && resultLength==0)) {
180 // NULL destination for pure preflighting: empty dummy string
181 // otherwise, alias the destination buffer
182 res.setTo(result, 0, resultLength);
183 }
184
185 FieldPosition fp;
186
187 if(pos != 0)
188 fp.setField(pos->field);
189
190 ((const NumberFormat*)fmt)->format(number, res, fp, *status);
191
192 if(pos != 0) {
193 pos->beginIndex = fp.getBeginIndex();
194 pos->endIndex = fp.getEndIndex();
195 }
196
197 return res.extract(result, resultLength, *status);
198 }
199
200 U_CAPI int32_t U_EXPORT2
unum_formatDouble(const UNumberFormat * fmt,double number,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)201 unum_formatDouble( const UNumberFormat* fmt,
202 double number,
203 UChar* result,
204 int32_t resultLength,
205 UFieldPosition *pos, /* 0 if ignore */
206 UErrorCode* status)
207 {
208
209 if(U_FAILURE(*status)) return -1;
210
211 UnicodeString res;
212 if(!(result==NULL && resultLength==0)) {
213 // NULL destination for pure preflighting: empty dummy string
214 // otherwise, alias the destination buffer
215 res.setTo(result, 0, resultLength);
216 }
217
218 FieldPosition fp;
219
220 if(pos != 0)
221 fp.setField(pos->field);
222
223 ((const NumberFormat*)fmt)->format(number, res, fp, *status);
224
225 if(pos != 0) {
226 pos->beginIndex = fp.getBeginIndex();
227 pos->endIndex = fp.getEndIndex();
228 }
229
230 return res.extract(result, resultLength, *status);
231 }
232
233
234 U_CAPI int32_t U_EXPORT2
unum_formatDecimal(const UNumberFormat * fmt,const char * number,int32_t length,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)235 unum_formatDecimal(const UNumberFormat* fmt,
236 const char * number,
237 int32_t length,
238 UChar* result,
239 int32_t resultLength,
240 UFieldPosition *pos, /* 0 if ignore */
241 UErrorCode* status) {
242
243 if(U_FAILURE(*status)) {
244 return -1;
245 }
246 if ((result == NULL && resultLength != 0) || resultLength < 0) {
247 *status = U_ILLEGAL_ARGUMENT_ERROR;
248 return -1;
249 }
250
251 FieldPosition fp;
252 if(pos != 0) {
253 fp.setField(pos->field);
254 }
255
256 if (length < 0) {
257 length = uprv_strlen(number);
258 }
259 StringPiece numSP(number, length);
260 Formattable numFmtbl(numSP, *status);
261
262 UnicodeString resultStr;
263 if (resultLength > 0) {
264 // Alias the destination buffer.
265 resultStr.setTo(result, 0, resultLength);
266 }
267 ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status);
268 if(pos != 0) {
269 pos->beginIndex = fp.getBeginIndex();
270 pos->endIndex = fp.getEndIndex();
271 }
272 return resultStr.extract(result, resultLength, *status);
273 }
274
275
276
277
278 U_CAPI int32_t U_EXPORT2
unum_formatDoubleCurrency(const UNumberFormat * fmt,double number,UChar * currency,UChar * result,int32_t resultLength,UFieldPosition * pos,UErrorCode * status)279 unum_formatDoubleCurrency(const UNumberFormat* fmt,
280 double number,
281 UChar* currency,
282 UChar* result,
283 int32_t resultLength,
284 UFieldPosition* pos, /* ignored if 0 */
285 UErrorCode* status) {
286 if (U_FAILURE(*status)) return -1;
287
288 UnicodeString res;
289 if (!(result==NULL && resultLength==0)) {
290 // NULL destination for pure preflighting: empty dummy string
291 // otherwise, alias the destination buffer
292 res.setTo(result, 0, resultLength);
293 }
294
295 FieldPosition fp;
296 if (pos != 0) {
297 fp.setField(pos->field);
298 }
299 CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status);
300 // Check for null pointer.
301 if (tempCurrAmnt == NULL) {
302 *status = U_MEMORY_ALLOCATION_ERROR;
303 return -1;
304 }
305 Formattable n(tempCurrAmnt);
306 ((const NumberFormat*)fmt)->format(n, res, fp, *status);
307
308 if (pos != 0) {
309 pos->beginIndex = fp.getBeginIndex();
310 pos->endIndex = fp.getEndIndex();
311 }
312
313 return res.extract(result, resultLength, *status);
314 }
315
316 static void
parseRes(Formattable & res,const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)317 parseRes(Formattable& res,
318 const UNumberFormat* fmt,
319 const UChar* text,
320 int32_t textLength,
321 int32_t *parsePos /* 0 = start */,
322 UErrorCode *status)
323 {
324 if(U_FAILURE(*status))
325 return;
326
327 const UnicodeString src((UBool)(textLength == -1), text, textLength);
328 ParsePosition pp;
329
330 if(parsePos != 0)
331 pp.setIndex(*parsePos);
332
333 ((const NumberFormat*)fmt)->parse(src, res, pp);
334
335 if(pp.getErrorIndex() != -1) {
336 *status = U_PARSE_ERROR;
337 if(parsePos != 0) {
338 *parsePos = pp.getErrorIndex();
339 }
340 } else if(parsePos != 0) {
341 *parsePos = pp.getIndex();
342 }
343 }
344
345 U_CAPI int32_t U_EXPORT2
unum_parse(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)346 unum_parse( 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, status);
354 return res.getLong(*status);
355 }
356
357 U_CAPI int64_t U_EXPORT2
unum_parseInt64(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)358 unum_parseInt64( const UNumberFormat* fmt,
359 const UChar* text,
360 int32_t textLength,
361 int32_t *parsePos /* 0 = start */,
362 UErrorCode *status)
363 {
364 Formattable res;
365 parseRes(res, fmt, text, textLength, parsePos, status);
366 return res.getInt64(*status);
367 }
368
369 U_CAPI double U_EXPORT2
unum_parseDouble(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)370 unum_parseDouble( const UNumberFormat* fmt,
371 const UChar* text,
372 int32_t textLength,
373 int32_t *parsePos /* 0 = start */,
374 UErrorCode *status)
375 {
376 Formattable res;
377 parseRes(res, fmt, text, textLength, parsePos, status);
378 return res.getDouble(*status);
379 }
380
381 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)382 unum_parseDecimal(const UNumberFormat* fmt,
383 const UChar* text,
384 int32_t textLength,
385 int32_t *parsePos /* 0 = start */,
386 char *outBuf,
387 int32_t outBufLength,
388 UErrorCode *status)
389 {
390 if (U_FAILURE(*status)) {
391 return -1;
392 }
393 if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) {
394 *status = U_ILLEGAL_ARGUMENT_ERROR;
395 return -1;
396 }
397 Formattable res;
398 parseRes(res, fmt, text, textLength, parsePos, status);
399 StringPiece sp = res.getDecimalNumber(*status);
400 if (U_FAILURE(*status)) {
401 return -1;
402 } else if (sp.size() > outBufLength) {
403 *status = U_BUFFER_OVERFLOW_ERROR;
404 } else if (sp.size() == outBufLength) {
405 uprv_strncpy(outBuf, sp.data(), sp.size());
406 *status = U_STRING_NOT_TERMINATED_WARNING;
407 } else {
408 U_ASSERT(outBufLength > 0);
409 uprv_strcpy(outBuf, sp.data());
410 }
411 return sp.size();
412 }
413
414 U_CAPI double U_EXPORT2
unum_parseDoubleCurrency(const UNumberFormat * fmt,const UChar * text,int32_t textLength,int32_t * parsePos,UChar * currency,UErrorCode * status)415 unum_parseDoubleCurrency(const UNumberFormat* fmt,
416 const UChar* text,
417 int32_t textLength,
418 int32_t* parsePos, /* 0 = start */
419 UChar* currency,
420 UErrorCode* status) {
421 double doubleVal = 0.0;
422 currency[0] = 0;
423 if (U_FAILURE(*status)) {
424 return doubleVal;
425 }
426 const UnicodeString src((UBool)(textLength == -1), text, textLength);
427 ParsePosition pp;
428 if (parsePos != NULL) {
429 pp.setIndex(*parsePos);
430 }
431 *status = U_PARSE_ERROR; // assume failure, reset if succeed
432 LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp));
433 if (pp.getErrorIndex() != -1) {
434 if (parsePos != NULL) {
435 *parsePos = pp.getErrorIndex();
436 }
437 } else {
438 if (parsePos != NULL) {
439 *parsePos = pp.getIndex();
440 }
441 if (pp.getIndex() > 0) {
442 *status = U_ZERO_ERROR;
443 u_strcpy(currency, currAmt->getISOCurrency());
444 doubleVal = currAmt->getNumber().getDouble(*status);
445 }
446 }
447 return doubleVal;
448 }
449
450 U_CAPI const char* U_EXPORT2
unum_getAvailable(int32_t index)451 unum_getAvailable(int32_t index)
452 {
453 return uloc_getAvailable(index);
454 }
455
456 U_CAPI int32_t U_EXPORT2
unum_countAvailable()457 unum_countAvailable()
458 {
459 return uloc_countAvailable();
460 }
461
462 U_CAPI int32_t U_EXPORT2
unum_getAttribute(const UNumberFormat * fmt,UNumberFormatAttribute attr)463 unum_getAttribute(const UNumberFormat* fmt,
464 UNumberFormatAttribute attr)
465 {
466 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
467 if ( attr == UNUM_LENIENT_PARSE ) {
468 // Supported for all subclasses
469 return nf->isLenient();
470 }
471
472 // The remaining attributea are only supported for DecimalFormat
473 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
474 if (df != NULL) {
475 UErrorCode ignoredStatus = U_ZERO_ERROR;
476 return df->getAttribute( attr, ignoredStatus );
477 }
478
479 return -1;
480 }
481
482 U_CAPI void U_EXPORT2
unum_setAttribute(UNumberFormat * fmt,UNumberFormatAttribute attr,int32_t newValue)483 unum_setAttribute( UNumberFormat* fmt,
484 UNumberFormatAttribute attr,
485 int32_t newValue)
486 {
487 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
488 if ( attr == UNUM_LENIENT_PARSE ) {
489 // Supported for all subclasses
490 // keep this here as the class may not be a DecimalFormat
491 return nf->setLenient(newValue != 0);
492 }
493 // The remaining attributea are only supported for DecimalFormat
494 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
495 if (df != NULL) {
496 UErrorCode ignoredStatus = U_ZERO_ERROR;
497 df->setAttribute(attr, newValue, ignoredStatus);
498 }
499 }
500
501 U_CAPI double U_EXPORT2
unum_getDoubleAttribute(const UNumberFormat * fmt,UNumberFormatAttribute attr)502 unum_getDoubleAttribute(const UNumberFormat* fmt,
503 UNumberFormatAttribute attr)
504 {
505 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
506 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
507 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
508 return df->getRoundingIncrement();
509 } else {
510 return -1.0;
511 }
512 }
513
514 U_CAPI void U_EXPORT2
unum_setDoubleAttribute(UNumberFormat * fmt,UNumberFormatAttribute attr,double newValue)515 unum_setDoubleAttribute( UNumberFormat* fmt,
516 UNumberFormatAttribute attr,
517 double newValue)
518 {
519 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
520 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
521 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
522 df->setRoundingIncrement(newValue);
523 }
524 }
525
526 U_CAPI int32_t U_EXPORT2
unum_getTextAttribute(const UNumberFormat * fmt,UNumberFormatTextAttribute tag,UChar * result,int32_t resultLength,UErrorCode * status)527 unum_getTextAttribute(const UNumberFormat* fmt,
528 UNumberFormatTextAttribute tag,
529 UChar* result,
530 int32_t resultLength,
531 UErrorCode* status)
532 {
533 if(U_FAILURE(*status))
534 return -1;
535
536 UnicodeString res;
537 if(!(result==NULL && resultLength==0)) {
538 // NULL destination for pure preflighting: empty dummy string
539 // otherwise, alias the destination buffer
540 res.setTo(result, 0, resultLength);
541 }
542
543 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
544 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
545 if (df != NULL) {
546 switch(tag) {
547 case UNUM_POSITIVE_PREFIX:
548 df->getPositivePrefix(res);
549 break;
550
551 case UNUM_POSITIVE_SUFFIX:
552 df->getPositiveSuffix(res);
553 break;
554
555 case UNUM_NEGATIVE_PREFIX:
556 df->getNegativePrefix(res);
557 break;
558
559 case UNUM_NEGATIVE_SUFFIX:
560 df->getNegativeSuffix(res);
561 break;
562
563 case UNUM_PADDING_CHARACTER:
564 res = df->getPadCharacterString();
565 break;
566
567 case UNUM_CURRENCY_CODE:
568 res = UnicodeString(df->getCurrency());
569 break;
570
571 default:
572 *status = U_UNSUPPORTED_ERROR;
573 return -1;
574 }
575 } else {
576 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
577 U_ASSERT(rbnf != NULL);
578 if (tag == UNUM_DEFAULT_RULESET) {
579 res = rbnf->getDefaultRuleSetName();
580 } else if (tag == UNUM_PUBLIC_RULESETS) {
581 int32_t count = rbnf->getNumberOfRuleSetNames();
582 for (int i = 0; i < count; ++i) {
583 res += rbnf->getRuleSetName(i);
584 res += (UChar)0x003b; // semicolon
585 }
586 } else {
587 *status = U_UNSUPPORTED_ERROR;
588 return -1;
589 }
590 }
591
592 return res.extract(result, resultLength, *status);
593 }
594
595 U_CAPI void U_EXPORT2
unum_setTextAttribute(UNumberFormat * fmt,UNumberFormatTextAttribute tag,const UChar * newValue,int32_t newValueLength,UErrorCode * status)596 unum_setTextAttribute( UNumberFormat* fmt,
597 UNumberFormatTextAttribute tag,
598 const UChar* newValue,
599 int32_t newValueLength,
600 UErrorCode *status)
601 {
602 if(U_FAILURE(*status))
603 return;
604
605 UnicodeString val(newValue, newValueLength);
606 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
607 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
608 if (df != NULL) {
609 switch(tag) {
610 case UNUM_POSITIVE_PREFIX:
611 df->setPositivePrefix(val);
612 break;
613
614 case UNUM_POSITIVE_SUFFIX:
615 df->setPositiveSuffix(val);
616 break;
617
618 case UNUM_NEGATIVE_PREFIX:
619 df->setNegativePrefix(val);
620 break;
621
622 case UNUM_NEGATIVE_SUFFIX:
623 df->setNegativeSuffix(val);
624 break;
625
626 case UNUM_PADDING_CHARACTER:
627 df->setPadCharacter(val);
628 break;
629
630 case UNUM_CURRENCY_CODE:
631 df->setCurrency(val.getTerminatedBuffer(), *status);
632 break;
633
634 default:
635 *status = U_UNSUPPORTED_ERROR;
636 break;
637 }
638 } else {
639 RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
640 U_ASSERT(rbnf != NULL);
641 if (tag == UNUM_DEFAULT_RULESET) {
642 rbnf->setDefaultRuleSet(val, *status);
643 } else {
644 *status = U_UNSUPPORTED_ERROR;
645 }
646 }
647 }
648
649 U_CAPI int32_t U_EXPORT2
unum_toPattern(const UNumberFormat * fmt,UBool isPatternLocalized,UChar * result,int32_t resultLength,UErrorCode * status)650 unum_toPattern( const UNumberFormat* fmt,
651 UBool isPatternLocalized,
652 UChar* result,
653 int32_t resultLength,
654 UErrorCode* status)
655 {
656 if(U_FAILURE(*status))
657 return -1;
658
659 UnicodeString pat;
660 if(!(result==NULL && resultLength==0)) {
661 // NULL destination for pure preflighting: empty dummy string
662 // otherwise, alias the destination buffer
663 pat.setTo(result, 0, resultLength);
664 }
665
666 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
667 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
668 if (df != NULL) {
669 if(isPatternLocalized)
670 df->toLocalizedPattern(pat);
671 else
672 df->toPattern(pat);
673 } else {
674 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
675 U_ASSERT(rbnf != NULL);
676 pat = rbnf->getRules();
677 }
678 return pat.extract(result, resultLength, *status);
679 }
680
681 U_CAPI int32_t U_EXPORT2
unum_getSymbol(const UNumberFormat * fmt,UNumberFormatSymbol symbol,UChar * buffer,int32_t size,UErrorCode * status)682 unum_getSymbol(const UNumberFormat *fmt,
683 UNumberFormatSymbol symbol,
684 UChar *buffer,
685 int32_t size,
686 UErrorCode *status)
687 {
688 if(status==NULL || U_FAILURE(*status)) {
689 return 0;
690 }
691 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
692 *status=U_ILLEGAL_ARGUMENT_ERROR;
693 return 0;
694 }
695 const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt);
696 const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf);
697 if (dcf == NULL) {
698 *status = U_UNSUPPORTED_ERROR;
699 return 0;
700 }
701
702 return dcf->
703 getDecimalFormatSymbols()->
704 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
705 extract(buffer, size, *status);
706 }
707
708 U_CAPI void U_EXPORT2
unum_setSymbol(UNumberFormat * fmt,UNumberFormatSymbol symbol,const UChar * value,int32_t length,UErrorCode * status)709 unum_setSymbol(UNumberFormat *fmt,
710 UNumberFormatSymbol symbol,
711 const UChar *value,
712 int32_t length,
713 UErrorCode *status)
714 {
715 if(status==NULL || U_FAILURE(*status)) {
716 return;
717 }
718 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
719 *status=U_ILLEGAL_ARGUMENT_ERROR;
720 return;
721 }
722 NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt);
723 DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf);
724 if (dcf == NULL) {
725 *status = U_UNSUPPORTED_ERROR;
726 return;
727 }
728
729 DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols());
730 symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
731 UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */
732 dcf->setDecimalFormatSymbols(symbols);
733 }
734
735 U_CAPI void U_EXPORT2
unum_applyPattern(UNumberFormat * fmt,UBool localized,const UChar * pattern,int32_t patternLength,UParseError * parseError,UErrorCode * status)736 unum_applyPattern( UNumberFormat *fmt,
737 UBool localized,
738 const UChar *pattern,
739 int32_t patternLength,
740 UParseError *parseError,
741 UErrorCode* status)
742 {
743 UErrorCode tStatus = U_ZERO_ERROR;
744 UParseError tParseError;
745
746 if(parseError == NULL){
747 parseError = &tParseError;
748 }
749
750 if(status==NULL){
751 status = &tStatus;
752 }
753
754 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
755 const UnicodeString pat((UChar*)pattern, len, len);
756
757 // Verify if the object passed is a DecimalFormat object
758 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
759 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
760 if (df != NULL) {
761 if(localized) {
762 df->applyLocalizedPattern(pat,*parseError, *status);
763 } else {
764 df->applyPattern(pat,*parseError, *status);
765 }
766 } else {
767 *status = U_UNSUPPORTED_ERROR;
768 return;
769 }
770 }
771
772 U_CAPI const char* U_EXPORT2
unum_getLocaleByType(const UNumberFormat * fmt,ULocDataLocaleType type,UErrorCode * status)773 unum_getLocaleByType(const UNumberFormat *fmt,
774 ULocDataLocaleType type,
775 UErrorCode* status)
776 {
777 if (fmt == NULL) {
778 if (U_SUCCESS(*status)) {
779 *status = U_ILLEGAL_ARGUMENT_ERROR;
780 }
781 return NULL;
782 }
783 return ((const Format*)fmt)->getLocaleID(type, *status);
784 }
785
786 #endif /* #if !UCONFIG_NO_FORMATTING */
787