QLocale tools: add q(u)int128toBasicLatin()
Add q(u)int128toBasicLatin() as helper functions until QString::number() natively supports q(u)int128. Change-Id: I920dff145eaa4e849d1f340ca5d5491d2da2821a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
28fd273080
commit
9d693dbfb1
@ -807,4 +807,78 @@ QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form, int precision, bool
|
||||
return dtoString<QByteArray>(d, form, precision, uppercase);
|
||||
}
|
||||
|
||||
#if defined(QT_SUPPORTS_INT128) || (defined(Q_CC_MSVC) && (_MSC_VER >= 1930))
|
||||
static inline quint64 toUInt64(qinternaluint128 v)
|
||||
{
|
||||
#ifdef Q_CC_MSVC
|
||||
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(Q_CC_MSVC) && (_MSC_VER >= 1930))
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -20,6 +20,15 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(QT_SUPPORTS_INT128)
|
||||
using qinternalint128 = qint128;
|
||||
using qinternaluint128 = quint128;
|
||||
#elif defined(Q_CC_MSVC) && (_MSC_VER >= 1930)
|
||||
#include <__msvc_int128.hpp>
|
||||
using qinternalint128 = std::_Signed128;
|
||||
using qinternaluint128 = std::_Unsigned128;
|
||||
#endif
|
||||
|
||||
enum StrayCharacterMode {
|
||||
TrailingJunkProhibited,
|
||||
TrailingJunkAllowed,
|
||||
@ -43,6 +52,13 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
|
||||
[[nodiscard]] QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form,
|
||||
int precision, bool uppercase);
|
||||
|
||||
#if defined(QT_SUPPORTS_INT128) || (defined(Q_CC_MSVC) && (_MSC_VER >= 1930))
|
||||
[[nodiscard]] Q_CORE_EXPORT QString quint128toBasicLatin(qinternaluint128 number,
|
||||
int base = 10);
|
||||
[[nodiscard]] Q_CORE_EXPORT QString qint128toBasicLatin(qinternalint128 number,
|
||||
int base = 10);
|
||||
#endif
|
||||
|
||||
[[nodiscard]] constexpr inline bool isZero(double d)
|
||||
{
|
||||
return d == 0; // Amusingly, compilers do not grumble.
|
||||
|
Loading…
x
Reference in New Issue
Block a user