summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2021-08-27 14:58:57 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2021-08-30 17:46:00 +0200
commit5644af6f8a800a1516360a42ba4c1a8dc61fc516 (patch)
tree0fb11871c40c7f389f95bc227699fdcda8b7889a /src
parent522ca997d3baab1b88f454bbeea9f357d3969dff (diff)
Replace FreeBSD's strtou?ll() with std::from_chars()-based strntou?ll()
Remove third-party code in favor of STL. Implement (for now) strtou?ll() as inlines on strntou?ll() calling strlen() for the size parameter. (This is not entirely safe, as a string lacking '\0'-termination but with at least some non-matching text after the numeric portion would formerly be parsed just fine, but would now produce a crash. However, strtou?ll() are internal and callers should be ensuring '\0'-termination.) Task-number: QTBUG-74286 Change-Id: I0c8ca7d4f6110367e93b4c0164854a82c5a545e1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch158
-rw-r--r--src/3rdparty/freebsd/LICENSE31
-rw-r--r--src/3rdparty/freebsd/qt_attribution.json18
-rw-r--r--src/3rdparty/freebsd/strtoll.c134
-rw-r--r--src/3rdparty/freebsd/strtoull.c112
-rw-r--r--src/corelib/text/qlocale_tools.cpp117
-rw-r--r--src/corelib/text/qlocale_tools_p.h11
7 files changed, 88 insertions, 493 deletions
diff --git a/src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch b/src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch
deleted file mode 100644
index 8fd012e4b1..0000000000
--- a/src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch
+++ /dev/null
@@ -1,158 +0,0 @@
-From 81a2d1a38becdeed2cd8b963e190aedf197e39c6 Mon Sep 17 00:00:00 2001
-From: Thiago Macieira <thiago.macieira@intel.com>
-Date: Thu, 2 Oct 2014 22:03:19 -0700
-Subject: [PATCH 1/1] Patch the FreeBSD strto(u)ll functions to work inside
- QtCore
-
-Changes:
- - remove the #includes and the SCCSID
- - rename from strtoxx_l to qt_strtoxx (merging the two functions)
- - remove __restrict
- - remove the locale_t parameter and use ascii_isspace instead of isspace_l
- - fix compilation with -Wcast-qual (requires C++)
-
- src/3rdparty/freebsd/strtoll.c | 27 +++------------------------
- src/3rdparty/freebsd/strtoull.c | 27 +++------------------------
- 2 files changed, 6 insertions(+), 48 deletions(-)
-
-diff --git a/src/3rdparty/freebsd/strtoll.c b/src/3rdparty/freebsd/strtoll.c
-index c87aefb1cd..89da83425d 100644
---- a/src/3rdparty/freebsd/strtoll.c
-+++ b/src/3rdparty/freebsd/strtoll.c
-@@ -1,6 +1,4 @@
- /*-
-- * SPDX-License-Identifier: BSD-3-Clause
-- *
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
-@@ -34,18 +32,6 @@
- * SUCH DAMAGE.
- */
-
--#if defined(LIBC_SCCS) && !defined(lint)
--static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
--#endif /* LIBC_SCCS and not lint */
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
--
--#include <limits.h>
--#include <errno.h>
--#include <ctype.h>
--#include <stdlib.h>
--#include "xlocale_private.h"
--
- /*
- * Convert a string to a long long integer.
- *
-@@ -53,15 +39,13 @@ __FBSDID("$FreeBSD$");
- * alphabets and digits are each contiguous.
- */
- long long
--strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base,
-- locale_t locale)
-+qt_strtoll(const char * nptr, char **endptr, int base)
- {
- const char *s;
- unsigned long long acc;
- char c;
- unsigned long long cutoff;
- int neg, any, cutlim;
-- FIX_LOCALE(locale);
-
- /*
- * Skip white space and pick up leading +/- sign if any.
-@@ -71,7 +55,7 @@ strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base,
- s = nptr;
- do {
- c = *s++;
-- } while (isspace_l((unsigned char)c, locale));
-+ } while (ascii_isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
-@@ -145,11 +129,6 @@ noconv:
- } else if (neg)
- acc = -acc;
- if (endptr != NULL)
-- *endptr = (char *)(any ? s - 1 : nptr);
-+ *endptr = const_cast<char *>(any ? s - 1 : nptr);
- return (acc);
- }
--long long
--strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
--{
-- return strtoll_l(nptr, endptr, base, __get_locale());
--}
-diff --git a/src/3rdparty/freebsd/strtoull.c b/src/3rdparty/freebsd/strtoull.c
-index 58a9b23b56..cf151691ad 100644
---- a/src/3rdparty/freebsd/strtoull.c
-+++ b/src/3rdparty/freebsd/strtoull.c
-@@ -1,6 +1,4 @@
- /*-
-- * SPDX-License-Identifier: BSD-3-Clause
-- *
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
-@@ -34,18 +32,6 @@
- * SUCH DAMAGE.
- */
-
--#if defined(LIBC_SCCS) && !defined(lint)
--static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
--#endif /* LIBC_SCCS and not lint */
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
--
--#include <limits.h>
--#include <errno.h>
--#include <ctype.h>
--#include <stdlib.h>
--#include "xlocale_private.h"
--
- /*
- * Convert a string to an unsigned long long integer.
- *
-@@ -53,15 +39,13 @@ __FBSDID("$FreeBSD$");
- * alphabets and digits are each contiguous.
- */
- unsigned long long
--strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base,
-- locale_t locale)
-+qt_strtoull(const char * nptr, char **endptr, int base)
- {
- const char *s;
- unsigned long long acc;
- char c;
- unsigned long long cutoff;
- int neg, any, cutlim;
-- FIX_LOCALE(locale);
-
- /*
- * See strtoq for comments as to the logic used.
-@@ -69,7 +53,7 @@ strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base,
- s = nptr;
- do {
- c = *s++;
-- } while (isspace_l((unsigned char)c, locale));
-+ } while (ascii_isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
-@@ -123,11 +107,6 @@ noconv:
- } else if (neg)
- acc = -acc;
- if (endptr != NULL)
-- *endptr = (char *)(any ? s - 1 : nptr);
-+ *endptr = const_cast<char *>(any ? s - 1 : nptr);
- return (acc);
- }
--unsigned long long
--strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
--{
-- return strtoull_l(nptr, endptr, base, __get_locale());
--}
---
-2.25.1
-
diff --git a/src/3rdparty/freebsd/LICENSE b/src/3rdparty/freebsd/LICENSE
deleted file mode 100644
index 5bb30318eb..0000000000
--- a/src/3rdparty/freebsd/LICENSE
+++ /dev/null
@@ -1,31 +0,0 @@
-Copyright (c) 1992, 1993
- The Regents of the University of California. All rights reserved.
-
-Copyright (c) 2011 The FreeBSD Foundation
-All rights reserved.
-Portions of this software were developed by David Chisnall
-under sponsorship from the FreeBSD Foundation.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
diff --git a/src/3rdparty/freebsd/qt_attribution.json b/src/3rdparty/freebsd/qt_attribution.json
deleted file mode 100644
index 644880a90d..0000000000
--- a/src/3rdparty/freebsd/qt_attribution.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "Id": "freebsd",
- "Name": "FreeBSD strtoll and strtoull",
- "QDocModule": "qtcore",
- "QtUsage": "Used in Qt Core.",
- "Files": "strtoll.c strtoull.c",
-
- "Description": "strtoll() and strtoull() are functions for converting a string to (unsigned) long long integer.",
- "Homepage": "https://github.com/freebsd/freebsd/",
- "DownloadLocation": "https://github.com/freebsd/freebsd/tree/master/lib/libc/stdlib",
- "Version": "upstream has complicated with std locales; do not update",
- "Version": "18b29f3fb8abee5d57ed8f4a44f806bec7e0eeff",
- "License": "BSD 3-clause \"New\" or \"Revised\" License",
- "LicenseId": "BSD-3-Clause",
- "LicenseFile": "LICENSE",
- "Copyright": "Copyright (c) 1992, 1993 The Regents of the University of California.
-Copyright (c) 2011 The FreeBSD Foundation"
-}
diff --git a/src/3rdparty/freebsd/strtoll.c b/src/3rdparty/freebsd/strtoll.c
deleted file mode 100644
index 89da83425d..0000000000
--- a/src/3rdparty/freebsd/strtoll.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 2011 The FreeBSD Foundation
- * All rights reserved.
- * Portions of this software were developed by David Chisnall
- * under sponsorship from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Convert a string to a long long integer.
- *
- * Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-long long
-qt_strtoll(const char * nptr, char **endptr, int base)
-{
- const char *s;
- unsigned long long acc;
- char c;
- unsigned long long cutoff;
- int neg, any, cutlim;
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- c = *s++;
- } while (ascii_isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+')
- c = *s++;
- }
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X') &&
- ((s[1] >= '0' && s[1] <= '9') ||
- (s[1] >= 'A' && s[1] <= 'F') ||
- (s[1] >= 'a' && s[1] <= 'f'))) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- acc = any = 0;
- if (base < 2 || base > 36)
- goto noconv;
-
- /*
- * Compute the cutoff value between legal numbers and illegal
- * numbers. That is the largest legal value, divided by the
- * base. An input number that is greater than this value, if
- * followed by a legal input character, is too big. One that
- * is equal to this value may be valid or not; the limit
- * between valid and invalid numbers is then based on the last
- * digit. For instance, if the range for quads is
- * [-9223372036854775808..9223372036854775807] and the input base
- * is 10, cutoff will be set to 922337203685477580 and cutlim to
- * either 7 (neg==0) or 8 (neg==1), meaning that if we have
- * accumulated a value > 922337203685477580, or equal but the
- * next digit is > 7 (or 8), the number is too big, and we will
- * return a range error.
- *
- * Set 'any' if any `digits' consumed; make it negative to indicate
- * overflow.
- */
- cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
- : LLONG_MAX;
- cutlim = cutoff % base;
- cutoff /= base;
- for ( ; ; c = *s++) {
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'A' && c <= 'Z')
- c -= 'A' - 10;
- else if (c >= 'a' && c <= 'z')
- c -= 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LLONG_MIN : LLONG_MAX;
- errno = ERANGE;
- } else if (!any) {
-noconv:
- errno = EINVAL;
- } else if (neg)
- acc = -acc;
- if (endptr != NULL)
- *endptr = const_cast<char *>(any ? s - 1 : nptr);
- return (acc);
-}
diff --git a/src/3rdparty/freebsd/strtoull.c b/src/3rdparty/freebsd/strtoull.c
deleted file mode 100644
index cf151691ad..0000000000
--- a/src/3rdparty/freebsd/strtoull.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 2011 The FreeBSD Foundation
- * All rights reserved.
- * Portions of this software were developed by David Chisnall
- * under sponsorship from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Convert a string to an unsigned long long integer.
- *
- * Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-unsigned long long
-qt_strtoull(const char * nptr, char **endptr, int base)
-{
- const char *s;
- unsigned long long acc;
- char c;
- unsigned long long cutoff;
- int neg, any, cutlim;
-
- /*
- * See strtoq for comments as to the logic used.
- */
- s = nptr;
- do {
- c = *s++;
- } while (ascii_isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+')
- c = *s++;
- }
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X') &&
- ((s[1] >= '0' && s[1] <= '9') ||
- (s[1] >= 'A' && s[1] <= 'F') ||
- (s[1] >= 'a' && s[1] <= 'f'))) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- acc = any = 0;
- if (base < 2 || base > 36)
- goto noconv;
-
- cutoff = ULLONG_MAX / base;
- cutlim = ULLONG_MAX % base;
- for ( ; ; c = *s++) {
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'A' && c <= 'Z')
- c -= 'A' - 10;
- else if (c >= 'a' && c <= 'z')
- c -= 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = ULLONG_MAX;
- errno = ERANGE;
- } else if (!any) {
-noconv:
- errno = EINVAL;
- } else if (neg)
- acc = -acc;
- if (endptr != NULL)
- *endptr = const_cast<char *>(any ? s - 1 : nptr);
- return (acc);
-}
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index 15933c3644..c144dba938 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -54,6 +54,7 @@
#include <time.h>
#include <limits>
+#include <charconv>
#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
# include <fenv.h>
@@ -72,13 +73,6 @@
QT_BEGIN_NAMESPACE
-QT_WARNING_PUSH
- /* "unary minus operator applied to unsigned type, result still unsigned" */
-QT_WARNING_DISABLE_MSVC(4146)
-#include "../../3rdparty/freebsd/strtoull.c"
-#include "../../3rdparty/freebsd/strtoll.c"
-QT_WARNING_POP
-
QT_CLOCALE_HOLDER
void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
@@ -416,50 +410,99 @@ double qt_asciiToDouble(const char *num, qsizetype numLen, bool &ok, int &proces
return d;
}
+/* Detect base if 0 and, if base is hex, skip over 0x prefix */
+static auto scanPrefix(const char *p, const char *stop, int base)
+{
+ if (p < stop && *p >= '0' && *p <= '9') {
+ if (*p == '0') {
+ const char *x = p + 1;
+ if (x < stop && (*x == 'x' || *x == 'X')) {
+ if (base == 0)
+ base = 16;
+ if (base == 16)
+ p += 2;
+ } else if (base == 0) {
+ base = 8;
+ }
+ } else if (base == 0) {
+ base = 10;
+ }
+ Q_ASSERT(base);
+ }
+ struct R
+ {
+ const char *next;
+ int base;
+ };
+ return R{p, base};
+}
+
unsigned long long
-qstrtoull(const char * nptr, const char **endptr, int base, bool *ok)
+qstrntoull(const char *begin, qsizetype size, const char **endptr, int base, bool *ok)
{
- // strtoull accepts negative numbers. We don't.
- // Use a different variable so we pass the original nptr to strtoul
- // (we need that so endptr may be nptr in case of failure)
- const char *begin = nptr;
- while (ascii_isspace(*begin))
- ++begin;
- if (*begin == '-') {
+ const char *p = begin, *const stop = begin + size;
+ while (p < stop && ascii_isspace(*p))
+ ++p;
+ unsigned long long result = 0;
+ if (p >= stop || *p == '-') {
*ok = false;
- return 0;
+ if (endptr)
+ *endptr = begin;
+ return result;
}
-
- *ok = true;
- errno = 0;
- char *endptr2 = nullptr;
- unsigned long long result = qt_strtoull(nptr, &endptr2, base);
- if (endptr)
- *endptr = endptr2;
- if ((result == 0 || result == std::numeric_limits<unsigned long long>::max())
- && (errno || endptr2 == nptr)) {
+ const auto prefix = scanPrefix(*p == '+' ? p + 1 : p, stop, base);
+ if (!prefix.base || prefix.next >= stop) {
+ if (endptr)
+ *endptr = begin;
*ok = false;
return 0;
}
+
+ const auto res = std::from_chars(prefix.next, stop, result, prefix.base);
+ *ok = res.ec == std::errc{};
+ if (endptr)
+ *endptr = res.ptr == prefix.next ? begin : res.ptr;
return result;
}
long long
-qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
+qstrntoll(const char *begin, qsizetype size, const char **endptr, int base, bool *ok)
{
- *ok = true;
- errno = 0;
- char *endptr2 = nullptr;
- long long result = qt_strtoll(nptr, &endptr2, base);
- if (endptr)
- *endptr = endptr2;
- if ((result == 0 || result == std::numeric_limits<long long>::min()
- || result == std::numeric_limits<long long>::max())
- && (errno || nptr == endptr2)) {
+ const char *p = begin, *const stop = begin + size;
+ while (p < stop && ascii_isspace(*p))
+ ++p;
+ // Frustratingly, std::from_chars() doesn't cope with a 0x prefix that might
+ // be between the sign and digits, so we have to handle that for it, which
+ // means we can't use its ability to read LLONG_MIN directly; see below.
+ const bool negate = p < stop && *p == '-';
+ if (negate || (p < stop && *p == '+'))
+ ++p;
+
+ const auto prefix = scanPrefix(p, stop, base);
+ if (!prefix.base || prefix.next >= stop) {
+ if (endptr)
+ *endptr = begin;
*ok = false;
return 0;
}
- return result;
+
+ long long result = 0;
+ auto res = std::from_chars(prefix.next, stop, result, prefix.base);
+ *ok = res.ec == std::errc{};
+ if (negate && res.ec == std::errc::result_out_of_range) {
+ // Maybe LLONG_MIN:
+ unsigned long long check = 0;
+ res = std::from_chars(prefix.next, stop, check, prefix.base);
+ if (res.ec == std::errc{} && check + std::numeric_limits<long long>::min() == 0) {
+ *ok = true;
+ if (endptr)
+ *endptr = res.ptr;
+ return std::numeric_limits<long long>::min();
+ }
+ }
+ if (endptr)
+ *endptr = res.ptr == prefix.next ? begin : res.ptr;
+ return negate && *ok ? -result : result;
}
template <typename Char>
diff --git a/src/corelib/text/qlocale_tools_p.h b/src/corelib/text/qlocale_tools_p.h
index b6ffff8224..27d849ea7a 100644
--- a/src/corelib/text/qlocale_tools_p.h
+++ b/src/corelib/text/qlocale_tools_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -117,8 +117,13 @@ inline double qstrtod(const char *s00, char const **se, bool *ok)
return qstrntod(s00, len, se, ok);
}
-qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok);
-qulonglong qstrtoull(const char *nptr, const char **endptr, int base, bool *ok);
+qlonglong qstrntoll(const char *nptr, qsizetype size, const char **endptr, int base, bool *ok);
+qulonglong qstrntoull(const char *nptr, qsizetype size, const char **endptr, int base, bool *ok);
+
+inline qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok)
+{ return qstrntoll(nptr, strlen(nptr), endptr, base, ok); }
+inline qulonglong qstrtoull(const char *nptr, const char **endptr, int base, bool *ok)
+{ return qstrntoull(nptr, strlen(nptr), endptr, base, ok); }
QT_END_NAMESPACE