]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/i18n/unum.cpp
ICU-531.31.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
... / ...
CommitLineData
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
34U_NAMESPACE_USE
35
36
37U_CAPI UNumberFormat* U_EXPORT2
38unum_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
128U_CAPI void U_EXPORT2
129unum_close(UNumberFormat* fmt)
130{
131 delete (NumberFormat*) fmt;
132}
133
134U_CAPI UNumberFormat* U_EXPORT2
135unum_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
160U_CAPI int32_t U_EXPORT2
161unum_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
171U_CAPI int32_t U_EXPORT2
172unum_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
204U_CAPI int32_t U_EXPORT2
205unum_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
238U_CAPI int32_t U_EXPORT2
239unum_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
282U_CAPI int32_t U_EXPORT2
283unum_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
320static void
321parseRes(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
349U_CAPI int32_t U_EXPORT2
350unum_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
361U_CAPI int64_t U_EXPORT2
362unum_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
373U_CAPI double U_EXPORT2
374unum_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
385U_CAPI int32_t U_EXPORT2
386unum_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
418U_CAPI double U_EXPORT2
419unum_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
454U_CAPI const char* U_EXPORT2
455unum_getAvailable(int32_t index)
456{
457 return uloc_getAvailable(index);
458}
459
460U_CAPI int32_t U_EXPORT2
461unum_countAvailable()
462{
463 return uloc_countAvailable();
464}
465
466U_CAPI int32_t U_EXPORT2
467unum_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
486U_CAPI void U_EXPORT2
487unum_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
505U_CAPI double U_EXPORT2
506unum_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
518U_CAPI void U_EXPORT2
519unum_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
530U_CAPI int32_t U_EXPORT2
531unum_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
599U_CAPI void U_EXPORT2
600unum_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
653U_CAPI int32_t U_EXPORT2
654unum_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
685U_CAPI int32_t U_EXPORT2
686unum_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
712U_CAPI void U_EXPORT2
713unum_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
739U_CAPI void U_EXPORT2
740unum_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
776U_CAPI const char* U_EXPORT2
777unum_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
790U_CAPI void U_EXPORT2
791unum_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
800U_CAPI UDisplayContext U_EXPORT2
801unum_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
809U_INTERNAL UFormattable * U_EXPORT2
810unum_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
833U_INTERNAL int32_t U_EXPORT2
834unum_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 */