summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text')
-rw-r--r--src/corelib/text/qlocale.cpp7
-rw-r--r--src/corelib/text/qlocale_p.h20
-rw-r--r--src/corelib/text/qlocale_tools.cpp4
-rw-r--r--src/corelib/text/qlocale_tools_p.h17
-rw-r--r--src/corelib/text/qlocale_win.cpp16
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);
}
}