• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2006, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 *
7 * File FMTABLE.CPP
8 *
9 * Modification History:
10 *
11 *   Date        Name        Description
12 *   03/25/97    clhuang     Initial Implementation.
13 ********************************************************************************
14 */
15 
16 #include "unicode/utypes.h"
17 
18 #if !UCONFIG_NO_FORMATTING
19 
20 #include "unicode/fmtable.h"
21 #include "unicode/ustring.h"
22 #include "unicode/measure.h"
23 #include "unicode/curramt.h"
24 #include "cmemory.h"
25 
26 // *****************************************************************************
27 // class Formattable
28 // *****************************************************************************
29 
30 U_NAMESPACE_BEGIN
31 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)32 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
33 
34 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
35 
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]
41 
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]
44 
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);
49 }
50 
51 // Return a clone of *a.
objectClone(const UObject * a)52 static inline UObject* objectClone(const UObject* a) {
53     // LATER: return a->clone();
54     return ((const Measure*) a)->clone();
55 }
56 
57 // Return TRUE if *a is an instance of Measure.
instanceOfMeasure(const UObject * a)58 static inline UBool instanceOfMeasure(const UObject* a) {
59     // LATER: return a->instanceof(Measure::getStaticClassID());
60     return a->getDynamicClassID() ==
61         CurrencyAmount::getStaticClassID();
62 }
63 
64 /**
65  * Creates a new Formattable array and copies the values from the specified
66  * original.
67  * @param array the original array
68  * @param count the original array count
69  * @return the new Formattable array.
70  */
createArrayCopy(const Formattable * array,int32_t count)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!
74     return result;
75 }
76 
77 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
78 
79 /**
80  * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
81  */
setError(UErrorCode & ec,UErrorCode err)82 static inline void setError(UErrorCode& ec, UErrorCode err) {
83     if (U_SUCCESS(ec)) {
84         ec = err;
85     }
86 }
87 
88 // -------------------------------------
89 // default constructor.
90 // Creates a formattable object with a long value 0.
91 
Formattable()92 Formattable::Formattable()
93     :   UObject(), fType(kLong)
94 {
95     fBogus.setToBogus();
96     fValue.fInt64 = 0;
97 }
98 
99 // -------------------------------------
100 // Creates a formattable object with a Date instance.
101 
Formattable(UDate date,ISDATE)102 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
103     :   UObject(), fType(kDate)
104 {
105     fBogus.setToBogus();
106     fValue.fDate = date;
107 }
108 
109 // -------------------------------------
110 // Creates a formattable object with a double value.
111 
Formattable(double value)112 Formattable::Formattable(double value)
113     :   UObject(), fType(kDouble)
114 {
115     fBogus.setToBogus();
116     fValue.fDouble = value;
117 }
118 
119 // -------------------------------------
120 // Creates a formattable object with a long value.
121 
Formattable(int32_t value)122 Formattable::Formattable(int32_t value)
123     :   UObject(), fType(kLong)
124 {
125     fBogus.setToBogus();
126     fValue.fInt64 = value;
127 }
128 
129 // -------------------------------------
130 // Creates a formattable object with a long value.
131 
Formattable(int64_t value)132 Formattable::Formattable(int64_t value)
133     :   UObject(), fType(kInt64)
134 {
135     fBogus.setToBogus();
136     fValue.fInt64 = value;
137 }
138 
139 // -------------------------------------
140 // Creates a formattable object with a UnicodeString instance.
141 
Formattable(const UnicodeString & stringToCopy)142 Formattable::Formattable(const UnicodeString& stringToCopy)
143     :   UObject(), fType(kString)
144 {
145     fBogus.setToBogus();
146     fValue.fString = new UnicodeString(stringToCopy);
147 }
148 
149 // -------------------------------------
150 // Creates a formattable object with a UnicodeString* value.
151 // (adopting symantics)
152 
Formattable(UnicodeString * stringToAdopt)153 Formattable::Formattable(UnicodeString* stringToAdopt)
154     :   UObject(), fType(kString)
155 {
156     fBogus.setToBogus();
157     fValue.fString = stringToAdopt;
158 }
159 
Formattable(UObject * objectToAdopt)160 Formattable::Formattable(UObject* objectToAdopt)
161     :   UObject(), fType(kObject)
162 {
163     fBogus.setToBogus();
164     fValue.fObject = objectToAdopt;
165 }
166 
167 // -------------------------------------
168 
Formattable(const Formattable * arrayToCopy,int32_t count)169 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
170     :   UObject(), fType(kArray)
171 {
172     fBogus.setToBogus();
173     fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
174     fValue.fArrayAndCount.fCount = count;
175 }
176 
177 // -------------------------------------
178 // copy constructor
179 
Formattable(const Formattable & source)180 Formattable::Formattable(const Formattable &source)
181     :   UObject(source), fType(kLong)
182 {
183     fBogus.setToBogus();
184     *this = source;
185 }
186 
187 // -------------------------------------
188 // assignment operator
189 
190 Formattable&
operator =(const Formattable & source)191 Formattable::operator=(const Formattable& source)
192 {
193     if (this != &source)
194     {
195         // Disposes the current formattable value/setting.
196         dispose();
197 
198         // Sets the correct data type for this value.
199         fType = source.fType;
200         switch (fType)
201         {
202         case kArray:
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);
207             break;
208         case kString:
209             // Sets the string value.
210             fValue.fString = new UnicodeString(*source.fValue.fString);
211             break;
212         case kDouble:
213             // Sets the double value.
214             fValue.fDouble = source.fValue.fDouble;
215             break;
216         case kLong:
217         case kInt64:
218             // Sets the long value.
219             fValue.fInt64 = source.fValue.fInt64;
220             break;
221         case kDate:
222             // Sets the Date value.
223             fValue.fDate = source.fValue.fDate;
224             break;
225         case kObject:
226             fValue.fObject = objectClone(source.fValue.fObject);
227             break;
228         }
229     }
230     return *this;
231 }
232 
233 // -------------------------------------
234 
235 UBool
operator ==(const Formattable & that) const236 Formattable::operator==(const Formattable& that) const
237 {
238     int32_t i;
239 
240     if (this == &that) return TRUE;
241 
242     // Returns FALSE if the data types are different.
243     if (fType != that.fType) return FALSE;
244 
245     // Compares the actual data values.
246     UBool equal = TRUE;
247     switch (fType) {
248     case kDate:
249         equal = (fValue.fDate == that.fValue.fDate);
250         break;
251     case kDouble:
252         equal = (fValue.fDouble == that.fValue.fDouble);
253         break;
254     case kLong:
255     case kInt64:
256         equal = (fValue.fInt64 == that.fValue.fInt64);
257         break;
258     case kString:
259         equal = (*(fValue.fString) == *(that.fValue.fString));
260         break;
261     case kArray:
262         if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
263             equal = FALSE;
264             break;
265         }
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]) {
269                 equal = FALSE;
270                 break;
271             }
272         }
273         break;
274     case kObject:
275         equal = objectEquals(fValue.fObject, that.fValue.fObject);
276         break;
277     }
278 
279     return equal;
280 }
281 
282 // -------------------------------------
283 
~Formattable()284 Formattable::~Formattable()
285 {
286     dispose();
287 }
288 
289 // -------------------------------------
290 
dispose()291 void Formattable::dispose()
292 {
293     // Deletes the data value if necessary.
294     switch (fType) {
295     case kString:
296         delete fValue.fString;
297         break;
298     case kArray:
299         delete[] fValue.fArrayAndCount.fArray;
300         break;
301     case kObject:
302         delete fValue.fObject;
303         break;
304     default:
305         break;
306     }
307 }
308 
309 Formattable *
clone() const310 Formattable::clone() const {
311     return new Formattable(*this);
312 }
313 
314 // -------------------------------------
315 // Gets the data type of this Formattable object.
316 Formattable::Type
getType() const317 Formattable::getType() const
318 {
319     return fType;
320 }
321 
322 UBool
isNumeric() const323 Formattable::isNumeric() const {
324     switch (fType) {
325     case kDouble:
326     case kLong:
327     case kInt64:
328         return TRUE;
329     default:
330         return FALSE;
331     }
332 }
333 
334 // -------------------------------------
335 int32_t
336 //Formattable::getLong(UErrorCode* status) const
getLong(UErrorCode & status) const337 Formattable::getLong(UErrorCode& status) const
338 {
339     if (U_FAILURE(status)) {
340         return 0;
341     }
342 
343     switch (fType) {
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;
349             return INT32_MAX;
350         } else if (fValue.fInt64 < INT32_MIN) {
351             status = U_INVALID_FORMAT_ERROR;
352             return INT32_MIN;
353         } else {
354             return (int32_t)fValue.fInt64;
355         }
356     case Formattable::kDouble:
357         if (fValue.fDouble > INT32_MAX) {
358             status = U_INVALID_FORMAT_ERROR;
359             return INT32_MAX;
360         } else if (fValue.fDouble < INT32_MIN) {
361             status = U_INVALID_FORMAT_ERROR;
362             return INT32_MIN;
363         } else {
364             return (int32_t)fValue.fDouble; // loses fraction
365         }
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);
371         }
372     default:
373         status = U_INVALID_FORMAT_ERROR;
374         return 0;
375     }
376 }
377 
378 // -------------------------------------
379 int64_t
getInt64(UErrorCode & status) const380 Formattable::getInt64(UErrorCode& status) const
381 {
382     if (U_FAILURE(status)) {
383         return 0;
384     }
385 
386     switch (fType) {
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;
393             return U_INT64_MAX;
394         } else if (fValue.fDouble < U_INT64_MIN) {
395             status = U_INVALID_FORMAT_ERROR;
396             return U_INT64_MIN;
397         } else {
398             return (int64_t)fValue.fDouble;
399         }
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);
405         }
406     default:
407         status = U_INVALID_FORMAT_ERROR;
408         return 0;
409     }
410 }
411 
412 // -------------------------------------
413 double
getDouble(UErrorCode & status) const414 Formattable::getDouble(UErrorCode& status) const
415 {
416     if (U_FAILURE(status)) {
417         return 0;
418     }
419 
420     switch (fType) {
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);
431         }
432     default:
433         status = U_INVALID_FORMAT_ERROR;
434         return 0;
435     }
436 }
437 
438 const UObject*
getObject() const439 Formattable::getObject() const {
440     return (fType == kObject) ? fValue.fObject : NULL;
441 }
442 
443 // -------------------------------------
444 // Sets the value to a double value d.
445 
446 void
setDouble(double d)447 Formattable::setDouble(double d)
448 {
449     dispose();
450     fType = kDouble;
451     fValue.fDouble = d;
452 }
453 
454 // -------------------------------------
455 // Sets the value to a long value l.
456 
457 void
setLong(int32_t l)458 Formattable::setLong(int32_t l)
459 {
460     dispose();
461     fType = kLong;
462     fValue.fInt64 = l;
463 }
464 
465 // -------------------------------------
466 // Sets the value to an int64 value ll.
467 
468 void
setInt64(int64_t ll)469 Formattable::setInt64(int64_t ll)
470 {
471     dispose();
472     fType = kInt64;
473     fValue.fInt64 = ll;
474 }
475 
476 // -------------------------------------
477 // Sets the value to a Date instance d.
478 
479 void
setDate(UDate d)480 Formattable::setDate(UDate d)
481 {
482     dispose();
483     fType = kDate;
484     fValue.fDate = d;
485 }
486 
487 // -------------------------------------
488 // Sets the value to a string value stringToCopy.
489 
490 void
setString(const UnicodeString & stringToCopy)491 Formattable::setString(const UnicodeString& stringToCopy)
492 {
493     dispose();
494     fType = kString;
495     fValue.fString = new UnicodeString(stringToCopy);
496 }
497 
498 // -------------------------------------
499 // Sets the value to an array of Formattable objects.
500 
501 void
setArray(const Formattable * array,int32_t count)502 Formattable::setArray(const Formattable* array, int32_t count)
503 {
504     dispose();
505     fType = kArray;
506     fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
507     fValue.fArrayAndCount.fCount = count;
508 }
509 
510 // -------------------------------------
511 // Adopts the stringToAdopt value.
512 
513 void
adoptString(UnicodeString * stringToAdopt)514 Formattable::adoptString(UnicodeString* stringToAdopt)
515 {
516     dispose();
517     fType = kString;
518     fValue.fString = stringToAdopt;
519 }
520 
521 // -------------------------------------
522 // Adopts the array value and its count.
523 
524 void
adoptArray(Formattable * array,int32_t count)525 Formattable::adoptArray(Formattable* array, int32_t count)
526 {
527     dispose();
528     fType = kArray;
529     fValue.fArrayAndCount.fArray = array;
530     fValue.fArrayAndCount.fCount = count;
531 }
532 
533 void
adoptObject(UObject * objectToAdopt)534 Formattable::adoptObject(UObject* objectToAdopt) {
535     dispose();
536     fType = kObject;
537     fValue.fObject = objectToAdopt;
538 }
539 
540 // -------------------------------------
541 UnicodeString&
getString(UnicodeString & result,UErrorCode & status) const542 Formattable::getString(UnicodeString& result, UErrorCode& status) const
543 {
544     if (fType != kString) {
545         setError(status, U_INVALID_FORMAT_ERROR);
546         result.setToBogus();
547     } else {
548         result = *fValue.fString;
549     }
550     return result;
551 }
552 
553 // -------------------------------------
554 const UnicodeString&
getString(UErrorCode & status) const555 Formattable::getString(UErrorCode& status) const
556 {
557     if (fType != kString) {
558         setError(status, U_INVALID_FORMAT_ERROR);
559         return *getBogus();
560     }
561     return *fValue.fString;
562 }
563 
564 // -------------------------------------
565 UnicodeString&
getString(UErrorCode & status)566 Formattable::getString(UErrorCode& status)
567 {
568     if (fType != kString) {
569         setError(status, U_INVALID_FORMAT_ERROR);
570         return *getBogus();
571     }
572     return *fValue.fString;
573 }
574 
575 // -------------------------------------
576 const Formattable*
getArray(int32_t & count,UErrorCode & status) const577 Formattable::getArray(int32_t& count, UErrorCode& status) const
578 {
579     if (fType != kArray) {
580         setError(status, U_INVALID_FORMAT_ERROR);
581         count = 0;
582         return NULL;
583     }
584     count = fValue.fArrayAndCount.fCount;
585     return fValue.fArrayAndCount.fArray;
586 }
587 
588 // -------------------------------------
589 // Gets the bogus string, ensures mondo bogosity.
590 
591 UnicodeString*
getBogus() const592 Formattable::getBogus() const
593 {
594     return (UnicodeString*)&fBogus; /* cast away const :-( */
595 }
596 
597 #if 0
598 //----------------------------------------------------
599 // console I/O
600 //----------------------------------------------------
601 #ifdef _DEBUG
602 
603 #if U_IOSTREAM_SOURCE >= 199711
604 #include <iostream>
605 using namespace std;
606 #elif U_IOSTREAM_SOURCE >= 198506
607 #include <iostream.h>
608 #endif
609 
610 #include "unicode/datefmt.h"
611 #include "unistrm.h"
612 
613 class FormattableStreamer /* not : public UObject because all methods are static */ {
614 public:
615     static void streamOut(ostream& stream, const Formattable& obj);
616 
617 private:
618     FormattableStreamer() {} // private - forbid instantiation
619 };
620 
621 // This is for debugging purposes only.  This will send a displayable
622 // form of the Formattable object to the output stream.
623 
624 void
625 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
626 {
627     static DateFormat *defDateFormat = 0;
628 
629     UnicodeString buffer;
630     switch(obj.getType()) {
631         case Formattable::kDate :
632             // Creates a DateFormat instance for formatting the
633             // Date instance.
634             if (defDateFormat == 0) {
635                 defDateFormat = DateFormat::createInstance();
636             }
637             defDateFormat->format(obj.getDate(), buffer);
638             stream << buffer;
639             break;
640         case Formattable::kDouble :
641             // Output the double as is.
642             stream << obj.getDouble() << 'D';
643             break;
644         case Formattable::kLong :
645             // Output the double as is.
646             stream << obj.getLong() << 'L';
647             break;
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) << '"';
652             break;
653         case Formattable::kArray:
654             int32_t i, count;
655             const Formattable* array;
656             array = obj.getArray(count);
657             stream << '[';
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)) ? "" : ", " );
662             }
663             stream << ']';
664             break;
665         default:
666             // Not a recognizable Formattable object.
667             stream << "INVALID_Formattable";
668     }
669     stream.flush();
670 }
671 #endif
672 
673 #endif
674 
675 U_NAMESPACE_END
676 
677 #endif /* #if !UCONFIG_NO_FORMATTING */
678 
679 //eof
680