diff options
Diffstat (limited to 'src/corelib/text/qlocale_tools.cpp')
-rw-r--r-- | src/corelib/text/qlocale_tools.cpp | 103 |
1 files changed, 95 insertions, 8 deletions
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp index 0402203c27..6b04bc92cd 100644 --- a/src/corelib/text/qlocale_tools.cpp +++ b/src/corelib/text/qlocale_tools.cpp @@ -310,8 +310,8 @@ QSimpleParsedNumber<double> qt_asciiToDouble(const char *num, qsizetype numLen, d = conv.StringToDouble(num, int(numLen), &processed); } - if (!qIsFinite(d)) { - if (qIsNaN(d)) { + if (!qt_is_finite(d)) { + if (qt_is_nan(d)) { // Garbage found. We don't accept it and return 0. return {}; } else { @@ -329,12 +329,12 @@ QSimpleParsedNumber<double> qt_asciiToDouble(const char *num, qsizetype numLen, if (qDoubleSscanf(num, QT_CLOCALE, fmt, &d, &processed) < 1) processed = 0; - if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) { + if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qt_is_nan(d)) { // Implementation defined nan symbol or garbage found. We don't accept it. return {}; } - if (!qIsFinite(d)) { + if (!qt_is_finite(d)) { // Overflow. Check for implementation-defined infinity symbols and reject them. // We assume that any infinity symbol has to contain a character that cannot be part of a // "normal" number (that is 0-9, ., -, +, e). @@ -552,6 +552,18 @@ QString qulltoa(qulonglong number, int base, const QStringView zero) return QString(reinterpret_cast<QChar *>(p), end - p); } +char *qulltoa2(char *p, qulonglong n, int base) +{ +#if defined(QT_CHECK_RANGE) + if (base < 2 || base > 36) { + qWarning("QByteArray::setNum: Invalid base %d", base); + base = 10; + } +#endif + qulltoString_helper(n, base, p); + return p; +} + /*! \internal @@ -651,7 +663,7 @@ static T dtoString(double d, QLocaleData::DoubleForm form, int precision, bool u int bufSize = 1; if (precision == QLocale::FloatingPointShortest) bufSize += D::max_digits10; - else if (form == QLocaleData::DFDecimal && qIsFinite(d)) + else if (form == QLocaleData::DFDecimal && qt_is_finite(d)) bufSize += wholePartSpace(qAbs(d)) + precision; else // Add extra digit due to different interpretations of precision. bufSize += qMax(2, precision) + 1; // Must also be big enough for "nan" or "inf" @@ -666,7 +678,7 @@ static T dtoString(double d, QLocaleData::DoubleForm form, int precision, bool u QLatin1StringView view(buffer.data(), length); const bool succinct = form == QLocaleData::DFSignificantDigits; qsizetype total = (negative ? 1 : 0) + length; - if (qIsFinite(d)) { + if (qt_is_finite(d)) { if (succinct) form = resolveFormat(precision, decpt, view.size()); @@ -708,7 +720,7 @@ static T dtoString(double d, QLocaleData::DoubleForm form, int precision, bool u if (negative && !isZero(d)) // We don't return "-0" result.append(Char('-')); - if (!qIsFinite(d)) { + if (!qt_is_finite(d)) { result.append(view); if (uppercase) result = std::move(result).toUpper(); @@ -729,7 +741,7 @@ static T dtoString(double d, QLocaleData::DoubleForm form, int precision, bool 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); + Q_ASSERT(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) @@ -795,4 +807,79 @@ QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form, int precision, bool return dtoString<QByteArray>(d, form, precision, uppercase); } +#if defined(QT_SUPPORTS_INT128) || defined(QT_USE_MSVC_INT128) +static inline quint64 toUInt64(qinternaluint128 v) +{ +#if defined(QT_USE_MSVC_INT128) + return quint64(v._Word[0]); +#else + return quint64(v); +#endif +} + +QString quint128toBasicLatin(qinternaluint128 number, int base) +{ + // We divide our 128-bit number into parts that we can do text + // concatenation with. This list is the maximum power of the + // base that is less than 2^64. + static constexpr auto dividers = []() constexpr { + std::array<quint64, 35> bases {}; + for (int base = 2; base <= 36; ++base) { + quint64 v = base; + while (v * base > v) + v *= base; + bases[base - 2] = v; + } + return bases; + }(); + static constexpr auto digitCounts = []() constexpr { + std::array<quint8, 35> digits{}; + for (int base = 2; base <= 36; ++base) { + quint64 v = base; + int i = 0; + for (i = 0; v * base > v; ++i) + v *= base; + digits[base - 2] = i; + } + return digits; + }(); + + QString result; + + constexpr unsigned flags = QLocaleData::NoFlags; + const QLocaleData *dd = QLocaleData::c(); + + // special base cases: + constexpr int Width = -1; + if (base == 2 || base == 4 || base == 16) { + // 2^64 is a power of 2, 4 and 16 + result = dd->unsLongLongToString(quint64(number), 64, base, Width, flags); + result.prepend(dd->unsLongLongToString(quint64(number >> 64), -1, base, Width, flags)); + } else { + int digitCount = digitCounts[base - 2]; + quint64 divider = dividers[base - 2]; + quint64 lower = toUInt64(number % divider); + number /= divider; + while (number) { + result.prepend(dd->unsLongLongToString(lower, digitCount, base, Width, flags)); + lower = toUInt64(number % divider); + number /= divider; + } + result.prepend(dd->unsLongLongToString(lower, -1, base, Width, flags)); + } + return result; +} + +QString qint128toBasicLatin(qinternalint128 number, int base) +{ + const bool negative = number < 0; + if (negative) + number *= -1; + QString result = quint128toBasicLatin(qinternaluint128(number), base); + if (negative) + result.prepend(u'-'); + return result; +} +#endif // defined(QT_SUPPORTS_INT128) || defined(QT_USE_MSVC_INT128) + QT_END_NAMESPACE |