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