summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-11-10 23:23:43 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-11-16 16:15:32 -0800
commit2ea3d2e924151843b8348871232eb88afb4cfe40 (patch)
tree7f174db7a33d3e4785f4d9c7b1b332335b8e14e8 /src
parentcc98a7d01f19ea99f97b59dc66181c0d560e2cc8 (diff)
QLocale: make qt_asciiToDouble() do case-insensitive comparisons
To "inf" and "nan". Change-Id: Ieba79baf5ac34264a988fffd172676e1a776a0b1 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/text/qlocale_tools.cpp48
-rw-r--r--src/corelib/text/qstring.cpp9
2 files changed, 30 insertions, 27 deletions
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index 405f096420..5d439f2b26 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -250,31 +250,43 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
QSimpleParsedNumber<double> qt_asciiToDouble(const char *num, qsizetype numLen,
StrayCharacterMode strayCharMode)
{
- auto string_equals = [](const char *needle, const char *haystack, qsizetype haystackLen) {
- qsizetype needleLen = strlen(needle);
- return needleLen == haystackLen && memcmp(needle, haystack, haystackLen) == 0;
- };
-
if (numLen <= 0)
return {};
// We have to catch NaN before because we need NaN as marker for "garbage" in the
// libdouble-conversion case and, in contrast to libdouble-conversion or sscanf, we don't allow
// "-nan" or "+nan"
- if (string_equals("nan", num, numLen)) {
- return { qt_qnan(), num + 3 };
- } else if (string_equals("+nan", num, numLen) || string_equals("-nan", num, numLen)) {
- return {};
- }
+ if (char c = *num; numLen >= 3
+ && (c == '-' || c == '+' || c == 'I' || c == 'i' || c == 'N' || c == 'n')) {
+ bool negative = (c == '-');
+ bool hasSign = negative || (c == '+');
+ qptrdiff offset = 0;
+ if (hasSign) {
+ offset = 1;
+ c = num[offset];
+ }
- // Infinity values are implementation defined in the sscanf case. In the libdouble-conversion
- // case we need infinity as overflow marker.
- if (string_equals("+inf", num, numLen)) {
- return { qt_inf(), num + 4 };
- } else if (string_equals("inf", num, numLen)) {
- return { qt_inf(), num + 3 };
- } else if (string_equals("-inf", num, numLen)) {
- return { -qt_inf(), num + 4 };
+ if (c > '9') {
+ auto lowered = [](char c) {
+ // this will mangle non-letters, but none can become a letter
+ return c | 0x20;
+ };
+
+ // Found a non-digit, so this MUST be either "inf", "+inf", "-inf"
+ // or "nan". Anything else is an invalid parse and we don't need to
+ // feed it to the converter below.
+ if (numLen != offset + 3)
+ return {};
+
+ c = lowered(c);
+ char c2 = lowered(num[offset + 1]);
+ char c3 = lowered(num[offset + 2]);
+ if (c == 'i' && c2 == 'n' && c3 == 'f')
+ return { negative ? -qt_inf() : qt_inf(), num + offset + 3 };
+ else if (c == 'n' && c2 == 'a' && c3 == 'n' && !hasSign)
+ return { qt_qnan(), num + 3 };
+ return {};
+ }
}
double d = 0.0;
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index b3e147c0ba..2ac8306eb4 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -7490,15 +7490,6 @@ double QStringView::toDouble(bool *ok) const
QStringView string = qt_trimmed(*this);
QVarLengthArray<uchar> latin1(string.size());
qt_to_latin1(latin1.data(), string.utf16(), string.size());
-
- // We need lowetcased "inf" and "nan".
- // This mangles the string, but nothing can become a number or letter
- // that isn't already a number or letter.
- for (uchar &c : latin1) {
- if (c >= 'A')
- c |= 0x20;
- }
-
auto r = qt_asciiToDouble(reinterpret_cast<const char *>(latin1.data()), string.size());
if (ok != nullptr)
*ok = r.ok();