]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/i18n/unum.cpp
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
... / ...
CommitLineData
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
35U_NAMESPACE_USE
36
37
38U_CAPI UNumberFormat* U_EXPORT2
39unum_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
139U_CAPI void U_EXPORT2
140unum_close(UNumberFormat* fmt)
141{
142 delete (NumberFormat*) fmt;
143}
144
145U_CAPI UNumberFormat* U_EXPORT2
146unum_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
171U_CAPI int32_t U_EXPORT2
172unum_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
182U_CAPI int32_t U_EXPORT2
183unum_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
220U_CAPI int32_t U_EXPORT2
221unum_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
259U_CAPI int32_t U_EXPORT2
260unum_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
303U_CAPI int32_t U_EXPORT2
304unum_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
341static void
342parseRes(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
370U_CAPI int32_t U_EXPORT2
371unum_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
382U_CAPI int64_t U_EXPORT2
383unum_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
394U_CAPI double U_EXPORT2
395unum_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
406U_CAPI int32_t U_EXPORT2
407unum_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
439U_CAPI double U_EXPORT2
440unum_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
475U_CAPI const char* U_EXPORT2
476unum_getAvailable(int32_t index)
477{
478 return uloc_getAvailable(index);
479}
480
481U_CAPI int32_t U_EXPORT2
482unum_countAvailable()
483{
484 return uloc_countAvailable();
485}
486
487U_CAPI int32_t U_EXPORT2
488unum_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
507U_CAPI void U_EXPORT2
508unum_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
526U_CAPI double U_EXPORT2
527unum_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
539U_CAPI void U_EXPORT2
540unum_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
551U_CAPI int32_t U_EXPORT2
552unum_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
620U_CAPI void U_EXPORT2
621unum_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
674U_CAPI int32_t U_EXPORT2
675unum_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
706U_CAPI int32_t U_EXPORT2
707unum_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
733U_CAPI void U_EXPORT2
734unum_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
760U_CAPI void U_EXPORT2
761unum_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
797U_CAPI const char* U_EXPORT2
798unum_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
811U_CAPI void U_EXPORT2
812unum_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
821U_CAPI UDisplayContext U_EXPORT2
822unum_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
830U_INTERNAL UFormattable * U_EXPORT2
831unum_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
854U_INTERNAL int32_t U_EXPORT2
855unum_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 */