summaryrefslogtreecommitdiff
path: root/deps/icu-small/source/i18n/fmtable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'deps/icu-small/source/i18n/fmtable.cpp')
-rw-r--r--deps/icu-small/source/i18n/fmtable.cpp160
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