]>
git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/fmtable.cpp
2 *******************************************************************************
3 * Copyright (C) 1997-2004, 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 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 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 inline UBool
instanceOfMeasure(const UObject
* a
) {
59 // LATER: return a->instanceof(Measure::getStaticClassID());
60 return a
->getDynamicClassID() ==
61 CurrencyAmount::getStaticClassID();
64 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
67 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
69 inline void setError(UErrorCode
& ec
, UErrorCode err
) {
75 // -------------------------------------
76 // default constructor.
77 // Creates a formattable object with a long value 0.
79 Formattable::Formattable()
80 : UObject(), fType(kLong
)
86 // -------------------------------------
87 // Creates a formattable object with a Date instance.
89 Formattable::Formattable(UDate date
, ISDATE
/*isDate*/)
90 : UObject(), fType(kDate
)
96 // -------------------------------------
97 // Creates a formattable object with a double value.
99 Formattable::Formattable(double value
)
100 : UObject(), fType(kDouble
)
103 fValue
.fDouble
= value
;
106 // -------------------------------------
107 // Creates a formattable object with a long value.
109 Formattable::Formattable(int32_t value
)
110 : UObject(), fType(kLong
)
113 fValue
.fInt64
= value
;
116 // -------------------------------------
117 // Creates a formattable object with a long value.
119 Formattable::Formattable(int64_t value
)
120 : UObject(), fType(kInt64
)
123 fValue
.fInt64
= value
;
126 // -------------------------------------
127 // Creates a formattable object with a char* string.
129 Formattable::Formattable(const char* stringToCopy
)
130 : UObject(), fType(kString
)
133 fValue
.fString
= new UnicodeString(stringToCopy
);
136 // -------------------------------------
137 // Creates a formattable object with a UnicodeString instance.
139 Formattable::Formattable(const UnicodeString
& stringToCopy
)
140 : UObject(), fType(kString
)
143 fValue
.fString
= new UnicodeString(stringToCopy
);
146 // -------------------------------------
147 // Creates a formattable object with a UnicodeString* value.
148 // (adopting symantics)
150 Formattable::Formattable(UnicodeString
* stringToAdopt
)
151 : UObject(), fType(kString
)
154 fValue
.fString
= stringToAdopt
;
157 Formattable::Formattable(UObject
* objectToAdopt
)
158 : UObject(), fType(kObject
)
161 fValue
.fObject
= objectToAdopt
;
164 // -------------------------------------
166 Formattable::Formattable(const Formattable
* arrayToCopy
, int32_t count
)
167 : UObject(), fType(kArray
)
170 fValue
.fArrayAndCount
.fArray
= createArrayCopy(arrayToCopy
, count
);
171 fValue
.fArrayAndCount
.fCount
= count
;
174 // -------------------------------------
177 Formattable::Formattable(const Formattable
&source
)
178 : UObject(source
), fType(kLong
)
184 // -------------------------------------
185 // assignment operator
188 Formattable::operator=(const Formattable
& source
)
192 // Disposes the current formattable value/setting.
195 // Sets the correct data type for this value.
196 fType
= source
.fType
;
200 // Sets each element in the array one by one and records the array count.
201 fValue
.fArrayAndCount
.fCount
= source
.fValue
.fArrayAndCount
.fCount
;
202 fValue
.fArrayAndCount
.fArray
= createArrayCopy(source
.fValue
.fArrayAndCount
.fArray
,
203 source
.fValue
.fArrayAndCount
.fCount
);
206 // Sets the string value.
207 fValue
.fString
= new UnicodeString(*source
.fValue
.fString
);
210 // Sets the double value.
211 fValue
.fDouble
= source
.fValue
.fDouble
;
215 // Sets the long value.
216 fValue
.fInt64
= source
.fValue
.fInt64
;
219 // Sets the Date value.
220 fValue
.fDate
= source
.fValue
.fDate
;
223 fValue
.fObject
= objectClone(source
.fValue
.fObject
);
230 // -------------------------------------
233 Formattable::operator==(const Formattable
& that
) const
237 if (this == &that
) return TRUE
;
239 // Returns FALSE if the data types are different.
240 if (fType
!= that
.fType
) return FALSE
;
242 // Compares the actual data values.
246 equal
= (fValue
.fDate
== that
.fValue
.fDate
);
249 equal
= (fValue
.fDouble
== that
.fValue
.fDouble
);
253 equal
= (fValue
.fInt64
== that
.fValue
.fInt64
);
256 equal
= (*(fValue
.fString
) == *(that
.fValue
.fString
));
259 if (fValue
.fArrayAndCount
.fCount
!= that
.fValue
.fArrayAndCount
.fCount
) {
263 // Checks each element for equality.
264 for (i
=0; i
<fValue
.fArrayAndCount
.fCount
; ++i
) {
265 if (fValue
.fArrayAndCount
.fArray
[i
] != that
.fValue
.fArrayAndCount
.fArray
[i
]) {
272 equal
= objectEquals(fValue
.fObject
, that
.fValue
.fObject
);
279 // -------------------------------------
281 Formattable::~Formattable()
286 // -------------------------------------
288 void Formattable::dispose()
290 // Deletes the data value if necessary.
293 delete fValue
.fString
;
296 delete[] fValue
.fArrayAndCount
.fArray
;
299 delete fValue
.fObject
;
307 Formattable::clone() const {
308 return new Formattable(*this);
311 // -------------------------------------
312 // Gets the data type of this Formattable object.
314 Formattable::getType() const
320 Formattable::isNumeric() const {
331 // -------------------------------------
333 //Formattable::getLong(UErrorCode* status) const
334 Formattable::getLong(UErrorCode
& status
) const
336 if (U_FAILURE(status
)) {
341 case Formattable::kLong
:
342 return (int32_t)fValue
.fInt64
;
343 case Formattable::kInt64
:
344 if (fValue
.fInt64
> INT32_MAX
) {
345 status
= U_INVALID_FORMAT_ERROR
;
347 } else if (fValue
.fInt64
< INT32_MIN
) {
348 status
= U_INVALID_FORMAT_ERROR
;
351 return (int32_t)fValue
.fInt64
;
353 case Formattable::kDouble
:
354 if (fValue
.fDouble
> INT32_MAX
) {
355 status
= U_INVALID_FORMAT_ERROR
;
357 } else if (fValue
.fDouble
< INT32_MIN
) {
358 status
= U_INVALID_FORMAT_ERROR
;
361 return (int32_t)fValue
.fDouble
; // loses fraction
363 case Formattable::kObject
:
364 // TODO Later replace this with instanceof call
365 if (instanceOfMeasure(fValue
.fObject
)) {
366 return ((const Measure
*) fValue
.fObject
)->
367 getNumber().getLong(status
);
370 status
= U_INVALID_FORMAT_ERROR
;
375 // -------------------------------------
377 Formattable::getInt64(UErrorCode
& status
) const
379 if (U_FAILURE(status
)) {
384 case Formattable::kLong
:
385 case Formattable::kInt64
:
386 return fValue
.fInt64
;
387 case Formattable::kDouble
:
388 if (fValue
.fDouble
> U_INT64_MAX
) {
389 status
= U_INVALID_FORMAT_ERROR
;
391 } else if (fValue
.fDouble
< U_INT64_MIN
) {
392 status
= U_INVALID_FORMAT_ERROR
;
395 return (int64_t)fValue
.fDouble
;
397 case Formattable::kObject
:
398 // TODO Later replace this with instanceof call
399 if (instanceOfMeasure(fValue
.fObject
)) {
400 return ((const Measure
*) fValue
.fObject
)->
401 getNumber().getInt64(status
);
404 status
= U_INVALID_FORMAT_ERROR
;
409 // -------------------------------------
411 Formattable::getDouble(UErrorCode
& status
) const
413 if (U_FAILURE(status
)) {
418 case Formattable::kLong
:
419 case Formattable::kInt64
: // loses precision
420 return (double)fValue
.fInt64
;
421 case Formattable::kDouble
:
422 return fValue
.fDouble
;
423 case Formattable::kObject
:
424 // TODO Later replace this with instanceof call
425 if (instanceOfMeasure(fValue
.fObject
)) {
426 return ((const Measure
*) fValue
.fObject
)->
427 getNumber().getDouble(status
);
430 status
= U_INVALID_FORMAT_ERROR
;
436 Formattable::getObject() const {
437 return (fType
== kObject
) ? fValue
.fObject
: NULL
;
440 // -------------------------------------
441 // Sets the value to a double value d.
444 Formattable::setDouble(double d
)
451 // -------------------------------------
452 // Sets the value to a long value l.
455 Formattable::setLong(int32_t l
)
462 // -------------------------------------
463 // Sets the value to an int64 value ll.
466 Formattable::setInt64(int64_t ll
)
473 // -------------------------------------
474 // Sets the value to a Date instance d.
477 Formattable::setDate(UDate d
)
484 // -------------------------------------
485 // Sets the value to a string value stringToCopy.
488 Formattable::setString(const UnicodeString
& stringToCopy
)
492 fValue
.fString
= new UnicodeString(stringToCopy
);
495 // -------------------------------------
496 // Sets the value to an array of Formattable objects.
499 Formattable::setArray(const Formattable
* array
, int32_t count
)
503 fValue
.fArrayAndCount
.fArray
= createArrayCopy(array
, count
);
504 fValue
.fArrayAndCount
.fCount
= count
;
507 // -------------------------------------
508 // Adopts the stringToAdopt value.
511 Formattable::adoptString(UnicodeString
* stringToAdopt
)
515 fValue
.fString
= stringToAdopt
;
518 // -------------------------------------
519 // Adopts the array value and its count.
522 Formattable::adoptArray(Formattable
* array
, int32_t count
)
526 fValue
.fArrayAndCount
.fArray
= array
;
527 fValue
.fArrayAndCount
.fCount
= count
;
531 Formattable::adoptObject(UObject
* objectToAdopt
) {
534 fValue
.fObject
= objectToAdopt
;
537 // -------------------------------------
539 Formattable::getString(UnicodeString
& result
, UErrorCode
& status
) const
541 if (fType
!= kString
) {
542 setError(status
, U_INVALID_FORMAT_ERROR
);
545 result
= *fValue
.fString
;
550 // -------------------------------------
552 Formattable::getString(UErrorCode
& status
) const
554 if (fType
!= kString
) {
555 setError(status
, U_INVALID_FORMAT_ERROR
);
558 return *fValue
.fString
;
561 // -------------------------------------
563 Formattable::getString(UErrorCode
& status
)
565 if (fType
!= kString
) {
566 setError(status
, U_INVALID_FORMAT_ERROR
);
569 return *fValue
.fString
;
572 // -------------------------------------
574 Formattable::getArray(int32_t& count
, UErrorCode
& status
) const
576 if (fType
!= kArray
) {
577 setError(status
, U_INVALID_FORMAT_ERROR
);
581 count
= fValue
.fArrayAndCount
.fCount
;
582 return fValue
.fArrayAndCount
.fArray
;
585 // -------------------------------------
586 // Gets the bogus string, ensures mondo bogosity.
589 Formattable::getBogus() const
591 return (UnicodeString
*)&fBogus
; /* cast away const :-( */
595 //----------------------------------------------------
597 //----------------------------------------------------
600 #if U_IOSTREAM_SOURCE >= 199711
603 #elif U_IOSTREAM_SOURCE >= 198506
604 #include <iostream.h>
607 #include "unicode/datefmt.h"
610 class FormattableStreamer
/* not : public UObject because all methods are static */ {
612 static void streamOut(ostream
& stream
, const Formattable
& obj
);
615 FormattableStreamer() {} // private - forbid instantiation
618 // This is for debugging purposes only. This will send a displayable
619 // form of the Formattable object to the output stream.
622 FormattableStreamer::streamOut(ostream
& stream
, const Formattable
& obj
)
624 static DateFormat
*defDateFormat
= 0;
626 UnicodeString buffer
;
627 switch(obj
.getType()) {
628 case Formattable::kDate
:
629 // Creates a DateFormat instance for formatting the
631 if (defDateFormat
== 0) {
632 defDateFormat
= DateFormat::createInstance();
634 defDateFormat
->format(obj
.getDate(), buffer
);
637 case Formattable::kDouble
:
638 // Output the double as is.
639 stream
<< obj
.getDouble() << 'D';
641 case Formattable::kLong
:
642 // Output the double as is.
643 stream
<< obj
.getLong() << 'L';
645 case Formattable::kString
:
646 // Output the double as is. Please see UnicodeString console
647 // I/O routine for more details.
648 stream
<< '"' << obj
.getString(buffer
) << '"';
650 case Formattable::kArray
:
652 const Formattable
* array
;
653 array
= obj
.getArray(count
);
655 // Recursively calling the console I/O routine for each element in the array.
656 for (i
=0; i
<count
; ++i
) {
657 FormattableStreamer::streamOut(stream
, array
[i
]);
658 stream
<< ( (i
==(count
-1)) ? "" : ", " );
663 // Not a recognizable Formattable object.
664 stream
<< "INVALID_Formattable";
674 #endif /* #if !UCONFIG_NO_FORMATTING */