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