2 *******************************************************************************
3 * Copyright (C) 1997-2011, 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 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
41 // NOTE: As of 3.0, there are limitations to the UObject API. It does
42 // not (yet) support cloning, operator=, nor operator==. To
43 // work around this, I implement some simple inlines here. Later
44 // these can be modified or removed. [alan]
46 // NOTE: These inlines assume that all fObjects are in fact instances
47 // of the Measure class, which is true as of 3.0. [alan]
49 // Return TRUE if *a == *b.
50 static inline UBool
objectEquals(const UObject
* a
, const UObject
* b
) {
51 // LATER: return *a == *b;
52 return *((const Measure
*) a
) == *((const Measure
*) b
);
55 // Return a clone of *a.
56 static inline UObject
* objectClone(const UObject
* a
) {
57 // LATER: return a->clone();
58 return ((const Measure
*) a
)->clone();
61 // Return TRUE if *a is an instance of Measure.
62 static inline UBool
instanceOfMeasure(const UObject
* a
) {
63 return dynamic_cast<const Measure
*>(a
) != NULL
;
67 * Creates a new Formattable array and copies the values from the specified
69 * @param array the original array
70 * @param count the original array count
71 * @return the new Formattable array.
73 static Formattable
* createArrayCopy(const Formattable
* array
, int32_t count
) {
74 Formattable
*result
= new Formattable
[count
];
76 for (int32_t i
=0; i
<count
; ++i
)
77 result
[i
] = array
[i
]; // Don't memcpy!
82 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
85 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
87 static void setError(UErrorCode
& ec
, UErrorCode err
) {
94 // Common initialization code, shared by constructors.
95 // Put everything into a known state.
97 void Formattable::init() {
105 // -------------------------------------
106 // default constructor.
107 // Creates a formattable object with a long value 0.
109 Formattable::Formattable() {
113 // -------------------------------------
114 // Creates a formattable object with a Date instance.
116 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
123 // -------------------------------------
124 // Creates a formattable object with a double value.
126 Formattable::Formattable(double value
)
130 fValue
.fDouble
= value
;
133 // -------------------------------------
134 // Creates a formattable object with an int32_t value.
136 Formattable::Formattable(int32_t value
)
139 fValue
.fInt64
= value
;
142 // -------------------------------------
143 // Creates a formattable object with an int64_t value.
145 Formattable::Formattable(int64_t value
)
149 fValue
.fInt64
= value
;
152 // -------------------------------------
153 // Creates a formattable object with a decimal number value from a string.
155 Formattable::Formattable(const StringPiece
&number
, UErrorCode
&status
) {
157 setDecimalNumber(number
, status
);
161 // -------------------------------------
162 // Creates a formattable object with a UnicodeString instance.
164 Formattable::Formattable(const UnicodeString
& stringToCopy
)
168 fValue
.fString
= new UnicodeString(stringToCopy
);
171 // -------------------------------------
172 // Creates a formattable object with a UnicodeString* value.
173 // (adopting symantics)
175 Formattable::Formattable(UnicodeString
* stringToAdopt
)
179 fValue
.fString
= stringToAdopt
;
182 Formattable::Formattable(UObject
* objectToAdopt
)
186 fValue
.fObject
= objectToAdopt
;
189 // -------------------------------------
191 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
192 : UObject(), fType(kArray
)
196 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
197 fValue
.fArrayAndCount
.fCount
= count
;
200 // -------------------------------------
204 Formattable::Formattable(const Formattable
&source
)
211 // -------------------------------------
212 // assignment operator
215 Formattable::operator=(const Formattable
& source
)
219 // Disposes the current formattable value/setting.
222 // Sets the correct data type for this value.
223 fType
= source
.fType
;
227 // Sets each element in the array one by one and records the array count.
228 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
229 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
230 source
.fValue
.fArrayAndCount
.fCount
);
233 // Sets the string value.
234 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
237 // Sets the double value.
238 fValue
.fDouble
= source
.fValue
.fDouble
;
242 // Sets the long value.
243 fValue
.fInt64
= source
.fValue
.fInt64
;
246 // Sets the Date value.
247 fValue
.fDate
= source
.fValue
.fDate
;
250 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
254 UErrorCode status
= U_ZERO_ERROR
;
255 if (source
.fDecimalNum
!= NULL
) {
256 fDecimalNum
= new DigitList(*source
.fDecimalNum
);
258 if (source
.fDecimalStr
!= NULL
) {
259 fDecimalStr
= new CharString(*source
.fDecimalStr
, status
);
260 if (U_FAILURE(status
)) {
269 // -------------------------------------
272 Formattable::operator==(const Formattable
& that
) const
276 if (this == &that
) return TRUE
;
278 // Returns FALSE if the data types are different.
279 if (fType
!= that
.fType
) return FALSE
;
281 // Compares the actual data values.
285 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
288 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
292 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
295 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
298 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
302 // Checks each element for equality.
303 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
304 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
311 if (fValue
.fObject
== NULL
|| that
.fValue
.fObject
== NULL
) {
314 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
319 // TODO: compare digit lists if numeric.
323 // -------------------------------------
325 Formattable::~Formattable()
330 // -------------------------------------
332 void Formattable::dispose()
334 // Deletes the data value if necessary.
337 delete fValue
.fString
;
340 delete[] fValue
.fArrayAndCount
.fArray
;
343 delete fValue
.fObject
;
358 Formattable::clone() const {
359 return new Formattable(*this);
362 // -------------------------------------
363 // Gets the data type of this Formattable object.
365 Formattable::getType() const
371 Formattable::isNumeric() const {
382 // -------------------------------------
384 //Formattable::getLong(UErrorCode* status) const
385 Formattable::getLong(UErrorCode
& status
) const
387 if (U_FAILURE(status
)) {
392 case Formattable::kLong
:
393 return (int32_t)fValue
.fInt64
;
394 case Formattable::kInt64
:
395 if (fValue
.fInt64
> INT32_MAX
) {
396 status
= U_INVALID_FORMAT_ERROR
;
398 } else if (fValue
.fInt64
< INT32_MIN
) {
399 status
= U_INVALID_FORMAT_ERROR
;
402 return (int32_t)fValue
.fInt64
;
404 case Formattable::kDouble
:
405 if (fValue
.fDouble
> INT32_MAX
) {
406 status
= U_INVALID_FORMAT_ERROR
;
408 } else if (fValue
.fDouble
< INT32_MIN
) {
409 status
= U_INVALID_FORMAT_ERROR
;
412 return (int32_t)fValue
.fDouble
; // loses fraction
414 case Formattable::kObject
:
415 if (fValue
.fObject
== NULL
) {
416 status
= U_MEMORY_ALLOCATION_ERROR
;
419 // TODO Later replace this with instanceof call
420 if (instanceOfMeasure(fValue
.fObject
)) {
421 return ((const Measure
*) fValue
.fObject
)->
422 getNumber().getLong(status
);
425 status
= U_INVALID_FORMAT_ERROR
;
430 // -------------------------------------
431 // Maximum int that can be represented exactly in a double. (53 bits)
432 // Larger ints may be rounded to a near-by value as not all are representable.
433 // TODO: move this constant elsewhere, possibly configure it for different
434 // floating point formats, if any non-standard ones are still in use.
435 static const int64_t U_DOUBLE_MAX_EXACT_INT
= 9007199254740992LL;
438 Formattable::getInt64(UErrorCode
& status
) const
440 if (U_FAILURE(status
)) {
445 case Formattable::kLong
:
446 case Formattable::kInt64
:
447 return fValue
.fInt64
;
448 case Formattable::kDouble
:
449 if (fValue
.fDouble
> (double)U_INT64_MAX
) {
450 status
= U_INVALID_FORMAT_ERROR
;
452 } else if (fValue
.fDouble
< (double)U_INT64_MIN
) {
453 status
= U_INVALID_FORMAT_ERROR
;
455 } else if (fabs(fValue
.fDouble
) > U_DOUBLE_MAX_EXACT_INT
&& fDecimalNum
!= NULL
) {
456 int64_t val
= fDecimalNum
->getInt64();
460 status
= U_INVALID_FORMAT_ERROR
;
461 return fValue
.fDouble
> 0 ? U_INT64_MAX
: U_INT64_MIN
;
464 return (int64_t)fValue
.fDouble
;
466 case Formattable::kObject
:
467 if (fValue
.fObject
== NULL
) {
468 status
= U_MEMORY_ALLOCATION_ERROR
;
471 if (instanceOfMeasure(fValue
.fObject
)) {
472 return ((const Measure
*) fValue
.fObject
)->
473 getNumber().getInt64(status
);
476 status
= U_INVALID_FORMAT_ERROR
;
481 // -------------------------------------
483 Formattable::getDouble(UErrorCode
& status
) const
485 if (U_FAILURE(status
)) {
490 case Formattable::kLong
:
491 case Formattable::kInt64
: // loses precision
492 return (double)fValue
.fInt64
;
493 case Formattable::kDouble
:
494 return fValue
.fDouble
;
495 case Formattable::kObject
:
496 if (fValue
.fObject
== NULL
) {
497 status
= U_MEMORY_ALLOCATION_ERROR
;
500 // TODO Later replace this with instanceof call
501 if (instanceOfMeasure(fValue
.fObject
)) {
502 return ((const Measure
*) fValue
.fObject
)->
503 getNumber().getDouble(status
);
506 status
= U_INVALID_FORMAT_ERROR
;
512 Formattable::getObject() const {
513 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
516 // -------------------------------------
517 // Sets the value to a double value d.
520 Formattable::setDouble(double d
)
527 // -------------------------------------
528 // Sets the value to a long value l.
531 Formattable::setLong(int32_t l
)
538 // -------------------------------------
539 // Sets the value to an int64 value ll.
542 Formattable::setInt64(int64_t ll
)
549 // -------------------------------------
550 // Sets the value to a Date instance d.
553 Formattable::setDate(UDate d
)
560 // -------------------------------------
561 // Sets the value to a string value stringToCopy.
564 Formattable::setString(const UnicodeString
& stringToCopy
)
568 fValue
.fString
= new UnicodeString(stringToCopy
);
571 // -------------------------------------
572 // Sets the value to an array of Formattable objects.
575 Formattable::setArray(const Formattable
* array
, int32_t count
)
579 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
580 fValue
.fArrayAndCount
.fCount
= count
;
583 // -------------------------------------
584 // Adopts the stringToAdopt value.
587 Formattable::adoptString(UnicodeString
* stringToAdopt
)
591 fValue
.fString
= stringToAdopt
;
594 // -------------------------------------
595 // Adopts the array value and its count.
598 Formattable::adoptArray(Formattable
* array
, int32_t count
)
602 fValue
.fArrayAndCount
.fArray
= array
;
603 fValue
.fArrayAndCount
.fCount
= count
;
607 Formattable::adoptObject(UObject
* objectToAdopt
) {
610 fValue
.fObject
= objectToAdopt
;
613 // -------------------------------------
615 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
617 if (fType
!= kString
) {
618 setError(status
, U_INVALID_FORMAT_ERROR
);
621 if (fValue
.fString
== NULL
) {
622 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
624 result
= *fValue
.fString
;
630 // -------------------------------------
632 Formattable::getString(UErrorCode
& status
) const
634 if (fType
!= kString
) {
635 setError(status
, U_INVALID_FORMAT_ERROR
);
638 if (fValue
.fString
== NULL
) {
639 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
642 return *fValue
.fString
;
645 // -------------------------------------
647 Formattable::getString(UErrorCode
& status
)
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::getArray(int32_t& count
, UErrorCode
& status
) const
664 if (fType
!= kArray
) {
665 setError(status
, U_INVALID_FORMAT_ERROR
);
669 count
= fValue
.fArrayAndCount
.fCount
;
670 return fValue
.fArrayAndCount
.fArray
;
673 // -------------------------------------
674 // Gets the bogus string, ensures mondo bogosity.
677 Formattable::getBogus() const
679 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
683 // --------------------------------------
684 StringPiece
Formattable::getDecimalNumber(UErrorCode
&status
) {
685 if (U_FAILURE(status
)) {
688 if (fDecimalStr
!= NULL
) {
689 return fDecimalStr
->toStringPiece();
692 if (fDecimalNum
== NULL
) {
693 // No decimal number for the formattable yet. Which means the value was
694 // set directly by the user as an int, int64 or double. If the value came
695 // from parsing, or from the user setting a decimal number, fDecimalNum
696 // would already be set.
698 fDecimalNum
= new DigitList
;
699 if (fDecimalNum
== NULL
) {
700 status
= U_MEMORY_ALLOCATION_ERROR
;
706 fDecimalNum
->set(this->getDouble());
709 fDecimalNum
->set(this->getLong());
712 fDecimalNum
->set(this->getInt64());
715 // The formattable's value is not a numeric type.
716 status
= U_INVALID_STATE_ERROR
;
721 fDecimalStr
= new CharString
;
722 if (fDecimalStr
== NULL
) {
723 status
= U_MEMORY_ALLOCATION_ERROR
;
726 fDecimalNum
->getDecimal(*fDecimalStr
, status
);
728 return fDecimalStr
->toStringPiece();
733 // ---------------------------------------
735 Formattable::adoptDigitList(DigitList
*dl
) {
740 // Set the value into the Union of simple type values.
741 // Cannot use the set() functions because they would delete the fDecimalNum value,
743 if (fDecimalNum
->fitsIntoLong(FALSE
)) {
745 fValue
.fInt64
= fDecimalNum
->getLong();
746 } else if (fDecimalNum
->fitsIntoInt64(FALSE
)) {
748 fValue
.fInt64
= fDecimalNum
->getInt64();
751 fValue
.fDouble
= fDecimalNum
->getDouble();
756 // ---------------------------------------
758 Formattable::setDecimalNumber(const StringPiece
&numberString
, UErrorCode
&status
) {
759 if (U_FAILURE(status
)) {
764 // Copy the input string and nul-terminate it.
765 // The decNumber library requires nul-terminated input. StringPiece input
766 // is not guaranteed nul-terminated. Too bad.
767 // CharString automatically adds the nul.
768 DigitList
*dnum
= new DigitList();
770 status
= U_MEMORY_ALLOCATION_ERROR
;
773 dnum
->set(CharString(numberString
, status
).toStringPiece(), status
);
774 if (U_FAILURE(status
)) {
776 return; // String didn't contain a decimal number.
778 adoptDigitList(dnum
);
780 // Note that we do not hang on to the caller's input string.
781 // If we are asked for the string, we will regenerate one from fDecimalNum.
785 //----------------------------------------------------
787 //----------------------------------------------------
790 #if U_IOSTREAM_SOURCE >= 199711
793 #elif U_IOSTREAM_SOURCE >= 198506
794 #include <iostream.h>
797 #include "unicode/datefmt.h"
800 class FormattableStreamer
/* not : public UObject because all methods are static */ {
802 static void streamOut(ostream
& stream
, const Formattable
& obj
);
805 FormattableStreamer() {} // private - forbid instantiation
808 // This is for debugging purposes only. This will send a displayable
809 // form of the Formattable object to the output stream.
812 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
814 static DateFormat
*defDateFormat
= 0;
816 UnicodeString buffer
;
817 switch(obj
.getType()) {
818 case Formattable::kDate
:
819 // Creates a DateFormat instance for formatting the
821 if (defDateFormat
== 0) {
822 defDateFormat
= DateFormat::createInstance();
824 defDateFormat
->format(obj
.getDate(), buffer
);
827 case Formattable::kDouble
:
828 // Output the double as is.
829 stream
<< obj
.getDouble() << 'D';
831 case Formattable::kLong
:
832 // Output the double as is.
833 stream
<< obj
.getLong() << 'L';
835 case Formattable::kString
:
836 // Output the double as is. Please see UnicodeString console
837 // I/O routine for more details.
838 stream
<< '"' << obj
.getString(buffer
) << '"';
840 case Formattable::kArray
:
842 const Formattable
* array
;
843 array
= obj
.getArray(count
);
845 // Recursively calling the console I/O routine for each element in the array.
846 for (i
=0; i
<count
; ++i
) {
847 FormattableStreamer::streamOut(stream
, array
[i
]);
848 stream
<< ( (i
==(count
-1)) ? "" : ", " );
853 // Not a recognizable Formattable object.
854 stream
<< "INVALID_Formattable";
864 #endif /* #if !UCONFIG_NO_FORMATTING */