2 *******************************************************************************
3 * Copyright (C) 1997-2014, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
9 * Modification History:
11 * Date Name Description
12 * 03/25/97 clhuang Initial Implementation.
13 ********************************************************************************
16 #include "unicode/utypes.h"
18 #if !UCONFIG_NO_FORMATTING
21 #include "unicode/fmtable.h"
22 #include "unicode/ustring.h"
23 #include "unicode/measure.h"
24 #include "unicode/curramt.h"
25 #include "unicode/uformattable.h"
29 #include "decNumber.h"
31 #include "fmtableimp.h"
33 // *****************************************************************************
35 // *****************************************************************************
39 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable
)
42 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
44 // NOTE: As of 3.0, there are limitations to the UObject API. It does
45 // not (yet) support cloning, operator=, nor operator==. To
46 // work around this, I implement some simple inlines here. Later
47 // these can be modified or removed. [alan]
49 // NOTE: These inlines assume that all fObjects are in fact instances
50 // of the Measure class, which is true as of 3.0. [alan]
52 // Return TRUE if *a == *b.
53 static inline UBool
objectEquals(const UObject
* a
, const UObject
* b
) {
54 // LATER: return *a == *b;
55 return *((const Measure
*) a
) == *((const Measure
*) b
);
58 // Return a clone of *a.
59 static inline UObject
* objectClone(const UObject
* a
) {
60 // LATER: return a->clone();
61 return ((const Measure
*) a
)->clone();
64 // Return TRUE if *a is an instance of Measure.
65 static inline UBool
instanceOfMeasure(const UObject
* a
) {
66 return dynamic_cast<const Measure
*>(a
) != NULL
;
70 * Creates a new Formattable array and copies the values from the specified
72 * @param array the original array
73 * @param count the original array count
74 * @return the new Formattable array.
76 static Formattable
* createArrayCopy(const Formattable
* array
, int32_t count
) {
77 Formattable
*result
= new Formattable
[count
];
79 for (int32_t i
=0; i
<count
; ++i
)
80 result
[i
] = array
[i
]; // Don't memcpy!
85 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
88 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
90 static void setError(UErrorCode
& ec
, UErrorCode err
) {
97 // Common initialization code, shared by constructors.
98 // Put everything into a known state.
100 void Formattable::init() {
108 // -------------------------------------
109 // default constructor.
110 // Creates a formattable object with a long value 0.
112 Formattable::Formattable() {
116 // -------------------------------------
117 // Creates a formattable object with a Date instance.
119 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
126 // -------------------------------------
127 // Creates a formattable object with a double value.
129 Formattable::Formattable(double value
)
133 fValue
.fDouble
= value
;
136 // -------------------------------------
137 // Creates a formattable object with an int32_t value.
139 Formattable::Formattable(int32_t value
)
142 fValue
.fInt64
= value
;
145 // -------------------------------------
146 // Creates a formattable object with an int64_t value.
148 Formattable::Formattable(int64_t value
)
152 fValue
.fInt64
= value
;
155 // -------------------------------------
156 // Creates a formattable object with a decimal number value from a string.
158 Formattable::Formattable(const StringPiece
&number
, UErrorCode
&status
) {
160 setDecimalNumber(number
, status
);
164 // -------------------------------------
165 // Creates a formattable object with a UnicodeString instance.
167 Formattable::Formattable(const UnicodeString
& stringToCopy
)
171 fValue
.fString
= new UnicodeString(stringToCopy
);
174 // -------------------------------------
175 // Creates a formattable object with a UnicodeString* value.
176 // (adopting symantics)
178 Formattable::Formattable(UnicodeString
* stringToAdopt
)
182 fValue
.fString
= stringToAdopt
;
185 Formattable::Formattable(UObject
* objectToAdopt
)
189 fValue
.fObject
= objectToAdopt
;
192 // -------------------------------------
194 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
195 : UObject(), fType(kArray
)
199 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
200 fValue
.fArrayAndCount
.fCount
= count
;
203 // -------------------------------------
207 Formattable::Formattable(const Formattable
&source
)
214 // -------------------------------------
215 // assignment operator
218 Formattable::operator=(const Formattable
& source
)
222 // Disposes the current formattable value/setting.
225 // Sets the correct data type for this value.
226 fType
= source
.fType
;
230 // Sets each element in the array one by one and records the array count.
231 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
232 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
233 source
.fValue
.fArrayAndCount
.fCount
);
236 // Sets the string value.
237 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
240 // Sets the double value.
241 fValue
.fDouble
= source
.fValue
.fDouble
;
245 // Sets the long value.
246 fValue
.fInt64
= source
.fValue
.fInt64
;
249 // Sets the Date value.
250 fValue
.fDate
= source
.fValue
.fDate
;
253 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
257 UErrorCode status
= U_ZERO_ERROR
;
258 if (source
.fDecimalNum
!= NULL
) {
259 fDecimalNum
= new DigitList(*source
.fDecimalNum
); // TODO: use internal digit list
261 if (source
.fDecimalStr
!= NULL
) {
262 fDecimalStr
= new CharString(*source
.fDecimalStr
, status
);
263 if (U_FAILURE(status
)) {
272 // -------------------------------------
275 Formattable::operator==(const Formattable
& that
) const
279 if (this == &that
) return TRUE
;
281 // Returns FALSE if the data types are different.
282 if (fType
!= that
.fType
) return FALSE
;
284 // Compares the actual data values.
288 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
291 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
295 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
298 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
301 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
305 // Checks each element for equality.
306 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
307 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
314 if (fValue
.fObject
== NULL
|| that
.fValue
.fObject
== NULL
) {
317 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
322 // TODO: compare digit lists if numeric.
326 // -------------------------------------
328 Formattable::~Formattable()
333 // -------------------------------------
335 void Formattable::dispose()
337 // Deletes the data value if necessary.
340 delete fValue
.fString
;
343 delete[] fValue
.fArrayAndCount
.fArray
;
346 delete fValue
.fObject
;
358 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
359 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
362 fDecimalNum
->~DigitList(); // destruct, don't deallocate
368 Formattable::clone() const {
369 return new Formattable(*this);
372 // -------------------------------------
373 // Gets the data type of this Formattable object.
375 Formattable::getType() const
381 Formattable::isNumeric() const {
392 // -------------------------------------
394 //Formattable::getLong(UErrorCode* status) const
395 Formattable::getLong(UErrorCode
& status
) const
397 if (U_FAILURE(status
)) {
402 case Formattable::kLong
:
403 return (int32_t)fValue
.fInt64
;
404 case Formattable::kInt64
:
405 if (fValue
.fInt64
> INT32_MAX
) {
406 status
= U_INVALID_FORMAT_ERROR
;
408 } else if (fValue
.fInt64
< INT32_MIN
) {
409 status
= U_INVALID_FORMAT_ERROR
;
412 return (int32_t)fValue
.fInt64
;
414 case Formattable::kDouble
:
415 if (fValue
.fDouble
> INT32_MAX
) {
416 status
= U_INVALID_FORMAT_ERROR
;
418 } else if (fValue
.fDouble
< INT32_MIN
) {
419 status
= U_INVALID_FORMAT_ERROR
;
422 return (int32_t)fValue
.fDouble
; // loses fraction
424 case Formattable::kObject
:
425 if (fValue
.fObject
== NULL
) {
426 status
= U_MEMORY_ALLOCATION_ERROR
;
429 // TODO Later replace this with instanceof call
430 if (instanceOfMeasure(fValue
.fObject
)) {
431 return ((const Measure
*) fValue
.fObject
)->
432 getNumber().getLong(status
);
435 status
= U_INVALID_FORMAT_ERROR
;
440 // -------------------------------------
441 // Maximum int that can be represented exactly in a double. (53 bits)
442 // Larger ints may be rounded to a near-by value as not all are representable.
443 // TODO: move this constant elsewhere, possibly configure it for different
444 // floating point formats, if any non-standard ones are still in use.
445 static const int64_t U_DOUBLE_MAX_EXACT_INT
= 9007199254740992LL;
448 Formattable::getInt64(UErrorCode
& status
) const
450 if (U_FAILURE(status
)) {
455 case Formattable::kLong
:
456 case Formattable::kInt64
:
457 return fValue
.fInt64
;
458 case Formattable::kDouble
:
459 if (fValue
.fDouble
> (double)U_INT64_MAX
) {
460 status
= U_INVALID_FORMAT_ERROR
;
462 } else if (fValue
.fDouble
< (double)U_INT64_MIN
) {
463 status
= U_INVALID_FORMAT_ERROR
;
465 } else if (fabs(fValue
.fDouble
) > U_DOUBLE_MAX_EXACT_INT
&& fDecimalNum
!= NULL
) {
466 int64_t val
= fDecimalNum
->getInt64();
470 status
= U_INVALID_FORMAT_ERROR
;
471 return fValue
.fDouble
> 0 ? U_INT64_MAX
: U_INT64_MIN
;
474 return (int64_t)fValue
.fDouble
;
476 case Formattable::kObject
:
477 if (fValue
.fObject
== NULL
) {
478 status
= U_MEMORY_ALLOCATION_ERROR
;
481 if (instanceOfMeasure(fValue
.fObject
)) {
482 return ((const Measure
*) fValue
.fObject
)->
483 getNumber().getInt64(status
);
486 status
= U_INVALID_FORMAT_ERROR
;
491 // -------------------------------------
493 Formattable::getDouble(UErrorCode
& status
) const
495 if (U_FAILURE(status
)) {
500 case Formattable::kLong
:
501 case Formattable::kInt64
: // loses precision
502 return (double)fValue
.fInt64
;
503 case Formattable::kDouble
:
504 return fValue
.fDouble
;
505 case Formattable::kObject
:
506 if (fValue
.fObject
== NULL
) {
507 status
= U_MEMORY_ALLOCATION_ERROR
;
510 // TODO Later replace this with instanceof call
511 if (instanceOfMeasure(fValue
.fObject
)) {
512 return ((const Measure
*) fValue
.fObject
)->
513 getNumber().getDouble(status
);
516 status
= U_INVALID_FORMAT_ERROR
;
522 Formattable::getObject() const {
523 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
526 // -------------------------------------
527 // Sets the value to a double value d.
530 Formattable::setDouble(double d
)
537 // -------------------------------------
538 // Sets the value to a long value l.
541 Formattable::setLong(int32_t l
)
548 // -------------------------------------
549 // Sets the value to an int64 value ll.
552 Formattable::setInt64(int64_t ll
)
559 // -------------------------------------
560 // Sets the value to a Date instance d.
563 Formattable::setDate(UDate d
)
570 // -------------------------------------
571 // Sets the value to a string value stringToCopy.
574 Formattable::setString(const UnicodeString
& stringToCopy
)
578 fValue
.fString
= new UnicodeString(stringToCopy
);
581 // -------------------------------------
582 // Sets the value to an array of Formattable objects.
585 Formattable::setArray(const Formattable
* array
, int32_t count
)
589 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
590 fValue
.fArrayAndCount
.fCount
= count
;
593 // -------------------------------------
594 // Adopts the stringToAdopt value.
597 Formattable::adoptString(UnicodeString
* stringToAdopt
)
601 fValue
.fString
= stringToAdopt
;
604 // -------------------------------------
605 // Adopts the array value and its count.
608 Formattable::adoptArray(Formattable
* array
, int32_t count
)
612 fValue
.fArrayAndCount
.fArray
= array
;
613 fValue
.fArrayAndCount
.fCount
= count
;
617 Formattable::adoptObject(UObject
* objectToAdopt
) {
620 fValue
.fObject
= objectToAdopt
;
623 // -------------------------------------
625 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
627 if (fType
!= kString
) {
628 setError(status
, U_INVALID_FORMAT_ERROR
);
631 if (fValue
.fString
== NULL
) {
632 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
634 result
= *fValue
.fString
;
640 // -------------------------------------
642 Formattable::getString(UErrorCode
& status
) const
644 if (fType
!= kString
) {
645 setError(status
, U_INVALID_FORMAT_ERROR
);
648 if (fValue
.fString
== NULL
) {
649 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
652 return *fValue
.fString
;
655 // -------------------------------------
657 Formattable::getString(UErrorCode
& status
)
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::getArray(int32_t& count
, UErrorCode
& status
) const
674 if (fType
!= kArray
) {
675 setError(status
, U_INVALID_FORMAT_ERROR
);
679 count
= fValue
.fArrayAndCount
.fCount
;
680 return fValue
.fArrayAndCount
.fArray
;
683 // -------------------------------------
684 // Gets the bogus string, ensures mondo bogosity.
687 Formattable::getBogus() const
689 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
693 // --------------------------------------
694 StringPiece
Formattable::getDecimalNumber(UErrorCode
&status
) {
695 if (U_FAILURE(status
)) {
698 if (fDecimalStr
!= NULL
) {
699 return fDecimalStr
->toStringPiece();
702 CharString
*decimalStr
= internalGetCharString(status
);
703 if(decimalStr
== NULL
) {
704 return ""; // getDecimalNumber returns "" for error cases
706 return decimalStr
->toStringPiece();
710 CharString
*Formattable::internalGetCharString(UErrorCode
&status
) {
711 if(fDecimalStr
== NULL
) {
712 if (fDecimalNum
== NULL
) {
713 // No decimal number for the formattable yet. Which means the value was
714 // set directly by the user as an int, int64 or double. If the value came
715 // from parsing, or from the user setting a decimal number, fDecimalNum
716 // would already be set.
718 fDecimalNum
= new DigitList
; // TODO: use internal digit list
719 if (fDecimalNum
== NULL
) {
720 status
= U_MEMORY_ALLOCATION_ERROR
;
726 fDecimalNum
->set(this->getDouble());
729 fDecimalNum
->set(this->getLong());
732 fDecimalNum
->set(this->getInt64());
735 // The formattable's value is not a numeric type.
736 status
= U_INVALID_STATE_ERROR
;
741 fDecimalStr
= new CharString
;
742 if (fDecimalStr
== NULL
) {
743 status
= U_MEMORY_ALLOCATION_ERROR
;
746 fDecimalNum
->getDecimal(*fDecimalStr
, status
);
753 Formattable::getInternalDigitList() {
754 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
755 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
757 fDecimalNum
= new (&(stackData
->stackDecimalNum
), kOnStack
) DigitList();
759 fDecimalNum
->clear();
764 // ---------------------------------------
766 Formattable::adoptDigitList(DigitList
*dl
) {
767 if(fDecimalNum
==dl
) {
768 fDecimalNum
= NULL
; // don't delete
774 if(dl
==NULL
) { // allow adoptDigitList(NULL) to clear
778 // Set the value into the Union of simple type values.
779 // Cannot use the set() functions because they would delete the fDecimalNum value,
781 if (fDecimalNum
->fitsIntoLong(FALSE
)) {
783 fValue
.fInt64
= fDecimalNum
->getLong();
784 } else if (fDecimalNum
->fitsIntoInt64(FALSE
)) {
786 fValue
.fInt64
= fDecimalNum
->getInt64();
789 fValue
.fDouble
= fDecimalNum
->getDouble();
794 // ---------------------------------------
796 Formattable::setDecimalNumber(const StringPiece
&numberString
, UErrorCode
&status
) {
797 if (U_FAILURE(status
)) {
802 // Copy the input string and nul-terminate it.
803 // The decNumber library requires nul-terminated input. StringPiece input
804 // is not guaranteed nul-terminated. Too bad.
805 // CharString automatically adds the nul.
806 DigitList
*dnum
= new DigitList(); // TODO: use getInternalDigitList
808 status
= U_MEMORY_ALLOCATION_ERROR
;
811 dnum
->set(CharString(numberString
, status
).toStringPiece(), status
);
812 if (U_FAILURE(status
)) {
814 return; // String didn't contain a decimal number.
816 adoptDigitList(dnum
);
818 // Note that we do not hang on to the caller's input string.
819 // If we are asked for the string, we will regenerate one from fDecimalNum.
823 //----------------------------------------------------
825 //----------------------------------------------------
831 #include "unicode/datefmt.h"
834 class FormattableStreamer
/* not : public UObject because all methods are static */ {
836 static void streamOut(ostream
& stream
, const Formattable
& obj
);
839 FormattableStreamer() {} // private - forbid instantiation
842 // This is for debugging purposes only. This will send a displayable
843 // form of the Formattable object to the output stream.
846 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
848 static DateFormat
*defDateFormat
= 0;
850 UnicodeString buffer
;
851 switch(obj
.getType()) {
852 case Formattable::kDate
:
853 // Creates a DateFormat instance for formatting the
855 if (defDateFormat
== 0) {
856 defDateFormat
= DateFormat::createInstance();
858 defDateFormat
->format(obj
.getDate(), buffer
);
861 case Formattable::kDouble
:
862 // Output the double as is.
863 stream
<< obj
.getDouble() << 'D';
865 case Formattable::kLong
:
866 // Output the double as is.
867 stream
<< obj
.getLong() << 'L';
869 case Formattable::kString
:
870 // Output the double as is. Please see UnicodeString console
871 // I/O routine for more details.
872 stream
<< '"' << obj
.getString(buffer
) << '"';
874 case Formattable::kArray
:
876 const Formattable
* array
;
877 array
= obj
.getArray(count
);
879 // Recursively calling the console I/O routine for each element in the array.
880 for (i
=0; i
<count
; ++i
) {
881 FormattableStreamer::streamOut(stream
, array
[i
]);
882 stream
<< ( (i
==(count
-1)) ? "" : ", " );
887 // Not a recognizable Formattable object.
888 stream
<< "INVALID_Formattable";
898 /* ---- UFormattable implementation ---- */
902 U_DRAFT UFormattable
* U_EXPORT2
903 ufmt_open(UErrorCode
*status
) {
904 if( U_FAILURE(*status
) ) {
907 UFormattable
*fmt
= (new Formattable())->toUFormattable();
910 *status
= U_MEMORY_ALLOCATION_ERROR
;
915 U_DRAFT
void U_EXPORT2
916 ufmt_close(UFormattable
*fmt
) {
917 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
922 U_INTERNAL UFormattableType U_EXPORT2
923 ufmt_getType(const UFormattable
*fmt
, UErrorCode
*status
) {
924 if(U_FAILURE(*status
)) {
925 return (UFormattableType
)UFMT_COUNT
;
927 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
928 return (UFormattableType
)obj
->getType();
932 U_INTERNAL UBool U_EXPORT2
933 ufmt_isNumeric(const UFormattable
*fmt
) {
934 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
935 return obj
->isNumeric();
938 U_DRAFT UDate U_EXPORT2
939 ufmt_getDate(const UFormattable
*fmt
, UErrorCode
*status
) {
940 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
942 return obj
->getDate(*status
);
945 U_DRAFT
double U_EXPORT2
946 ufmt_getDouble(UFormattable
*fmt
, UErrorCode
*status
) {
947 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
949 return obj
->getDouble(*status
);
952 U_DRAFT
int32_t U_EXPORT2
953 ufmt_getLong(UFormattable
*fmt
, UErrorCode
*status
) {
954 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
956 return obj
->getLong(*status
);
960 U_DRAFT
const void *U_EXPORT2
961 ufmt_getObject(const UFormattable
*fmt
, UErrorCode
*status
) {
962 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
964 const void *ret
= obj
->getObject();
966 (obj
->getType() != Formattable::kObject
) &&
967 U_SUCCESS( *status
)) {
968 *status
= U_INVALID_FORMAT_ERROR
;
973 U_DRAFT
const UChar
* U_EXPORT2
974 ufmt_getUChars(UFormattable
*fmt
, int32_t *len
, UErrorCode
*status
) {
975 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
977 // avoid bogosity by checking the type first.
978 if( obj
->getType() != Formattable::kString
) {
979 if( U_SUCCESS(*status
) ){
980 *status
= U_INVALID_FORMAT_ERROR
;
985 // This should return a valid string
986 UnicodeString
&str
= obj
->getString(*status
);
987 if( U_SUCCESS(*status
) && len
!= NULL
) {
990 return str
.getTerminatedBuffer();
993 U_DRAFT
int32_t U_EXPORT2
994 ufmt_getArrayLength(const UFormattable
* fmt
, UErrorCode
*status
) {
995 const Formattable
*obj
= Formattable::fromUFormattable(fmt
);
998 (void)obj
->getArray(count
, *status
);
1002 U_DRAFT UFormattable
* U_EXPORT2
1003 ufmt_getArrayItemByIndex(UFormattable
* fmt
, int32_t n
, UErrorCode
*status
) {
1004 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1006 (void)obj
->getArray(count
, *status
);
1007 if(U_FAILURE(*status
)) {
1009 } else if(n
<0 || n
>=count
) {
1010 setError(*status
, U_INDEX_OUTOFBOUNDS_ERROR
);
1013 return (*obj
)[n
].toUFormattable(); // returns non-const Formattable
1017 U_DRAFT
const char * U_EXPORT2
1018 ufmt_getDecNumChars(UFormattable
*fmt
, int32_t *len
, UErrorCode
*status
) {
1019 if(U_FAILURE(*status
)) {
1022 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1023 CharString
*charString
= obj
->internalGetCharString(*status
);
1024 if(U_FAILURE(*status
)) {
1027 if(charString
== NULL
) {
1028 *status
= U_MEMORY_ALLOCATION_ERROR
;
1032 *len
= charString
->length();
1034 return charString
->data();
1038 U_DRAFT
int64_t U_EXPORT2
1039 ufmt_getInt64(UFormattable
*fmt
, UErrorCode
*status
) {
1040 Formattable
*obj
= Formattable::fromUFormattable(fmt
);
1041 return obj
->getInt64(*status
);
1044 #endif /* #if !UCONFIG_NO_FORMATTING */