Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 1997-2011, 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 <math.h>
     21 #include "unicode/fmtable.h"
     22 #include "unicode/ustring.h"
     23 #include "unicode/measure.h"
     24 #include "unicode/curramt.h"
     25 #include "charstr.h"
     26 #include "cmemory.h"
     27 #include "cstring.h"
     28 #include "decNumber.h"
     29 #include "digitlst.h"
     30 
     31 // *****************************************************************************
     32 // class Formattable
     33 // *****************************************************************************
     34 
     35 U_NAMESPACE_BEGIN
     36 
     37 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
     38 
     39 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
     40 
     41 // NOTE: As of 3.0, there are limitations to the UObject API.  It does
     42 // not (yet) support cloning, operator=, nor operator==.  To
     43 // work around this, I implement some simple inlines here.  Later
     44 // these can be modified or removed.  [alan]
     45 
     46 // NOTE: These inlines assume that all fObjects are in fact instances
     47 // of the Measure class, which is true as of 3.0.  [alan]
     48 
     49 // Return TRUE if *a == *b.
     50 static inline UBool objectEquals(const UObject* a, const UObject* b) {
     51     // LATER: return *a == *b;
     52     return *((const Measure*) a) == *((const Measure*) b);
     53 }
     54 
     55 // Return a clone of *a.
     56 static inline UObject* objectClone(const UObject* a) {
     57     // LATER: return a->clone();
     58     return ((const Measure*) a)->clone();
     59 }
     60 
     61 // Return TRUE if *a is an instance of Measure.
     62 static inline UBool instanceOfMeasure(const UObject* a) {
     63     return dynamic_cast<const Measure*>(a) != NULL;
     64 }
     65 
     66 /**
     67  * Creates a new Formattable array and copies the values from the specified
     68  * original.
     69  * @param array the original array
     70  * @param count the original array count
     71  * @return the new Formattable array.
     72  */
     73 static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
     74     Formattable *result = new Formattable[count];
     75     if (result != NULL) {
     76         for (int32_t i=0; i<count; ++i)
     77             result[i] = array[i]; // Don't memcpy!
     78     }
     79     return result;
     80 }
     81 
     82 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
     83 
     84 /**
     85  * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
     86  */
     87 static void setError(UErrorCode& ec, UErrorCode err) {
     88     if (U_SUCCESS(ec)) {
     89         ec = err;
     90     }
     91 }
     92 
     93 //
     94 //  Common initialization code, shared by constructors.
     95 //  Put everything into a known state.
     96 //
     97 void  Formattable::init() {
     98     fValue.fInt64 = 0;
     99     fType = kLong;
    100     fDecimalStr = NULL;
    101     fDecimalNum = NULL;
    102     fBogus.setToBogus();
    103 }
    104 
    105 // -------------------------------------
    106 // default constructor.
    107 // Creates a formattable object with a long value 0.
    108 
    109 Formattable::Formattable() {
    110     init();
    111 }
    112 
    113 // -------------------------------------
    114 // Creates a formattable object with a Date instance.
    115 
    116 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
    117 {
    118     init();
    119     fType = kDate;
    120     fValue.fDate = date;
    121 }
    122 
    123 // -------------------------------------
    124 // Creates a formattable object with a double value.
    125 
    126 Formattable::Formattable(double value)
    127 {
    128     init();
    129     fType = kDouble;
    130     fValue.fDouble = value;
    131 }
    132 
    133 // -------------------------------------
    134 // Creates a formattable object with an int32_t value.
    135 
    136 Formattable::Formattable(int32_t value)
    137 {
    138     init();
    139     fValue.fInt64 = value;
    140 }
    141 
    142 // -------------------------------------
    143 // Creates a formattable object with an int64_t value.
    144 
    145 Formattable::Formattable(int64_t value)
    146 {
    147     init();
    148     fType = kInt64;
    149     fValue.fInt64 = value;
    150 }
    151 
    152 // -------------------------------------
    153 // Creates a formattable object with a decimal number value from a string.
    154 
    155 Formattable::Formattable(const StringPiece &number, UErrorCode &status) {
    156     init();
    157     setDecimalNumber(number, status);
    158 }
    159 
    160 
    161 // -------------------------------------
    162 // Creates a formattable object with a UnicodeString instance.
    163 
    164 Formattable::Formattable(const UnicodeString& stringToCopy)
    165 {
    166     init();
    167     fType = kString;
    168     fValue.fString = new UnicodeString(stringToCopy);
    169 }
    170 
    171 // -------------------------------------
    172 // Creates a formattable object with a UnicodeString* value.
    173 // (adopting symantics)
    174 
    175 Formattable::Formattable(UnicodeString* stringToAdopt)
    176 {
    177     init();
    178     fType = kString;
    179     fValue.fString = stringToAdopt;
    180 }
    181 
    182 Formattable::Formattable(UObject* objectToAdopt)
    183 {
    184     init();
    185     fType = kObject;
    186     fValue.fObject = objectToAdopt;
    187 }
    188 
    189 // -------------------------------------
    190 
    191 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
    192     :   UObject(), fType(kArray)
    193 {
    194     init();
    195     fType = kArray;
    196     fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
    197     fValue.fArrayAndCount.fCount = count;
    198 }
    199 
    200 // -------------------------------------
    201 // copy constructor
    202 
    203 
    204 Formattable::Formattable(const Formattable &source)
    205      :  UObject(*this)
    206 {
    207     init();
    208     *this = source;
    209 }
    210 
    211 // -------------------------------------
    212 // assignment operator
    213 
    214 Formattable&
    215 Formattable::operator=(const Formattable& source)
    216 {
    217     if (this != &source)
    218     {
    219         // Disposes the current formattable value/setting.
    220         dispose();
    221 
    222         // Sets the correct data type for this value.
    223         fType = source.fType;
    224         switch (fType)
    225         {
    226         case kArray:
    227             // Sets each element in the array one by one and records the array count.
    228             fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
    229             fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
    230                                                            source.fValue.fArrayAndCount.fCount);
    231             break;
    232         case kString:
    233             // Sets the string value.
    234             fValue.fString = new UnicodeString(*source.fValue.fString);
    235             break;
    236         case kDouble:
    237             // Sets the double value.
    238             fValue.fDouble = source.fValue.fDouble;
    239             break;
    240         case kLong:
    241         case kInt64:
    242             // Sets the long value.
    243             fValue.fInt64 = source.fValue.fInt64;
    244             break;
    245         case kDate:
    246             // Sets the Date value.
    247             fValue.fDate = source.fValue.fDate;
    248             break;
    249         case kObject:
    250             fValue.fObject = objectClone(source.fValue.fObject);
    251             break;
    252         }
    253 
    254         UErrorCode status = U_ZERO_ERROR;
    255         if (source.fDecimalNum != NULL) {
    256             fDecimalNum = new DigitList(*source.fDecimalNum);
    257         }
    258         if (source.fDecimalStr != NULL) {
    259             fDecimalStr = new CharString(*source.fDecimalStr, status);
    260             if (U_FAILURE(status)) {
    261                 delete fDecimalStr;
    262                 fDecimalStr = NULL;
    263             }
    264         }
    265     }
    266     return *this;
    267 }
    268 
    269 // -------------------------------------
    270 
    271 UBool
    272 Formattable::operator==(const Formattable& that) const
    273 {
    274     int32_t i;
    275 
    276     if (this == &that) return TRUE;
    277 
    278     // Returns FALSE if the data types are different.
    279     if (fType != that.fType) return FALSE;
    280 
    281     // Compares the actual data values.
    282     UBool equal = TRUE;
    283     switch (fType) {
    284     case kDate:
    285         equal = (fValue.fDate == that.fValue.fDate);
    286         break;
    287     case kDouble:
    288         equal = (fValue.fDouble == that.fValue.fDouble);
    289         break;
    290     case kLong:
    291     case kInt64:
    292         equal = (fValue.fInt64 == that.fValue.fInt64);
    293         break;
    294     case kString:
    295         equal = (*(fValue.fString) == *(that.fValue.fString));
    296         break;
    297     case kArray:
    298         if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
    299             equal = FALSE;
    300             break;
    301         }
    302         // Checks each element for equality.
    303         for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
    304             if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
    305                 equal = FALSE;
    306                 break;
    307             }
    308         }
    309         break;
    310     case kObject:
    311         if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
    312             equal = FALSE;
    313         } else {
    314             equal = objectEquals(fValue.fObject, that.fValue.fObject);
    315         }
    316         break;
    317     }
    318 
    319     // TODO:  compare digit lists if numeric.
    320     return equal;
    321 }
    322 
    323 // -------------------------------------
    324 
    325 Formattable::~Formattable()
    326 {
    327     dispose();
    328 }
    329 
    330 // -------------------------------------
    331 
    332 void Formattable::dispose()
    333 {
    334     // Deletes the data value if necessary.
    335     switch (fType) {
    336     case kString:
    337         delete fValue.fString;
    338         break;
    339     case kArray:
    340         delete[] fValue.fArrayAndCount.fArray;
    341         break;
    342     case kObject:
    343         delete fValue.fObject;
    344         break;
    345     default:
    346         break;
    347     }
    348 
    349     fType = kLong;
    350     fValue.fInt64 = 0;
    351     delete fDecimalStr;
    352     fDecimalStr = NULL;
    353     delete fDecimalNum;
    354     fDecimalNum = NULL;
    355 }
    356 
    357 Formattable *
    358 Formattable::clone() const {
    359     return new Formattable(*this);
    360 }
    361 
    362 // -------------------------------------
    363 // Gets the data type of this Formattable object.
    364 Formattable::Type
    365 Formattable::getType() const
    366 {
    367     return fType;
    368 }
    369 
    370 UBool
    371 Formattable::isNumeric() const {
    372     switch (fType) {
    373     case kDouble:
    374     case kLong:
    375     case kInt64:
    376         return TRUE;
    377     default:
    378         return FALSE;
    379     }
    380 }
    381 
    382 // -------------------------------------
    383 int32_t
    384 //Formattable::getLong(UErrorCode* status) const
    385 Formattable::getLong(UErrorCode& status) const
    386 {
    387     if (U_FAILURE(status)) {
    388         return 0;
    389     }
    390 
    391     switch (fType) {
    392     case Formattable::kLong:
    393         return (int32_t)fValue.fInt64;
    394     case Formattable::kInt64:
    395         if (fValue.fInt64 > INT32_MAX) {
    396             status = U_INVALID_FORMAT_ERROR;
    397             return INT32_MAX;
    398         } else if (fValue.fInt64 < INT32_MIN) {
    399             status = U_INVALID_FORMAT_ERROR;
    400             return INT32_MIN;
    401         } else {
    402             return (int32_t)fValue.fInt64;
    403         }
    404     case Formattable::kDouble:
    405         if (fValue.fDouble > INT32_MAX) {
    406             status = U_INVALID_FORMAT_ERROR;
    407             return INT32_MAX;
    408         } else if (fValue.fDouble < INT32_MIN) {
    409             status = U_INVALID_FORMAT_ERROR;
    410             return INT32_MIN;
    411         } else {
    412             return (int32_t)fValue.fDouble; // loses fraction
    413         }
    414     case Formattable::kObject:
    415         if (fValue.fObject == NULL) {
    416             status = U_MEMORY_ALLOCATION_ERROR;
    417             return 0;
    418         }
    419         // TODO Later replace this with instanceof call
    420         if (instanceOfMeasure(fValue.fObject)) {
    421             return ((const Measure*) fValue.fObject)->
    422                 getNumber().getLong(status);
    423         }
    424     default:
    425         status = U_INVALID_FORMAT_ERROR;
    426         return 0;
    427     }
    428 }
    429 
    430 // -------------------------------------
    431 // Maximum int that can be represented exactly in a double.  (53 bits)
    432 //    Larger ints may be rounded to a near-by value as not all are representable.
    433 // TODO:  move this constant elsewhere, possibly configure it for different
    434 //        floating point formats, if any non-standard ones are still in use.
    435 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
    436 
    437 int64_t
    438 Formattable::getInt64(UErrorCode& status) const
    439 {
    440     if (U_FAILURE(status)) {
    441         return 0;
    442     }
    443 
    444     switch (fType) {
    445     case Formattable::kLong:
    446     case Formattable::kInt64:
    447         return fValue.fInt64;
    448     case Formattable::kDouble:
    449         if (fValue.fDouble > (double)U_INT64_MAX) {
    450             status = U_INVALID_FORMAT_ERROR;
    451             return U_INT64_MAX;
    452         } else if (fValue.fDouble < (double)U_INT64_MIN) {
    453             status = U_INVALID_FORMAT_ERROR;
    454             return U_INT64_MIN;
    455         } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
    456             int64_t val = fDecimalNum->getInt64();
    457             if (val != 0) {
    458                 return val;
    459             } else {
    460                 status = U_INVALID_FORMAT_ERROR;
    461                 return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN;
    462             }
    463         } else {
    464             return (int64_t)fValue.fDouble;
    465         }
    466     case Formattable::kObject:
    467         if (fValue.fObject == NULL) {
    468             status = U_MEMORY_ALLOCATION_ERROR;
    469             return 0;
    470         }
    471         if (instanceOfMeasure(fValue.fObject)) {
    472             return ((const Measure*) fValue.fObject)->
    473                 getNumber().getInt64(status);
    474         }
    475     default:
    476         status = U_INVALID_FORMAT_ERROR;
    477         return 0;
    478     }
    479 }
    480 
    481 // -------------------------------------
    482 double
    483 Formattable::getDouble(UErrorCode& status) const
    484 {
    485     if (U_FAILURE(status)) {
    486         return 0;
    487     }
    488 
    489     switch (fType) {
    490     case Formattable::kLong:
    491     case Formattable::kInt64: // loses precision
    492         return (double)fValue.fInt64;
    493     case Formattable::kDouble:
    494         return fValue.fDouble;
    495     case Formattable::kObject:
    496         if (fValue.fObject == NULL) {
    497             status = U_MEMORY_ALLOCATION_ERROR;
    498             return 0;
    499         }
    500         // TODO Later replace this with instanceof call
    501         if (instanceOfMeasure(fValue.fObject)) {
    502             return ((const Measure*) fValue.fObject)->
    503                 getNumber().getDouble(status);
    504         }
    505     default:
    506         status = U_INVALID_FORMAT_ERROR;
    507         return 0;
    508     }
    509 }
    510 
    511 const UObject*
    512 Formattable::getObject() const {
    513     return (fType == kObject) ? fValue.fObject : NULL;
    514 }
    515 
    516 // -------------------------------------
    517 // Sets the value to a double value d.
    518 
    519 void
    520 Formattable::setDouble(double d)
    521 {
    522     dispose();
    523     fType = kDouble;
    524     fValue.fDouble = d;
    525 }
    526 
    527 // -------------------------------------
    528 // Sets the value to a long value l.
    529 
    530 void
    531 Formattable::setLong(int32_t l)
    532 {
    533     dispose();
    534     fType = kLong;
    535     fValue.fInt64 = l;
    536 }
    537 
    538 // -------------------------------------
    539 // Sets the value to an int64 value ll.
    540 
    541 void
    542 Formattable::setInt64(int64_t ll)
    543 {
    544     dispose();
    545     fType = kInt64;
    546     fValue.fInt64 = ll;
    547 }
    548 
    549 // -------------------------------------
    550 // Sets the value to a Date instance d.
    551 
    552 void
    553 Formattable::setDate(UDate d)
    554 {
    555     dispose();
    556     fType = kDate;
    557     fValue.fDate = d;
    558 }
    559 
    560 // -------------------------------------
    561 // Sets the value to a string value stringToCopy.
    562 
    563 void
    564 Formattable::setString(const UnicodeString& stringToCopy)
    565 {
    566     dispose();
    567     fType = kString;
    568     fValue.fString = new UnicodeString(stringToCopy);
    569 }
    570 
    571 // -------------------------------------
    572 // Sets the value to an array of Formattable objects.
    573 
    574 void
    575 Formattable::setArray(const Formattable* array, int32_t count)
    576 {
    577     dispose();
    578     fType = kArray;
    579     fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
    580     fValue.fArrayAndCount.fCount = count;
    581 }
    582 
    583 // -------------------------------------
    584 // Adopts the stringToAdopt value.
    585 
    586 void
    587 Formattable::adoptString(UnicodeString* stringToAdopt)
    588 {
    589     dispose();
    590     fType = kString;
    591     fValue.fString = stringToAdopt;
    592 }
    593 
    594 // -------------------------------------
    595 // Adopts the array value and its count.
    596 
    597 void
    598 Formattable::adoptArray(Formattable* array, int32_t count)
    599 {
    600     dispose();
    601     fType = kArray;
    602     fValue.fArrayAndCount.fArray = array;
    603     fValue.fArrayAndCount.fCount = count;
    604 }
    605 
    606 void
    607 Formattable::adoptObject(UObject* objectToAdopt) {
    608     dispose();
    609     fType = kObject;
    610     fValue.fObject = objectToAdopt;
    611 }
    612 
    613 // -------------------------------------
    614 UnicodeString&
    615 Formattable::getString(UnicodeString& result, UErrorCode& status) const
    616 {
    617     if (fType != kString) {
    618         setError(status, U_INVALID_FORMAT_ERROR);
    619         result.setToBogus();
    620     } else {
    621         if (fValue.fString == NULL) {
    622             setError(status, U_MEMORY_ALLOCATION_ERROR);
    623         } else {
    624             result = *fValue.fString;
    625         }
    626     }
    627     return result;
    628 }
    629 
    630 // -------------------------------------
    631 const UnicodeString&
    632 Formattable::getString(UErrorCode& status) const
    633 {
    634     if (fType != kString) {
    635         setError(status, U_INVALID_FORMAT_ERROR);
    636         return *getBogus();
    637     }
    638     if (fValue.fString == NULL) {
    639         setError(status, U_MEMORY_ALLOCATION_ERROR);
    640         return *getBogus();
    641     }
    642     return *fValue.fString;
    643 }
    644 
    645 // -------------------------------------
    646 UnicodeString&
    647 Formattable::getString(UErrorCode& status)
    648 {
    649     if (fType != kString) {
    650         setError(status, U_INVALID_FORMAT_ERROR);
    651         return *getBogus();
    652     }
    653     if (fValue.fString == NULL) {
    654     	setError(status, U_MEMORY_ALLOCATION_ERROR);
    655     	return *getBogus();
    656     }
    657     return *fValue.fString;
    658 }
    659 
    660 // -------------------------------------
    661 const Formattable*
    662 Formattable::getArray(int32_t& count, UErrorCode& status) const
    663 {
    664     if (fType != kArray) {
    665         setError(status, U_INVALID_FORMAT_ERROR);
    666         count = 0;
    667         return NULL;
    668     }
    669     count = fValue.fArrayAndCount.fCount;
    670     return fValue.fArrayAndCount.fArray;
    671 }
    672 
    673 // -------------------------------------
    674 // Gets the bogus string, ensures mondo bogosity.
    675 
    676 UnicodeString*
    677 Formattable::getBogus() const
    678 {
    679     return (UnicodeString*)&fBogus; /* cast away const :-( */
    680 }
    681 
    682 
    683 // --------------------------------------
    684 StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
    685     if (U_FAILURE(status)) {
    686         return "";
    687     }
    688     if (fDecimalStr != NULL) {
    689         return fDecimalStr->toStringPiece();
    690     }
    691 
    692     if (fDecimalNum == NULL) {
    693         // No decimal number for the formattable yet.  Which means the value was
    694         // set directly by the user as an int, int64 or double.  If the value came
    695         // from parsing, or from the user setting a decimal number, fDecimalNum
    696         // would already be set.
    697         //
    698         fDecimalNum = new DigitList;
    699         if (fDecimalNum == NULL) {
    700             status = U_MEMORY_ALLOCATION_ERROR;
    701             return "";
    702         }
    703 
    704         switch (fType) {
    705         case kDouble:
    706             fDecimalNum->set(this->getDouble());
    707             break;
    708         case kLong:
    709             fDecimalNum->set(this->getLong());
    710             break;
    711         case kInt64:
    712             fDecimalNum->set(this->getInt64());
    713             break;
    714         default:
    715             // The formattable's value is not a numeric type.
    716             status = U_INVALID_STATE_ERROR;
    717             return "";
    718         }
    719     }
    720 
    721     fDecimalStr = new CharString;
    722     if (fDecimalStr == NULL) {
    723         status = U_MEMORY_ALLOCATION_ERROR;
    724         return "";
    725     }
    726     fDecimalNum->getDecimal(*fDecimalStr, status);
    727 
    728     return fDecimalStr->toStringPiece();
    729 }
    730 
    731 
    732 
    733 // ---------------------------------------
    734 void
    735 Formattable::adoptDigitList(DigitList *dl) {
    736     dispose();
    737 
    738     fDecimalNum = dl;
    739 
    740     // Set the value into the Union of simple type values.
    741     // Cannot use the set() functions because they would delete the fDecimalNum value,
    742 
    743     if (fDecimalNum->fitsIntoLong(FALSE)) {
    744         fType = kLong;
    745         fValue.fInt64 = fDecimalNum->getLong();
    746     } else if (fDecimalNum->fitsIntoInt64(FALSE)) {
    747         fType = kInt64;
    748         fValue.fInt64 = fDecimalNum->getInt64();
    749     } else {
    750         fType = kDouble;
    751         fValue.fDouble = fDecimalNum->getDouble();
    752     }
    753 }
    754 
    755 
    756 // ---------------------------------------
    757 void
    758 Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &status) {
    759     if (U_FAILURE(status)) {
    760         return;
    761     }
    762     dispose();
    763 
    764     // Copy the input string and nul-terminate it.
    765     //    The decNumber library requires nul-terminated input.  StringPiece input
    766     //    is not guaranteed nul-terminated.  Too bad.
    767     //    CharString automatically adds the nul.
    768     DigitList *dnum = new DigitList();
    769     if (dnum == NULL) {
    770         status = U_MEMORY_ALLOCATION_ERROR;
    771         return;
    772     }
    773     dnum->set(CharString(numberString, status).toStringPiece(), status);
    774     if (U_FAILURE(status)) {
    775         delete dnum;
    776         return;   // String didn't contain a decimal number.
    777     }
    778     adoptDigitList(dnum);
    779 
    780     // Note that we do not hang on to the caller's input string.
    781     // If we are asked for the string, we will regenerate one from fDecimalNum.
    782 }
    783 
    784 #if 0
    785 //----------------------------------------------------
    786 // console I/O
    787 //----------------------------------------------------
    788 #ifdef _DEBUG
    789 
    790 #if U_IOSTREAM_SOURCE >= 199711
    791 #include <iostream>
    792 using namespace std;
    793 #elif U_IOSTREAM_SOURCE >= 198506
    794 #include <iostream.h>
    795 #endif
    796 
    797 #include "unicode/datefmt.h"
    798 #include "unistrm.h"
    799 
    800 class FormattableStreamer /* not : public UObject because all methods are static */ {
    801 public:
    802     static void streamOut(ostream& stream, const Formattable& obj);
    803 
    804 private:
    805     FormattableStreamer() {} // private - forbid instantiation
    806 };
    807 
    808 // This is for debugging purposes only.  This will send a displayable
    809 // form of the Formattable object to the output stream.
    810 
    811 void
    812 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
    813 {
    814     static DateFormat *defDateFormat = 0;
    815 
    816     UnicodeString buffer;
    817     switch(obj.getType()) {
    818         case Formattable::kDate :
    819             // Creates a DateFormat instance for formatting the
    820             // Date instance.
    821             if (defDateFormat == 0) {
    822                 defDateFormat = DateFormat::createInstance();
    823             }
    824             defDateFormat->format(obj.getDate(), buffer);
    825             stream << buffer;
    826             break;
    827         case Formattable::kDouble :
    828             // Output the double as is.
    829             stream << obj.getDouble() << 'D';
    830             break;
    831         case Formattable::kLong :
    832             // Output the double as is.
    833             stream << obj.getLong() << 'L';
    834             break;
    835         case Formattable::kString:
    836             // Output the double as is.  Please see UnicodeString console
    837             // I/O routine for more details.
    838             stream << '"' << obj.getString(buffer) << '"';
    839             break;
    840         case Formattable::kArray:
    841             int32_t i, count;
    842             const Formattable* array;
    843             array = obj.getArray(count);
    844             stream << '[';
    845             // Recursively calling the console I/O routine for each element in the array.
    846             for (i=0; i<count; ++i) {
    847                 FormattableStreamer::streamOut(stream, array[i]);
    848                 stream << ( (i==(count-1)) ? "" : ", " );
    849             }
    850             stream << ']';
    851             break;
    852         default:
    853             // Not a recognizable Formattable object.
    854             stream << "INVALID_Formattable";
    855     }
    856     stream.flush();
    857 }
    858 #endif
    859 
    860 #endif
    861 
    862 U_NAMESPACE_END
    863 
    864 #endif /* #if !UCONFIG_NO_FORMATTING */
    865 
    866 //eof
    867