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"
35 // *****************************************************************************
37 // *****************************************************************************
41 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable
)
44 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
46 // NOTE: As of 3.0, there are limitations to the UObject API. It does
47 // not (yet) support cloning, operator=, nor operator==. To
48 // work around this, I implement some simple inlines here. Later
49 // these can be modified or removed. [alan]
51 // NOTE: These inlines assume that all fObjects are in fact instances
52 // of the Measure class, which is true as of 3.0. [alan]
54 // Return TRUE if *a == *b.
55 static inline UBool
objectEquals(const UObject
* a
, const UObject
* b
) {
56 // LATER: return *a == *b;
57 return *((const Measure
*) a
) == *((const Measure
*) b
);
60 // Return a clone of *a.
61 static inline UObject
* objectClone(const UObject
* a
) {
62 // LATER: return a->clone();
63 return ((const Measure
*) a
)->clone();
66 // Return TRUE if *a is an instance of Measure.
67 static inline UBool
instanceOfMeasure(const UObject
* a
) {
68 return dynamic_cast<const Measure
*>(a
) != NULL
;
72 * Creates a new Formattable array and copies the values from the specified
74 * @param array the original array
75 * @param count the original array count
76 * @return the new Formattable array.
78 static Formattable
* createArrayCopy(const Formattable
* array
, int32_t count
) {
79 Formattable
*result
= new Formattable
[count
];
81 for (int32_t i
=0; i
<count
; ++i
)
82 result
[i
] = array
[i
]; // Don't memcpy!
87 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
90 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
92 static void setError(UErrorCode
& ec
, UErrorCode err
) {
99 // Common initialization code, shared by constructors.
100 // Put everything into a known state.
102 void Formattable::init() {
110 // -------------------------------------
111 // default constructor.
112 // Creates a formattable object with a long value 0.
114 Formattable::Formattable() {
118 // -------------------------------------
119 // Creates a formattable object with a Date instance.
121 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
128 // -------------------------------------
129 // Creates a formattable object with a double value.
131 Formattable::Formattable(double value
)
135 fValue
.fDouble
= value
;
138 // -------------------------------------
139 // Creates a formattable object with an int32_t value.
141 Formattable::Formattable(int32_t value
)
144 fValue
.fInt64
= value
;
147 // -------------------------------------
148 // Creates a formattable object with an int64_t value.
150 Formattable::Formattable(int64_t value
)
154 fValue
.fInt64
= value
;
157 // -------------------------------------
158 // Creates a formattable object with a decimal number value from a string.
160 Formattable::Formattable(StringPiece number
, UErrorCode
&status
) {
162 setDecimalNumber(number
, status
);
166 // -------------------------------------
167 // Creates a formattable object with a UnicodeString instance.
169 Formattable::Formattable(const UnicodeString
& stringToCopy
)
173 fValue
.fString
= new UnicodeString(stringToCopy
);
176 // -------------------------------------
177 // Creates a formattable object with a UnicodeString* value.
178 // (adopting symantics)
180 Formattable::Formattable(UnicodeString
* stringToAdopt
)
184 fValue
.fString
= stringToAdopt
;
187 Formattable::Formattable(UObject
* objectToAdopt
)
191 fValue
.fObject
= objectToAdopt
;
194 // -------------------------------------
196 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
197 : UObject(), fType(kArray
)
201 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
202 fValue
.fArrayAndCount
.fCount
= count
;
205 // -------------------------------------
209 Formattable::Formattable(const Formattable
&source
)
216 // -------------------------------------
217 // assignment operator
220 Formattable::operator=(const Formattable
& source
)
224 // Disposes the current formattable value/setting.
227 // Sets the correct data type for this value.
228 fType
= source
.fType
;
232 // Sets each element in the array one by one and records the array count.
233 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
234 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
235 source
.fValue
.fArrayAndCount
.fCount
);
238 // Sets the string value.
239 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
242 // Sets the double value.
243 fValue
.fDouble
= source
.fValue
.fDouble
;
247 // Sets the long value.
248 fValue
.fInt64
= source
.fValue
.fInt64
;
251 // Sets the Date value.
252 fValue
.fDate
= source
.fValue
.fDate
;
255 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
259 UErrorCode status
= U_ZERO_ERROR
;
260 if (source
.fDecimalNum
!= NULL
) {
261 fDecimalNum
= new DigitList(*source
.fDecimalNum
); // TODO: use internal digit list
263 if (source
.fDecimalStr
!= NULL
) {
264 fDecimalStr
= new CharString(*source
.fDecimalStr
, status
);
265 if (U_FAILURE(status
)) {
274 // -------------------------------------
277 Formattable::operator==(const Formattable
& that
) const
281 if (this == &that
) return TRUE
;
283 // Returns FALSE if the data types are different.
284 if (fType
!= that
.fType
) return FALSE
;
286 // Compares the actual data values.
290 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
293 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
297 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
300 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
303 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
307 // Checks each element for equality.
308 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
309 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
316 if (fValue
.fObject
== NULL
|| that
.fValue
.fObject
== NULL
) {
319 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
324 // TODO: compare digit lists if numeric.
328 // -------------------------------------
330 Formattable::~Formattable()
335 // -------------------------------------
337 void Formattable::dispose()
339 // Deletes the data value if necessary.
342 delete fValue
.fString
;
345 delete[] fValue
.fArrayAndCount
.fArray
;
348 delete fValue
.fObject
;
360 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
361 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
364 fDecimalNum
->~DigitList(); // destruct, don't deallocate
370 Formattable::clone() const {
371 return new Formattable(*this);
374 // -------------------------------------
375 // Gets the data type of this Formattable object.
377 Formattable::getType() const
383 Formattable::isNumeric() const {
394 // -------------------------------------
396 //Formattable::getLong(UErrorCode* status) const
397 Formattable::getLong(UErrorCode
& status
) const
399 if (U_FAILURE(status
)) {
404 case Formattable::kLong
:
405 return (int32_t)fValue
.fInt64
;
406 case Formattable::kInt64
:
407 if (fValue
.fInt64
> INT32_MAX
) {
408 status
= U_INVALID_FORMAT_ERROR
;
410 } else if (fValue
.fInt64
< INT32_MIN
) {
411 status
= U_INVALID_FORMAT_ERROR
;
414 return (int32_t)fValue
.fInt64
;
416 case Formattable::kDouble
:
417 if (fValue
.fDouble
> INT32_MAX
) {
418 status
= U_INVALID_FORMAT_ERROR
;
420 } else if (fValue
.fDouble
< INT32_MIN
) {
421 status
= U_INVALID_FORMAT_ERROR
;
424 return (int32_t)fValue
.fDouble
; // loses fraction
426 case Formattable::kObject
:
427 if (fValue
.fObject
== NULL
) {
428 status
= U_MEMORY_ALLOCATION_ERROR
;
431 // TODO Later replace this with instanceof call
432 if (instanceOfMeasure(fValue
.fObject
)) {
433 return ((const Measure
*) fValue
.fObject
)->
434 getNumber().getLong(status
);
438 status
= U_INVALID_FORMAT_ERROR
;
443 // -------------------------------------
444 // Maximum int that can be represented exactly in a double. (53 bits)
445 // Larger ints may be rounded to a near-by value as not all are representable.
446 // TODO: move this constant elsewhere, possibly configure it for different
447 // floating point formats, if any non-standard ones are still in use.
448 static const int64_t U_DOUBLE_MAX_EXACT_INT
= 9007199254740992LL;
451 Formattable::getInt64(UErrorCode
& status
) const
453 if (U_FAILURE(status
)) {
458 case Formattable::kLong
:
459 case Formattable::kInt64
:
460 return fValue
.fInt64
;
461 case Formattable::kDouble
:
462 if (fValue
.fDouble
> (double)U_INT64_MAX
) {
463 status
= U_INVALID_FORMAT_ERROR
;
465 } else if (fValue
.fDouble
< (double)U_INT64_MIN
) {
466 status
= U_INVALID_FORMAT_ERROR
;
468 } else if (fabs(fValue
.fDouble
) > U_DOUBLE_MAX_EXACT_INT
&& fDecimalNum
!= NULL
) {
469 int64_t val
= fDecimalNum
->getInt64();
473 status
= U_INVALID_FORMAT_ERROR
;
474 return fValue
.fDouble
> 0 ? U_INT64_MAX
: U_INT64_MIN
;
477 return (int64_t)fValue
.fDouble
;
479 case Formattable::kObject
:
480 if (fValue
.fObject
== NULL
) {
481 status
= U_MEMORY_ALLOCATION_ERROR
;
484 if (instanceOfMeasure(fValue
.fObject
)) {
485 return ((const Measure
*) fValue
.fObject
)->
486 getNumber().getInt64(status
);
490 status
= U_INVALID_FORMAT_ERROR
;
495 // -------------------------------------
497 Formattable::getDouble(UErrorCode
& status
) const
499 if (U_FAILURE(status
)) {
504 case Formattable::kLong
:
505 case Formattable::kInt64
: // loses precision
506 return (double)fValue
.fInt64
;
507 case Formattable::kDouble
:
508 return fValue
.fDouble
;
509 case Formattable::kObject
:
510 if (fValue
.fObject
== NULL
) {
511 status
= U_MEMORY_ALLOCATION_ERROR
;
514 // TODO Later replace this with instanceof call
515 if (instanceOfMeasure(fValue
.fObject
)) {
516 return ((const Measure
*) fValue
.fObject
)->
517 getNumber().getDouble(status
);
521 status
= U_INVALID_FORMAT_ERROR
;
527 Formattable::getObject() const {
528 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
531 // -------------------------------------
532 // Sets the value to a double value d.
535 Formattable::setDouble(double d
)
542 // -------------------------------------
543 // Sets the value to a long value l.
546 Formattable::setLong(int32_t l
)
553 // -------------------------------------
554 // Sets the value to an int64 value ll.
557 Formattable::setInt64(int64_t ll
)
564 // -------------------------------------
565 // Sets the value to a Date instance d.
568 Formattable::setDate(UDate d
)
575 // -------------------------------------
576 // Sets the value to a string value stringToCopy.
579 Formattable::setString(const UnicodeString
& stringToCopy
)
583 fValue
.fString
= new UnicodeString(stringToCopy
);
586 // -------------------------------------
587 // Sets the value to an array of Formattable objects.
590 Formattable::setArray(const Formattable
* array
, int32_t count
)
594 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
595 fValue
.fArrayAndCount
.fCount
= count
;
598 // -------------------------------------
599 // Adopts the stringToAdopt value.
602 Formattable::adoptString(UnicodeString
* stringToAdopt
)
606 fValue
.fString
= stringToAdopt
;
609 // -------------------------------------
610 // Adopts the array value and its count.
613 Formattable::adoptArray(Formattable
* array
, int32_t count
)
617 fValue
.fArrayAndCount
.fArray
= array
;
618 fValue
.fArrayAndCount
.fCount
= count
;
622 Formattable::adoptObject(UObject
* objectToAdopt
) {
625 fValue
.fObject
= objectToAdopt
;
628 // -------------------------------------
630 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
632 if (fType
!= kString
) {
633 setError(status
, U_INVALID_FORMAT_ERROR
);
636 if (fValue
.fString
== NULL
) {
637 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
639 result
= *fValue
.fString
;
645 // -------------------------------------
647 Formattable::getString(UErrorCode
& status
) const
649 if (fType
!= kString
) {
650 setError(status
, U_INVALID_FORMAT_ERROR
);
653 if (fValue
.fString
== NULL
) {
654 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
657 return *fValue
.fString
;
660 // -------------------------------------
662 Formattable::getString(UErrorCode
& status
)
664 if (fType
!= kString
) {
665 setError(status
, U_INVALID_FORMAT_ERROR
);
668 if (fValue
.fString
== NULL
) {
669 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
672 return *fValue
.fString
;
675 // -------------------------------------
677 Formattable::getArray(int32_t& count
, UErrorCode
& status
) const
679 if (fType
!= kArray
) {
680 setError(status
, U_INVALID_FORMAT_ERROR
);
684 count
= fValue
.fArrayAndCount
.fCount
;
685 return fValue
.fArrayAndCount
.fArray
;
688 // -------------------------------------
689 // Gets the bogus string, ensures mondo bogosity.
692 Formattable::getBogus() const
694 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
698 // --------------------------------------
699 StringPiece
Formattable::getDecimalNumber(UErrorCode
&status
) {
700 if (U_FAILURE(status
)) {
703 if (fDecimalStr
!= NULL
) {
704 return fDecimalStr
->toStringPiece();
707 CharString
*decimalStr
= internalGetCharString(status
);
708 if(decimalStr
== NULL
) {
709 return ""; // getDecimalNumber returns "" for error cases
711 return decimalStr
->toStringPiece();
715 CharString
*Formattable::internalGetCharString(UErrorCode
&status
) {
716 if(fDecimalStr
== NULL
) {
717 if (fDecimalNum
== NULL
) {
718 // No decimal number for the formattable yet. Which means the value was
719 // set directly by the user as an int, int64 or double. If the value came
720 // from parsing, or from the user setting a decimal number, fDecimalNum
721 // would already be set.
723 fDecimalNum
= new DigitList
; // TODO: use internal digit list
724 if (fDecimalNum
== NULL
) {
725 status
= U_MEMORY_ALLOCATION_ERROR
;
731 fDecimalNum
->set(this->getDouble());
734 fDecimalNum
->set(this->getLong());
737 fDecimalNum
->set(this->getInt64());
740 // The formattable's value is not a numeric type.
741 status
= U_INVALID_STATE_ERROR
;
746 fDecimalStr
= new CharString
;
747 if (fDecimalStr
== NULL
) {
748 status
= U_MEMORY_ALLOCATION_ERROR
;
751 fDecimalNum
->getDecimal(*fDecimalStr
, status
);
758 Formattable::getInternalDigitList() {
759 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
760 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
762 fDecimalNum
= new (&(stackData
->stackDecimalNum
), kOnStack
) DigitList();
764 fDecimalNum
->clear();
769 // ---------------------------------------
771 Formattable::adoptDigitList(DigitList
*dl
) {
772 if(fDecimalNum
==dl
) {
773 fDecimalNum
= NULL
; // don't delete
779 if(dl
==NULL
) { // allow adoptDigitList(NULL) to clear
783 // Set the value into the Union of simple type values.
784 // Cannot use the set() functions because they would delete the fDecimalNum value,
786 if (fDecimalNum
->fitsIntoLong(FALSE
)) {
788 fValue
.fInt64
= fDecimalNum
->getLong();
789 } else if (fDecimalNum
->fitsIntoInt64(FALSE
)) {
791 fValue
.fInt64
= fDecimalNum
->getInt64();
794 fValue
.fDouble
= fDecimalNum
->getDouble();
799 // ---------------------------------------
801 Formattable::setDecimalNumber(StringPiece numberString
, UErrorCode
&status
) {
802 if (U_FAILURE(status
)) {
807 // Copy the input string and nul-terminate it.
808 // The decNumber library requires nul-terminated input. StringPiece input
809 // is not guaranteed nul-terminated. Too bad.
810 // CharString automatically adds the nul.
811 DigitList
*dnum
= new DigitList(); // TODO: use getInternalDigitList
813 status
= U_MEMORY_ALLOCATION_ERROR
;
816 dnum
->set(CharString(numberString
, status
).toStringPiece(), status
);
817 if (U_FAILURE(status
)) {
819 return; // String didn't contain a decimal number.
821 adoptDigitList(dnum
);
823 // Note that we do not hang on to the caller's input string.
824 // If we are asked for the string, we will regenerate one from fDecimalNum.
828 //----------------------------------------------------
830 //----------------------------------------------------
836 #include "unicode/datefmt.h"
839 class FormattableStreamer
/* not : public UObject because all methods are static */ {
841 static void streamOut(ostream
& stream
, const Formattable
& obj
);
844 FormattableStreamer() {} // private - forbid instantiation
847 // This is for debugging purposes only. This will send a displayable
848 // form of the Formattable object to the output stream.
851 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
853 static DateFormat
*defDateFormat
= 0;
855 UnicodeString buffer
;
856 switch(obj
.getType()) {
857 case Formattable::kDate
:
858 // Creates a DateFormat instance for formatting the
860 if (defDateFormat
== 0) {
861 defDateFormat
= DateFormat::createInstance();
863 defDateFormat
->format(obj
.getDate(), buffer
);
866 case Formattable::kDouble
:
867 // Output the double as is.
868 stream
<< obj
.getDouble() << 'D';
870 case Formattable::kLong
:
871 // Output the double as is.
872 stream
<< obj
.getLong() << 'L';
874 case Formattable::kString
:
875 // Output the double as is. Please see UnicodeString console
876 // I/O routine for more details.
877 stream
<< '"' << obj
.getString(buffer
) << '"';
879 case Formattable::kArray
:
881 const Formattable
* array
;
882 array
= obj
.getArray(count
);
884 // Recursively calling the console I/O routine for each element in the array.
885 for (i
=0; i
<count
; ++i
) {
886 FormattableStreamer::streamOut(stream
, array
[i
]);
887 stream
<< ( (i
==(count
-1)) ? "" : ", " );
892 // Not a recognizable Formattable object.
893 stream
<< "INVALID_Formattable";
903 /* ---- UFormattable implementation ---- */
907 U_DRAFT UFormattable
* U_EXPORT2
908 ufmt_open(UErrorCode
*status
) {
909 if( U_FAILURE(*status
) ) {
912 UFormattable
*fmt
= (new Formattable())->toUFormattable();
915 *status
= U_MEMORY_ALLOCATION_ERROR
;
920 U_DRAFT
void U_EXPORT2
921 ufmt_close(UFormattable
*fmt
) {
922 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
927 U_INTERNAL UFormattableType U_EXPORT2
928 ufmt_getType(const UFormattable
*fmt
, UErrorCode
*status
) {
929 if(U_FAILURE(*status
)) {
930 return (UFormattableType
)UFMT_COUNT
;
932 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
933 return (UFormattableType
)obj
->getType();
937 U_INTERNAL UBool U_EXPORT2
938 ufmt_isNumeric(const UFormattable
*fmt
) {
939 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
940 return obj
->isNumeric();
943 U_DRAFT UDate U_EXPORT2
944 ufmt_getDate(const UFormattable
*fmt
, UErrorCode
*status
) {
945 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
947 return obj
->getDate(*status
);
950 U_DRAFT
double U_EXPORT2
951 ufmt_getDouble(UFormattable
*fmt
, UErrorCode
*status
) {
952 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
954 return obj
->getDouble(*status
);
957 U_DRAFT
int32_t U_EXPORT2
958 ufmt_getLong(UFormattable
*fmt
, UErrorCode
*status
) {
959 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
961 return obj
->getLong(*status
);
965 U_DRAFT
const void *U_EXPORT2
966 ufmt_getObject(const UFormattable
*fmt
, UErrorCode
*status
) {
967 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
969 const void *ret
= obj
->getObject();
971 (obj
->getType() != Formattable::kObject
) &&
972 U_SUCCESS( *status
)) {
973 *status
= U_INVALID_FORMAT_ERROR
;
978 U_DRAFT
const UChar
* U_EXPORT2
979 ufmt_getUChars(UFormattable
*fmt
, int32_t *len
, UErrorCode
*status
) {
980 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
982 // avoid bogosity by checking the type first.
983 if( obj
->getType() != Formattable::kString
) {
984 if( U_SUCCESS(*status
) ){
985 *status
= U_INVALID_FORMAT_ERROR
;
990 // This should return a valid string
991 UnicodeString
&str
= obj
->getString(*status
);
992 if( U_SUCCESS(*status
) && len
!= NULL
) {
995 return str
.getTerminatedBuffer();
998 U_DRAFT
int32_t U_EXPORT2
999 ufmt_getArrayLength(const UFormattable
* fmt
, UErrorCode
*status
) {
1000 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1003 (void)obj
->getArray(count
, *status
);
1007 U_DRAFT UFormattable
* U_EXPORT2
1008 ufmt_getArrayItemByIndex(UFormattable
* fmt
, int32_t n
, UErrorCode
*status
) {
1009 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1011 (void)obj
->getArray(count
, *status
);
1012 if(U_FAILURE(*status
)) {
1014 } else if(n
<0 || n
>=count
) {
1015 setError(*status
, U_INDEX_OUTOFBOUNDS_ERROR
);
1018 return (*obj
)[n
].toUFormattable(); // returns non-const Formattable
1022 U_DRAFT
const char * U_EXPORT2
1023 ufmt_getDecNumChars(UFormattable
*fmt
, int32_t *len
, UErrorCode
*status
) {
1024 if(U_FAILURE(*status
)) {
1027 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1028 CharString
*charString
= obj
->internalGetCharString(*status
);
1029 if(U_FAILURE(*status
)) {
1032 if(charString
== NULL
) {
1033 *status
= U_MEMORY_ALLOCATION_ERROR
;
1037 *len
= charString
->length();
1039 return charString
->data();
1043 U_DRAFT
int64_t U_EXPORT2
1044 ufmt_getInt64(UFormattable
*fmt
, UErrorCode
*status
) {
1045 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1046 return obj
->getInt64(*status
);
1049 #endif /* #if !UCONFIG_NO_FORMATTING */