tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fmtable.cpp (28109B)


      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 "cmemory.h"
     30 #include "cstring.h"
     31 #include "fixedstring.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) == *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) != nullptr;
     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 != nullptr) {
     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 = nullptr;
    108    fDecimalQuantity = nullptr;
    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 semantics)
    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        if (source.fDecimalQuantity != nullptr) {
    262          fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
    263        }
    264        if (source.fDecimalStr != nullptr) {
    265            fDecimalStr = new FixedString(*source.fDecimalStr);
    266        }
    267    }
    268    return *this;
    269 }
    270 
    271 // -------------------------------------
    272 
    273 bool
    274 Formattable::operator==(const Formattable& that) const
    275 {
    276    int32_t i;
    277 
    278    if (this == &that) return true;
    279 
    280    // Returns false if the data types are different.
    281    if (fType != that.fType) return false;
    282 
    283    // Compares the actual data values.
    284    bool equal = true;
    285    switch (fType) {
    286    case kDate:
    287        equal = (fValue.fDate == that.fValue.fDate);
    288        break;
    289    case kDouble:
    290        equal = (fValue.fDouble == that.fValue.fDouble);
    291        break;
    292    case kLong:
    293    case kInt64:
    294        equal = (fValue.fInt64 == that.fValue.fInt64);
    295        break;
    296    case kString:
    297        equal = (*(fValue.fString) == *(that.fValue.fString));
    298        break;
    299    case kArray:
    300        if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
    301            equal = false;
    302            break;
    303        }
    304        // Checks each element for equality.
    305        for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
    306            if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
    307                equal = false;
    308                break;
    309            }
    310        }
    311        break;
    312    case kObject:
    313        if (fValue.fObject == nullptr || that.fValue.fObject == nullptr) {
    314            equal = false;
    315        } else {
    316            equal = objectEquals(fValue.fObject, that.fValue.fObject);
    317        }
    318        break;
    319    }
    320 
    321    // TODO:  compare digit lists if numeric.
    322    return equal;
    323 }
    324 
    325 // -------------------------------------
    326 
    327 Formattable::~Formattable()
    328 {
    329    dispose();
    330 }
    331 
    332 // -------------------------------------
    333 
    334 void Formattable::dispose()
    335 {
    336    // Deletes the data value if necessary.
    337    switch (fType) {
    338    case kString:
    339        delete fValue.fString;
    340        break;
    341    case kArray:
    342        delete[] fValue.fArrayAndCount.fArray;
    343        break;
    344    case kObject:
    345        delete fValue.fObject;
    346        break;
    347    default:
    348        break;
    349    }
    350 
    351    fType = kLong;
    352    fValue.fInt64 = 0;
    353 
    354    delete fDecimalStr;
    355    fDecimalStr = nullptr;
    356 
    357    delete fDecimalQuantity;
    358    fDecimalQuantity = nullptr;
    359 }
    360 
    361 Formattable *
    362 Formattable::clone() const {
    363    return new Formattable(*this);
    364 }
    365 
    366 // -------------------------------------
    367 // Gets the data type of this Formattable object. 
    368 Formattable::Type
    369 Formattable::getType() const
    370 {
    371    return fType;
    372 }
    373 
    374 UBool
    375 Formattable::isNumeric() const {
    376    switch (fType) {
    377    case kDouble:
    378    case kLong:
    379    case kInt64:
    380        return true;
    381    default:
    382        return false;
    383    }
    384 }
    385 
    386 // -------------------------------------
    387 int32_t
    388 //Formattable::getLong(UErrorCode* status) const
    389 Formattable::getLong(UErrorCode& status) const
    390 {
    391    if (U_FAILURE(status)) {
    392        return 0;
    393    }
    394        
    395    switch (fType) {
    396    case Formattable::kLong: 
    397        return static_cast<int32_t>(fValue.fInt64);
    398    case Formattable::kInt64:
    399        if (fValue.fInt64 > INT32_MAX) {
    400            status = U_INVALID_FORMAT_ERROR;
    401            return INT32_MAX;
    402        } else if (fValue.fInt64 < INT32_MIN) {
    403            status = U_INVALID_FORMAT_ERROR;
    404            return INT32_MIN;
    405        } else {
    406            return static_cast<int32_t>(fValue.fInt64);
    407        }
    408    case Formattable::kDouble:
    409        if (fValue.fDouble > INT32_MAX) {
    410            status = U_INVALID_FORMAT_ERROR;
    411            return INT32_MAX;
    412        } else if (fValue.fDouble < INT32_MIN) {
    413            status = U_INVALID_FORMAT_ERROR;
    414            return INT32_MIN;
    415        } else {
    416            return static_cast<int32_t>(fValue.fDouble); // loses fraction
    417        }
    418    case Formattable::kObject:
    419        if (fValue.fObject == nullptr) {
    420            status = U_MEMORY_ALLOCATION_ERROR;
    421            return 0;
    422        }
    423        // TODO Later replace this with instanceof call
    424        if (instanceOfMeasure(fValue.fObject)) {
    425            return ((const Measure*) fValue.fObject)->
    426                getNumber().getLong(status);
    427        }
    428        U_FALLTHROUGH;
    429    default:
    430        status = U_INVALID_FORMAT_ERROR;
    431        return 0;
    432    }
    433 }
    434 
    435 // -------------------------------------
    436 // Maximum int that can be represented exactly in a double.  (53 bits)
    437 //    Larger ints may be rounded to a near-by value as not all are representable.
    438 // TODO:  move this constant elsewhere, possibly configure it for different
    439 //        floating point formats, if any non-standard ones are still in use.
    440 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
    441 
    442 int64_t
    443 Formattable::getInt64(UErrorCode& status) const
    444 {
    445    if (U_FAILURE(status)) {
    446        return 0;
    447    }
    448        
    449    switch (fType) {
    450    case Formattable::kLong: 
    451    case Formattable::kInt64: 
    452        return fValue.fInt64;
    453    case Formattable::kDouble:
    454        if (fValue.fDouble > static_cast<double>(U_INT64_MAX)) {
    455            status = U_INVALID_FORMAT_ERROR;
    456            return U_INT64_MAX;
    457        } else if (fValue.fDouble < static_cast<double>(U_INT64_MIN)) {
    458            status = U_INVALID_FORMAT_ERROR;
    459            return U_INT64_MIN;
    460        } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != nullptr) {
    461            if (fDecimalQuantity->fitsInLong(true)) {
    462                return fDecimalQuantity->toLong();
    463            } else {
    464                // Unexpected
    465                status = U_INVALID_FORMAT_ERROR;
    466                return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX;
    467            }
    468        } else {
    469            return static_cast<int64_t>(fValue.fDouble);
    470        } 
    471    case Formattable::kObject:
    472        if (fValue.fObject == nullptr) {
    473            status = U_MEMORY_ALLOCATION_ERROR;
    474            return 0;
    475        }
    476        if (instanceOfMeasure(fValue.fObject)) {
    477            return ((const Measure*) fValue.fObject)->
    478                getNumber().getInt64(status);
    479        }
    480        U_FALLTHROUGH;
    481    default:
    482        status = U_INVALID_FORMAT_ERROR;
    483        return 0;
    484    }
    485 }
    486 
    487 // -------------------------------------
    488 double
    489 Formattable::getDouble(UErrorCode& status) const
    490 {
    491    if (U_FAILURE(status)) {
    492        return 0;
    493    }
    494        
    495    switch (fType) {
    496    case Formattable::kLong: 
    497    case Formattable::kInt64: // loses precision
    498        return static_cast<double>(fValue.fInt64);
    499    case Formattable::kDouble:
    500        return fValue.fDouble;
    501    case Formattable::kObject:
    502        if (fValue.fObject == nullptr) {
    503            status = U_MEMORY_ALLOCATION_ERROR;
    504            return 0;
    505        }
    506        // TODO Later replace this with instanceof call
    507        if (instanceOfMeasure(fValue.fObject)) {
    508            return ((const Measure*) fValue.fObject)->
    509                getNumber().getDouble(status);
    510        }
    511        U_FALLTHROUGH;
    512    default:
    513        status = U_INVALID_FORMAT_ERROR;
    514        return 0;
    515    }
    516 }
    517 
    518 const UObject*
    519 Formattable::getObject() const {
    520    return (fType == kObject) ? fValue.fObject : nullptr;
    521 }
    522 
    523 // -------------------------------------
    524 // Sets the value to a double value d.
    525 
    526 void
    527 Formattable::setDouble(double d)
    528 {
    529    dispose();
    530    fType = kDouble;
    531    fValue.fDouble = d;
    532 }
    533 
    534 // -------------------------------------
    535 // Sets the value to a long value l.
    536 
    537 void
    538 Formattable::setLong(int32_t l)
    539 {
    540    dispose();
    541    fType = kLong;
    542    fValue.fInt64 = l;
    543 }
    544 
    545 // -------------------------------------
    546 // Sets the value to an int64 value ll.
    547 
    548 void
    549 Formattable::setInt64(int64_t ll)
    550 {
    551    dispose();
    552    fType = kInt64;
    553    fValue.fInt64 = ll;
    554 }
    555 
    556 // -------------------------------------
    557 // Sets the value to a Date instance d.
    558 
    559 void
    560 Formattable::setDate(UDate d)
    561 {
    562    dispose();
    563    fType = kDate;
    564    fValue.fDate = d;
    565 }
    566 
    567 // -------------------------------------
    568 // Sets the value to a string value stringToCopy.
    569 
    570 void
    571 Formattable::setString(const UnicodeString& stringToCopy)
    572 {
    573    dispose();
    574    fType = kString;
    575    fValue.fString = new UnicodeString(stringToCopy);
    576 }
    577 
    578 // -------------------------------------
    579 // Sets the value to an array of Formattable objects.
    580 
    581 void
    582 Formattable::setArray(const Formattable* array, int32_t count)
    583 {
    584    dispose();
    585    fType = kArray;
    586    fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
    587    fValue.fArrayAndCount.fCount = count;
    588 }
    589 
    590 // -------------------------------------
    591 // Adopts the stringToAdopt value.
    592 
    593 void
    594 Formattable::adoptString(UnicodeString* stringToAdopt)
    595 {
    596    dispose();
    597    fType = kString;
    598    fValue.fString = stringToAdopt;
    599 }
    600 
    601 // -------------------------------------
    602 // Adopts the array value and its count.
    603 
    604 void
    605 Formattable::adoptArray(Formattable* array, int32_t count)
    606 {
    607    dispose();
    608    fType = kArray;
    609    fValue.fArrayAndCount.fArray = array;
    610    fValue.fArrayAndCount.fCount = count;
    611 }
    612 
    613 void
    614 Formattable::adoptObject(UObject* objectToAdopt) {
    615    dispose();
    616    fType = kObject;
    617    fValue.fObject = objectToAdopt;
    618 }
    619 
    620 // -------------------------------------
    621 UnicodeString& 
    622 Formattable::getString(UnicodeString& result, UErrorCode& status) const 
    623 {
    624    if (fType != kString) {
    625        setError(status, U_INVALID_FORMAT_ERROR);
    626        result.setToBogus();
    627    } else {
    628        if (fValue.fString == nullptr) {
    629            setError(status, U_MEMORY_ALLOCATION_ERROR);
    630        } else {
    631            result = *fValue.fString;
    632        }
    633    }
    634    return result;
    635 }
    636 
    637 // -------------------------------------
    638 const UnicodeString& 
    639 Formattable::getString(UErrorCode& status) const 
    640 {
    641    if (fType != kString) {
    642        setError(status, U_INVALID_FORMAT_ERROR);
    643        return *getBogus();
    644    }
    645    if (fValue.fString == nullptr) {
    646        setError(status, U_MEMORY_ALLOCATION_ERROR);
    647        return *getBogus();
    648    }
    649    return *fValue.fString;
    650 }
    651 
    652 // -------------------------------------
    653 UnicodeString& 
    654 Formattable::getString(UErrorCode& status) 
    655 {
    656    if (fType != kString) {
    657        setError(status, U_INVALID_FORMAT_ERROR);
    658        return *getBogus();
    659    }
    660    if (fValue.fString == nullptr) {
    661    	setError(status, U_MEMORY_ALLOCATION_ERROR);
    662    	return *getBogus();
    663    }
    664    return *fValue.fString;
    665 }
    666 
    667 // -------------------------------------
    668 const Formattable* 
    669 Formattable::getArray(int32_t& count, UErrorCode& status) const 
    670 {
    671    if (fType != kArray) {
    672        setError(status, U_INVALID_FORMAT_ERROR);
    673        count = 0;
    674        return nullptr;
    675    }
    676    count = fValue.fArrayAndCount.fCount; 
    677    return fValue.fArrayAndCount.fArray;
    678 }
    679 
    680 // -------------------------------------
    681 // Gets the bogus string, ensures mondo bogosity.
    682 
    683 UnicodeString*
    684 Formattable::getBogus() const 
    685 {
    686    return const_cast<UnicodeString*>(&fBogus); /* cast away const :-( */
    687 }
    688 
    689 
    690 // --------------------------------------
    691 StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
    692    if (U_FAILURE(status)) {
    693        return "";
    694    }
    695    if (fDecimalStr != nullptr) {
    696      return fDecimalStr->data();
    697    }
    698 
    699    FixedString* decimalStr = internalGetFixedString(status);
    700    if(decimalStr == nullptr) {
    701      return ""; // getDecimalNumber returns "" for error cases
    702    } else {
    703      return decimalStr->data();
    704    }
    705 }
    706 
    707 FixedString *Formattable::internalGetFixedString(UErrorCode &status) {
    708    if(fDecimalStr == nullptr) {
    709      if (fDecimalQuantity == nullptr) {
    710        // No decimal number for the formattable yet.  Which means the value was
    711        // set directly by the user as an int, int64 or double.  If the value came
    712        // from parsing, or from the user setting a decimal number, fDecimalNum
    713        // would already be set.
    714        //
    715        LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
    716        if (U_FAILURE(status)) { return nullptr; }
    717        populateDecimalQuantity(*dq, status);
    718        if (U_FAILURE(status)) { return nullptr; }
    719        fDecimalQuantity = dq.orphan();
    720      }
    721 
    722      fDecimalStr = new FixedString();
    723      if (fDecimalStr == nullptr) {
    724        status = U_MEMORY_ALLOCATION_ERROR;
    725        return nullptr;
    726      }
    727      // Older ICUs called uprv_decNumberToString here, which is not exactly the same as
    728      // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does
    729      // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
    730      if (fDecimalQuantity->isInfinite()) {
    731        *fDecimalStr = "Infinity";
    732      } else if (fDecimalQuantity->isNaN()) {
    733        *fDecimalStr = "NaN";
    734      } else if (fDecimalQuantity->isZeroish()) {
    735        *fDecimalStr = "0";
    736      } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types
    737                  (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) {
    738        copyInvariantChars(fDecimalQuantity->toPlainString(), *fDecimalStr, status);
    739      } else {
    740        copyInvariantChars(fDecimalQuantity->toScientificString(), *fDecimalStr, status);
    741      }
    742      if (U_SUCCESS(status) && fDecimalStr->isEmpty()) {
    743        status = U_MEMORY_ALLOCATION_ERROR;
    744        return nullptr;
    745      }
    746    }
    747    return fDecimalStr;
    748 }
    749 
    750 void
    751 Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
    752    if (fDecimalQuantity != nullptr) {
    753        output = *fDecimalQuantity;
    754        return;
    755    }
    756 
    757    switch (fType) {
    758        case kDouble:
    759            output.setToDouble(this->getDouble());
    760            output.roundToInfinity();
    761            break;
    762        case kLong:
    763            output.setToInt(this->getLong());
    764            break;
    765        case kInt64:
    766            output.setToLong(this->getInt64());
    767            break;
    768        default:
    769            // The formattable's value is not a numeric type.
    770            status = U_INVALID_STATE_ERROR;
    771    }
    772 }
    773 
    774 // ---------------------------------------
    775 void
    776 Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
    777    delete fDecimalQuantity;
    778    fDecimalQuantity = dq;
    779    if (dq == nullptr) { // allow adoptDigitList(nullptr) to clear
    780        return;
    781    }
    782 
    783    // Set the value into the Union of simple type values.
    784    // Cannot use the set() functions because they would delete the fDecimalNum value.
    785    if (fDecimalQuantity->fitsInLong()) {
    786        fValue.fInt64 = fDecimalQuantity->toLong();
    787        if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
    788            fType = kLong;
    789        } else {
    790            fType = kInt64;
    791        }
    792    } else {
    793        fType = kDouble;
    794        fValue.fDouble = fDecimalQuantity->toDouble();
    795    }
    796 }
    797 
    798 
    799 // ---------------------------------------
    800 void
    801 Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
    802    if (U_FAILURE(status)) {
    803        return;
    804    }
    805    dispose();
    806 
    807    auto* dq = new DecimalQuantity();
    808    dq->setToDecNumber(numberString, status);
    809    adoptDecimalQuantity(dq);
    810 
    811    // Note that we do not hang on to the caller's input string.
    812    // If we are asked for the string, we will regenerate one from fDecimalQuantity.
    813 }
    814 
    815 #if 0
    816 //----------------------------------------------------
    817 // console I/O
    818 //----------------------------------------------------
    819 #ifdef _DEBUG
    820 
    821 #include <iostream>
    822 using namespace std;
    823 
    824 #include "unicode/datefmt.h"
    825 #include "unistrm.h"
    826 
    827 class FormattableStreamer /* not : public UObject because all methods are static */ {
    828 public:
    829    static void streamOut(ostream& stream, const Formattable& obj);
    830 
    831 private:
    832    FormattableStreamer() {} // private - forbid instantiation
    833 };
    834 
    835 // This is for debugging purposes only.  This will send a displayable
    836 // form of the Formattable object to the output stream.
    837 
    838 void
    839 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
    840 {
    841    static DateFormat *defDateFormat = 0;
    842 
    843    UnicodeString buffer;
    844    switch(obj.getType()) {
    845        case Formattable::kDate : 
    846            // Creates a DateFormat instance for formatting the
    847            // Date instance.
    848            if (defDateFormat == 0) {
    849                defDateFormat = DateFormat::createInstance();
    850            }
    851            defDateFormat->format(obj.getDate(), buffer);
    852            stream << buffer;
    853            break;
    854        case Formattable::kDouble :
    855            // Output the double as is.
    856            stream << obj.getDouble() << 'D';
    857            break;
    858        case Formattable::kLong :
    859            // Output the double as is.
    860            stream << obj.getLong() << 'L';
    861            break;
    862        case Formattable::kString:
    863            // Output the double as is.  Please see UnicodeString console
    864            // I/O routine for more details.
    865            stream << '"' << obj.getString(buffer) << '"';
    866            break;
    867        case Formattable::kArray:
    868            int32_t i, count;
    869            const Formattable* array;
    870            array = obj.getArray(count);
    871            stream << '[';
    872            // Recursively calling the console I/O routine for each element in the array.
    873            for (i=0; i<count; ++i) {
    874                FormattableStreamer::streamOut(stream, array[i]);
    875                stream << ( (i==(count-1)) ? "" : ", " );
    876            }
    877            stream << ']';
    878            break;
    879        default:
    880            // Not a recognizable Formattable object.
    881            stream << "INVALID_Formattable";
    882    }
    883    stream.flush();
    884 }
    885 #endif
    886 
    887 #endif
    888 
    889 U_NAMESPACE_END
    890 
    891 /* ---- UFormattable implementation ---- */
    892 
    893 U_NAMESPACE_USE
    894 
    895 U_CAPI UFormattable* U_EXPORT2
    896 ufmt_open(UErrorCode *status) {
    897  if( U_FAILURE(*status) ) {
    898    return nullptr;
    899  }
    900  UFormattable *fmt = (new Formattable())->toUFormattable();
    901 
    902  if( fmt == nullptr ) {
    903    *status = U_MEMORY_ALLOCATION_ERROR;
    904  }
    905  return fmt;
    906 }
    907 
    908 U_CAPI void U_EXPORT2
    909 ufmt_close(UFormattable *fmt) {
    910  Formattable *obj = Formattable::fromUFormattable(fmt);
    911 
    912  delete obj;
    913 }
    914 
    915 U_CAPI UFormattableType U_EXPORT2
    916 ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
    917  if(U_FAILURE(*status)) {
    918    return (UFormattableType)UFMT_COUNT;
    919  }
    920  const Formattable *obj = Formattable::fromUFormattable(fmt);
    921  return (UFormattableType)obj->getType();
    922 }
    923 
    924 
    925 U_CAPI UBool U_EXPORT2
    926 ufmt_isNumeric(const UFormattable *fmt) {
    927  const Formattable *obj = Formattable::fromUFormattable(fmt);
    928  return obj->isNumeric();
    929 }
    930 
    931 U_CAPI UDate U_EXPORT2
    932 ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
    933  const Formattable *obj = Formattable::fromUFormattable(fmt);
    934 
    935  return obj->getDate(*status);
    936 }
    937 
    938 U_CAPI double U_EXPORT2
    939 ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
    940  Formattable *obj = Formattable::fromUFormattable(fmt);
    941 
    942  return obj->getDouble(*status);
    943 }
    944 
    945 U_CAPI int32_t U_EXPORT2
    946 ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
    947  Formattable *obj = Formattable::fromUFormattable(fmt);
    948 
    949  return obj->getLong(*status);
    950 }
    951 
    952 
    953 U_CAPI const void *U_EXPORT2
    954 ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
    955  const Formattable *obj = Formattable::fromUFormattable(fmt);
    956 
    957  const void *ret = obj->getObject();
    958  if( ret==nullptr &&
    959      (obj->getType() != Formattable::kObject) &&
    960      U_SUCCESS( *status )) {
    961    *status = U_INVALID_FORMAT_ERROR;
    962  }
    963  return ret;
    964 }
    965 
    966 U_CAPI const char16_t* U_EXPORT2
    967 ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
    968  Formattable *obj = Formattable::fromUFormattable(fmt);
    969 
    970  // avoid bogosity by checking the type first.
    971  if( obj->getType() != Formattable::kString ) {
    972    if( U_SUCCESS(*status) ){
    973      *status = U_INVALID_FORMAT_ERROR;
    974    }
    975    return nullptr;
    976  }
    977 
    978  // This should return a valid string
    979  UnicodeString &str = obj->getString(*status);
    980  if( U_SUCCESS(*status) && len != nullptr ) {
    981    *len = str.length();
    982  }
    983  return str.getTerminatedBuffer();
    984 }
    985 
    986 U_CAPI int32_t U_EXPORT2
    987 ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
    988  const Formattable *obj = Formattable::fromUFormattable(fmt);
    989 
    990  int32_t count;
    991  (void)obj->getArray(count, *status);
    992  return count;
    993 }
    994 
    995 U_CAPI UFormattable * U_EXPORT2
    996 ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
    997  Formattable *obj = Formattable::fromUFormattable(fmt);
    998  int32_t count;
    999  (void)obj->getArray(count, *status);
   1000  if(U_FAILURE(*status)) {
   1001    return nullptr;
   1002  } else if(n<0 || n>=count) {
   1003    setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
   1004    return nullptr;
   1005  } else {
   1006    return (*obj)[n].toUFormattable(); // returns non-const Formattable
   1007  }
   1008 }
   1009 
   1010 U_CAPI const char * U_EXPORT2
   1011 ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
   1012  if(U_FAILURE(*status)) {
   1013    return "";
   1014  }
   1015  Formattable *obj = Formattable::fromUFormattable(fmt);
   1016  FixedString *charString = obj->internalGetFixedString(*status);
   1017  if(U_FAILURE(*status)) {
   1018    return "";
   1019  }
   1020  if(charString == nullptr) {
   1021    *status = U_MEMORY_ALLOCATION_ERROR;
   1022    return "";
   1023  } else {
   1024    if(len!=nullptr) {
   1025      *len = static_cast<int32_t>(uprv_strlen(charString->data()));
   1026    }
   1027    return charString->data();
   1028  }
   1029 }
   1030 
   1031 U_CAPI int64_t U_EXPORT2
   1032 ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
   1033  Formattable *obj = Formattable::fromUFormattable(fmt);
   1034  return obj->getInt64(*status);
   1035 }
   1036 
   1037 #endif /* #if !UCONFIG_NO_FORMATTING */
   1038 
   1039 //eof