Home | History | Annotate | Download | only in i18n
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 * Copyright (C) 1997-2016, International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 *******************************************************************************
      8 *
      9 * File FMTABLE.CPP
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   03/25/97    clhuang     Initial Implementation.
     15 ********************************************************************************
     16 */
     17 
     18 #include "unicode/utypes.h"
     19 
     20 #if !UCONFIG_NO_FORMATTING
     21 
     22 #include <cstdlib>
     23 #include <math.h>
     24 #include "unicode/fmtable.h"
     25 #include "unicode/ustring.h"
     26 #include "unicode/measure.h"
     27 #include "unicode/curramt.h"
     28 #include "unicode/uformattable.h"
     29 #include "charstr.h"
     30 #include "cmemory.h"
     31 #include "cstring.h"
     32 #include "fmtableimp.h"
     33 #include "number_decimalquantity.h"
     34 
     35 // *****************************************************************************
     36 // class Formattable
     37 // *****************************************************************************
     38 
     39 U_NAMESPACE_BEGIN
     40 
     41 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
     42 
     43 using number::impl::DecimalQuantity;
     44 
     45 
     46 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
     47 
     48 // NOTE: As of 3.0, there are limitations to the UObject API.  It does
     49 // not (yet) support cloning, operator=, nor operator==.  To
     50 // work around this, I implement some simple inlines here.  Later
     51 // these can be modified or removed.  [alan]
     52 
     53 // NOTE: These inlines assume that all fObjects are in fact instances
     54 // of the Measure class, which is true as of 3.0.  [alan]
     55 
     56 // Return TRUE if *a == *b.
     57 static inline UBool objectEquals(const UObject* a, const UObject* b) {
     58     // LATER: return *a == *b;
     59     return *((const Measure*) a) == *((const Measure*) b);
     60 }
     61 
     62 // Return a clone of *a.
     63 static inline UObject* objectClone(const UObject* a) {
     64     // LATER: return a->clone();
     65     return ((const Measure*) a)->clone();
     66 }
     67 
     68 // Return TRUE if *a is an instance of Measure.
     69 static inline UBool instanceOfMeasure(const UObject* a) {
     70     return dynamic_cast<const Measure*>(a) != NULL;
     71 }
     72 
     73 /**
     74  * Creates a new Formattable array and copies the values from the specified
     75  * original.
     76  * @param array the original array
     77  * @param count the original array count
     78  * @return the new Formattable array.
     79  */
     80 static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
     81     Formattable *result = new Formattable[count];
     82     if (result != NULL) {
     83         for (int32_t i=0; i<count; ++i)
     84             result[i] = array[i]; // Don't memcpy!
     85     }
     86     return result;
     87 }
     88 
     89 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
     90 
     91 /**
     92  * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
     93  */
     94 static void setError(UErrorCode& ec, UErrorCode err) {
     95     if (U_SUCCESS(ec)) {
     96         ec = err;
     97     }
     98 }
     99 
    100 //
    101 //  Common initialization code, shared by constructors.
    102 //  Put everything into a known state.
    103 //
    104 void  Formattable::init() {
    105     fValue.fInt64 = 0;
    106     fType = kLong;
    107     fDecimalStr = NULL;
    108     fDecimalQuantity = NULL;
    109     fBogus.setToBogus();
    110 }
    111 
    112 // -------------------------------------
    113 // default constructor.
    114 // Creates a formattable object with a long value 0.
    115 
    116 Formattable::Formattable() {
    117     init();
    118 }
    119 
    120 // -------------------------------------
    121 // Creates a formattable object with a Date instance.
    122 
    123 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
    124 {
    125     init();
    126     fType = kDate;
    127     fValue.fDate = date;
    128 }
    129 
    130 // -------------------------------------
    131 // Creates a formattable object with a double value.
    132 
    133 Formattable::Formattable(double value)
    134 {
    135     init();
    136     fType = kDouble;
    137     fValue.fDouble = value;
    138 }
    139 
    140 // -------------------------------------
    141 // Creates a formattable object with an int32_t value.
    142 
    143 Formattable::Formattable(int32_t value)
    144 {
    145     init();
    146     fValue.fInt64 = value;
    147 }
    148 
    149 // -------------------------------------
    150 // Creates a formattable object with an int64_t value.
    151 
    152 Formattable::Formattable(int64_t value)
    153 {
    154     init();
    155     fType = kInt64;
    156     fValue.fInt64 = value;
    157 }
    158 
    159 // -------------------------------------
    160 // Creates a formattable object with a decimal number value from a string.
    161 
    162 Formattable::Formattable(StringPiece number, UErrorCode &status) {
    163     init();
    164     setDecimalNumber(number, status);
    165 }
    166 
    167 
    168 // -------------------------------------
    169 // Creates a formattable object with a UnicodeString instance.
    170 
    171 Formattable::Formattable(const UnicodeString& stringToCopy)
    172 {
    173     init();
    174     fType = kString;
    175     fValue.fString = new UnicodeString(stringToCopy);
    176 }
    177 
    178 // -------------------------------------
    179 // Creates a formattable object with a UnicodeString* value.
    180 // (adopting symantics)
    181 
    182 Formattable::Formattable(UnicodeString* stringToAdopt)
    183 {
    184     init();
    185     fType = kString;
    186     fValue.fString = stringToAdopt;
    187 }
    188 
    189 Formattable::Formattable(UObject* objectToAdopt)
    190 {
    191     init();
    192     fType = kObject;
    193     fValue.fObject = objectToAdopt;
    194 }
    195 
    196 // -------------------------------------
    197 
    198 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
    199     :   UObject(), fType(kArray)
    200 {
    201     init();
    202     fType = kArray;
    203     fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
    204     fValue.fArrayAndCount.fCount = count;
    205 }
    206 
    207 // -------------------------------------
    208 // copy constructor
    209 
    210 
    211 Formattable::Formattable(const Formattable &source)
    212      :  UObject(*this)
    213 {
    214     init();
    215     *this = source;
    216 }
    217 
    218 // -------------------------------------
    219 // assignment operator
    220 
    221 Formattable&
    222 Formattable::operator=(const Formattable& source)
    223 {
    224     if (this != &source)
    225     {
    226         // Disposes the current formattable value/setting.
    227         dispose();
    228 
    229         // Sets the correct data type for this value.
    230         fType = source.fType;
    231         switch (fType)
    232         {
    233         case kArray:
    234             // Sets each element in the array one by one and records the array count.
    235             fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
    236             fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
    237                                                            source.fValue.fArrayAndCount.fCount);
    238             break;
    239         case kString:
    240             // Sets the string value.
    241             fValue.fString = new UnicodeString(*source.fValue.fString);
    242             break;
    243         case kDouble:
    244             // Sets the double value.
    245             fValue.fDouble = source.fValue.fDouble;
    246             break;
    247         case kLong:
    248         case kInt64:
    249             // Sets the long value.
    250             fValue.fInt64 = source.fValue.fInt64;
    251             break;
    252         case kDate:
    253             // Sets the Date value.
    254             fValue.fDate = source.fValue.fDate;
    255             break;
    256         case kObject:
    257             fValue.fObject = objectClone(source.fValue.fObject);
    258             break;
    259         }
    260 
    261         UErrorCode status = U_ZERO_ERROR;
    262         if (source.fDecimalQuantity != NULL) {
    263           fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
    264         }
    265         if (source.fDecimalStr != NULL) {
    266             fDecimalStr = new CharString(*source.fDecimalStr, status);
    267             if (U_FAILURE(status)) {
    268                 delete fDecimalStr;
    269                 fDecimalStr = NULL;
    270             }
    271         }
    272     }
    273     return *this;
    274 }
    275 
    276 // -------------------------------------
    277 
    278 UBool
    279 Formattable::operator==(const Formattable& that) const
    280 {
    281     int32_t i;
    282 
    283     if (this == &that) return TRUE;
    284 
    285     // Returns FALSE if the data types are different.
    286     if (fType != that.fType) return FALSE;
    287 
    288     // Compares the actual data values.
    289     UBool equal = TRUE;
    290     switch (fType) {
    291     case kDate:
    292         equal = (fValue.fDate == that.fValue.fDate);
    293         break;
    294     case kDouble:
    295         equal = (fValue.fDouble == that.fValue.fDouble);
    296         break;
    297     case kLong:
    298     case kInt64:
    299         equal = (fValue.fInt64 == that.fValue.fInt64);
    300         break;
    301     case kString:
    302         equal = (*(fValue.fString) == *(that.fValue.fString));
    303         break;
    304     case kArray:
    305         if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
    306             equal = FALSE;
    307             break;
    308         }
    309         // Checks each element for equality.
    310         for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
    311             if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
    312                 equal = FALSE;
    313                 break;
    314             }
    315         }
    316         break;
    317     case kObject:
    318         if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
    319             equal = FALSE;
    320         } else {
    321             equal = objectEquals(fValue.fObject, that.fValue.fObject);
    322         }
    323         break;
    324     }
    325 
    326     // TODO:  compare digit lists if numeric.
    327     return equal;
    328 }
    329 
    330 // -------------------------------------
    331 
    332 Formattable::~Formattable()
    333 {
    334     dispose();
    335 }
    336 
    337 // -------------------------------------
    338 
    339 void Formattable::dispose()
    340 {
    341     // Deletes the data value if necessary.
    342     switch (fType) {
    343     case kString:
    344         delete fValue.fString;
    345         break;
    346     case kArray:
    347         delete[] fValue.fArrayAndCount.fArray;
    348         break;
    349     case kObject:
    350         delete fValue.fObject;
    351         break;
    352     default:
    353         break;
    354     }
    355 
    356     fType = kLong;
    357     fValue.fInt64 = 0;
    358 
    359     delete fDecimalStr;
    360     fDecimalStr = NULL;
    361 
    362     delete fDecimalQuantity;
    363     fDecimalQuantity = NULL;
    364 }
    365 
    366 Formattable *
    367 Formattable::clone() const {
    368     return new Formattable(*this);
    369 }
    370 
    371 // -------------------------------------
    372 // Gets the data type of this Formattable object.
    373 Formattable::Type
    374 Formattable::getType() const
    375 {
    376     return fType;
    377 }
    378 
    379 UBool
    380 Formattable::isNumeric() const {
    381     switch (fType) {
    382     case kDouble:
    383     case kLong:
    384     case kInt64:
    385         return TRUE;
    386     default:
    387         return FALSE;
    388     }
    389 }
    390 
    391 // -------------------------------------
    392 int32_t
    393 //Formattable::getLong(UErrorCode* status) const
    394 Formattable::getLong(UErrorCode& status) const
    395 {
    396     if (U_FAILURE(status)) {
    397         return 0;
    398     }
    399 
    400     switch (fType) {
    401     case Formattable::kLong:
    402         return (int32_t)fValue.fInt64;
    403     case Formattable::kInt64:
    404         if (fValue.fInt64 > INT32_MAX) {
    405             status = U_INVALID_FORMAT_ERROR;
    406             return INT32_MAX;
    407         } else if (fValue.fInt64 < INT32_MIN) {
    408             status = U_INVALID_FORMAT_ERROR;
    409             return INT32_MIN;
    410         } else {
    411             return (int32_t)fValue.fInt64;
    412         }
    413     case Formattable::kDouble:
    414         if (fValue.fDouble > INT32_MAX) {
    415             status = U_INVALID_FORMAT_ERROR;
    416             return INT32_MAX;
    417         } else if (fValue.fDouble < INT32_MIN) {
    418             status = U_INVALID_FORMAT_ERROR;
    419             return INT32_MIN;
    420         } else {
    421             return (int32_t)fValue.fDouble; // loses fraction
    422         }
    423     case Formattable::kObject:
    424         if (fValue.fObject == NULL) {
    425             status = U_MEMORY_ALLOCATION_ERROR;
    426             return 0;
    427         }
    428         // TODO Later replace this with instanceof call
    429         if (instanceOfMeasure(fValue.fObject)) {
    430             return ((const Measure*) fValue.fObject)->
    431                 getNumber().getLong(status);
    432         }
    433         U_FALLTHROUGH;
    434     default:
    435         status = U_INVALID_FORMAT_ERROR;
    436         return 0;
    437     }
    438 }
    439 
    440 // -------------------------------------
    441 // Maximum int that can be represented exactly in a double.  (53 bits)
    442 //    Larger ints may be rounded to a near-by value as not all are representable.
    443 // TODO:  move this constant elsewhere, possibly configure it for different
    444 //        floating point formats, if any non-standard ones are still in use.
    445 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
    446 
    447 int64_t
    448 Formattable::getInt64(UErrorCode& status) const
    449 {
    450     if (U_FAILURE(status)) {
    451         return 0;
    452     }
    453 
    454     switch (fType) {
    455     case Formattable::kLong:
    456     case Formattable::kInt64:
    457         return fValue.fInt64;
    458     case Formattable::kDouble:
    459         if (fValue.fDouble > (double)U_INT64_MAX) {
    460             status = U_INVALID_FORMAT_ERROR;
    461             return U_INT64_MAX;
    462         } else if (fValue.fDouble < (double)U_INT64_MIN) {
    463             status = U_INVALID_FORMAT_ERROR;
    464             return U_INT64_MIN;
    465         } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != NULL) {
    466             if (fDecimalQuantity->fitsInLong(true)) {
    467                 return fDecimalQuantity->toLong();
    468             } else {
    469                 // Unexpected
    470                 status = U_INVALID_FORMAT_ERROR;
    471                 return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX;
    472             }
    473         } else {
    474             return (int64_t)fValue.fDouble;
    475         }
    476     case Formattable::kObject:
    477         if (fValue.fObject == NULL) {
    478             status = U_MEMORY_ALLOCATION_ERROR;
    479             return 0;
    480         }
    481         if (instanceOfMeasure(fValue.fObject)) {
    482             return ((const Measure*) fValue.fObject)->
    483                 getNumber().getInt64(status);
    484         }
    485         U_FALLTHROUGH;
    486     default:
    487         status = U_INVALID_FORMAT_ERROR;
    488         return 0;
    489     }
    490 }
    491 
    492 // -------------------------------------
    493 double
    494 Formattable::getDouble(UErrorCode& status) const
    495 {
    496     if (U_FAILURE(status)) {
    497         return 0;
    498     }
    499 
    500     switch (fType) {
    501     case Formattable::kLong:
    502     case Formattable::kInt64: // loses precision
    503         return (double)fValue.fInt64;
    504     case Formattable::kDouble:
    505         return fValue.fDouble;
    506     case Formattable::kObject:
    507         if (fValue.fObject == NULL) {
    508             status = U_MEMORY_ALLOCATION_ERROR;
    509             return 0;
    510         }
    511         // TODO Later replace this with instanceof call
    512         if (instanceOfMeasure(fValue.fObject)) {
    513             return ((const Measure*) fValue.fObject)->
    514                 getNumber().getDouble(status);
    515         }
    516         U_FALLTHROUGH;
    517     default:
    518         status = U_INVALID_FORMAT_ERROR;
    519         return 0;
    520     }
    521 }
    522 
    523 const UObject*
    524 Formattable::getObject() const {
    525     return (fType == kObject) ? fValue.fObject : NULL;
    526 }
    527 
    528 // -------------------------------------
    529 // Sets the value to a double value d.
    530 
    531 void
    532 Formattable::setDouble(double d)
    533 {
    534     dispose();
    535     fType = kDouble;
    536     fValue.fDouble = d;
    537 }
    538 
    539 // -------------------------------------
    540 // Sets the value to a long value l.
    541 
    542 void
    543 Formattable::setLong(int32_t l)
    544 {
    545     dispose();
    546     fType = kLong;
    547     fValue.fInt64 = l;
    548 }
    549 
    550 // -------------------------------------
    551 // Sets the value to an int64 value ll.
    552 
    553 void
    554 Formattable::setInt64(int64_t ll)
    555 {
    556     dispose();
    557     fType = kInt64;
    558     fValue.fInt64 = ll;
    559 }
    560 
    561 // -------------------------------------
    562 // Sets the value to a Date instance d.
    563 
    564 void
    565 Formattable::setDate(UDate d)
    566 {
    567     dispose();
    568     fType = kDate;
    569     fValue.fDate = d;
    570 }
    571 
    572 // -------------------------------------
    573 // Sets the value to a string value stringToCopy.
    574 
    575 void
    576 Formattable::setString(const UnicodeString& stringToCopy)
    577 {
    578     dispose();
    579     fType = kString;
    580     fValue.fString = new UnicodeString(stringToCopy);
    581 }
    582 
    583 // -------------------------------------
    584 // Sets the value to an array of Formattable objects.
    585 
    586 void
    587 Formattable::setArray(const Formattable* array, int32_t count)
    588 {
    589     dispose();
    590     fType = kArray;
    591     fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
    592     fValue.fArrayAndCount.fCount = count;
    593 }
    594 
    595 // -------------------------------------
    596 // Adopts the stringToAdopt value.
    597 
    598 void
    599 Formattable::adoptString(UnicodeString* stringToAdopt)
    600 {
    601     dispose();
    602     fType = kString;
    603     fValue.fString = stringToAdopt;
    604 }
    605 
    606 // -------------------------------------
    607 // Adopts the array value and its count.
    608 
    609 void
    610 Formattable::adoptArray(Formattable* array, int32_t count)
    611 {
    612     dispose();
    613     fType = kArray;
    614     fValue.fArrayAndCount.fArray = array;
    615     fValue.fArrayAndCount.fCount = count;
    616 }
    617 
    618 void
    619 Formattable::adoptObject(UObject* objectToAdopt) {
    620     dispose();
    621     fType = kObject;
    622     fValue.fObject = objectToAdopt;
    623 }
    624 
    625 // -------------------------------------
    626 UnicodeString&
    627 Formattable::getString(UnicodeString& result, UErrorCode& status) const
    628 {
    629     if (fType != kString) {
    630         setError(status, U_INVALID_FORMAT_ERROR);
    631         result.setToBogus();
    632     } else {
    633         if (fValue.fString == NULL) {
    634             setError(status, U_MEMORY_ALLOCATION_ERROR);
    635         } else {
    636             result = *fValue.fString;
    637         }
    638     }
    639     return result;
    640 }
    641 
    642 // -------------------------------------
    643 const UnicodeString&
    644 Formattable::getString(UErrorCode& status) const
    645 {
    646     if (fType != kString) {
    647         setError(status, U_INVALID_FORMAT_ERROR);
    648         return *getBogus();
    649     }
    650     if (fValue.fString == NULL) {
    651         setError(status, U_MEMORY_ALLOCATION_ERROR);
    652         return *getBogus();
    653     }
    654     return *fValue.fString;
    655 }
    656 
    657 // -------------------------------------
    658 UnicodeString&
    659 Formattable::getString(UErrorCode& status)
    660 {
    661     if (fType != kString) {
    662         setError(status, U_INVALID_FORMAT_ERROR);
    663         return *getBogus();
    664     }
    665     if (fValue.fString == NULL) {
    666     	setError(status, U_MEMORY_ALLOCATION_ERROR);
    667     	return *getBogus();
    668     }
    669     return *fValue.fString;
    670 }
    671 
    672 // -------------------------------------
    673 const Formattable*
    674 Formattable::getArray(int32_t& count, UErrorCode& status) const
    675 {
    676     if (fType != kArray) {
    677         setError(status, U_INVALID_FORMAT_ERROR);
    678         count = 0;
    679         return NULL;
    680     }
    681     count = fValue.fArrayAndCount.fCount;
    682     return fValue.fArrayAndCount.fArray;
    683 }
    684 
    685 // -------------------------------------
    686 // Gets the bogus string, ensures mondo bogosity.
    687 
    688 UnicodeString*
    689 Formattable::getBogus() const
    690 {
    691     return (UnicodeString*)&fBogus; /* cast away const :-( */
    692 }
    693 
    694 
    695 // --------------------------------------
    696 StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
    697     if (U_FAILURE(status)) {
    698         return "";
    699     }
    700     if (fDecimalStr != NULL) {
    701       return fDecimalStr->toStringPiece();
    702     }
    703 
    704     CharString *decimalStr = internalGetCharString(status);
    705     if(decimalStr == NULL) {
    706       return ""; // getDecimalNumber returns "" for error cases
    707     } else {
    708       return decimalStr->toStringPiece();
    709     }
    710 }
    711 
    712 CharString *Formattable::internalGetCharString(UErrorCode &status) {
    713     if(fDecimalStr == NULL) {
    714       if (fDecimalQuantity == NULL) {
    715         // No decimal number for the formattable yet.  Which means the value was
    716         // set directly by the user as an int, int64 or double.  If the value came
    717         // from parsing, or from the user setting a decimal number, fDecimalNum
    718         // would already be set.
    719         //
    720         LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
    721         if (U_FAILURE(status)) { return nullptr; }
    722         populateDecimalQuantity(*dq, status);
    723         if (U_FAILURE(status)) { return nullptr; }
    724         fDecimalQuantity = dq.orphan();
    725       }
    726 
    727       fDecimalStr = new CharString();
    728       if (fDecimalStr == NULL) {
    729         status = U_MEMORY_ALLOCATION_ERROR;
    730         return NULL;
    731       }
    732       // Older ICUs called uprv_decNumberToString here, which is not exactly the same as
    733       // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does
    734       // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
    735       if (fDecimalQuantity->isZero()) {
    736         fDecimalStr->append("0", -1, status);
    737       } else if (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5) {
    738         fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status);
    739       } else {
    740         fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status);
    741       }
    742     }
    743     return fDecimalStr;
    744 }
    745 
    746 void
    747 Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
    748     if (fDecimalQuantity != nullptr) {
    749         output = *fDecimalQuantity;
    750         return;
    751     }
    752 
    753     switch (fType) {
    754         case kDouble:
    755             output.setToDouble(this->getDouble());
    756             output.roundToInfinity();
    757             break;
    758         case kLong:
    759             output.setToInt(this->getLong());
    760             break;
    761         case kInt64:
    762             output.setToLong(this->getInt64());
    763             break;
    764         default:
    765             // The formattable's value is not a numeric type.
    766             status = U_INVALID_STATE_ERROR;
    767     }
    768 }
    769 
    770 // ---------------------------------------
    771 void
    772 Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
    773     if (fDecimalQuantity != NULL) {
    774         delete fDecimalQuantity;
    775     }
    776     fDecimalQuantity = dq;
    777     if (dq == NULL) { // allow adoptDigitList(NULL) to clear
    778         return;
    779     }
    780 
    781     // Set the value into the Union of simple type values.
    782     // Cannot use the set() functions because they would delete the fDecimalNum value.
    783     if (fDecimalQuantity->fitsInLong()) {
    784         fValue.fInt64 = fDecimalQuantity->toLong();
    785         if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
    786             fType = kLong;
    787         } else {
    788             fType = kInt64;
    789         }
    790     } else {
    791         fType = kDouble;
    792         fValue.fDouble = fDecimalQuantity->toDouble();
    793     }
    794 }
    795 
    796 
    797 // ---------------------------------------
    798 void
    799 Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
    800     if (U_FAILURE(status)) {
    801         return;
    802     }
    803     dispose();
    804 
    805     auto* dq = new DecimalQuantity();
    806     dq->setToDecNumber(numberString, status);
    807     adoptDecimalQuantity(dq);
    808 
    809     // Note that we do not hang on to the caller's input string.
    810     // If we are asked for the string, we will regenerate one from fDecimalQuantity.
    811 }
    812 
    813 #if 0
    814 //----------------------------------------------------
    815 // console I/O
    816 //----------------------------------------------------
    817 #ifdef _DEBUG
    818 
    819 #include <iostream>
    820 using namespace std;
    821 
    822 #include "unicode/datefmt.h"
    823 #include "unistrm.h"
    824 
    825 class FormattableStreamer /* not : public UObject because all methods are static */ {
    826 public:
    827     static void streamOut(ostream& stream, const Formattable& obj);
    828 
    829 private:
    830     FormattableStreamer() {} // private - forbid instantiation
    831 };
    832 
    833 // This is for debugging purposes only.  This will send a displayable
    834 // form of the Formattable object to the output stream.
    835 
    836 void
    837 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
    838 {
    839     static DateFormat *defDateFormat = 0;
    840 
    841     UnicodeString buffer;
    842     switch(obj.getType()) {
    843         case Formattable::kDate :
    844             // Creates a DateFormat instance for formatting the
    845             // Date instance.
    846             if (defDateFormat == 0) {
    847                 defDateFormat = DateFormat::createInstance();
    848             }
    849             defDateFormat->format(obj.getDate(), buffer);
    850             stream << buffer;
    851             break;
    852         case Formattable::kDouble :
    853             // Output the double as is.
    854             stream << obj.getDouble() << 'D';
    855             break;
    856         case Formattable::kLong :
    857             // Output the double as is.
    858             stream << obj.getLong() << 'L';
    859             break;
    860         case Formattable::kString:
    861             // Output the double as is.  Please see UnicodeString console
    862             // I/O routine for more details.
    863             stream << '"' << obj.getString(buffer) << '"';
    864             break;
    865         case Formattable::kArray:
    866             int32_t i, count;
    867             const Formattable* array;
    868             array = obj.getArray(count);
    869             stream << '[';
    870             // Recursively calling the console I/O routine for each element in the array.
    871             for (i=0; i<count; ++i) {
    872                 FormattableStreamer::streamOut(stream, array[i]);
    873                 stream << ( (i==(count-1)) ? "" : ", " );
    874             }
    875             stream << ']';
    876             break;
    877         default:
    878             // Not a recognizable Formattable object.
    879             stream << "INVALID_Formattable";
    880     }
    881     stream.flush();
    882 }
    883 #endif
    884 
    885 #endif
    886 
    887 U_NAMESPACE_END
    888 
    889 /* ---- UFormattable implementation ---- */
    890 
    891 U_NAMESPACE_USE
    892 
    893 U_DRAFT UFormattable* U_EXPORT2
    894 ufmt_open(UErrorCode *status) {
    895   if( U_FAILURE(*status) ) {
    896     return NULL;
    897   }
    898   UFormattable *fmt = (new Formattable())->toUFormattable();
    899 
    900   if( fmt == NULL ) {
    901     *status = U_MEMORY_ALLOCATION_ERROR;
    902   }
    903   return fmt;
    904 }
    905 
    906 U_DRAFT void U_EXPORT2
    907 ufmt_close(UFormattable *fmt) {
    908   Formattable *obj = Formattable::fromUFormattable(fmt);
    909 
    910   delete obj;
    911 }
    912 
    913 U_INTERNAL UFormattableType U_EXPORT2
    914 ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
    915   if(U_FAILURE(*status)) {
    916     return (UFormattableType)UFMT_COUNT;
    917   }
    918   const Formattable *obj = Formattable::fromUFormattable(fmt);
    919   return (UFormattableType)obj->getType();
    920 }
    921 
    922 
    923 U_INTERNAL UBool U_EXPORT2
    924 ufmt_isNumeric(const UFormattable *fmt) {
    925   const Formattable *obj = Formattable::fromUFormattable(fmt);
    926   return obj->isNumeric();
    927 }
    928 
    929 U_DRAFT UDate U_EXPORT2
    930 ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
    931   const Formattable *obj = Formattable::fromUFormattable(fmt);
    932 
    933   return obj->getDate(*status);
    934 }
    935 
    936 U_DRAFT double U_EXPORT2
    937 ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
    938   Formattable *obj = Formattable::fromUFormattable(fmt);
    939 
    940   return obj->getDouble(*status);
    941 }
    942 
    943 U_DRAFT int32_t U_EXPORT2
    944 ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
    945   Formattable *obj = Formattable::fromUFormattable(fmt);
    946 
    947   return obj->getLong(*status);
    948 }
    949 
    950 
    951 U_DRAFT const void *U_EXPORT2
    952 ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
    953   const Formattable *obj = Formattable::fromUFormattable(fmt);
    954 
    955   const void *ret = obj->getObject();
    956   if( ret==NULL &&
    957       (obj->getType() != Formattable::kObject) &&
    958       U_SUCCESS( *status )) {
    959     *status = U_INVALID_FORMAT_ERROR;
    960   }
    961   return ret;
    962 }
    963 
    964 U_DRAFT const UChar* U_EXPORT2
    965 ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
    966   Formattable *obj = Formattable::fromUFormattable(fmt);
    967 
    968   // avoid bogosity by checking the type first.
    969   if( obj->getType() != Formattable::kString ) {
    970     if( U_SUCCESS(*status) ){
    971       *status = U_INVALID_FORMAT_ERROR;
    972     }
    973     return NULL;
    974   }
    975 
    976   // This should return a valid string
    977   UnicodeString &str = obj->getString(*status);
    978   if( U_SUCCESS(*status) && len != NULL ) {
    979     *len = str.length();
    980   }
    981   return str.getTerminatedBuffer();
    982 }
    983 
    984 U_DRAFT int32_t U_EXPORT2
    985 ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
    986   const Formattable *obj = Formattable::fromUFormattable(fmt);
    987 
    988   int32_t count;
    989   (void)obj->getArray(count, *status);
    990   return count;
    991 }
    992 
    993 U_DRAFT UFormattable * U_EXPORT2
    994 ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
    995   Formattable *obj = Formattable::fromUFormattable(fmt);
    996   int32_t count;
    997   (void)obj->getArray(count, *status);
    998   if(U_FAILURE(*status)) {
    999     return NULL;
   1000   } else if(n<0 || n>=count) {
   1001     setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
   1002     return NULL;
   1003   } else {
   1004     return (*obj)[n].toUFormattable(); // returns non-const Formattable
   1005   }
   1006 }
   1007 
   1008 U_DRAFT const char * U_EXPORT2
   1009 ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
   1010   if(U_FAILURE(*status)) {
   1011     return "";
   1012   }
   1013   Formattable *obj = Formattable::fromUFormattable(fmt);
   1014   CharString *charString = obj->internalGetCharString(*status);
   1015   if(U_FAILURE(*status)) {
   1016     return "";
   1017   }
   1018   if(charString == NULL) {
   1019     *status = U_MEMORY_ALLOCATION_ERROR;
   1020     return "";
   1021   } else {
   1022     if(len!=NULL) {
   1023       *len = charString->length();
   1024     }
   1025     return charString->data();
   1026   }
   1027 }
   1028 
   1029 U_DRAFT int64_t U_EXPORT2
   1030 ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
   1031   Formattable *obj = Formattable::fromUFormattable(fmt);
   1032   return obj->getInt64(*status);
   1033 }
   1034 
   1035 #endif /* #if !UCONFIG_NO_FORMATTING */
   1036 
   1037 //eof
   1038