Make double-formatting code ready for QByteArray
Split off the actual logic in qdtoBasicLatin into a templated function, qdtoString, which supports both QByteArray and QString. Since it uses qullToBasicLatin_helper as part of its fallback path make the same change to it. Task-number: QTBUG-88484 Change-Id: Icac75ee74ba6a9ddc3aa8d4782a981ef50a88db4 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
2696d5a71b
commit
e5e8e4f59b
@ -462,22 +462,23 @@ qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
|
||||
return result;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE void qulltoBasicLatin_helper(qulonglong number, int base, char16_t *&p)
|
||||
template <typename Char>
|
||||
static Q_ALWAYS_INLINE void qulltoString_helper(qulonglong number, int base, Char *&p)
|
||||
{
|
||||
// Performance-optimized code. Compiler can generate faster code when base is known.
|
||||
switch (base) {
|
||||
#define BIG_BASE_LOOP(b) \
|
||||
do { \
|
||||
const int r = number % b; \
|
||||
*--p = (r < 10 ? u'0' : u'a' - 10) + r; \
|
||||
number /= b; \
|
||||
#define BIG_BASE_LOOP(b) \
|
||||
do { \
|
||||
const int r = number % b; \
|
||||
*--p = Char((r < 10 ? '0' : 'a' - 10) + r); \
|
||||
number /= b; \
|
||||
} while (number)
|
||||
#ifndef __OPTIMIZE_SIZE__
|
||||
#define SMALL_BASE_LOOP(b) \
|
||||
do { \
|
||||
*--p = u'0' + number % b; \
|
||||
number /= b; \
|
||||
} while (number)
|
||||
# define SMALL_BASE_LOOP(b) \
|
||||
do { \
|
||||
*--p = Char('0' + number % b); \
|
||||
number /= b; \
|
||||
} while (number)
|
||||
|
||||
case 2: SMALL_BASE_LOOP(2); break;
|
||||
case 8: SMALL_BASE_LOOP(8); break;
|
||||
@ -502,7 +503,7 @@ QString qulltoBasicLatin(qulonglong number, int base, bool negative)
|
||||
char16_t buff[maxlen];
|
||||
char16_t *const end = buff + maxlen, *p = end;
|
||||
|
||||
qulltoBasicLatin_helper(number, base, p);
|
||||
qulltoString_helper<char16_t>(number, base, p);
|
||||
if (negative)
|
||||
*--p = u'-';
|
||||
|
||||
@ -519,7 +520,7 @@ QString qulltoa(qulonglong number, int base, const QStringView zero)
|
||||
char16_t *const end = buff + maxlen, *p = end;
|
||||
|
||||
if (base != 10 || zero == u"0") {
|
||||
qulltoBasicLatin_helper(number, base, p);
|
||||
qulltoString_helper<char16_t>(number, base, p);
|
||||
} else if (zero.size() && !zero.at(0).isSurrogate()) {
|
||||
const char16_t zeroUcs2 = zero.at(0).unicode();
|
||||
while (number != 0) {
|
||||
@ -627,7 +628,8 @@ static constexpr int digits(int number)
|
||||
return i;
|
||||
}
|
||||
|
||||
QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, int precision, bool uppercase)
|
||||
template <typename T>
|
||||
static T dtoString(double d, QLocaleData::DoubleForm form, int precision, bool uppercase)
|
||||
{
|
||||
// Undocumented: aside from F.P.Shortest, precision < 0 is treated as
|
||||
// default, 6 - same as printf().
|
||||
@ -690,10 +692,15 @@ QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, int precision, bo
|
||||
Q_UNREACHABLE(); // Handled earlier
|
||||
}
|
||||
}
|
||||
QString result;
|
||||
|
||||
constexpr bool IsQString = std::is_same_v<T, QString>;
|
||||
using Char = std::conditional_t<IsQString, char16_t, char>;
|
||||
|
||||
T result;
|
||||
result.reserve(total);
|
||||
|
||||
if (negative && !isZero(d)) // We don't return "-0"
|
||||
result.append(u'-');
|
||||
result.append(Char('-'));
|
||||
if (!qIsFinite(d)) {
|
||||
result.append(view);
|
||||
if (uppercase)
|
||||
@ -704,57 +711,60 @@ QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, int precision, bo
|
||||
result.append(view.first(1));
|
||||
view = view.sliced(1);
|
||||
if (!view.isEmpty() || (!succinct && precision > 0)) {
|
||||
result.append(u'.');
|
||||
result.append(Char('.'));
|
||||
result.append(view);
|
||||
if (qsizetype pad = precision - view.size(); !succinct && pad > 0) {
|
||||
for (int i = 0; i < pad; ++i)
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
}
|
||||
}
|
||||
int exponent = decpt - 1;
|
||||
result.append(uppercase ? u'E' : u'e');
|
||||
result.append(exponent < 0 ? u'-' : u'+');
|
||||
result.append(Char(uppercase ? 'E' : 'e'));
|
||||
result.append(Char(exponent < 0 ? '-' : '+'));
|
||||
exponent = std::abs(exponent);
|
||||
Q_ASSUME(exponent <= D::max_exponent10 + D::max_digits10);
|
||||
int exponentDigits = digits(exponent);
|
||||
// C's printf guarantees a two-digit exponent, and so do we:
|
||||
if (exponentDigits == 1)
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
result.resize(result.size() + exponentDigits);
|
||||
auto location = reinterpret_cast<char16_t *>(result.end());
|
||||
qulltoBasicLatin_helper(exponent, 10, location);
|
||||
auto location = reinterpret_cast<Char *>(result.end());
|
||||
qulltoString_helper<Char>(exponent, 10, location);
|
||||
break;
|
||||
}
|
||||
case QLocaleData::DFDecimal:
|
||||
if (decpt < 0) {
|
||||
result.append(u"0.0");
|
||||
if constexpr (IsQString)
|
||||
result.append(u"0.0");
|
||||
else
|
||||
result.append("0.0");
|
||||
while (++decpt < 0)
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
result.append(view);
|
||||
if (!succinct) {
|
||||
auto numDecimals = result.size() - 2 - (negative ? 1 : 0);
|
||||
for (qsizetype i = numDecimals; i < precision; ++i)
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
}
|
||||
} else {
|
||||
if (decpt > view.size()) {
|
||||
result.append(view);
|
||||
const int sign = negative ? 1 : 0;
|
||||
while (result.size() - sign < decpt)
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
view = {};
|
||||
} else if (decpt) {
|
||||
result.append(view.first(decpt));
|
||||
view = view.sliced(decpt);
|
||||
} else {
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
}
|
||||
if (!view.isEmpty() || (!succinct && view.size() < precision)) {
|
||||
result.append(u'.');
|
||||
result.append(Char('.'));
|
||||
result.append(view);
|
||||
if (!succinct) {
|
||||
for (qsizetype i = view.size(); i < precision; ++i)
|
||||
result.append(u'0');
|
||||
result.append(Char('0'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -768,4 +778,9 @@ QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, int precision, bo
|
||||
return result;
|
||||
}
|
||||
|
||||
QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, int precision, bool uppercase)
|
||||
{
|
||||
return dtoString<QString>(d, form, precision, uppercase);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
Reference in New Issue
Block a user