1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 03/25/97 clhuang Initial Implementation.
15 ********************************************************************************
18 #include "unicode/utypes.h"
20 #if !UCONFIG_NO_FORMATTING
23 #include "unicode/fmtable.h"
24 #include "unicode/ustring.h"
25 #include "unicode/measure.h"
26 #include "unicode/curramt.h"
27 #include "unicode/uformattable.h"
31 #include "decNumber.h"
33 #include "fmtableimp.h"
34 #include "number_decimalquantity.h"
36 // *****************************************************************************
38 // *****************************************************************************
42 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable
)
44 using number::impl::DecimalQuantity
;
47 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
49 // NOTE: As of 3.0, there are limitations to the UObject API. It does
50 // not (yet) support cloning, operator=, nor operator==. To
51 // work around this, I implement some simple inlines here. Later
52 // these can be modified or removed. [alan]
54 // NOTE: These inlines assume that all fObjects are in fact instances
55 // of the Measure class, which is true as of 3.0. [alan]
57 // Return TRUE if *a == *b.
58 static inline UBool
objectEquals(const UObject
* a
, const UObject
* b
) {
59 // LATER: return *a == *b;
60 return *((const Measure
*) a
) == *((const Measure
*) b
);
63 // Return a clone of *a.
64 static inline UObject
* objectClone(const UObject
* a
) {
65 // LATER: return a->clone();
66 return ((const Measure
*) a
)->clone();
69 // Return TRUE if *a is an instance of Measure.
70 static inline UBool
instanceOfMeasure(const UObject
* a
) {
71 return dynamic_cast<const Measure
*>(a
) != NULL
;
75 * Creates a new Formattable array and copies the values from the specified
77 * @param array the original array
78 * @param count the original array count
79 * @return the new Formattable array.
81 static Formattable
* createArrayCopy(const Formattable
* array
, int32_t count
) {
82 Formattable
*result
= new Formattable
[count
];
84 for (int32_t i
=0; i
<count
; ++i
)
85 result
[i
] = array
[i
]; // Don't memcpy!
90 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
93 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
95 static void setError(UErrorCode
& ec
, UErrorCode err
) {
102 // Common initialization code, shared by constructors.
103 // Put everything into a known state.
105 void Formattable::init() {
110 fDecimalQuantity
= NULL
;
114 // -------------------------------------
115 // default constructor.
116 // Creates a formattable object with a long value 0.
118 Formattable::Formattable() {
122 // -------------------------------------
123 // Creates a formattable object with a Date instance.
125 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
132 // -------------------------------------
133 // Creates a formattable object with a double value.
135 Formattable::Formattable(double value
)
139 fValue
.fDouble
= value
;
142 // -------------------------------------
143 // Creates a formattable object with an int32_t value.
145 Formattable::Formattable(int32_t value
)
148 fValue
.fInt64
= value
;
151 // -------------------------------------
152 // Creates a formattable object with an int64_t value.
154 Formattable::Formattable(int64_t value
)
158 fValue
.fInt64
= value
;
161 // -------------------------------------
162 // Creates a formattable object with a decimal number value from a string.
164 Formattable::Formattable(StringPiece number
, UErrorCode
&status
) {
166 setDecimalNumber(number
, status
);
170 // -------------------------------------
171 // Creates a formattable object with a UnicodeString instance.
173 Formattable::Formattable(const UnicodeString
& stringToCopy
)
177 fValue
.fString
= new UnicodeString(stringToCopy
);
180 // -------------------------------------
181 // Creates a formattable object with a UnicodeString* value.
182 // (adopting symantics)
184 Formattable::Formattable(UnicodeString
* stringToAdopt
)
188 fValue
.fString
= stringToAdopt
;
191 Formattable::Formattable(UObject
* objectToAdopt
)
195 fValue
.fObject
= objectToAdopt
;
198 // -------------------------------------
200 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
201 : UObject(), fType(kArray
)
205 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
206 fValue
.fArrayAndCount
.fCount
= count
;
209 // -------------------------------------
213 Formattable::Formattable(const Formattable
&source
)
220 // -------------------------------------
221 // assignment operator
224 Formattable::operator=(const Formattable
& source
)
228 // Disposes the current formattable value/setting.
231 // Sets the correct data type for this value.
232 fType
= source
.fType
;
236 // Sets each element in the array one by one and records the array count.
237 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
238 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
239 source
.fValue
.fArrayAndCount
.fCount
);
242 // Sets the string value.
243 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
246 // Sets the double value.
247 fValue
.fDouble
= source
.fValue
.fDouble
;
251 // Sets the long value.
252 fValue
.fInt64
= source
.fValue
.fInt64
;
255 // Sets the Date value.
256 fValue
.fDate
= source
.fValue
.fDate
;
259 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
263 UErrorCode status
= U_ZERO_ERROR
;
264 if (source
.fDecimalNum
!= NULL
) {
265 fDecimalNum
= new DigitList(*source
.fDecimalNum
); // TODO: use internal digit list
267 if (source
.fDecimalQuantity
!= NULL
) {
268 fDecimalQuantity
= new DecimalQuantity(*source
.fDecimalQuantity
);
270 if (source
.fDecimalStr
!= NULL
) {
271 fDecimalStr
= new CharString(*source
.fDecimalStr
, status
);
272 if (U_FAILURE(status
)) {
281 // -------------------------------------
284 Formattable::operator==(const Formattable
& that
) const
288 if (this == &that
) return TRUE
;
290 // Returns FALSE if the data types are different.
291 if (fType
!= that
.fType
) return FALSE
;
293 // Compares the actual data values.
297 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
300 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
304 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
307 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
310 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
314 // Checks each element for equality.
315 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
316 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
323 if (fValue
.fObject
== NULL
|| that
.fValue
.fObject
== NULL
) {
326 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
331 // TODO: compare digit lists if numeric.
335 // -------------------------------------
337 Formattable::~Formattable()
342 // -------------------------------------
344 void Formattable::dispose()
346 // Deletes the data value if necessary.
349 delete fValue
.fString
;
352 delete[] fValue
.fArrayAndCount
.fArray
;
355 delete fValue
.fObject
;
367 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
368 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
371 fDecimalNum
->~DigitList(); // destruct, don't deallocate
375 delete fDecimalQuantity
;
376 fDecimalQuantity
= NULL
;
380 Formattable::clone() const {
381 return new Formattable(*this);
384 // -------------------------------------
385 // Gets the data type of this Formattable object.
387 Formattable::getType() const
393 Formattable::isNumeric() const {
404 // -------------------------------------
406 //Formattable::getLong(UErrorCode* status) const
407 Formattable::getLong(UErrorCode
& status
) const
409 if (U_FAILURE(status
)) {
414 case Formattable::kLong
:
415 return (int32_t)fValue
.fInt64
;
416 case Formattable::kInt64
:
417 if (fValue
.fInt64
> INT32_MAX
) {
418 status
= U_INVALID_FORMAT_ERROR
;
420 } else if (fValue
.fInt64
< INT32_MIN
) {
421 status
= U_INVALID_FORMAT_ERROR
;
424 return (int32_t)fValue
.fInt64
;
426 case Formattable::kDouble
:
427 if (fValue
.fDouble
> INT32_MAX
) {
428 status
= U_INVALID_FORMAT_ERROR
;
430 } else if (fValue
.fDouble
< INT32_MIN
) {
431 status
= U_INVALID_FORMAT_ERROR
;
434 return (int32_t)fValue
.fDouble
; // loses fraction
436 case Formattable::kObject
:
437 if (fValue
.fObject
== NULL
) {
438 status
= U_MEMORY_ALLOCATION_ERROR
;
441 // TODO Later replace this with instanceof call
442 if (instanceOfMeasure(fValue
.fObject
)) {
443 return ((const Measure
*) fValue
.fObject
)->
444 getNumber().getLong(status
);
448 status
= U_INVALID_FORMAT_ERROR
;
453 // -------------------------------------
454 // Maximum int that can be represented exactly in a double. (53 bits)
455 // Larger ints may be rounded to a near-by value as not all are representable.
456 // TODO: move this constant elsewhere, possibly configure it for different
457 // floating point formats, if any non-standard ones are still in use.
458 static const int64_t U_DOUBLE_MAX_EXACT_INT
= 9007199254740992LL;
461 Formattable::getInt64(UErrorCode
& status
) const
463 if (U_FAILURE(status
)) {
468 case Formattable::kLong
:
469 case Formattable::kInt64
:
470 return fValue
.fInt64
;
471 case Formattable::kDouble
:
472 if (fValue
.fDouble
> (double)U_INT64_MAX
) {
473 status
= U_INVALID_FORMAT_ERROR
;
475 } else if (fValue
.fDouble
< (double)U_INT64_MIN
) {
476 status
= U_INVALID_FORMAT_ERROR
;
478 } else if (fabs(fValue
.fDouble
) > U_DOUBLE_MAX_EXACT_INT
&& fDecimalNum
!= NULL
) {
479 int64_t val
= fDecimalNum
->getInt64();
483 status
= U_INVALID_FORMAT_ERROR
;
484 return fValue
.fDouble
> 0 ? U_INT64_MAX
: U_INT64_MIN
;
487 return (int64_t)fValue
.fDouble
;
489 case Formattable::kObject
:
490 if (fValue
.fObject
== NULL
) {
491 status
= U_MEMORY_ALLOCATION_ERROR
;
494 if (instanceOfMeasure(fValue
.fObject
)) {
495 return ((const Measure
*) fValue
.fObject
)->
496 getNumber().getInt64(status
);
500 status
= U_INVALID_FORMAT_ERROR
;
505 // -------------------------------------
507 Formattable::getDouble(UErrorCode
& status
) const
509 if (U_FAILURE(status
)) {
514 case Formattable::kLong
:
515 case Formattable::kInt64
: // loses precision
516 return (double)fValue
.fInt64
;
517 case Formattable::kDouble
:
518 return fValue
.fDouble
;
519 case Formattable::kObject
:
520 if (fValue
.fObject
== NULL
) {
521 status
= U_MEMORY_ALLOCATION_ERROR
;
524 // TODO Later replace this with instanceof call
525 if (instanceOfMeasure(fValue
.fObject
)) {
526 return ((const Measure
*) fValue
.fObject
)->
527 getNumber().getDouble(status
);
531 status
= U_INVALID_FORMAT_ERROR
;
537 Formattable::getObject() const {
538 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
541 // -------------------------------------
542 // Sets the value to a double value d.
545 Formattable::setDouble(double d
)
552 // -------------------------------------
553 // Sets the value to a long value l.
556 Formattable::setLong(int32_t l
)
563 // -------------------------------------
564 // Sets the value to an int64 value ll.
567 Formattable::setInt64(int64_t ll
)
574 // -------------------------------------
575 // Sets the value to a Date instance d.
578 Formattable::setDate(UDate d
)
585 // -------------------------------------
586 // Sets the value to a string value stringToCopy.
589 Formattable::setString(const UnicodeString
& stringToCopy
)
593 fValue
.fString
= new UnicodeString(stringToCopy
);
596 // -------------------------------------
597 // Sets the value to an array of Formattable objects.
600 Formattable::setArray(const Formattable
* array
, int32_t count
)
604 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
605 fValue
.fArrayAndCount
.fCount
= count
;
608 // -------------------------------------
609 // Adopts the stringToAdopt value.
612 Formattable::adoptString(UnicodeString
* stringToAdopt
)
616 fValue
.fString
= stringToAdopt
;
619 // -------------------------------------
620 // Adopts the array value and its count.
623 Formattable::adoptArray(Formattable
* array
, int32_t count
)
627 fValue
.fArrayAndCount
.fArray
= array
;
628 fValue
.fArrayAndCount
.fCount
= count
;
632 Formattable::adoptObject(UObject
* objectToAdopt
) {
635 fValue
.fObject
= objectToAdopt
;
638 // -------------------------------------
640 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
642 if (fType
!= kString
) {
643 setError(status
, U_INVALID_FORMAT_ERROR
);
646 if (fValue
.fString
== NULL
) {
647 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
649 result
= *fValue
.fString
;
655 // -------------------------------------
657 Formattable::getString(UErrorCode
& status
) const
659 if (fType
!= kString
) {
660 setError(status
, U_INVALID_FORMAT_ERROR
);
663 if (fValue
.fString
== NULL
) {
664 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
667 return *fValue
.fString
;
670 // -------------------------------------
672 Formattable::getString(UErrorCode
& status
)
674 if (fType
!= kString
) {
675 setError(status
, U_INVALID_FORMAT_ERROR
);
678 if (fValue
.fString
== NULL
) {
679 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
682 return *fValue
.fString
;
685 // -------------------------------------
687 Formattable::getArray(int32_t& count
, UErrorCode
& status
) const
689 if (fType
!= kArray
) {
690 setError(status
, U_INVALID_FORMAT_ERROR
);
694 count
= fValue
.fArrayAndCount
.fCount
;
695 return fValue
.fArrayAndCount
.fArray
;
698 // -------------------------------------
699 // Gets the bogus string, ensures mondo bogosity.
702 Formattable::getBogus() const
704 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
708 // --------------------------------------
709 StringPiece
Formattable::getDecimalNumber(UErrorCode
&status
) {
710 if (U_FAILURE(status
)) {
713 if (fDecimalStr
!= NULL
) {
714 return fDecimalStr
->toStringPiece();
717 CharString
*decimalStr
= internalGetCharString(status
);
718 if(decimalStr
== NULL
) {
719 return ""; // getDecimalNumber returns "" for error cases
721 return decimalStr
->toStringPiece();
725 CharString
*Formattable::internalGetCharString(UErrorCode
&status
) {
726 if(fDecimalStr
== NULL
) {
727 if (fDecimalNum
== NULL
) {
728 // No decimal number for the formattable yet. Which means the value was
729 // set directly by the user as an int, int64 or double. If the value came
730 // from parsing, or from the user setting a decimal number, fDecimalNum
731 // would already be set.
733 fDecimalNum
= new DigitList
; // TODO: use internal digit list
734 if (fDecimalNum
== NULL
) {
735 status
= U_MEMORY_ALLOCATION_ERROR
;
741 fDecimalNum
->set(this->getDouble());
744 fDecimalNum
->set(this->getLong());
747 fDecimalNum
->set(this->getInt64());
750 // The formattable's value is not a numeric type.
751 status
= U_INVALID_STATE_ERROR
;
756 if (fDecimalQuantity
== NULL
) {
757 // No decimal number for the formattable yet...
758 LocalPointer
<DecimalQuantity
> dq(new DecimalQuantity(), status
);
759 if (U_FAILURE(status
)) { return nullptr; }
760 populateDecimalQuantity(*dq
, status
);
761 if (U_FAILURE(status
)) { return nullptr; }
762 fDecimalQuantity
= dq
.orphan();
765 fDecimalStr
= new CharString
;
766 if (fDecimalStr
== NULL
) {
767 status
= U_MEMORY_ALLOCATION_ERROR
;
770 fDecimalNum
->getDecimal(*fDecimalStr
, status
);
776 Formattable::populateDecimalQuantity(number::impl::DecimalQuantity
& output
, UErrorCode
& status
) const {
777 if (fDecimalQuantity
!= nullptr) {
778 output
= *fDecimalQuantity
;
784 output
.setToDouble(this->getDouble());
785 output
.roundToInfinity();
788 output
.setToInt(this->getLong());
791 output
.setToLong(this->getInt64());
794 // The formattable's value is not a numeric type.
795 status
= U_INVALID_STATE_ERROR
;
800 Formattable::getInternalDigitList() {
801 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
802 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
804 fDecimalNum
= new (&(stackData
->stackDecimalNum
), kOnStack
) DigitList();
806 fDecimalNum
->clear();
811 // ---------------------------------------
813 Formattable::adoptDigitList(DigitList
*dl
) {
814 if(fDecimalNum
==dl
) {
815 fDecimalNum
= NULL
; // don't delete
821 if(dl
==NULL
) { // allow adoptDigitList(NULL) to clear
825 // Set the value into the Union of simple type values.
826 // Cannot use the set() functions because they would delete the fDecimalNum value,
828 if (fDecimalNum
->fitsIntoLong(FALSE
)) {
830 fValue
.fInt64
= fDecimalNum
->getLong();
831 } else if (fDecimalNum
->fitsIntoInt64(FALSE
)) {
833 fValue
.fInt64
= fDecimalNum
->getInt64();
836 fValue
.fDouble
= fDecimalNum
->getDouble();
840 // ---------------------------------------
842 Formattable::adoptDecimalQuantity(DecimalQuantity
*dq
) {
843 if (fDecimalQuantity
!= NULL
) {
844 delete fDecimalQuantity
;
846 fDecimalQuantity
= dq
;
847 if (dq
== NULL
) { // allow adoptDigitList(NULL) to clear
851 // Set the value into the Union of simple type values.
852 // Cannot use the set() functions because they would delete the fDecimalNum value.
853 if (fDecimalQuantity
->fitsInLong()) {
854 fValue
.fInt64
= fDecimalQuantity
->toLong();
855 if (fValue
.fInt64
<= INT32_MAX
&& fValue
.fInt64
>= INT32_MIN
) {
862 fValue
.fDouble
= fDecimalQuantity
->toDouble();
867 // ---------------------------------------
869 Formattable::setDecimalNumber(StringPiece numberString
, UErrorCode
&status
) {
870 if (U_FAILURE(status
)) {
875 // Copy the input string and nul-terminate it.
876 // The decNumber library requires nul-terminated input. StringPiece input
877 // is not guaranteed nul-terminated. Too bad.
878 // CharString automatically adds the nul.
879 DigitList
*dnum
= new DigitList(); // TODO: use getInternalDigitList
881 status
= U_MEMORY_ALLOCATION_ERROR
;
884 dnum
->set(CharString(numberString
, status
).toStringPiece(), status
);
885 if (U_FAILURE(status
)) {
887 return; // String didn't contain a decimal number.
889 adoptDigitList(dnum
);
891 auto* dq
= new DecimalQuantity();
892 dq
->setToDecNumber(numberString
, status
);
893 adoptDecimalQuantity(dq
);
895 // Note that we do not hang on to the caller's input string.
896 // If we are asked for the string, we will regenerate one from fDecimalNum.
900 //----------------------------------------------------
902 //----------------------------------------------------
908 #include "unicode/datefmt.h"
911 class FormattableStreamer
/* not : public UObject because all methods are static */ {
913 static void streamOut(ostream
& stream
, const Formattable
& obj
);
916 FormattableStreamer() {} // private - forbid instantiation
919 // This is for debugging purposes only. This will send a displayable
920 // form of the Formattable object to the output stream.
923 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
925 static DateFormat
*defDateFormat
= 0;
927 UnicodeString buffer
;
928 switch(obj
.getType()) {
929 case Formattable::kDate
:
930 // Creates a DateFormat instance for formatting the
932 if (defDateFormat
== 0) {
933 defDateFormat
= DateFormat::createInstance();
935 defDateFormat
->format(obj
.getDate(), buffer
);
938 case Formattable::kDouble
:
939 // Output the double as is.
940 stream
<< obj
.getDouble() << 'D';
942 case Formattable::kLong
:
943 // Output the double as is.
944 stream
<< obj
.getLong() << 'L';
946 case Formattable::kString
:
947 // Output the double as is. Please see UnicodeString console
948 // I/O routine for more details.
949 stream
<< '"' << obj
.getString(buffer
) << '"';
951 case Formattable::kArray
:
953 const Formattable
* array
;
954 array
= obj
.getArray(count
);
956 // Recursively calling the console I/O routine for each element in the array.
957 for (i
=0; i
<count
; ++i
) {
958 FormattableStreamer::streamOut(stream
, array
[i
]);
959 stream
<< ( (i
==(count
-1)) ? "" : ", " );
964 // Not a recognizable Formattable object.
965 stream
<< "INVALID_Formattable";
975 /* ---- UFormattable implementation ---- */
979 U_DRAFT UFormattable
* U_EXPORT2
980 ufmt_open(UErrorCode
*status
) {
981 if( U_FAILURE(*status
) ) {
984 UFormattable
*fmt
= (new Formattable())->toUFormattable();
987 *status
= U_MEMORY_ALLOCATION_ERROR
;
992 U_DRAFT
void U_EXPORT2
993 ufmt_close(UFormattable
*fmt
) {
994 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
999 U_INTERNAL UFormattableType U_EXPORT2
1000 ufmt_getType(const UFormattable
*fmt
, UErrorCode
*status
) {
1001 if(U_FAILURE(*status
)) {
1002 return (UFormattableType
)UFMT_COUNT
;
1004 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1005 return (UFormattableType
)obj
->getType();
1009 U_INTERNAL UBool U_EXPORT2
1010 ufmt_isNumeric(const UFormattable
*fmt
) {
1011 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1012 return obj
->isNumeric();
1015 U_DRAFT UDate U_EXPORT2
1016 ufmt_getDate(const UFormattable
*fmt
, UErrorCode
*status
) {
1017 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1019 return obj
->getDate(*status
);
1022 U_DRAFT
double U_EXPORT2
1023 ufmt_getDouble(UFormattable
*fmt
, UErrorCode
*status
) {
1024 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1026 return obj
->getDouble(*status
);
1029 U_DRAFT
int32_t U_EXPORT2
1030 ufmt_getLong(UFormattable
*fmt
, UErrorCode
*status
) {
1031 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1033 return obj
->getLong(*status
);
1037 U_DRAFT
const void *U_EXPORT2
1038 ufmt_getObject(const UFormattable
*fmt
, UErrorCode
*status
) {
1039 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1041 const void *ret
= obj
->getObject();
1043 (obj
->getType() != Formattable::kObject
) &&
1044 U_SUCCESS( *status
)) {
1045 *status
= U_INVALID_FORMAT_ERROR
;
1050 U_DRAFT
const UChar
* U_EXPORT2
1051 ufmt_getUChars(UFormattable
*fmt
, int32_t *len
, UErrorCode
*status
) {
1052 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1054 // avoid bogosity by checking the type first.
1055 if( obj
->getType() != Formattable::kString
) {
1056 if( U_SUCCESS(*status
) ){
1057 *status
= U_INVALID_FORMAT_ERROR
;
1062 // This should return a valid string
1063 UnicodeString
&str
= obj
->getString(*status
);
1064 if( U_SUCCESS(*status
) && len
!= NULL
) {
1065 *len
= str
.length();
1067 return str
.getTerminatedBuffer();
1070 U_DRAFT
int32_t U_EXPORT2
1071 ufmt_getArrayLength(const UFormattable
* fmt
, UErrorCode
*status
) {
1072 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1075 (void)obj
->getArray(count
, *status
);
1079 U_DRAFT UFormattable
* U_EXPORT2
1080 ufmt_getArrayItemByIndex(UFormattable
* fmt
, int32_t n
, UErrorCode
*status
) {
1081 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1083 (void)obj
->getArray(count
, *status
);
1084 if(U_FAILURE(*status
)) {
1086 } else if(n
<0 || n
>=count
) {
1087 setError(*status
, U_INDEX_OUTOFBOUNDS_ERROR
);
1090 return (*obj
)[n
].toUFormattable(); // returns non-const Formattable
1094 U_DRAFT
const char * U_EXPORT2
1095 ufmt_getDecNumChars(UFormattable
*fmt
, int32_t *len
, UErrorCode
*status
) {
1096 if(U_FAILURE(*status
)) {
1099 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1100 CharString
*charString
= obj
->internalGetCharString(*status
);
1101 if(U_FAILURE(*status
)) {
1104 if(charString
== NULL
) {
1105 *status
= U_MEMORY_ALLOCATION_ERROR
;
1109 *len
= charString
->length();
1111 return charString
->data();
1115 U_DRAFT
int64_t U_EXPORT2
1116 ufmt_getInt64(UFormattable
*fmt
, UErrorCode
*status
) {
1117 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1118 return obj
->getInt64(*status
);
1121 #endif /* #if !UCONFIG_NO_FORMATTING */