summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qlocale_tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qlocale_tools.cpp')
-rw-r--r--src/corelib/text/qlocale_tools.cpp120
1 files changed, 69 insertions, 51 deletions
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index 0da769d694..9adb6e4a23 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -428,72 +428,85 @@ qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
return result;
}
-QString qulltoa(qulonglong l, int base, const QChar _zero)
+QString qulltoa(qulonglong number, int base, const QStringView zero)
{
- ushort buff[65]; // length of MAX_ULLONG in base 2
- ushort *p = buff + 65;
-
- if (base != 10 || _zero.unicode() == '0') {
- while (l != 0) {
- int c = l % base;
-
- --p;
-
- if (c < 10)
- *p = '0' + c;
- else
- *p = c - 10 + 'a';
+ // Length of MAX_ULLONG in base 2 is 64; and we may need a surrogate pair
+ // per digit. We do not need a terminator.
+ const unsigned maxlen = 128;
+ Q_STATIC_ASSERT(CHAR_BIT * sizeof(number) <= maxlen);
+ ushort buff[maxlen];
+ ushort *const end = buff + maxlen, *p = end;
+
+ if (base != 10 || zero == u"0") {
+ while (number != 0) {
+ int c = number % base;
+ *--p = c < 10 ? '0' + c : c - 10 + 'a';
+ number /= base;
+ }
+ } else if (zero.size() && !zero.at(0).isSurrogate()) {
+ const ushort zeroUcs4 = zero.at(0).unicode();
+ while (number != 0) {
+ *(--p) = zeroUcs4 + number % base;
- l /= base;
+ number /= base;
}
- }
- else {
- while (l != 0) {
- int c = l % base;
+ } else if (zero.size() == 2 && zero.at(0).isHighSurrogate()) {
+ const uint zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
+ while (number != 0) {
+ const uint digit = zeroUcs4 + number % base;
- *(--p) = _zero.unicode() + c;
+ *(--p) = QChar::lowSurrogate(digit);
+ *(--p) = QChar::highSurrogate(digit);
- l /= base;
+ number /= base;
}
+ } else {
+ return QString();
}
- return QString(reinterpret_cast<QChar *>(p), 65 - (p - buff));
+ return QString(reinterpret_cast<QChar *>(p), end - p);
}
-QString &decimalForm(QChar zero, QChar decimal, QChar group,
+QString &decimalForm(const QString &zero, const QString &decimal, const QString &group,
QString &digits, int decpt, int precision,
PrecisionMode pm,
bool always_show_decpt,
bool thousands_group)
{
+ const auto digitWidth = zero.size();
+ Q_ASSERT(digitWidth == 1 || digitWidth == 2);
+ Q_ASSERT(digits.size() % digitWidth == 0);
+
if (decpt < 0) {
for (int i = 0; i < -decpt; ++i)
digits.prepend(zero);
decpt = 0;
- }
- else if (decpt > digits.length()) {
- for (int i = digits.length(); i < decpt; ++i)
+ } else {
+ for (int i = digits.length() / digitWidth; i < decpt; ++i)
digits.append(zero);
}
- if (pm == PMDecimalDigits) {
- uint decimal_digits = digits.length() - decpt;
- for (int i = decimal_digits; i < precision; ++i)
+ switch (pm) {
+ case PMDecimalDigits:
+ for (int i = digits.length() / digitWidth - decpt; i < precision; ++i)
digits.append(zero);
- }
- else if (pm == PMSignificantDigits) {
- for (int i = digits.length(); i < precision; ++i)
+ break;
+ case PMSignificantDigits:
+ for (int i = digits.length() / digitWidth; i < precision; ++i)
digits.append(zero);
- }
- else { // pm == PMChopTrailingZeros
+ break;
+ case PMChopTrailingZeros:
+ break;
}
- if (always_show_decpt || decpt < digits.length())
- digits.insert(decpt, decimal);
+ if (always_show_decpt || decpt < digits.length() / digitWidth)
+ digits.insert(decpt * digitWidth, decimal);
+ // FIXME: they're not simply thousands separators !
+ // Need to mirror IndianNumberGrouping code in QLocaleData::longLongToString()
if (thousands_group) {
for (int i = decpt - 3; i > 0; i -= 3)
- digits.insert(i, group);
+ digits.insert(i * digitWidth, group);
}
if (decpt == 0)
@@ -502,32 +515,37 @@ QString &decimalForm(QChar zero, QChar decimal, QChar group,
return digits;
}
-QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
- QChar group, QChar plus, QChar minus,
+QString &exponentForm(const QString &zero, const QString &decimal, const QString &exponential,
+ const QString &group, const QString &plus, const QString &minus,
QString &digits, int decpt, int precision,
PrecisionMode pm,
bool always_show_decpt,
bool leading_zero_in_exponent)
{
- int exp = decpt - 1;
+ const auto digitWidth = zero.size();
+ Q_ASSERT(digitWidth == 1 || digitWidth == 2);
+ Q_ASSERT(digits.size() % digitWidth == 0);
- if (pm == PMDecimalDigits) {
- for (int i = digits.length(); i < precision + 1; ++i)
+ switch (pm) {
+ case PMDecimalDigits:
+ for (int i = digits.length() / digitWidth; i < precision + 1; ++i)
digits.append(zero);
- }
- else if (pm == PMSignificantDigits) {
- for (int i = digits.length(); i < precision; ++i)
+ break;
+ case PMSignificantDigits:
+ for (int i = digits.length() / digitWidth; i < precision; ++i)
digits.append(zero);
- }
- else { // pm == PMChopTrailingZeros
+ break;
+ case PMChopTrailingZeros:
+ break;
}
- if (always_show_decpt || digits.length() > 1)
- digits.insert(1, decimal);
+ if (always_show_decpt || digits.length() > digitWidth)
+ digits.insert(digitWidth, decimal);
digits.append(exponential);
- digits.append(QLocaleData::longLongToString(zero, group, plus, minus,
- exp, leading_zero_in_exponent ? 2 : 1, 10, -1, QLocaleData::AlwaysShowSign));
+ digits.append(QLocaleData::longLongToString(zero, group, plus, minus, decpt - 1,
+ leading_zero_in_exponent ? 2 : 1,
+ 10, -1, QLocaleData::AlwaysShowSign));
return digits;
}