2 *******************************************************************************
3 * Copyright (C) 1997-2008, 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
20 #include "unicode/fmtable.h"
21 #include "unicode/ustring.h"
22 #include "unicode/measure.h"
23 #include "unicode/curramt.h"
26 // *****************************************************************************
28 // *****************************************************************************
32 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable
)
34 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
36 // NOTE: As of 3.0, there are limitations to the UObject API. It does
37 // not (yet) support cloning, operator=, nor operator==. RTTI is also
38 // restricted in that subtype testing is not (yet) implemented. To
39 // work around this, I implement some simple inlines here. Later
40 // these can be modified or removed. [alan]
42 // NOTE: These inlines assume that all fObjects are in fact instances
43 // of the Measure class, which is true as of 3.0. [alan]
45 // Return TRUE if *a == *b.
46 static inline UBool
objectEquals(const UObject
* a
, const UObject
* b
) {
47 // LATER: return *a == *b;
48 return *((const Measure
*) a
) == *((const Measure
*) b
);
51 // Return a clone of *a.
52 static inline UObject
* objectClone(const UObject
* a
) {
53 // LATER: return a->clone();
54 return ((const Measure
*) a
)->clone();
57 // Return TRUE if *a is an instance of Measure.
58 static inline UBool
instanceOfMeasure(const UObject
* a
) {
59 // LATER: return a->instanceof(Measure::getStaticClassID());
60 return a
->getDynamicClassID() ==
61 CurrencyAmount::getStaticClassID();
65 * Creates a new Formattable array and copies the values from the specified
67 * @param array the original array
68 * @param count the original array count
69 * @return the new Formattable array.
71 static inline Formattable
* createArrayCopy(const Formattable
* array
, int32_t count
) {
72 Formattable
*result
= new Formattable
[count
];
74 for (int32_t i
=0; i
<count
; ++i
)
75 result
[i
] = array
[i
]; // Don't memcpy!
80 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
83 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
85 static inline void setError(UErrorCode
& ec
, UErrorCode err
) {
91 // -------------------------------------
92 // default constructor.
93 // Creates a formattable object with a long value 0.
95 Formattable::Formattable()
96 : UObject(), fType(kLong
)
102 // -------------------------------------
103 // Creates a formattable object with a Date instance.
105 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
106 : UObject(), fType(kDate
)
112 // -------------------------------------
113 // Creates a formattable object with a double value.
115 Formattable::Formattable(double value
)
116 : UObject(), fType(kDouble
)
119 fValue
.fDouble
= value
;
122 // -------------------------------------
123 // Creates a formattable object with a long value.
125 Formattable::Formattable(int32_t value
)
126 : UObject(), fType(kLong
)
129 fValue
.fInt64
= value
;
132 // -------------------------------------
133 // Creates a formattable object with a long value.
135 Formattable::Formattable(int64_t value
)
136 : UObject(), fType(kInt64
)
139 fValue
.fInt64
= value
;
142 // -------------------------------------
143 // Creates a formattable object with a UnicodeString instance.
145 Formattable::Formattable(const UnicodeString
& stringToCopy
)
146 : UObject(), fType(kString
)
149 fValue
.fString
= new UnicodeString(stringToCopy
);
152 // -------------------------------------
153 // Creates a formattable object with a UnicodeString* value.
154 // (adopting symantics)
156 Formattable::Formattable(UnicodeString
* stringToAdopt
)
157 : UObject(), fType(kString
)
160 fValue
.fString
= stringToAdopt
;
163 Formattable::Formattable(UObject
* objectToAdopt
)
164 : UObject(), fType(kObject
)
167 fValue
.fObject
= objectToAdopt
;
170 // -------------------------------------
172 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
173 : UObject(), fType(kArray
)
176 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
177 fValue
.fArrayAndCount
.fCount
= count
;
180 // -------------------------------------
183 Formattable::Formattable(const Formattable
&source
)
184 : UObject(source
), fType(kLong
)
190 // -------------------------------------
191 // assignment operator
194 Formattable::operator=(const Formattable
& source
)
198 // Disposes the current formattable value/setting.
201 // Sets the correct data type for this value.
202 fType
= source
.fType
;
206 // Sets each element in the array one by one and records the array count.
207 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
208 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
209 source
.fValue
.fArrayAndCount
.fCount
);
212 // Sets the string value.
213 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
216 // Sets the double value.
217 fValue
.fDouble
= source
.fValue
.fDouble
;
221 // Sets the long value.
222 fValue
.fInt64
= source
.fValue
.fInt64
;
225 // Sets the Date value.
226 fValue
.fDate
= source
.fValue
.fDate
;
229 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
236 // -------------------------------------
239 Formattable::operator==(const Formattable
& that
) const
243 if (this == &that
) return TRUE
;
245 // Returns FALSE if the data types are different.
246 if (fType
!= that
.fType
) return FALSE
;
248 // Compares the actual data values.
252 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
255 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
259 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
262 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
265 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
269 // Checks each element for equality.
270 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
271 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
278 if (fValue
.fObject
== NULL
|| that
.fValue
.fObject
== NULL
) {
281 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
289 // -------------------------------------
291 Formattable::~Formattable()
296 // -------------------------------------
298 void Formattable::dispose()
300 // Deletes the data value if necessary.
303 delete fValue
.fString
;
306 delete[] fValue
.fArrayAndCount
.fArray
;
309 delete fValue
.fObject
;
317 Formattable::clone() const {
318 return new Formattable(*this);
321 // -------------------------------------
322 // Gets the data type of this Formattable object.
324 Formattable::getType() const
330 Formattable::isNumeric() const {
341 // -------------------------------------
343 //Formattable::getLong(UErrorCode* status) const
344 Formattable::getLong(UErrorCode
& status
) const
346 if (U_FAILURE(status
)) {
351 case Formattable::kLong
:
352 return (int32_t)fValue
.fInt64
;
353 case Formattable::kInt64
:
354 if (fValue
.fInt64
> INT32_MAX
) {
355 status
= U_INVALID_FORMAT_ERROR
;
357 } else if (fValue
.fInt64
< INT32_MIN
) {
358 status
= U_INVALID_FORMAT_ERROR
;
361 return (int32_t)fValue
.fInt64
;
363 case Formattable::kDouble
:
364 if (fValue
.fDouble
> INT32_MAX
) {
365 status
= U_INVALID_FORMAT_ERROR
;
367 } else if (fValue
.fDouble
< INT32_MIN
) {
368 status
= U_INVALID_FORMAT_ERROR
;
371 return (int32_t)fValue
.fDouble
; // loses fraction
373 case Formattable::kObject
:
374 if (fValue
.fObject
== NULL
) {
375 status
= U_MEMORY_ALLOCATION_ERROR
;
378 // TODO Later replace this with instanceof call
379 if (instanceOfMeasure(fValue
.fObject
)) {
380 return ((const Measure
*) fValue
.fObject
)->
381 getNumber().getLong(status
);
384 status
= U_INVALID_FORMAT_ERROR
;
389 // -------------------------------------
391 Formattable::getInt64(UErrorCode
& status
) const
393 if (U_FAILURE(status
)) {
398 case Formattable::kLong
:
399 case Formattable::kInt64
:
400 return fValue
.fInt64
;
401 case Formattable::kDouble
:
402 if (fValue
.fDouble
> U_INT64_MAX
) {
403 status
= U_INVALID_FORMAT_ERROR
;
405 } else if (fValue
.fDouble
< U_INT64_MIN
) {
406 status
= U_INVALID_FORMAT_ERROR
;
409 return (int64_t)fValue
.fDouble
;
411 case Formattable::kObject
:
412 if (fValue
.fObject
== NULL
) {
413 status
= U_MEMORY_ALLOCATION_ERROR
;
416 // TODO Later replace this with instanceof call
417 if (instanceOfMeasure(fValue
.fObject
)) {
418 return ((const Measure
*) fValue
.fObject
)->
419 getNumber().getInt64(status
);
422 status
= U_INVALID_FORMAT_ERROR
;
427 // -------------------------------------
429 Formattable::getDouble(UErrorCode
& status
) const
431 if (U_FAILURE(status
)) {
436 case Formattable::kLong
:
437 case Formattable::kInt64
: // loses precision
438 return (double)fValue
.fInt64
;
439 case Formattable::kDouble
:
440 return fValue
.fDouble
;
441 case Formattable::kObject
:
442 if (fValue
.fObject
== NULL
) {
443 status
= U_MEMORY_ALLOCATION_ERROR
;
446 // TODO Later replace this with instanceof call
447 if (instanceOfMeasure(fValue
.fObject
)) {
448 return ((const Measure
*) fValue
.fObject
)->
449 getNumber().getDouble(status
);
452 status
= U_INVALID_FORMAT_ERROR
;
458 Formattable::getObject() const {
459 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
462 // -------------------------------------
463 // Sets the value to a double value d.
466 Formattable::setDouble(double d
)
473 // -------------------------------------
474 // Sets the value to a long value l.
477 Formattable::setLong(int32_t l
)
484 // -------------------------------------
485 // Sets the value to an int64 value ll.
488 Formattable::setInt64(int64_t ll
)
495 // -------------------------------------
496 // Sets the value to a Date instance d.
499 Formattable::setDate(UDate d
)
506 // -------------------------------------
507 // Sets the value to a string value stringToCopy.
510 Formattable::setString(const UnicodeString
& stringToCopy
)
514 fValue
.fString
= new UnicodeString(stringToCopy
);
517 // -------------------------------------
518 // Sets the value to an array of Formattable objects.
521 Formattable::setArray(const Formattable
* array
, int32_t count
)
525 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
526 fValue
.fArrayAndCount
.fCount
= count
;
529 // -------------------------------------
530 // Adopts the stringToAdopt value.
533 Formattable::adoptString(UnicodeString
* stringToAdopt
)
537 fValue
.fString
= stringToAdopt
;
540 // -------------------------------------
541 // Adopts the array value and its count.
544 Formattable::adoptArray(Formattable
* array
, int32_t count
)
548 fValue
.fArrayAndCount
.fArray
= array
;
549 fValue
.fArrayAndCount
.fCount
= count
;
553 Formattable::adoptObject(UObject
* objectToAdopt
) {
556 fValue
.fObject
= objectToAdopt
;
559 // -------------------------------------
561 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
563 if (fType
!= kString
) {
564 setError(status
, U_INVALID_FORMAT_ERROR
);
567 if (fValue
.fString
== NULL
) {
568 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
570 result
= *fValue
.fString
;
576 // -------------------------------------
578 Formattable::getString(UErrorCode
& status
) const
580 if (fType
!= kString
) {
581 setError(status
, U_INVALID_FORMAT_ERROR
);
584 if (fValue
.fString
== NULL
) {
585 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
588 return *fValue
.fString
;
591 // -------------------------------------
593 Formattable::getString(UErrorCode
& status
)
595 if (fType
!= kString
) {
596 setError(status
, U_INVALID_FORMAT_ERROR
);
599 if (fValue
.fString
== NULL
) {
600 setError(status
, U_MEMORY_ALLOCATION_ERROR
);
603 return *fValue
.fString
;
606 // -------------------------------------
608 Formattable::getArray(int32_t& count
, UErrorCode
& status
) const
610 if (fType
!= kArray
) {
611 setError(status
, U_INVALID_FORMAT_ERROR
);
615 count
= fValue
.fArrayAndCount
.fCount
;
616 return fValue
.fArrayAndCount
.fArray
;
619 // -------------------------------------
620 // Gets the bogus string, ensures mondo bogosity.
623 Formattable::getBogus() const
625 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
629 //----------------------------------------------------
631 //----------------------------------------------------
634 #if U_IOSTREAM_SOURCE >= 199711
637 #elif U_IOSTREAM_SOURCE >= 198506
638 #include <iostream.h>
641 #include "unicode/datefmt.h"
644 class FormattableStreamer
/* not : public UObject because all methods are static */ {
646 static void streamOut(ostream
& stream
, const Formattable
& obj
);
649 FormattableStreamer() {} // private - forbid instantiation
652 // This is for debugging purposes only. This will send a displayable
653 // form of the Formattable object to the output stream.
656 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
658 static DateFormat
*defDateFormat
= 0;
660 UnicodeString buffer
;
661 switch(obj
.getType()) {
662 case Formattable::kDate
:
663 // Creates a DateFormat instance for formatting the
665 if (defDateFormat
== 0) {
666 defDateFormat
= DateFormat::createInstance();
668 defDateFormat
->format(obj
.getDate(), buffer
);
671 case Formattable::kDouble
:
672 // Output the double as is.
673 stream
<< obj
.getDouble() << 'D';
675 case Formattable::kLong
:
676 // Output the double as is.
677 stream
<< obj
.getLong() << 'L';
679 case Formattable::kString
:
680 // Output the double as is. Please see UnicodeString console
681 // I/O routine for more details.
682 stream
<< '"' << obj
.getString(buffer
) << '"';
684 case Formattable::kArray
:
686 const Formattable
* array
;
687 array
= obj
.getArray(count
);
689 // Recursively calling the console I/O routine for each element in the array.
690 for (i
=0; i
<count
; ++i
) {
691 FormattableStreamer::streamOut(stream
, array
[i
]);
692 stream
<< ( (i
==(count
-1)) ? "" : ", " );
697 // Not a recognizable Formattable object.
698 stream
<< "INVALID_Formattable";
708 #endif /* #if !UCONFIG_NO_FORMATTING */