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