Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 1997-2008, 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 
     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.
     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.
     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  */
     71 static inline Formattable* createArrayCopy(const Formattable* array, int32_t count) {
     72     Formattable *result = new Formattable[count];
     73     if (result != NULL) {
     74         for (int32_t i=0; i<count; ++i)
     75             result[i] = array[i]; // Don't memcpy!
     76     }
     77     return result;
     78 }
     79 
     80 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
     81 
     82 /**
     83  * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
     84  */
     85 static inline void setError(UErrorCode& ec, UErrorCode err) {
     86     if (U_SUCCESS(ec)) {
     87         ec = err;
     88     }
     89 }
     90 
     91 // -------------------------------------
     92 // default constructor.
     93 // Creates a formattable object with a long value 0.
     94 
     95 Formattable::Formattable()
     96     :   UObject(), fType(kLong)
     97 {
     98     fBogus.setToBogus();
     99     fValue.fInt64 = 0;
    100 }
    101 
    102 // -------------------------------------
    103 // Creates a formattable object with a Date instance.
    104 
    105 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
    106     :   UObject(), fType(kDate)
    107 {
    108     fBogus.setToBogus();
    109     fValue.fDate = date;
    110 }
    111 
    112 // -------------------------------------
    113 // Creates a formattable object with a double value.
    114 
    115 Formattable::Formattable(double value)
    116     :   UObject(), fType(kDouble)
    117 {
    118     fBogus.setToBogus();
    119     fValue.fDouble = value;
    120 }
    121 
    122 // -------------------------------------
    123 // Creates a formattable object with a long value.
    124 
    125 Formattable::Formattable(int32_t value)
    126     :   UObject(), fType(kLong)
    127 {
    128     fBogus.setToBogus();
    129     fValue.fInt64 = value;
    130 }
    131 
    132 // -------------------------------------
    133 // Creates a formattable object with a long value.
    134 
    135 Formattable::Formattable(int64_t value)
    136     :   UObject(), fType(kInt64)
    137 {
    138     fBogus.setToBogus();
    139     fValue.fInt64 = value;
    140 }
    141 
    142 // -------------------------------------
    143 // Creates a formattable object with a UnicodeString instance.
    144 
    145 Formattable::Formattable(const UnicodeString& stringToCopy)
    146     :   UObject(), fType(kString)
    147 {
    148     fBogus.setToBogus();
    149     fValue.fString = new UnicodeString(stringToCopy);
    150 }
    151 
    152 // -------------------------------------
    153 // Creates a formattable object with a UnicodeString* value.
    154 // (adopting symantics)
    155 
    156 Formattable::Formattable(UnicodeString* stringToAdopt)
    157     :   UObject(), fType(kString)
    158 {
    159     fBogus.setToBogus();
    160     fValue.fString = stringToAdopt;
    161 }
    162 
    163 Formattable::Formattable(UObject* objectToAdopt)
    164     :   UObject(), fType(kObject)
    165 {
    166     fBogus.setToBogus();
    167     fValue.fObject = objectToAdopt;
    168 }
    169 
    170 // -------------------------------------
    171 
    172 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
    173     :   UObject(), fType(kArray)
    174 {
    175     fBogus.setToBogus();
    176     fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
    177     fValue.fArrayAndCount.fCount = count;
    178 }
    179 
    180 // -------------------------------------
    181 // copy constructor
    182 
    183 Formattable::Formattable(const Formattable &source)
    184     :   UObject(source), fType(kLong)
    185 {
    186     fBogus.setToBogus();
    187     *this = source;
    188 }
    189 
    190 // -------------------------------------
    191 // assignment operator
    192 
    193 Formattable&
    194 Formattable::operator=(const Formattable& source)
    195 {
    196     if (this != &source)
    197     {
    198         // Disposes the current formattable value/setting.
    199         dispose();
    200 
    201         // Sets the correct data type for this value.
    202         fType = source.fType;
    203         switch (fType)
    204         {
    205         case kArray:
    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);
    210             break;
    211         case kString:
    212             // Sets the string value.
    213             fValue.fString = new UnicodeString(*source.fValue.fString);
    214             break;
    215         case kDouble:
    216             // Sets the double value.
    217             fValue.fDouble = source.fValue.fDouble;
    218             break;
    219         case kLong:
    220         case kInt64:
    221             // Sets the long value.
    222             fValue.fInt64 = source.fValue.fInt64;
    223             break;
    224         case kDate:
    225             // Sets the Date value.
    226             fValue.fDate = source.fValue.fDate;
    227             break;
    228         case kObject:
    229             fValue.fObject = objectClone(source.fValue.fObject);
    230             break;
    231         }
    232     }
    233     return *this;
    234 }
    235 
    236 // -------------------------------------
    237 
    238 UBool
    239 Formattable::operator==(const Formattable& that) const
    240 {
    241     int32_t i;
    242 
    243     if (this == &that) return TRUE;
    244 
    245     // Returns FALSE if the data types are different.
    246     if (fType != that.fType) return FALSE;
    247 
    248     // Compares the actual data values.
    249     UBool equal = TRUE;
    250     switch (fType) {
    251     case kDate:
    252         equal = (fValue.fDate == that.fValue.fDate);
    253         break;
    254     case kDouble:
    255         equal = (fValue.fDouble == that.fValue.fDouble);
    256         break;
    257     case kLong:
    258     case kInt64:
    259         equal = (fValue.fInt64 == that.fValue.fInt64);
    260         break;
    261     case kString:
    262         equal = (*(fValue.fString) == *(that.fValue.fString));
    263         break;
    264     case kArray:
    265         if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
    266             equal = FALSE;
    267             break;
    268         }
    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]) {
    272                 equal = FALSE;
    273                 break;
    274             }
    275         }
    276         break;
    277     case kObject:
    278         if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
    279             equal = FALSE;
    280         } else {
    281             equal = objectEquals(fValue.fObject, that.fValue.fObject);
    282         }
    283         break;
    284     }
    285 
    286     return equal;
    287 }
    288 
    289 // -------------------------------------
    290 
    291 Formattable::~Formattable()
    292 {
    293     dispose();
    294 }
    295 
    296 // -------------------------------------
    297 
    298 void Formattable::dispose()
    299 {
    300     // Deletes the data value if necessary.
    301     switch (fType) {
    302     case kString:
    303         delete fValue.fString;
    304         break;
    305     case kArray:
    306         delete[] fValue.fArrayAndCount.fArray;
    307         break;
    308     case kObject:
    309         delete fValue.fObject;
    310         break;
    311     default:
    312         break;
    313     }
    314 }
    315 
    316 Formattable *
    317 Formattable::clone() const {
    318     return new Formattable(*this);
    319 }
    320 
    321 // -------------------------------------
    322 // Gets the data type of this Formattable object.
    323 Formattable::Type
    324 Formattable::getType() const
    325 {
    326     return fType;
    327 }
    328 
    329 UBool
    330 Formattable::isNumeric() const {
    331     switch (fType) {
    332     case kDouble:
    333     case kLong:
    334     case kInt64:
    335         return TRUE;
    336     default:
    337         return FALSE;
    338     }
    339 }
    340 
    341 // -------------------------------------
    342 int32_t
    343 //Formattable::getLong(UErrorCode* status) const
    344 Formattable::getLong(UErrorCode& status) const
    345 {
    346     if (U_FAILURE(status)) {
    347         return 0;
    348     }
    349 
    350     switch (fType) {
    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;
    356             return INT32_MAX;
    357         } else if (fValue.fInt64 < INT32_MIN) {
    358             status = U_INVALID_FORMAT_ERROR;
    359             return INT32_MIN;
    360         } else {
    361             return (int32_t)fValue.fInt64;
    362         }
    363     case Formattable::kDouble:
    364         if (fValue.fDouble > INT32_MAX) {
    365             status = U_INVALID_FORMAT_ERROR;
    366             return INT32_MAX;
    367         } else if (fValue.fDouble < INT32_MIN) {
    368             status = U_INVALID_FORMAT_ERROR;
    369             return INT32_MIN;
    370         } else {
    371             return (int32_t)fValue.fDouble; // loses fraction
    372         }
    373     case Formattable::kObject:
    374         if (fValue.fObject == NULL) {
    375             status = U_MEMORY_ALLOCATION_ERROR;
    376             return 0;
    377         }
    378         // TODO Later replace this with instanceof call
    379         if (instanceOfMeasure(fValue.fObject)) {
    380             return ((const Measure*) fValue.fObject)->
    381                 getNumber().getLong(status);
    382         }
    383     default:
    384         status = U_INVALID_FORMAT_ERROR;
    385         return 0;
    386     }
    387 }
    388 
    389 // -------------------------------------
    390 int64_t
    391 Formattable::getInt64(UErrorCode& status) const
    392 {
    393     if (U_FAILURE(status)) {
    394         return 0;
    395     }
    396 
    397     switch (fType) {
    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;
    404             return U_INT64_MAX;
    405         } else if (fValue.fDouble < U_INT64_MIN) {
    406             status = U_INVALID_FORMAT_ERROR;
    407             return U_INT64_MIN;
    408         } else {
    409             return (int64_t)fValue.fDouble;
    410         }
    411     case Formattable::kObject:
    412         if (fValue.fObject == NULL) {
    413             status = U_MEMORY_ALLOCATION_ERROR;
    414             return 0;
    415         }
    416         // TODO Later replace this with instanceof call
    417         if (instanceOfMeasure(fValue.fObject)) {
    418             return ((const Measure*) fValue.fObject)->
    419                 getNumber().getInt64(status);
    420         }
    421     default:
    422         status = U_INVALID_FORMAT_ERROR;
    423         return 0;
    424     }
    425 }
    426 
    427 // -------------------------------------
    428 double
    429 Formattable::getDouble(UErrorCode& status) const
    430 {
    431     if (U_FAILURE(status)) {
    432         return 0;
    433     }
    434 
    435     switch (fType) {
    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;
    444             return 0;
    445         }
    446         // TODO Later replace this with instanceof call
    447         if (instanceOfMeasure(fValue.fObject)) {
    448             return ((const Measure*) fValue.fObject)->
    449                 getNumber().getDouble(status);
    450         }
    451     default:
    452         status = U_INVALID_FORMAT_ERROR;
    453         return 0;
    454     }
    455 }
    456 
    457 const UObject*
    458 Formattable::getObject() const {
    459     return (fType == kObject) ? fValue.fObject : NULL;
    460 }
    461 
    462 // -------------------------------------
    463 // Sets the value to a double value d.
    464 
    465 void
    466 Formattable::setDouble(double d)
    467 {
    468     dispose();
    469     fType = kDouble;
    470     fValue.fDouble = d;
    471 }
    472 
    473 // -------------------------------------
    474 // Sets the value to a long value l.
    475 
    476 void
    477 Formattable::setLong(int32_t l)
    478 {
    479     dispose();
    480     fType = kLong;
    481     fValue.fInt64 = l;
    482 }
    483 
    484 // -------------------------------------
    485 // Sets the value to an int64 value ll.
    486 
    487 void
    488 Formattable::setInt64(int64_t ll)
    489 {
    490     dispose();
    491     fType = kInt64;
    492     fValue.fInt64 = ll;
    493 }
    494 
    495 // -------------------------------------
    496 // Sets the value to a Date instance d.
    497 
    498 void
    499 Formattable::setDate(UDate d)
    500 {
    501     dispose();
    502     fType = kDate;
    503     fValue.fDate = d;
    504 }
    505 
    506 // -------------------------------------
    507 // Sets the value to a string value stringToCopy.
    508 
    509 void
    510 Formattable::setString(const UnicodeString& stringToCopy)
    511 {
    512     dispose();
    513     fType = kString;
    514     fValue.fString = new UnicodeString(stringToCopy);
    515 }
    516 
    517 // -------------------------------------
    518 // Sets the value to an array of Formattable objects.
    519 
    520 void
    521 Formattable::setArray(const Formattable* array, int32_t count)
    522 {
    523     dispose();
    524     fType = kArray;
    525     fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
    526     fValue.fArrayAndCount.fCount = count;
    527 }
    528 
    529 // -------------------------------------
    530 // Adopts the stringToAdopt value.
    531 
    532 void
    533 Formattable::adoptString(UnicodeString* stringToAdopt)
    534 {
    535     dispose();
    536     fType = kString;
    537     fValue.fString = stringToAdopt;
    538 }
    539 
    540 // -------------------------------------
    541 // Adopts the array value and its count.
    542 
    543 void
    544 Formattable::adoptArray(Formattable* array, int32_t count)
    545 {
    546     dispose();
    547     fType = kArray;
    548     fValue.fArrayAndCount.fArray = array;
    549     fValue.fArrayAndCount.fCount = count;
    550 }
    551 
    552 void
    553 Formattable::adoptObject(UObject* objectToAdopt) {
    554     dispose();
    555     fType = kObject;
    556     fValue.fObject = objectToAdopt;
    557 }
    558 
    559 // -------------------------------------
    560 UnicodeString&
    561 Formattable::getString(UnicodeString& result, UErrorCode& status) const
    562 {
    563     if (fType != kString) {
    564         setError(status, U_INVALID_FORMAT_ERROR);
    565         result.setToBogus();
    566     } else {
    567         if (fValue.fString == NULL) {
    568             setError(status, U_MEMORY_ALLOCATION_ERROR);
    569         } else {
    570             result = *fValue.fString;
    571         }
    572     }
    573     return result;
    574 }
    575 
    576 // -------------------------------------
    577 const UnicodeString&
    578 Formattable::getString(UErrorCode& status) const
    579 {
    580     if (fType != kString) {
    581         setError(status, U_INVALID_FORMAT_ERROR);
    582         return *getBogus();
    583     }
    584     if (fValue.fString == NULL) {
    585         setError(status, U_MEMORY_ALLOCATION_ERROR);
    586         return *getBogus();
    587     }
    588     return *fValue.fString;
    589 }
    590 
    591 // -------------------------------------
    592 UnicodeString&
    593 Formattable::getString(UErrorCode& status)
    594 {
    595     if (fType != kString) {
    596         setError(status, U_INVALID_FORMAT_ERROR);
    597         return *getBogus();
    598     }
    599     if (fValue.fString == NULL) {
    600     	setError(status, U_MEMORY_ALLOCATION_ERROR);
    601     	return *getBogus();
    602     }
    603     return *fValue.fString;
    604 }
    605 
    606 // -------------------------------------
    607 const Formattable*
    608 Formattable::getArray(int32_t& count, UErrorCode& status) const
    609 {
    610     if (fType != kArray) {
    611         setError(status, U_INVALID_FORMAT_ERROR);
    612         count = 0;
    613         return NULL;
    614     }
    615     count = fValue.fArrayAndCount.fCount;
    616     return fValue.fArrayAndCount.fArray;
    617 }
    618 
    619 // -------------------------------------
    620 // Gets the bogus string, ensures mondo bogosity.
    621 
    622 UnicodeString*
    623 Formattable::getBogus() const
    624 {
    625     return (UnicodeString*)&fBogus; /* cast away const :-( */
    626 }
    627 
    628 #if 0
    629 //----------------------------------------------------
    630 // console I/O
    631 //----------------------------------------------------
    632 #ifdef _DEBUG
    633 
    634 #if U_IOSTREAM_SOURCE >= 199711
    635 #include <iostream>
    636 using namespace std;
    637 #elif U_IOSTREAM_SOURCE >= 198506
    638 #include <iostream.h>
    639 #endif
    640 
    641 #include "unicode/datefmt.h"
    642 #include "unistrm.h"
    643 
    644 class FormattableStreamer /* not : public UObject because all methods are static */ {
    645 public:
    646     static void streamOut(ostream& stream, const Formattable& obj);
    647 
    648 private:
    649     FormattableStreamer() {} // private - forbid instantiation
    650 };
    651 
    652 // This is for debugging purposes only.  This will send a displayable
    653 // form of the Formattable object to the output stream.
    654 
    655 void
    656 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
    657 {
    658     static DateFormat *defDateFormat = 0;
    659 
    660     UnicodeString buffer;
    661     switch(obj.getType()) {
    662         case Formattable::kDate :
    663             // Creates a DateFormat instance for formatting the
    664             // Date instance.
    665             if (defDateFormat == 0) {
    666                 defDateFormat = DateFormat::createInstance();
    667             }
    668             defDateFormat->format(obj.getDate(), buffer);
    669             stream << buffer;
    670             break;
    671         case Formattable::kDouble :
    672             // Output the double as is.
    673             stream << obj.getDouble() << 'D';
    674             break;
    675         case Formattable::kLong :
    676             // Output the double as is.
    677             stream << obj.getLong() << 'L';
    678             break;
    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) << '"';
    683             break;
    684         case Formattable::kArray:
    685             int32_t i, count;
    686             const Formattable* array;
    687             array = obj.getArray(count);
    688             stream << '[';
    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)) ? "" : ", " );
    693             }
    694             stream << ']';
    695             break;
    696         default:
    697             // Not a recognizable Formattable object.
    698             stream << "INVALID_Formattable";
    699     }
    700     stream.flush();
    701 }
    702 #endif
    703 
    704 #endif
    705 
    706 U_NAMESPACE_END
    707 
    708 #endif /* #if !UCONFIG_NO_FORMATTING */
    709 
    710 //eof
    711