diff options
Diffstat (limited to 'src/corelib/text')
-rw-r--r-- | src/corelib/text/qlocale.cpp | 7 | ||||
-rw-r--r-- | src/corelib/text/qlocale_p.h | 20 | ||||
-rw-r--r-- | src/corelib/text/qlocale_tools.cpp | 4 | ||||
-rw-r--r-- | src/corelib/text/qlocale_tools_p.h | 17 | ||||
-rw-r--r-- | src/corelib/text/qlocale_win.cpp | 16 |
5 files changed, 46 insertions, 18 deletions
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 5bf2f7b296..2febee62a9 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -3363,7 +3363,7 @@ QString QLocaleData::doubleToString(double d, int precision, DoubleForm form, QString converted; converted.reserve(2 * digits.size()); for (int i = 0; i < digits.length(); ++i) { - const uint digit = zeroUcs4 - '0' + digits.at(i).unicode(); + const uint digit = unicodeForDigit(digits.at(i).unicode() - '0', zeroUcs4); Q_ASSERT(QChar::requiresSurrogates(digit)); converted.append(QChar::highSurrogate(digit)); converted.append(QChar::lowSurrogate(digit)); @@ -3372,9 +3372,10 @@ QString QLocaleData::doubleToString(double d, int precision, DoubleForm form, } else { Q_ASSERT(zero.size() == 1); Q_ASSERT(!zero.at(0).isSurrogate()); - ushort z = zero.at(0).unicode() - '0'; + ushort z = zero.at(0).unicode(); + ushort *const value = reinterpret_cast<ushort *>(digits.data()); for (int i = 0; i < digits.length(); ++i) - reinterpret_cast<ushort *>(digits.data())[i] += z; + value[i] = unicodeForDigit(value[i] - '0', z); } const bool mustMarkDecimal = flags & ForcePoint; diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h index 818fdf27a1..d822f86b72 100644 --- a/src/corelib/text/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -463,14 +463,22 @@ inline char QLocaleData::numericToCLocale(QStringView in) const if ((group == u"\xa0" || group == u"\x202f") && in == u" ") return ','; - const uint zeroUcs4 = zeroUcs(); - const uint tenUcs4 = zeroUcs4 + 10; const uint inUcs4 = in.size() == 2 ? QChar::surrogateToUcs4(in.at(0), in.at(1)) : in.at(0).unicode(); - - if (zeroUcs4 <= inUcs4 && inUcs4 < tenUcs4) - return '0' + inUcs4 - zeroUcs4; - + const uint zeroUcs4 = zeroUcs(); + // Must match qlocale_tools.h's unicodeForDigit() + if (zeroUcs4 == 0x3007u) { + // QTBUG-85409: Suzhou's digits aren't contiguous ! + if (inUcs4 == zeroUcs4) + return '0'; + if (inUcs4 > 0x3020u && inUcs4 <= 0x3029u) + return inUcs4 - 0x3020u; + } else { + const uint tenUcs4 = zeroUcs4 + 10; + + if (zeroUcs4 <= inUcs4 && inUcs4 < tenUcs4) + return '0' + inUcs4 - zeroUcs4; + } if ('0' <= inUcs4 && inUcs4 <= '9') return inUcs4; diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp index 9466edb234..4f3912224b 100644 --- a/src/corelib/text/qlocale_tools.cpp +++ b/src/corelib/text/qlocale_tools.cpp @@ -447,14 +447,14 @@ QString qulltoa(qulonglong number, int base, const QStringView zero) } else if (zero.size() && !zero.at(0).isSurrogate()) { const ushort zeroUcs4 = zero.at(0).unicode(); while (number != 0) { - *(--p) = zeroUcs4 + number % base; + *(--p) = unicodeForDigit(number % base, zeroUcs4); number /= 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; + const uint digit = unicodeForDigit(number % base, zeroUcs4); *(--p) = QChar::lowSurrogate(digit); *(--p) = QChar::highSurrogate(digit); diff --git a/src/corelib/text/qlocale_tools_p.h b/src/corelib/text/qlocale_tools_p.h index e2e60b159d..17bfcb2e36 100644 --- a/src/corelib/text/qlocale_tools_p.h +++ b/src/corelib/text/qlocale_tools_p.h @@ -89,6 +89,23 @@ inline int wholePartSpace(double d) return d > (1 << 19) ? std::numeric_limits<double>::max_exponent10 + 1 : 6; } +// Returns code-point of same kind (UCS2 or UCS4) as zero; digit is 0 through 9 +template <typename UcsInt> +inline UcsInt unicodeForDigit(uint digit, UcsInt zero) +{ + // Must match QLocaleData::numericToCLocale()'s digit-digestion. + Q_ASSERT(digit < 10); + if (!digit) + return zero; + + // See QTBUG-85409: Suzhou's digits are U+3007, U+2021, ..., U+3029 + if (zero == 0x3007u) + return 0x3020u + digit; + // At CLDR 36.1, no other number system's digits were discontinuous. + + return zero + digit; +} + Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); Q_CORE_EXPORT double qstrntod(const char *s00, int len, char const **se, bool *ok); qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok); diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp index a1a1e1c43c..d74ae40313 100644 --- a/src/corelib/text/qlocale_win.cpp +++ b/src/corelib/text/qlocale_win.cpp @@ -235,23 +235,24 @@ QString QSystemLocalePrivate::substituteDigits(QString &&string) zeroDigit(); // Ensure zero is set. switch (zero.size()) { case 1: { - const ushort offset = zero.at(0).unicode() - '0'; - if (!offset) // Nothing to do + ushort z = zero.at(0).unicode(); + if (z == '0') // Nothing to do break; - Q_ASSERT(offset > 9); + Q_ASSERT(z > '9'); ushort *const qch = reinterpret_cast<ushort *>(string.data()); for (int i = 0, stop = string.size(); i < stop; ++i) { ushort &ch = qch[i]; if (ch >= '0' && ch <= '9') - ch += offset; + ch = unicodeForDigit(ch - '0', z); } break; } case 2: { // Surrogate pair (high, low): - uint digit = QChar::surrogateToUcs4(zero.at(0), zero.at(1)); + uint z = QChar::surrogateToUcs4(zero.at(0), zero.at(1)); for (int i = 0; i < 10; i++) { - const QChar s[2] = { QChar::highSurrogate(digit + i), QChar::lowSurrogate(digit + i) }; + uint digit = unicodeForDigit(i, z); + const QChar s[2] = { QChar::highSurrogate(digit), QChar::lowSurrogate(digit) }; string.replace(QString(QLatin1Char('0' + i)), QString(s, 2)); } break; @@ -276,7 +277,8 @@ QVariant QSystemLocalePrivate::zeroDigit() */ wchar_t digits[11]; if (getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) { - // assert all(digits[i] == i + digits[0] for i in range(1, 10)), assumed above + // assert all(digits[i] == i + digits[0] for i in range(1, 10)), + // assumed above (unless digits[0] is 0x3007; see QTBUG-85409). zero = QString::fromWCharArray(digits, 1); } } |