Refactor QLocale's integer formatting
Break out some shared code in the integer formatting to save duplicating it. Simplify what's left. Renamed some variables to match Qt style. Change-Id: I369a013802a267a94725302de0d1d33291c29538 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
0b0bc0ce20
commit
19ed60d703
@ -3561,14 +3561,6 @@ QString QLocaleData::signPrefix(bool negative, unsigned flags) const
|
|||||||
QString QLocaleData::longLongToString(qlonglong l, int precision,
|
QString QLocaleData::longLongToString(qlonglong l, int precision,
|
||||||
int base, int width, unsigned flags) const
|
int base, int width, unsigned flags) const
|
||||||
{
|
{
|
||||||
const QString zero = zeroDigit();
|
|
||||||
|
|
||||||
bool precision_not_specified = false;
|
|
||||||
if (precision == -1) {
|
|
||||||
precision_not_specified = true;
|
|
||||||
precision = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool negative = l < 0;
|
bool negative = l < 0;
|
||||||
if (base != 10) {
|
if (base != 10) {
|
||||||
// these are not supported by sprintf for octal and hex
|
// these are not supported by sprintf for octal and hex
|
||||||
@ -3584,150 +3576,80 @@ QT_WARNING_DISABLE_MSVC(4146)
|
|||||||
Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
|
Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
|
||||||
taking an absolute value has to cast to unsigned to change sign.
|
taking an absolute value has to cast to unsigned to change sign.
|
||||||
*/
|
*/
|
||||||
QString num_str = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zero);
|
QString numStr = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zeroDigit());
|
||||||
QT_WARNING_POP
|
QT_WARNING_POP
|
||||||
|
|
||||||
const QString resultZero = base == 10 ? zero : QStringLiteral("0");
|
return applyIntegerFormatting(std::move(numStr), negative, precision, base, width, flags);
|
||||||
const auto digitWidth = resultZero.size();
|
|
||||||
uint cnt_thousand_sep = 0;
|
|
||||||
if (base == 10) {
|
|
||||||
const QString &group = groupSeparator();
|
|
||||||
if (flags & ThousandsGroup) {
|
|
||||||
for (int i = num_str.length() / digitWidth - 3; i > 0; i -= 3) {
|
|
||||||
num_str.insert(i * digitWidth, group);
|
|
||||||
++cnt_thousand_sep;
|
|
||||||
}
|
|
||||||
} else if (flags & IndianNumberGrouping) {
|
|
||||||
const int size = num_str.length();
|
|
||||||
if (size > 3 * digitWidth)
|
|
||||||
num_str.insert(size - 3 * digitWidth , group);
|
|
||||||
for (int i = size / digitWidth - 5; i > 0; i -= 2) {
|
|
||||||
num_str.insert(i * digitWidth, group);
|
|
||||||
++cnt_thousand_sep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
|
|
||||||
num_str.prepend(resultZero);
|
|
||||||
|
|
||||||
if ((flags & ShowBase)
|
|
||||||
&& base == 8
|
|
||||||
&& (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
|
|
||||||
num_str.prepend(QLatin1Char('0'));
|
|
||||||
|
|
||||||
// LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
|
|
||||||
// when precision is not specified in the format string
|
|
||||||
bool zero_padded = flags & ZeroPadded
|
|
||||||
&& !(flags & LeftAdjusted)
|
|
||||||
&& precision_not_specified;
|
|
||||||
|
|
||||||
if (zero_padded) {
|
|
||||||
int num_pad_chars = width - num_str.length() / digitWidth;
|
|
||||||
|
|
||||||
// leave space for the sign
|
|
||||||
if (negative
|
|
||||||
|| flags & AlwaysShowSign
|
|
||||||
|| flags & BlankBeforePositive)
|
|
||||||
--num_pad_chars;
|
|
||||||
|
|
||||||
// leave space for optional '0x' in hex form
|
|
||||||
if (base == 16 && (flags & ShowBase))
|
|
||||||
num_pad_chars -= 2;
|
|
||||||
// leave space for optional '0b' in binary form
|
|
||||||
else if (base == 2 && (flags & ShowBase))
|
|
||||||
num_pad_chars -= 2;
|
|
||||||
|
|
||||||
while (num_pad_chars-- > 0)
|
|
||||||
num_str.prepend(resultZero);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & CapitalEorX)
|
|
||||||
num_str = std::move(num_str).toUpper();
|
|
||||||
|
|
||||||
if (base == 16 && (flags & ShowBase))
|
|
||||||
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
|
|
||||||
if (base == 2 && (flags & ShowBase))
|
|
||||||
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
|
|
||||||
|
|
||||||
return signPrefix(negative, flags) + num_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QLocaleData::unsLongLongToString(qulonglong l, int precision,
|
QString QLocaleData::unsLongLongToString(qulonglong l, int precision,
|
||||||
int base, int width, unsigned flags) const
|
int base, int width, unsigned flags) const
|
||||||
{
|
{
|
||||||
const QString zero = zeroDigit();
|
const QString zero = zeroDigit();
|
||||||
|
QString resultZero = base == 10 ? zero : QStringLiteral("0");
|
||||||
|
return applyIntegerFormatting(l ? qulltoa(l, base, zero) : resultZero,
|
||||||
|
false, precision, base, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
const QString resultZero = base == 10 ? zero : QStringLiteral("0");
|
QString QLocaleData::applyIntegerFormatting(QString &&numStr, bool negative, int precision,
|
||||||
QString num_str = l ? qulltoa(l, base, zero) : resultZero;
|
int base, int width, unsigned flags) const
|
||||||
|
{
|
||||||
|
const QString zero = base == 10 ? zeroDigit() : QStringLiteral("0");
|
||||||
|
const auto digitWidth = zero.size();
|
||||||
|
const auto digitCount = numStr.length() / digitWidth;
|
||||||
|
|
||||||
bool precision_not_specified = false;
|
const auto basePrefix = [numStr, zero, base, flags] () -> QStringView {
|
||||||
if (precision == -1) {
|
if (flags & ShowBase) {
|
||||||
if (flags == NoFlags)
|
const bool upper = flags & UppercaseBase;
|
||||||
return num_str; // fast-path: nothing below applies, so we're done.
|
if (base == 16)
|
||||||
|
return upper ? u"0X" : u"0x";
|
||||||
|
if (base == 2)
|
||||||
|
return upper ? u"0B" : u"0b";
|
||||||
|
if (base == 8 && !numStr.startsWith(zero))
|
||||||
|
return zero;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
precision_not_specified = true;
|
const QString prefix = signPrefix(negative, flags) + basePrefix();
|
||||||
precision = 1;
|
// Count how much of width we've used up. Each digit counts as one
|
||||||
}
|
int usedWidth = digitCount + prefix.size();
|
||||||
|
|
||||||
const auto digitWidth = resultZero.size();
|
|
||||||
uint cnt_thousand_sep = 0;
|
|
||||||
if (base == 10) {
|
if (base == 10) {
|
||||||
const QString group = groupSeparator();
|
const QString group = groupSeparator();
|
||||||
if (flags & ThousandsGroup) {
|
if (flags & ThousandsGroup) {
|
||||||
for (int i = num_str.length() / digitWidth - 3; i > 0; i -= 3) {
|
for (int i = numStr.length() / digitWidth - 3; i > 0; i -= 3) {
|
||||||
num_str.insert(i * digitWidth, group);
|
numStr.insert(i * digitWidth, group);
|
||||||
++cnt_thousand_sep;
|
++usedWidth;
|
||||||
}
|
}
|
||||||
} else if (flags & IndianNumberGrouping) {
|
} else if (flags & IndianNumberGrouping) {
|
||||||
const int size = num_str.length();
|
const int size = numStr.length();
|
||||||
if (size > 3 * digitWidth)
|
if (size > 3 * digitWidth)
|
||||||
num_str.insert(size - 3 * digitWidth , group);
|
numStr.insert(size - 3 * digitWidth , group);
|
||||||
for (int i = size / digitWidth - 5; i > 0; i -= 2) {
|
for (int i = size / digitWidth - 5; i > 0; i -= 2) {
|
||||||
num_str.insert(i * digitWidth, group);
|
numStr.insert(i * digitWidth, group);
|
||||||
++cnt_thousand_sep;
|
++usedWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int zeroPadding = precision - num_str.length() / digitWidth /* + cnt_thousand_sep*/;
|
const bool noPrecision = precision == -1;
|
||||||
while (zeroPadding-- > 0)
|
if (noPrecision)
|
||||||
num_str.prepend(resultZero);
|
precision = 1;
|
||||||
|
|
||||||
if ((flags & ShowBase)
|
for (int i = numStr.length(); i < precision; ++i) {
|
||||||
&& base == 8
|
numStr.prepend(zero);
|
||||||
&& (num_str.isEmpty() || num_str.at(0).unicode() != QLatin1Char('0')))
|
usedWidth++;
|
||||||
num_str.prepend(QLatin1Char('0'));
|
|
||||||
|
|
||||||
// LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
|
|
||||||
// when precision is not specified in the format string
|
|
||||||
bool zero_padded = flags & ZeroPadded
|
|
||||||
&& !(flags & LeftAdjusted)
|
|
||||||
&& precision_not_specified;
|
|
||||||
|
|
||||||
if (zero_padded) {
|
|
||||||
int num_pad_chars = width - num_str.length() / digitWidth;
|
|
||||||
|
|
||||||
// leave space for optional '0x' in hex form
|
|
||||||
if (base == 16 && flags & ShowBase)
|
|
||||||
num_pad_chars -= 2;
|
|
||||||
// leave space for optional '0b' in binary form
|
|
||||||
else if (base == 2 && flags & ShowBase)
|
|
||||||
num_pad_chars -= 2;
|
|
||||||
|
|
||||||
while (num_pad_chars-- > 0)
|
|
||||||
num_str.prepend(resultZero);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & CapitalEorX)
|
// LeftAdjusted overrides ZeroPadded; and sprintf() only pads when
|
||||||
num_str = std::move(num_str).toUpper();
|
// precision is not specified in the format string.
|
||||||
|
if (noPrecision && flags & ZeroPadded && !(flags & LeftAdjusted)) {
|
||||||
|
for (int i = usedWidth; i < width; ++i)
|
||||||
|
numStr.prepend(zero);
|
||||||
|
}
|
||||||
|
|
||||||
if (base == 16 && flags & ShowBase)
|
return prefix + (flags & CapitalEorX ? std::move(numStr).toUpper() : numStr);
|
||||||
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
|
|
||||||
else if (base == 2 && flags & ShowBase)
|
|
||||||
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
|
|
||||||
|
|
||||||
return signPrefix(false, flags) + num_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -224,6 +224,8 @@ private:
|
|||||||
PrecisionMode pm, bool mustMarkDecimal,
|
PrecisionMode pm, bool mustMarkDecimal,
|
||||||
int minExponentDigits) const;
|
int minExponentDigits) const;
|
||||||
QString signPrefix(bool negative, unsigned flags) const;
|
QString signPrefix(bool negative, unsigned flags) const;
|
||||||
|
QString applyIntegerFormatting(QString &&numStr, bool negative, int precision,
|
||||||
|
int base, int width, unsigned flags) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString doubleToString(double d,
|
QString doubleToString(double d,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user