]>
git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/fmtable.cpp
2 *******************************************************************************
3 * Copyright (C) 1997-2006, 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
];
73 for (int32_t i
=0; i
<count
; ++i
) result
[i
] = array
[i
]; // Don't memcpy!
77 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
80 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
82 static inline void setError(UErrorCode
& ec
, UErrorCode err
) {
88 // -------------------------------------
89 // default constructor.
90 // Creates a formattable object with a long value 0.
92 Formattable::Formattable()
93 : UObject(), fType(kLong
)
99 // -------------------------------------
100 // Creates a formattable object with a Date instance.
102 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
103 : UObject(), fType(kDate
)
109 // -------------------------------------
110 // Creates a formattable object with a double value.
112 Formattable::Formattable(double value
)
113 : UObject(), fType(kDouble
)
116 fValue
.fDouble
= value
;
119 // -------------------------------------
120 // Creates a formattable object with a long value.
122 Formattable::Formattable(int32_t value
)
123 : UObject(), fType(kLong
)
126 fValue
.fInt64
= value
;
129 // -------------------------------------
130 // Creates a formattable object with a long value.
132 Formattable::Formattable(int64_t value
)
133 : UObject(), fType(kInt64
)
136 fValue
.fInt64
= value
;
139 // -------------------------------------
140 // Creates a formattable object with a UnicodeString instance.
142 Formattable::Formattable(const UnicodeString
& stringToCopy
)
143 : UObject(), fType(kString
)
146 fValue
.fString
= new UnicodeString(stringToCopy
);
149 // -------------------------------------
150 // Creates a formattable object with a UnicodeString* value.
151 // (adopting symantics)
153 Formattable::Formattable(UnicodeString
* stringToAdopt
)
154 : UObject(), fType(kString
)
157 fValue
.fString
= stringToAdopt
;
160 Formattable::Formattable(UObject
* objectToAdopt
)
161 : UObject(), fType(kObject
)
164 fValue
.fObject
= objectToAdopt
;
167 // -------------------------------------
169 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
170 : UObject(), fType(kArray
)
173 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
174 fValue
.fArrayAndCount
.fCount
= count
;
177 // -------------------------------------
180 Formattable::Formattable(const Formattable
&source
)
181 : UObject(source
), fType(kLong
)
187 // -------------------------------------
188 // assignment operator
191 Formattable::operator=(const Formattable
& source
)
195 // Disposes the current formattable value/setting.
198 // Sets the correct data type for this value.
199 fType
= source
.fType
;
203 // Sets each element in the array one by one and records the array count.
204 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
205 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
206 source
.fValue
.fArrayAndCount
.fCount
);
209 // Sets the string value.
210 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
213 // Sets the double value.
214 fValue
.fDouble
= source
.fValue
.fDouble
;
218 // Sets the long value.
219 fValue
.fInt64
= source
.fValue
.fInt64
;
222 // Sets the Date value.
223 fValue
.fDate
= source
.fValue
.fDate
;
226 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
233 // -------------------------------------
236 Formattable::operator==(const Formattable
& that
) const
240 if (this == &that
) return TRUE
;
242 // Returns FALSE if the data types are different.
243 if (fType
!= that
.fType
) return FALSE
;
245 // Compares the actual data values.
249 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
252 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
256 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
259 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
262 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
266 // Checks each element for equality.
267 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
268 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
275 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
282 // -------------------------------------
284 Formattable::~Formattable()
289 // -------------------------------------
291 void Formattable::dispose()
293 // Deletes the data value if necessary.
296 delete fValue
.fString
;
299 delete[] fValue
.fArrayAndCount
.fArray
;
302 delete fValue
.fObject
;
310 Formattable::clone() const {
311 return new Formattable(*this);
314 // -------------------------------------
315 // Gets the data type of this Formattable object.
317 Formattable::getType() const
323 Formattable::isNumeric() const {
334 // -------------------------------------
336 //Formattable::getLong(UErrorCode* status) const
337 Formattable::getLong(UErrorCode
& status
) const
339 if (U_FAILURE(status
)) {
344 case Formattable::kLong
:
345 return (int32_t)fValue
.fInt64
;
346 case Formattable::kInt64
:
347 if (fValue
.fInt64
> INT32_MAX
) {
348 status
= U_INVALID_FORMAT_ERROR
;
350 } else if (fValue
.fInt64
< INT32_MIN
) {
351 status
= U_INVALID_FORMAT_ERROR
;
354 return (int32_t)fValue
.fInt64
;
356 case Formattable::kDouble
:
357 if (fValue
.fDouble
> INT32_MAX
) {
358 status
= U_INVALID_FORMAT_ERROR
;
360 } else if (fValue
.fDouble
< INT32_MIN
) {
361 status
= U_INVALID_FORMAT_ERROR
;
364 return (int32_t)fValue
.fDouble
; // loses fraction
366 case Formattable::kObject
:
367 // TODO Later replace this with instanceof call
368 if (instanceOfMeasure(fValue
.fObject
)) {
369 return ((const Measure
*) fValue
.fObject
)->
370 getNumber().getLong(status
);
373 status
= U_INVALID_FORMAT_ERROR
;
378 // -------------------------------------
380 Formattable::getInt64(UErrorCode
& status
) const
382 if (U_FAILURE(status
)) {
387 case Formattable::kLong
:
388 case Formattable::kInt64
:
389 return fValue
.fInt64
;
390 case Formattable::kDouble
:
391 if (fValue
.fDouble
> U_INT64_MAX
) {
392 status
= U_INVALID_FORMAT_ERROR
;
394 } else if (fValue
.fDouble
< U_INT64_MIN
) {
395 status
= U_INVALID_FORMAT_ERROR
;
398 return (int64_t)fValue
.fDouble
;
400 case Formattable::kObject
:
401 // TODO Later replace this with instanceof call
402 if (instanceOfMeasure(fValue
.fObject
)) {
403 return ((const Measure
*) fValue
.fObject
)->
404 getNumber().getInt64(status
);
407 status
= U_INVALID_FORMAT_ERROR
;
412 // -------------------------------------
414 Formattable::getDouble(UErrorCode
& status
) const
416 if (U_FAILURE(status
)) {
421 case Formattable::kLong
:
422 case Formattable::kInt64
: // loses precision
423 return (double)fValue
.fInt64
;
424 case Formattable::kDouble
:
425 return fValue
.fDouble
;
426 case Formattable::kObject
:
427 // TODO Later replace this with instanceof call
428 if (instanceOfMeasure(fValue
.fObject
)) {
429 return ((const Measure
*) fValue
.fObject
)->
430 getNumber().getDouble(status
);
433 status
= U_INVALID_FORMAT_ERROR
;
439 Formattable::getObject() const {
440 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
443 // -------------------------------------
444 // Sets the value to a double value d.
447 Formattable::setDouble(double d
)
454 // -------------------------------------
455 // Sets the value to a long value l.
458 Formattable::setLong(int32_t l
)
465 // -------------------------------------
466 // Sets the value to an int64 value ll.
469 Formattable::setInt64(int64_t ll
)
476 // -------------------------------------
477 // Sets the value to a Date instance d.
480 Formattable::setDate(UDate d
)
487 // -------------------------------------
488 // Sets the value to a string value stringToCopy.
491 Formattable::setString(const UnicodeString
& stringToCopy
)
495 fValue
.fString
= new UnicodeString(stringToCopy
);
498 // -------------------------------------
499 // Sets the value to an array of Formattable objects.
502 Formattable::setArray(const Formattable
* array
, int32_t count
)
506 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
507 fValue
.fArrayAndCount
.fCount
= count
;
510 // -------------------------------------
511 // Adopts the stringToAdopt value.
514 Formattable::adoptString(UnicodeString
* stringToAdopt
)
518 fValue
.fString
= stringToAdopt
;
521 // -------------------------------------
522 // Adopts the array value and its count.
525 Formattable::adoptArray(Formattable
* array
, int32_t count
)
529 fValue
.fArrayAndCount
.fArray
= array
;
530 fValue
.fArrayAndCount
.fCount
= count
;
534 Formattable::adoptObject(UObject
* objectToAdopt
) {
537 fValue
.fObject
= objectToAdopt
;
540 // -------------------------------------
542 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
544 if (fType
!= kString
) {
545 setError(status
, U_INVALID_FORMAT_ERROR
);
548 result
= *fValue
.fString
;
553 // -------------------------------------
555 Formattable::getString(UErrorCode
& status
) const
557 if (fType
!= kString
) {
558 setError(status
, U_INVALID_FORMAT_ERROR
);
561 return *fValue
.fString
;
564 // -------------------------------------
566 Formattable::getString(UErrorCode
& status
)
568 if (fType
!= kString
) {
569 setError(status
, U_INVALID_FORMAT_ERROR
);
572 return *fValue
.fString
;
575 // -------------------------------------
577 Formattable::getArray(int32_t& count
, UErrorCode
& status
) const
579 if (fType
!= kArray
) {
580 setError(status
, U_INVALID_FORMAT_ERROR
);
584 count
= fValue
.fArrayAndCount
.fCount
;
585 return fValue
.fArrayAndCount
.fArray
;
588 // -------------------------------------
589 // Gets the bogus string, ensures mondo bogosity.
592 Formattable::getBogus() const
594 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
598 //----------------------------------------------------
600 //----------------------------------------------------
603 #if U_IOSTREAM_SOURCE >= 199711
606 #elif U_IOSTREAM_SOURCE >= 198506
607 #include <iostream.h>
610 #include "unicode/datefmt.h"
613 class FormattableStreamer
/* not : public UObject because all methods are static */ {
615 static void streamOut(ostream
& stream
, const Formattable
& obj
);
618 FormattableStreamer() {} // private - forbid instantiation
621 // This is for debugging purposes only. This will send a displayable
622 // form of the Formattable object to the output stream.
625 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
627 static DateFormat
*defDateFormat
= 0;
629 UnicodeString buffer
;
630 switch(obj
.getType()) {
631 case Formattable::kDate
:
632 // Creates a DateFormat instance for formatting the
634 if (defDateFormat
== 0) {
635 defDateFormat
= DateFormat::createInstance();
637 defDateFormat
->format(obj
.getDate(), buffer
);
640 case Formattable::kDouble
:
641 // Output the double as is.
642 stream
<< obj
.getDouble() << 'D';
644 case Formattable::kLong
:
645 // Output the double as is.
646 stream
<< obj
.getLong() << 'L';
648 case Formattable::kString
:
649 // Output the double as is. Please see UnicodeString console
650 // I/O routine for more details.
651 stream
<< '"' << obj
.getString(buffer
) << '"';
653 case Formattable::kArray
:
655 const Formattable
* array
;
656 array
= obj
.getArray(count
);
658 // Recursively calling the console I/O routine for each element in the array.
659 for (i
=0; i
<count
; ++i
) {
660 FormattableStreamer::streamOut(stream
, array
[i
]);
661 stream
<< ( (i
==(count
-1)) ? "" : ", " );
666 // Not a recognizable Formattable object.
667 stream
<< "INVALID_Formattable";
677 #endif /* #if !UCONFIG_NO_FORMATTING */