Use numeric_limits instead of hand-coded equivalents
As a comment noted, the reason for QLocaleData rolling its own values describing the ranges of digits and exponents in a double were all about std::numeric_limits's constants not being constexpr - which they have now been since C++11, so we can do away with our own. One of the constants was used in two places in the same way; so abstract that use out into an inline function in qlocale_tools, to save duplication and give somewhere to document it. Change-Id: I7e3740ece9b499c0ec434de18d70abe69e1fe079 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
72be9bdd37
commit
e8d5000026
@ -3354,10 +3354,9 @@ QString QLocaleData::doubleToString(const QString &zero, const QString &plus, co
|
|||||||
int decpt;
|
int decpt;
|
||||||
int bufSize = 1;
|
int bufSize = 1;
|
||||||
if (precision == QLocale::FloatingPointShortest)
|
if (precision == QLocale::FloatingPointShortest)
|
||||||
bufSize += DoubleMaxSignificant;
|
bufSize += std::numeric_limits<double>::max_digits10;
|
||||||
else if (form == DFDecimal) // optimize for numbers between -512k and 512k
|
else if (form == DFDecimal)
|
||||||
bufSize += ((d > (1 << 19) || d < -(1 << 19)) ? DoubleMaxDigitsBeforeDecimal : 6) +
|
bufSize += wholePartSpace(qAbs(d)) + precision;
|
||||||
precision;
|
|
||||||
else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit.
|
else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit.
|
||||||
bufSize += qMax(2, precision) + 1;
|
bufSize += qMax(2, precision) + 1;
|
||||||
|
|
||||||
|
@ -182,17 +182,6 @@ public:
|
|||||||
QLocale::Country country);
|
QLocale::Country country);
|
||||||
static const QLocaleData *c();
|
static const QLocaleData *c();
|
||||||
|
|
||||||
// Maximum number of significant digits needed to represent a double.
|
|
||||||
// We cannot use std::numeric_limits here without constexpr.
|
|
||||||
static const int DoubleMantissaBits = 53;
|
|
||||||
static const int Log10_2_100000 = 30103; // log10(2) * 100000
|
|
||||||
// same as C++11 std::numeric_limits<T>::max_digits10
|
|
||||||
static const int DoubleMaxSignificant = (DoubleMantissaBits * Log10_2_100000) / 100000 + 2;
|
|
||||||
|
|
||||||
// Maximum number of digits before decimal point to represent a double
|
|
||||||
// Same as std::numeric_limits<double>::max_exponent10 + 1
|
|
||||||
static const int DoubleMaxDigitsBeforeDecimal = 309;
|
|
||||||
|
|
||||||
enum DoubleForm {
|
enum DoubleForm {
|
||||||
DFExponent = 0,
|
DFExponent = 0,
|
||||||
DFDecimal,
|
DFDecimal,
|
||||||
|
@ -139,7 +139,7 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
|
|||||||
if (precision > 999)
|
if (precision > 999)
|
||||||
precision = 999;
|
precision = 999;
|
||||||
else if (precision == QLocale::FloatingPointShortest)
|
else if (precision == QLocale::FloatingPointShortest)
|
||||||
precision = QLocaleData::DoubleMaxSignificant; // "shortest" mode not supported by snprintf
|
precision = std::numeric_limits<double>::max_digits10; // snprintf lacks "shortest" mode
|
||||||
|
|
||||||
if (isZero(d)) {
|
if (isZero(d)) {
|
||||||
// Negative zero is expected as simple "0", not "-0". We cannot do d < 0, though.
|
// Negative zero is expected as simple "0", not "-0". We cannot do d < 0, though.
|
||||||
@ -167,8 +167,8 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
|
|||||||
switch (form) {
|
switch (form) {
|
||||||
case QLocaleData::DFDecimal:
|
case QLocaleData::DFDecimal:
|
||||||
format[formatLength - 2] = 'f';
|
format[formatLength - 2] = 'f';
|
||||||
// <anything> '.' <precision> '\0' - optimize for numbers smaller than 512k
|
// <anything> '.' <precision> '\0'
|
||||||
extraChars = (d > (1 << 19) ? QLocaleData::DoubleMaxDigitsBeforeDecimal : 6) + 2;
|
extraChars = wholePartSpace(d) + 2;
|
||||||
break;
|
break;
|
||||||
case QLocaleData::DFExponent:
|
case QLocaleData::DFExponent:
|
||||||
format[formatLength - 2] = 'e';
|
format[formatLength - 2] = 'e';
|
||||||
@ -581,9 +581,10 @@ QString qdtoa(qreal d, int *decpt, int *sign)
|
|||||||
int length = 0;
|
int length = 0;
|
||||||
|
|
||||||
// Some versions of libdouble-conversion like an extra digit, probably for '\0'
|
// Some versions of libdouble-conversion like an extra digit, probably for '\0'
|
||||||
char result[QLocaleData::DoubleMaxSignificant + 1];
|
constexpr int digits = std::numeric_limits<double>::max_digits10 + 1;
|
||||||
qt_doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest, result,
|
char result[digits];
|
||||||
QLocaleData::DoubleMaxSignificant + 1, nonNullSign, length, nonNullDecpt);
|
qt_doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest,
|
||||||
|
result, digits, nonNullSign, length, nonNullDecpt);
|
||||||
|
|
||||||
if (sign)
|
if (sign)
|
||||||
*sign = nonNullSign ? 1 : 0;
|
*sign = nonNullSign ? 1 : 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the QtCore module of the Qt Toolkit.
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
@ -98,6 +98,15 @@ inline bool isZero(double d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enough space for the digits before the decimal separator:
|
||||||
|
inline int wholePartSpace(double d)
|
||||||
|
{
|
||||||
|
Q_ASSERT(d >= 0); // caller should call qAbs() if needed
|
||||||
|
// Optimize for numbers between -512k and 512k - otherwise, use the
|
||||||
|
// maximum number of digits in the whole number part of a double:
|
||||||
|
return d > (1 << 19) ? std::numeric_limits<double>::max_exponent10 + 1 : 6;
|
||||||
|
}
|
||||||
|
|
||||||
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
|
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
|
||||||
Q_CORE_EXPORT double qstrntod(const char *s00, int len, char const **se, bool *ok);
|
Q_CORE_EXPORT double qstrntod(const char *s00, int len, char const **se, bool *ok);
|
||||||
qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok);
|
qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user