2 *******************************************************************************
3 * Copyright (C) 1997-2012, 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"
28 #include "decNumber.h"
31 // *****************************************************************************
33 // *****************************************************************************
37 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable
)
39 #include "fmtableimp.h"
41 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
43 // NOTE: As of 3.0, there are limitations to the UObject API. It does
44 // not (yet) support cloning, operator=, nor operator==. To
45 // work around this, I implement some simple inlines here. Later
46 // these can be modified or removed. [alan]
48 // NOTE: These inlines assume that all fObjects are in fact instances
49 // of the Measure class, which is true as of 3.0. [alan]
51 // Return TRUE if *a == *b.
52 static inline UBool
objectEquals(const UObject
* a
, const UObject
* b
) {
53 // LATER: return *a == *b;
54 return *((const Measure
*) a
) == *((const Measure
*) b
);
57 // Return a clone of *a.
58 static inline UObject
* objectClone(const UObject
* a
) {
59 // LATER: return a->clone();
60 return ((const Measure
*) a
)->clone();
63 // Return TRUE if *a is an instance of Measure.
64 static inline UBool
instanceOfMeasure(const UObject
* a
) {
65 return dynamic_cast<const Measure
*>(a
) != NULL
;
69 * Creates a new Formattable array and copies the values from the specified
71 * @param array the original array
72 * @param count the original array count
73 * @return the new Formattable array.
75 static Formattable
* createArrayCopy(const Formattable
* array
, int32_t count
) {
76 Formattable
*result
= new Formattable
[count
];
78 for (int32_t i
=0; i
<count
; ++i
)
79 result
[i
] = array
[i
]; // Don't memcpy!
84 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
87 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
89 static void setError(UErrorCode
& ec
, UErrorCode err
) {
96 // Common initialization code, shared by constructors.
97 // Put everything into a known state.
99 void Formattable::init() {
107 // -------------------------------------
108 // default constructor.
109 // Creates a formattable object with a long value 0.
111 Formattable::Formattable() {
115 // -------------------------------------
116 // Creates a formattable object with a Date instance.
118 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
125 // -------------------------------------
126 // Creates a formattable object with a double value.
128 Formattable::Formattable(double value
)
132 fValue
.fDouble
= value
;
135 // -------------------------------------
136 // Creates a formattable object with an int32_t value.
138 Formattable::Formattable(int32_t value
)
141 fValue
.fInt64
= value
;
144 // -------------------------------------
145 // Creates a formattable object with an int64_t value.
147 Formattable::Formattable(int64_t value
)
151 fValue
.fInt64
= value
;
154 // -------------------------------------
155 // Creates a formattable object with a decimal number value from a string.
157 Formattable::Formattable(const StringPiece
&number
, UErrorCode
&status
) {
159 setDecimalNumber(number
, status
);
163 // -------------------------------------
164 // Creates a formattable object with a UnicodeString instance.
166 Formattable::Formattable(const UnicodeString
& stringToCopy
)
170 fValue
.fString
= new UnicodeString(stringToCopy
);
173 // -------------------------------------
174 // Creates a formattable object with a UnicodeString* value.
175 // (adopting symantics)
177 Formattable::Formattable(UnicodeString
* stringToAdopt
)
181 fValue
.fString
= stringToAdopt
;
184 Formattable::Formattable(UObject
* objectToAdopt
)
188 fValue
.fObject
= objectToAdopt
;
191 // -------------------------------------
193 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
194 : UObject(), fType(kArray
)
198 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
199 fValue
.fArrayAndCount
.fCount
= count
;
202 // -------------------------------------
206 Formattable::Formattable(const Formattable
&source
)
213 // -------------------------------------
214 // assignment operator
217 Formattable::operator=(const Formattable
& source
)
221 // Disposes the current formattable value/setting.
224 // Sets the correct data type for this value.
225 fType
= source
.fType
;
229 // Sets each element in the array one by one and records the array count.
230 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
231 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
232 source
.fValue
.fArrayAndCount
.fCount
);
235 // Sets the string value.
236 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
239 // Sets the double value.
240 fValue
.fDouble
= source
.fValue
.fDouble
;
244 // Sets the long value.
245 fValue
.fInt64
= source
.fValue
.fInt64
;
248 // Sets the Date value.
249 fValue
.fDate
= source
.fValue
.fDate
;
252 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
256 UErrorCode status
= U_ZERO_ERROR
;
257 if (source
.fDecimalNum
!= NULL
) {
258 fDecimalNum
= new DigitList(*source
.fDecimalNum
); // TODO: use internal digit list
260 if (source
.fDecimalStr
!= NULL
) {
261 fDecimalStr
= new CharString(*source
.fDecimalStr
, status
);
262 if (U_FAILURE(status
)) {
271 // -------------------------------------
274 Formattable::operator==(const Formattable
& that
) const
278 if (this == &that
) return TRUE
;
280 // Returns FALSE if the data types are different.
281 if (fType
!= that
.fType
) return FALSE
;
283 // Compares the actual data values.
287 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
290 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
294 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
297 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
300 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
304 // Checks each element for equality.
305 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
306 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
313 if (fValue
.fObject
== NULL
|| that
.fValue
.fObject
== NULL
) {
316 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
321 // TODO: compare digit lists if numeric.
325 // -------------------------------------
327 Formattable::~Formattable()
332 // -------------------------------------
334 void Formattable::dispose()
336 // Deletes the data value if necessary.
339 delete fValue
.fString
;
342 delete[] fValue
.fArrayAndCount
.fArray
;
345 delete fValue
.fObject
;
357 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
358 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
361 fDecimalNum
->~DigitList(); // destruct, don't deallocate
367 Formattable::clone() const {
368 return new Formattable(*this);
371 // -------------------------------------
372 // Gets the data type of this Formattable object.
374 Formattable::getType() const
380 Formattable::isNumeric() const {
391 // -------------------------------------
393 //Formattable::getLong(UErrorCode* status) const
394 Formattable::getLong(UErrorCode
& status
) const
396 if (U_FAILURE(status
)) {
401 case Formattable::kLong
:
402 return (int32_t)fValue
.fInt64
;
403 case Formattable::kInt64
:
404 if (fValue
.fInt64
> INT32_MAX
) {
405 status
= U_INVALID_FORMAT_ERROR
;
407 } else if (fValue
.fInt64
< INT32_MIN
) {
408 status
= U_INVALID_FORMAT_ERROR
;
411 return (int32_t)fValue
.fInt64
;
413 case Formattable::kDouble
:
414 if (fValue
.fDouble
> INT32_MAX
) {
415 status
= U_INVALID_FORMAT_ERROR
;
417 } else if (fValue
.fDouble
< INT32_MIN
) {
418 status
= U_INVALID_FORMAT_ERROR
;
421 return (int32_t)fValue
.fDouble
; // loses fraction
423 case Formattable::kObject
:
424 if (fValue
.fObject
== NULL
) {
425 status
= U_MEMORY_ALLOCATION_ERROR
;
428 // TODO Later replace this with instanceof call
429 if (instanceOfMeasure(fValue
.fObject
)) {
430 return ((const Measure
*) fValue
.fObject
)->
431 getNumber().getLong(status
);
434 status
= U_INVALID_FORMAT_ERROR
;
439 // -------------------------------------
440 // Maximum int that can be represented exactly in a double. (53 bits)
441 // Larger ints may be rounded to a near-by value as not all are representable.
442 // TODO: move this constant elsewhere, possibly configure it for different
443 // floating point formats, if any non-standard ones are still in use.
444 static const int64_t U_DOUBLE_MAX_EXACT_INT
= 9007199254740992LL;
447 Formattable::getInt64(UErrorCode
& status
) const
449 if (U_FAILURE(status
)) {
454 case Formattable::kLong
:
455 case Formattable::kInt64
:
456 return fValue
.fInt64
;
457 case Formattable::kDouble
:
458 if (fValue
.fDouble
> (double)U_INT64_MAX
) {
459 status
= U_INVALID_FORMAT_ERROR
;
461 } else if (fValue
.fDouble
< (double)U_INT64_MIN
) {
462 status
= U_INVALID_FORMAT_ERROR
;
464 } else if (fabs(fValue
.fDouble
) > U_DOUBLE_MAX_EXACT_INT
&& fDecimalNum
!= NULL
) {
465 int64_t val
= fDecimalNum
->getInt64();
469 status
= U_INVALID_FORMAT_ERROR
;
470 return fValue
.fDouble
> 0 ? U_INT64_MAX
: U_INT64_MIN
;
473 return (int64_t)fValue
.fDouble
;
475 case Formattable::kObject
:
476 if (fValue
.fObject
== NULL
) {
477 status
= U_MEMORY_ALLOCATION_ERROR
;
480 if (instanceOfMeasure(fValue
.fObject
)) {
481 return ((const Measure
*) fValue
.fObject
)->
482 getNumber().getInt64(status
);
485 status
= U_INVALID_FORMAT_ERROR
;
490 // -------------------------------------
492 Formattable::getDouble(UErrorCode
& status
) const
494 if (U_FAILURE(status
)) {
499 case Formattable::kLong
:
500 case Formattable::kInt64
: // loses precision
501 return (double)fValue
.fInt64
;
502 case Formattable::kDouble
:
503 return fValue
.fDouble
;
504 case Formattable::kObject
:
505 if (fValue
.fObject
== NULL
) {
506 status
= U_MEMORY_ALLOCATION_ERROR
;
509 // TODO Later replace this with instanceof call
510 if (instanceOfMeasure(fValue
.fObject
)) {
511 return ((const Measure
*) fValue
.fObject
)->
512 getNumber().getDouble(status
);
515 status
= U_INVALID_FORMAT_ERROR
;
521 Formattable::getObject() const {
522 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
525 // -------------------------------------
526 // Sets the value to a double value d.
529 Formattable::setDouble(double d
)
536 // -------------------------------------
537 // Sets the value to a long value l.
540 Formattable::setLong(int32_t l
)
547 // -------------------------------------
548 // Sets the value to an int64 value ll.
551 Formattable::setInt64(int64_t ll
)
558 // -------------------------------------
559 // Sets the value to a Date instance d.
562 Formattable::setDate(UDate d
)
569 // -------------------------------------
570 // Sets the value to a string value stringToCopy.
573 Formattable::setString(const UnicodeString
& stringToCopy
)
577 fValue
.fString
= new UnicodeString(stringToCopy
);
580 // -------------------------------------
581 // Sets the value to an array of Formattable objects.
584 Formattable::setArray(const Formattable
* array
, int32_t count
)
588 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
589 fValue
.fArrayAndCount
.fCount
= count
;
592 // -------------------------------------
593 // Adopts the stringToAdopt value.
596 Formattable::adoptString(UnicodeString
* stringToAdopt
)
600 fValue
.fString
= stringToAdopt
;
603 // -------------------------------------
604 // Adopts the array value and its count.
607 Formattable::adoptArray(Formattable
* array
, int32_t count
)
611 fValue
.fArrayAndCount
.fArray
= array
;
612 fValue
.fArrayAndCount
.fCount
= count
;
616 Formattable::adoptObject(UObject
* objectToAdopt
) {
619 fValue
.fObject
= objectToAdopt
;
622 // -------------------------------------
624 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
626 if (fType
!= kString
) {
627 setError(status
, U_INVALID_FORMAT_ERROR
);
630 if (fValue
.fString
== NULL
) {
631 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
633 result
= *fValue
.fString
;
639 // -------------------------------------
641 Formattable::getString(UErrorCode
& status
) const
643 if (fType
!= kString
) {
644 setError(status
, U_INVALID_FORMAT_ERROR
);
647 if (fValue
.fString
== NULL
) {
648 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
651 return *fValue
.fString
;
654 // -------------------------------------
656 Formattable::getString(UErrorCode
& status
)
658 if (fType
!= kString
) {
659 setError(status
, U_INVALID_FORMAT_ERROR
);
662 if (fValue
.fString
== NULL
) {
663 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
666 return *fValue
.fString
;
669 // -------------------------------------
671 Formattable::getArray(int32_t& count
, UErrorCode
& status
) const
673 if (fType
!= kArray
) {
674 setError(status
, U_INVALID_FORMAT_ERROR
);
678 count
= fValue
.fArrayAndCount
.fCount
;
679 return fValue
.fArrayAndCount
.fArray
;
682 // -------------------------------------
683 // Gets the bogus string, ensures mondo bogosity.
686 Formattable::getBogus() const
688 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
692 // --------------------------------------
693 StringPiece
Formattable::getDecimalNumber(UErrorCode
&status
) {
694 if (U_FAILURE(status
)) {
697 if (fDecimalStr
!= NULL
) {
698 return fDecimalStr
->toStringPiece();
701 if (fDecimalNum
== NULL
) {
702 // No decimal number for the formattable yet. Which means the value was
703 // set directly by the user as an int, int64 or double. If the value came
704 // from parsing, or from the user setting a decimal number, fDecimalNum
705 // would already be set.
707 fDecimalNum
= new DigitList
; // TODO: use internal digit list
708 if (fDecimalNum
== NULL
) {
709 status
= U_MEMORY_ALLOCATION_ERROR
;
715 fDecimalNum
->set(this->getDouble());
718 fDecimalNum
->set(this->getLong());
721 fDecimalNum
->set(this->getInt64());
724 // The formattable's value is not a numeric type.
725 status
= U_INVALID_STATE_ERROR
;
730 fDecimalStr
= new CharString
;
731 if (fDecimalStr
== NULL
) {
732 status
= U_MEMORY_ALLOCATION_ERROR
;
735 fDecimalNum
->getDecimal(*fDecimalStr
, status
);
737 return fDecimalStr
->toStringPiece();
742 Formattable::getInternalDigitList() {
743 FmtStackData
*stackData
= (FmtStackData
*)fStackData
;
744 if(fDecimalNum
!= &(stackData
->stackDecimalNum
)) {
746 fDecimalNum
= new (&(stackData
->stackDecimalNum
), kOnStack
) DigitList();
748 fDecimalNum
->clear();
753 // ---------------------------------------
755 Formattable::adoptDigitList(DigitList
*dl
) {
756 if(fDecimalNum
==dl
) {
757 fDecimalNum
= NULL
; // don't delete
763 if(dl
==NULL
) { // allow adoptDigitList(NULL) to clear
767 // Set the value into the Union of simple type values.
768 // Cannot use the set() functions because they would delete the fDecimalNum value,
770 if (fDecimalNum
->fitsIntoLong(FALSE
)) {
772 fValue
.fInt64
= fDecimalNum
->getLong();
773 } else if (fDecimalNum
->fitsIntoInt64(FALSE
)) {
775 fValue
.fInt64
= fDecimalNum
->getInt64();
778 fValue
.fDouble
= fDecimalNum
->getDouble();
783 // ---------------------------------------
785 Formattable::setDecimalNumber(const StringPiece
&numberString
, UErrorCode
&status
) {
786 if (U_FAILURE(status
)) {
791 // Copy the input string and nul-terminate it.
792 // The decNumber library requires nul-terminated input. StringPiece input
793 // is not guaranteed nul-terminated. Too bad.
794 // CharString automatically adds the nul.
795 DigitList
*dnum
= new DigitList(); // TODO: use getInternalDigitList
797 status
= U_MEMORY_ALLOCATION_ERROR
;
800 dnum
->set(CharString(numberString
, status
).toStringPiece(), status
);
801 if (U_FAILURE(status
)) {
803 return; // String didn't contain a decimal number.
805 adoptDigitList(dnum
);
807 // Note that we do not hang on to the caller's input string.
808 // If we are asked for the string, we will regenerate one from fDecimalNum.
812 //----------------------------------------------------
814 //----------------------------------------------------
820 #include "unicode/datefmt.h"
823 class FormattableStreamer
/* not : public UObject because all methods are static */ {
825 static void streamOut(ostream
& stream
, const Formattable
& obj
);
828 FormattableStreamer() {} // private - forbid instantiation
831 // This is for debugging purposes only. This will send a displayable
832 // form of the Formattable object to the output stream.
835 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
837 static DateFormat
*defDateFormat
= 0;
839 UnicodeString buffer
;
840 switch(obj
.getType()) {
841 case Formattable::kDate
:
842 // Creates a DateFormat instance for formatting the
844 if (defDateFormat
== 0) {
845 defDateFormat
= DateFormat::createInstance();
847 defDateFormat
->format(obj
.getDate(), buffer
);
850 case Formattable::kDouble
:
851 // Output the double as is.
852 stream
<< obj
.getDouble() << 'D';
854 case Formattable::kLong
:
855 // Output the double as is.
856 stream
<< obj
.getLong() << 'L';
858 case Formattable::kString
:
859 // Output the double as is. Please see UnicodeString console
860 // I/O routine for more details.
861 stream
<< '"' << obj
.getString(buffer
) << '"';
863 case Formattable::kArray
:
865 const Formattable
* array
;
866 array
= obj
.getArray(count
);
868 // Recursively calling the console I/O routine for each element in the array.
869 for (i
=0; i
<count
; ++i
) {
870 FormattableStreamer::streamOut(stream
, array
[i
]);
871 stream
<< ( (i
==(count
-1)) ? "" : ", " );
876 // Not a recognizable Formattable object.
877 stream
<< "INVALID_Formattable";
887 #endif /* #if !UCONFIG_NO_FORMATTING */