diff options
Diffstat (limited to 'deps/icu-small/source/i18n/fmtable.cpp')
-rw-r--r-- | deps/icu-small/source/i18n/fmtable.cpp | 160 |
1 files changed, 73 insertions, 87 deletions
diff --git a/deps/icu-small/source/i18n/fmtable.cpp b/deps/icu-small/source/i18n/fmtable.cpp index 73f9b66ab6..cb6134cb4b 100644 --- a/deps/icu-small/source/i18n/fmtable.cpp +++ b/deps/icu-small/source/i18n/fmtable.cpp @@ -19,6 +19,7 @@ #if !UCONFIG_NO_FORMATTING +#include <cstdlib> #include <math.h> #include "unicode/fmtable.h" #include "unicode/ustring.h" @@ -28,9 +29,8 @@ #include "charstr.h" #include "cmemory.h" #include "cstring.h" -#include "decNumber.h" -#include "digitlst.h" #include "fmtableimp.h" +#include "number_decimalquantity.h" // ***************************************************************************** // class Formattable @@ -40,6 +40,8 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable) +using number::impl::DecimalQuantity; + //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. @@ -103,7 +105,7 @@ void Formattable::init() { fValue.fInt64 = 0; fType = kLong; fDecimalStr = NULL; - fDecimalNum = NULL; + fDecimalQuantity = NULL; fBogus.setToBogus(); } @@ -257,8 +259,8 @@ Formattable::operator=(const Formattable& source) } UErrorCode status = U_ZERO_ERROR; - if (source.fDecimalNum != NULL) { - fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list + if (source.fDecimalQuantity != NULL) { + fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity); } if (source.fDecimalStr != NULL) { fDecimalStr = new CharString(*source.fDecimalStr, status); @@ -357,13 +359,8 @@ void Formattable::dispose() delete fDecimalStr; fDecimalStr = NULL; - FmtStackData *stackData = (FmtStackData*)fStackData; - if(fDecimalNum != &(stackData->stackDecimalNum)) { - delete fDecimalNum; - } else { - fDecimalNum->~DigitList(); // destruct, don't deallocate - } - fDecimalNum = NULL; + delete fDecimalQuantity; + fDecimalQuantity = NULL; } Formattable * @@ -465,13 +462,13 @@ Formattable::getInt64(UErrorCode& status) const } else if (fValue.fDouble < (double)U_INT64_MIN) { status = U_INVALID_FORMAT_ERROR; return U_INT64_MIN; - } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) { - int64_t val = fDecimalNum->getInt64(); - if (val != 0) { - return val; + } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != NULL) { + if (fDecimalQuantity->fitsInLong(true)) { + return fDecimalQuantity->toLong(); } else { + // Unexpected status = U_INVALID_FORMAT_ERROR; - return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN; + return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX; } } else { return (int64_t)fValue.fDouble; @@ -714,84 +711,85 @@ StringPiece Formattable::getDecimalNumber(UErrorCode &status) { CharString *Formattable::internalGetCharString(UErrorCode &status) { if(fDecimalStr == NULL) { - if (fDecimalNum == NULL) { + if (fDecimalQuantity == NULL) { // No decimal number for the formattable yet. Which means the value was // set directly by the user as an int, int64 or double. If the value came // from parsing, or from the user setting a decimal number, fDecimalNum // would already be set. // - fDecimalNum = new DigitList; // TODO: use internal digit list - if (fDecimalNum == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - - switch (fType) { - case kDouble: - fDecimalNum->set(this->getDouble()); - break; - case kLong: - fDecimalNum->set(this->getLong()); - break; - case kInt64: - fDecimalNum->set(this->getInt64()); - break; - default: - // The formattable's value is not a numeric type. - status = U_INVALID_STATE_ERROR; - return NULL; - } + LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status); + if (U_FAILURE(status)) { return nullptr; } + populateDecimalQuantity(*dq, status); + if (U_FAILURE(status)) { return nullptr; } + fDecimalQuantity = dq.orphan(); } - fDecimalStr = new CharString; + fDecimalStr = new CharString(); if (fDecimalStr == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } - fDecimalNum->getDecimal(*fDecimalStr, status); + // Older ICUs called uprv_decNumberToString here, which is not exactly the same as + // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does + // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?). + if (fDecimalQuantity->isZero()) { + fDecimalStr->append("0", -1, status); + } else if (std::abs(fDecimalQuantity->getMagnitude()) < 5) { + fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status); + } else { + fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status); + } } return fDecimalStr; } +void +Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const { + if (fDecimalQuantity != nullptr) { + output = *fDecimalQuantity; + return; + } -DigitList * -Formattable::getInternalDigitList() { - FmtStackData *stackData = (FmtStackData*)fStackData; - if(fDecimalNum != &(stackData->stackDecimalNum)) { - delete fDecimalNum; - fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList(); - } else { - fDecimalNum->clear(); - } - return fDecimalNum; + switch (fType) { + case kDouble: + output.setToDouble(this->getDouble()); + output.roundToInfinity(); + break; + case kLong: + output.setToInt(this->getLong()); + break; + case kInt64: + output.setToLong(this->getInt64()); + break; + default: + // The formattable's value is not a numeric type. + status = U_INVALID_STATE_ERROR; + } } // --------------------------------------- void -Formattable::adoptDigitList(DigitList *dl) { - if(fDecimalNum==dl) { - fDecimalNum = NULL; // don't delete - } - dispose(); - - fDecimalNum = dl; - - if(dl==NULL) { // allow adoptDigitList(NULL) to clear - return; - } +Formattable::adoptDecimalQuantity(DecimalQuantity *dq) { + if (fDecimalQuantity != NULL) { + delete fDecimalQuantity; + } + fDecimalQuantity = dq; + if (dq == NULL) { // allow adoptDigitList(NULL) to clear + return; + } // Set the value into the Union of simple type values. - // Cannot use the set() functions because they would delete the fDecimalNum value, - - if (fDecimalNum->fitsIntoLong(FALSE)) { - fType = kLong; - fValue.fInt64 = fDecimalNum->getLong(); - } else if (fDecimalNum->fitsIntoInt64(FALSE)) { - fType = kInt64; - fValue.fInt64 = fDecimalNum->getInt64(); + // Cannot use the set() functions because they would delete the fDecimalNum value. + if (fDecimalQuantity->fitsInLong()) { + fValue.fInt64 = fDecimalQuantity->toLong(); + if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) { + fType = kLong; + } else { + fType = kInt64; + } } else { fType = kDouble; - fValue.fDouble = fDecimalNum->getDouble(); + fValue.fDouble = fDecimalQuantity->toDouble(); } } @@ -804,24 +802,12 @@ Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) { } dispose(); - // Copy the input string and nul-terminate it. - // The decNumber library requires nul-terminated input. StringPiece input - // is not guaranteed nul-terminated. Too bad. - // CharString automatically adds the nul. - DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList - if (dnum == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - dnum->set(CharString(numberString, status).toStringPiece(), status); - if (U_FAILURE(status)) { - delete dnum; - return; // String didn't contain a decimal number. - } - adoptDigitList(dnum); + auto* dq = new DecimalQuantity(); + dq->setToDecNumber(numberString, status); + adoptDecimalQuantity(dq); // Note that we do not hang on to the caller's input string. - // If we are asked for the string, we will regenerate one from fDecimalNum. + // If we are asked for the string, we will regenerate one from fDecimalQuantity. } #if 0 |