1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1996-2015, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * Modification History:
10 * Date Name Description
11 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
12 *******************************************************************************
15 #include "unicode/utypes.h"
17 #if !UCONFIG_NO_FORMATTING
19 #include "unicode/unum.h"
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"
40 U_CAPI UNumberFormat
* U_EXPORT2
41 unum_open( UNumberFormatStyle style
,
43 int32_t patternLength
,
45 UParseError
* parseErr
,
47 if(U_FAILURE(*status
)) {
51 NumberFormat
*retVal
= NULL
;
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
);
66 case UNUM_PATTERN_DECIMAL
: {
68 /* UnicodeString can handle the case when patternLength = -1. */
69 const UnicodeString
pat(pattern
, patternLength
);
75 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale(locale
), *status
);
77 *status
= U_MEMORY_ALLOCATION_ERROR
;
80 if (U_FAILURE(*status
)) {
85 retVal
= new DecimalFormat(pat
, syms
, *parseErr
, *status
);
92 case UNUM_PATTERN_RULEBASED
: {
94 /* UnicodeString can handle the case when patternLength = -1. */
95 const UnicodeString
pat(pattern
, patternLength
);
101 retVal
= new RuleBasedNumberFormat(pat
, Locale(locale
), *parseErr
, *status
);
105 retVal
= new RuleBasedNumberFormat(URBNF_SPELLOUT
, Locale(locale
), *status
);
109 retVal
= new RuleBasedNumberFormat(URBNF_ORDINAL
, Locale(locale
), *status
);
113 retVal
= new RuleBasedNumberFormat(URBNF_DURATION
, Locale(locale
), *status
);
116 case UNUM_NUMBERING_SYSTEM
:
117 retVal
= new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM
, Locale(locale
), *status
);
121 case UNUM_DECIMAL_COMPACT_SHORT
:
122 retVal
= CompactDecimalFormat::createInstance(Locale(locale
), UNUM_SHORT
, *status
);
125 case UNUM_DECIMAL_COMPACT_LONG
:
126 retVal
= CompactDecimalFormat::createInstance(Locale(locale
), UNUM_LONG
, *status
);
130 *status
= U_UNSUPPORTED_ERROR
;
134 if(retVal
== NULL
&& U_SUCCESS(*status
)) {
135 *status
= U_MEMORY_ALLOCATION_ERROR
;
138 return reinterpret_cast<UNumberFormat
*>(retVal
);
141 U_CAPI
void U_EXPORT2
142 unum_close(UNumberFormat
* fmt
)
144 delete (NumberFormat
*) fmt
;
147 U_CAPI UNumberFormat
* U_EXPORT2
148 unum_clone(const UNumberFormat
*fmt
,
151 if(U_FAILURE(*status
))
155 const NumberFormat
* nf
= reinterpret_cast<const NumberFormat
*>(fmt
);
156 const DecimalFormat
* df
= dynamic_cast<const DecimalFormat
*>(nf
);
160 const RuleBasedNumberFormat
* rbnf
= dynamic_cast<const RuleBasedNumberFormat
*>(nf
);
161 U_ASSERT(rbnf
!= NULL
);
166 *status
= U_MEMORY_ALLOCATION_ERROR
;
170 return (UNumberFormat
*) res
;
173 U_CAPI
int32_t U_EXPORT2
174 unum_format( const UNumberFormat
* fmt
,
177 int32_t resultLength
,
181 return unum_formatInt64(fmt
, number
, result
, resultLength
, pos
, status
);
184 U_CAPI
int32_t U_EXPORT2
185 unum_formatInt64(const UNumberFormat
* fmt
,
188 int32_t resultLength
,
192 if(U_FAILURE(*status
))
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
);
205 fp
.setField(pos
->field
);
207 const CompactDecimalFormat
* cdf
= dynamic_cast<const CompactDecimalFormat
*>((const NumberFormat
*)fmt
);
209 cdf
->format(number
, res
, fp
); // CompactDecimalFormat does not override the version with UErrorCode& !!
211 ((const NumberFormat
*)fmt
)->format(number
, res
, fp
, *status
);
215 pos
->beginIndex
= fp
.getBeginIndex();
216 pos
->endIndex
= fp
.getEndIndex();
219 return res
.extract(result
, resultLength
, *status
);
222 U_CAPI
int32_t U_EXPORT2
223 unum_formatDouble( const UNumberFormat
* fmt
,
226 int32_t resultLength
,
227 UFieldPosition
*pos
, /* 0 if ignore */
231 if(U_FAILURE(*status
)) return -1;
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
);
243 fp
.setField(pos
->field
);
245 const CompactDecimalFormat
* cdf
= dynamic_cast<const CompactDecimalFormat
*>((const NumberFormat
*)fmt
);
247 cdf
->format(number
, res
, fp
); // CompactDecimalFormat does not override the version with UErrorCode& !!
249 ((const NumberFormat
*)fmt
)->format(number
, res
, fp
, *status
);
253 pos
->beginIndex
= fp
.getBeginIndex();
254 pos
->endIndex
= fp
.getEndIndex();
257 return res
.extract(result
, resultLength
, *status
);
260 U_CAPI
int32_t U_EXPORT2
261 unum_formatDoubleForFields(const UNumberFormat
* format
,
264 int32_t resultLength
,
265 UFieldPositionIterator
* fpositer
,
268 if (U_FAILURE(*status
))
271 if (result
== NULL
? resultLength
!= 0 : resultLength
< 0) {
272 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
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
);
283 ((const NumberFormat
*)format
)->format(number
, res
, (FieldPositionIterator
*)fpositer
, *status
);
285 return res
.extract(result
, resultLength
, *status
);
288 U_CAPI
int32_t U_EXPORT2
289 unum_formatDecimal(const UNumberFormat
* fmt
,
293 int32_t resultLength
,
294 UFieldPosition
*pos
, /* 0 if ignore */
295 UErrorCode
* status
) {
297 if(U_FAILURE(*status
)) {
300 if ((result
== NULL
&& resultLength
!= 0) || resultLength
< 0) {
301 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
307 fp
.setField(pos
->field
);
311 length
= uprv_strlen(number
);
313 StringPiece
numSP(number
, length
);
314 Formattable
numFmtbl(numSP
, *status
);
316 UnicodeString resultStr
;
317 if (resultLength
> 0) {
318 // Alias the destination buffer.
319 resultStr
.setTo(result
, 0, resultLength
);
321 ((const NumberFormat
*)fmt
)->format(numFmtbl
, resultStr
, fp
, *status
);
323 pos
->beginIndex
= fp
.getBeginIndex();
324 pos
->endIndex
= fp
.getEndIndex();
326 return resultStr
.extract(result
, resultLength
, *status
);
332 U_CAPI
int32_t U_EXPORT2
333 unum_formatDoubleCurrency(const UNumberFormat
* fmt
,
337 int32_t resultLength
,
338 UFieldPosition
* pos
, /* ignored if 0 */
339 UErrorCode
* status
) {
340 if (U_FAILURE(*status
)) return -1;
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
);
351 fp
.setField(pos
->field
);
353 CurrencyAmount
*tempCurrAmnt
= new CurrencyAmount(number
, currency
, *status
);
354 // Check for null pointer.
355 if (tempCurrAmnt
== NULL
) {
356 *status
= U_MEMORY_ALLOCATION_ERROR
;
359 Formattable
n(tempCurrAmnt
);
360 ((const NumberFormat
*)fmt
)->format(n
, res
, fp
, *status
);
363 pos
->beginIndex
= fp
.getBeginIndex();
364 pos
->endIndex
= fp
.getEndIndex();
367 return res
.extract(result
, resultLength
, *status
);
371 parseRes(Formattable
& res
,
372 const UNumberFormat
* fmt
,
375 int32_t *parsePos
/* 0 = start */,
378 if(U_FAILURE(*status
))
381 const UnicodeString
src((UBool
)(textLength
== -1), text
, textLength
);
385 pp
.setIndex(*parsePos
);
387 ((const NumberFormat
*)fmt
)->parse(src
, res
, pp
);
389 if(pp
.getErrorIndex() != -1) {
390 *status
= U_PARSE_ERROR
;
392 *parsePos
= pp
.getErrorIndex();
394 } else if(parsePos
!= 0) {
395 *parsePos
= pp
.getIndex();
399 U_CAPI
int32_t U_EXPORT2
400 unum_parse( const UNumberFormat
* fmt
,
403 int32_t *parsePos
/* 0 = start */,
407 parseRes(res
, fmt
, text
, textLength
, parsePos
, status
);
408 return res
.getLong(*status
);
411 U_CAPI
int64_t U_EXPORT2
412 unum_parseInt64( const UNumberFormat
* fmt
,
415 int32_t *parsePos
/* 0 = start */,
419 parseRes(res
, fmt
, text
, textLength
, parsePos
, status
);
420 return res
.getInt64(*status
);
423 U_CAPI
double U_EXPORT2
424 unum_parseDouble( const UNumberFormat
* fmt
,
427 int32_t *parsePos
/* 0 = start */,
431 parseRes(res
, fmt
, text
, textLength
, parsePos
, status
);
432 return res
.getDouble(*status
);
435 U_CAPI
int32_t U_EXPORT2
436 unum_parseDecimal(const UNumberFormat
* fmt
,
439 int32_t *parsePos
/* 0 = start */,
441 int32_t outBufLength
,
444 if (U_FAILURE(*status
)) {
447 if ((outBuf
== NULL
&& outBufLength
!= 0) || outBufLength
< 0) {
448 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
452 parseRes(res
, fmt
, text
, textLength
, parsePos
, status
);
453 StringPiece sp
= res
.getDecimalNumber(*status
);
454 if (U_FAILURE(*status
)) {
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
;
462 U_ASSERT(outBufLength
> 0);
463 uprv_strcpy(outBuf
, sp
.data());
468 U_CAPI
double U_EXPORT2
469 unum_parseDoubleCurrency(const UNumberFormat
* fmt
,
472 int32_t* parsePos
, /* 0 = start */
474 UErrorCode
* status
) {
475 double doubleVal
= 0.0;
477 if (U_FAILURE(*status
)) {
480 const UnicodeString
src((UBool
)(textLength
== -1), text
, textLength
);
482 if (parsePos
!= NULL
) {
483 pp
.setIndex(*parsePos
);
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();
492 if (parsePos
!= NULL
) {
493 *parsePos
= pp
.getIndex();
495 if (pp
.getIndex() > 0) {
496 *status
= U_ZERO_ERROR
;
497 u_strcpy(currency
, currAmt
->getISOCurrency());
498 doubleVal
= currAmt
->getNumber().getDouble(*status
);
504 U_CAPI
const char* U_EXPORT2
505 unum_getAvailable(int32_t index
)
507 return uloc_getAvailable(index
);
510 U_CAPI
int32_t U_EXPORT2
511 unum_countAvailable()
513 return uloc_countAvailable();
516 U_CAPI
int32_t U_EXPORT2
517 unum_getAttribute(const UNumberFormat
* fmt
,
518 UNumberFormatAttribute attr
)
520 const NumberFormat
* nf
= reinterpret_cast<const NumberFormat
*>(fmt
);
521 if ( attr
== UNUM_LENIENT_PARSE
) {
522 // Supported for all subclasses
523 return nf
->isLenient();
526 // The remaining attributea are only supported for DecimalFormat
527 const DecimalFormat
* df
= dynamic_cast<const DecimalFormat
*>(nf
);
529 UErrorCode ignoredStatus
= U_ZERO_ERROR
;
530 return df
->getAttribute( attr
, ignoredStatus
);
536 U_CAPI
void U_EXPORT2
537 unum_setAttribute( UNumberFormat
* fmt
,
538 UNumberFormatAttribute attr
,
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);
547 // The remaining attributea are only supported for DecimalFormat
548 DecimalFormat
* df
= dynamic_cast<DecimalFormat
*>(nf
);
550 UErrorCode ignoredStatus
= U_ZERO_ERROR
;
551 df
->setAttribute(attr
, newValue
, ignoredStatus
);
555 U_CAPI
double U_EXPORT2
556 unum_getDoubleAttribute(const UNumberFormat
* fmt
,
557 UNumberFormatAttribute attr
)
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();
568 U_CAPI
void U_EXPORT2
569 unum_setDoubleAttribute( UNumberFormat
* fmt
,
570 UNumberFormatAttribute attr
,
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
);
580 U_CAPI
int32_t U_EXPORT2
581 unum_getTextAttribute(const UNumberFormat
* fmt
,
582 UNumberFormatTextAttribute tag
,
584 int32_t resultLength
,
587 if(U_FAILURE(*status
))
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
);
597 const NumberFormat
* nf
= reinterpret_cast<const NumberFormat
*>(fmt
);
598 const DecimalFormat
* df
= dynamic_cast<const DecimalFormat
*>(nf
);
601 case UNUM_POSITIVE_PREFIX
:
602 df
->getPositivePrefix(res
);
605 case UNUM_POSITIVE_SUFFIX
:
606 df
->getPositiveSuffix(res
);
609 case UNUM_NEGATIVE_PREFIX
:
610 df
->getNegativePrefix(res
);
613 case UNUM_NEGATIVE_SUFFIX
:
614 df
->getNegativeSuffix(res
);
617 case UNUM_PADDING_CHARACTER
:
618 res
= df
->getPadCharacterString();
621 case UNUM_CURRENCY_CODE
:
622 res
= UnicodeString(df
->getCurrency());
626 *status
= U_UNSUPPORTED_ERROR
;
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
641 *status
= U_UNSUPPORTED_ERROR
;
646 return res
.extract(result
, resultLength
, *status
);
649 U_CAPI
void U_EXPORT2
650 unum_setTextAttribute( UNumberFormat
* fmt
,
651 UNumberFormatTextAttribute tag
,
652 const UChar
* newValue
,
653 int32_t newValueLength
,
656 if(U_FAILURE(*status
))
659 UnicodeString
val(newValue
, newValueLength
);
660 NumberFormat
* nf
= reinterpret_cast<NumberFormat
*>(fmt
);
661 DecimalFormat
* df
= dynamic_cast<DecimalFormat
*>(nf
);
664 case UNUM_POSITIVE_PREFIX
:
665 df
->setPositivePrefix(val
);
668 case UNUM_POSITIVE_SUFFIX
:
669 df
->setPositiveSuffix(val
);
672 case UNUM_NEGATIVE_PREFIX
:
673 df
->setNegativePrefix(val
);
676 case UNUM_NEGATIVE_SUFFIX
:
677 df
->setNegativeSuffix(val
);
680 case UNUM_PADDING_CHARACTER
:
681 df
->setPadCharacter(val
);
684 case UNUM_CURRENCY_CODE
:
685 df
->setCurrency(val
.getTerminatedBuffer(), *status
);
689 *status
= U_UNSUPPORTED_ERROR
;
693 RuleBasedNumberFormat
* rbnf
= dynamic_cast<RuleBasedNumberFormat
*>(nf
);
694 U_ASSERT(rbnf
!= NULL
);
695 if (tag
== UNUM_DEFAULT_RULESET
) {
696 rbnf
->setDefaultRuleSet(val
, *status
);
698 *status
= U_UNSUPPORTED_ERROR
;
703 U_CAPI
int32_t U_EXPORT2
704 unum_toPattern( const UNumberFormat
* fmt
,
705 UBool isPatternLocalized
,
707 int32_t resultLength
,
710 if(U_FAILURE(*status
))
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
);
720 const NumberFormat
* nf
= reinterpret_cast<const NumberFormat
*>(fmt
);
721 const DecimalFormat
* df
= dynamic_cast<const DecimalFormat
*>(nf
);
723 if(isPatternLocalized
)
724 df
->toLocalizedPattern(pat
);
728 const RuleBasedNumberFormat
* rbnf
= dynamic_cast<const RuleBasedNumberFormat
*>(nf
);
729 U_ASSERT(rbnf
!= NULL
);
730 pat
= rbnf
->getRules();
732 return pat
.extract(result
, resultLength
, *status
);
735 U_CAPI
int32_t U_EXPORT2
736 unum_getSymbol(const UNumberFormat
*fmt
,
737 UNumberFormatSymbol symbol
,
742 if(status
==NULL
|| U_FAILURE(*status
)) {
745 if(fmt
==NULL
|| symbol
< 0 || symbol
>=UNUM_FORMAT_SYMBOL_COUNT
) {
746 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
749 const NumberFormat
*nf
= reinterpret_cast<const NumberFormat
*>(fmt
);
750 const DecimalFormat
*dcf
= dynamic_cast<const DecimalFormat
*>(nf
);
752 *status
= U_UNSUPPORTED_ERROR
;
757 getDecimalFormatSymbols()->
758 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbol
).
759 extract(buffer
, size
, *status
);
762 U_CAPI
void U_EXPORT2
763 unum_setSymbol(UNumberFormat
*fmt
,
764 UNumberFormatSymbol symbol
,
769 if(status
==NULL
|| U_FAILURE(*status
)) {
772 if(fmt
==NULL
|| symbol
< 0 || symbol
>=UNUM_FORMAT_SYMBOL_COUNT
|| value
==NULL
|| length
<-1) {
773 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
776 NumberFormat
*nf
= reinterpret_cast<NumberFormat
*>(fmt
);
777 DecimalFormat
*dcf
= dynamic_cast<DecimalFormat
*>(nf
);
779 *status
= U_UNSUPPORTED_ERROR
;
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
);
789 U_CAPI
void U_EXPORT2
790 unum_applyPattern( UNumberFormat
*fmt
,
792 const UChar
*pattern
,
793 int32_t patternLength
,
794 UParseError
*parseError
,
797 UErrorCode tStatus
= U_ZERO_ERROR
;
798 UParseError tParseError
;
800 if(parseError
== NULL
){
801 parseError
= &tParseError
;
808 int32_t len
= (patternLength
== -1 ? u_strlen(pattern
) : patternLength
);
809 const UnicodeString
pat((UChar
*)pattern
, len
, len
);
811 // Verify if the object passed is a DecimalFormat object
812 NumberFormat
* nf
= reinterpret_cast<NumberFormat
*>(fmt
);
813 DecimalFormat
* df
= dynamic_cast<DecimalFormat
*>(nf
);
816 df
->applyLocalizedPattern(pat
,*parseError
, *status
);
818 df
->applyPattern(pat
,*parseError
, *status
);
821 *status
= U_UNSUPPORTED_ERROR
;
826 U_CAPI
const char* U_EXPORT2
827 unum_getLocaleByType(const UNumberFormat
*fmt
,
828 ULocDataLocaleType type
,
832 if (U_SUCCESS(*status
)) {
833 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
837 return ((const Format
*)fmt
)->getLocaleID(type
, *status
);
840 U_CAPI
void U_EXPORT2
841 unum_setContext(UNumberFormat
* fmt
, UDisplayContext value
, UErrorCode
* status
)
843 if (U_FAILURE(*status
)) {
846 ((NumberFormat
*)fmt
)->setContext(value
, *status
);
850 U_CAPI UDisplayContext U_EXPORT2
851 unum_getContext(const UNumberFormat
*fmt
, UDisplayContextType type
, UErrorCode
* status
)
853 if (U_FAILURE(*status
)) {
854 return (UDisplayContext
)0;
856 return ((const NumberFormat
*)fmt
)->getContext(type
, *status
);
859 U_INTERNAL UFormattable
* U_EXPORT2
860 unum_parseToUFormattable(const UNumberFormat
* fmt
,
861 UFormattable
*result
,
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
;
872 if (result
== NULL
) { // allocate if not allocated.
873 newFormattable
= result
= ufmt_open(status
);
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
883 U_INTERNAL
int32_t U_EXPORT2
884 unum_formatUFormattable(const UNumberFormat
* fmt
,
885 const UFormattable
*number
,
887 int32_t resultLength
,
888 UFieldPosition
*pos
, /* ignored if 0 */
889 UErrorCode
*status
) {
890 if (U_FAILURE(*status
)) {
893 if (fmt
== NULL
|| number
==NULL
||
894 (result
==NULL
? resultLength
!=0 : resultLength
<0)) {
895 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
898 UnicodeString
res(result
, 0, resultLength
);
903 fp
.setField(pos
->field
);
905 ((const NumberFormat
*)fmt
)->format(*(Formattable::fromUFormattable(number
)), res
, fp
, *status
);
908 pos
->beginIndex
= fp
.getBeginIndex();
909 pos
->endIndex
= fp
.getEndIndex();
912 return res
.extract(result
, resultLength
, *status
);
915 #endif /* #if !UCONFIG_NO_FORMATTING */