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>
This commit is contained in:
parent
522ca997d3
commit
5644af6f8a
@ -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
|
||||
|
31
src/3rdparty/freebsd/LICENSE
vendored
31
src/3rdparty/freebsd/LICENSE
vendored
@ -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.
|
18
src/3rdparty/freebsd/qt_attribution.json
vendored
18
src/3rdparty/freebsd/qt_attribution.json
vendored
@ -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"
|
||||
}
|
134
src/3rdparty/freebsd/strtoll.c
vendored
134
src/3rdparty/freebsd/strtoll.c
vendored
@ -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);
|
||||
}
|
112
src/3rdparty/freebsd/strtoull.c
vendored
112
src/3rdparty/freebsd/strtoull.c
vendored
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
unsigned long long
|
||||
qstrtoull(const char * nptr, const char **endptr, int base, bool *ok)
|
||||
/* Detect base if 0 and, if base is hex, skip over 0x prefix */
|
||||
static auto scanPrefix(const char *p, const char *stop, int base)
|
||||
{
|
||||
// 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 == '-') {
|
||||
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
|
||||
qstrntoull(const char *begin, qsizetype size, const char **endptr, int base, bool *ok)
|
||||
{
|
||||
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;
|
||||
if (endptr)
|
||||
*endptr = begin;
|
||||
return result;
|
||||
}
|
||||
const auto prefix = scanPrefix(*p == '+' ? p + 1 : p, stop, base);
|
||||
if (!prefix.base || prefix.next >= stop) {
|
||||
if (endptr)
|
||||
*endptr = begin;
|
||||
*ok = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ok = true;
|
||||
errno = 0;
|
||||
char *endptr2 = nullptr;
|
||||
unsigned long long result = qt_strtoull(nptr, &endptr2, base);
|
||||
const auto res = std::from_chars(prefix.next, stop, result, prefix.base);
|
||||
*ok = res.ec == std::errc{};
|
||||
if (endptr)
|
||||
*endptr = endptr2;
|
||||
if ((result == 0 || result == std::numeric_limits<unsigned long long>::max())
|
||||
&& (errno || endptr2 == nptr)) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
}
|
||||
*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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <private/qtools_p.h>
|
||||
|
||||
#include "../shared/test_number_shared.h"
|
||||
#include <limits>
|
||||
|
||||
class tst_QByteArray : public QObject
|
||||
{
|
||||
@ -1674,6 +1675,20 @@ void tst_QByteArray::toULong()
|
||||
QCOMPARE(b, ok);
|
||||
}
|
||||
|
||||
static QByteArray decNext(QByteArray &&big)
|
||||
{
|
||||
// Increments a decimal digit-string (ignoring sign, so decrements if
|
||||
// negative); only intended for taking a boundary value just out of range,
|
||||
// so big is never a string of only 9s (that'd be one less than a power of
|
||||
// ten, which cannot be a power of two, as odd, or one less than one, as the
|
||||
// power of ten isn't a power of two).
|
||||
int i = big.size() - 1;
|
||||
while (big.at(i) == '9')
|
||||
big[i--] = '0';
|
||||
big[i] += 1;
|
||||
return big;
|
||||
}
|
||||
|
||||
void tst_QByteArray::toLongLong_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("str");
|
||||
@ -1689,10 +1704,14 @@ void tst_QByteArray::toLongLong_data()
|
||||
<< 7679359922672374856LL << true;
|
||||
QTest::newRow("in range dec neg") << QByteArray("-7679359922672374856") << 10
|
||||
<< -7679359922672374856LL << true;
|
||||
QTest::newRow("in range hex") << QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448LL
|
||||
<< true;
|
||||
QTest::newRow("in range hex neg") << QByteArray("-6A929129A5421448") << 16
|
||||
<< -0x6A929129A5421448LL << true;
|
||||
QTest::newRow("in range hex")
|
||||
<< QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448LL << true;
|
||||
QTest::newRow("in range hex prefix")
|
||||
<< QByteArray("0x6A929129A5421448") << 16 << 0x6A929129A5421448LL << true;
|
||||
QTest::newRow("in range hex neg")
|
||||
<< QByteArray("-6A929129A5421448") << 16 << -0x6A929129A5421448LL << true;
|
||||
QTest::newRow("in range hex prefix neg")
|
||||
<< QByteArray("-0x6A929129A5421448") << 16 << -0x6A929129A5421448LL << true;
|
||||
QTest::newRow("Fibonacci's last int64") << QByteArray("7540113804746346429") << 10
|
||||
<< 7540113804746346429LL << true;
|
||||
|
||||
@ -1700,6 +1719,8 @@ void tst_QByteArray::toLongLong_data()
|
||||
<< 0xABCFFFFFFF123LL << true;
|
||||
QTest::newRow("trailing spaces") << QByteArray("9876543210\t\r \n") << 10
|
||||
<< 9876543210LL << true;
|
||||
QTest::newRow("space after plus") << QByteArray("+ 12") << 10 << 0LL << false;
|
||||
QTest::newRow("space after minus") << QByteArray("- 12") << 10 << 0LL << false;
|
||||
QTest::newRow("leading junk") << QByteArray("q12345") << 10 << 0LL << false;
|
||||
QTest::newRow("trailing junk") << QByteArray("abc12345t") << 16 << 0LL << false;
|
||||
|
||||
@ -1716,13 +1737,86 @@ void tst_QByteArray::toLongLong_data()
|
||||
QTest::newRow("base 3") << QByteArray("12012") << 3 << 140LL << true;
|
||||
QTest::newRow("neg base 3") << QByteArray("-201") << 3 << -19LL << true;
|
||||
|
||||
QTest::newRow("max dec") << QByteArray("9223372036854775807") << 10 << 9223372036854775807LL
|
||||
<< true;
|
||||
QTest::newRow("mix hex") << QByteArray("-7FFFFFFFFFFFFFFF") << 16 << -0x7FFFFFFFFFFFFFFFLL
|
||||
<< true;
|
||||
// Boundary values, first in every base:
|
||||
using LL = std::numeric_limits<qlonglong>;
|
||||
for (int b = 0; b <= 36; ++b) {
|
||||
if (b == 1) // bases 0 and 2 through 36 are allowed
|
||||
++b;
|
||||
QTest::addRow("max base %d", b)
|
||||
<< QByteArray::number(LL::max(), b ? b : 10) << b << LL::max() << true;
|
||||
QTest::addRow("min base %d", b)
|
||||
<< QByteArray::number(LL::min(), b ? b : 10) << b << LL::min() << true;
|
||||
}
|
||||
// Check leading zeros don't hit any buffer-too-big problems:
|
||||
QTest::newRow("many-0 max dec")
|
||||
<< (QByteArray(512, '0') + QByteArray::number(LL::max())) << 10 << LL::max() << true;
|
||||
|
||||
QTest::newRow("max + 1 dec") << QByteArray("9223372036854775808") << 10 << 0LL << false;
|
||||
QTest::newRow("min - 1 hex") << QByteArray("-8000000000000001") << 16 << 0LL << false;
|
||||
// Special bases (and let's include some leading space, too !), first decimal:
|
||||
QTest::newRow("max dec, base 0") << QByteArray::number(LL::max()) << 0 << LL::max() << true;
|
||||
QTest::newRow("max space dec")
|
||||
<< ("\t\r\n\f\v " + QByteArray::number(LL::max())) << 10 << LL::max() << true;
|
||||
QTest::newRow("max space dec, base 0")
|
||||
<< ("\t\r\n\f\v " + QByteArray::number(LL::max())) << 0 << LL::max() << true;
|
||||
QTest::newRow("min dec, base 0") << QByteArray::number(LL::min()) << 0 << LL::min() << true;
|
||||
QTest::newRow("min space dec")
|
||||
<< ("\t\r\n\f\v " + QByteArray::number(LL::min())) << 10 << LL::min() << true;
|
||||
QTest::newRow("min space dec, base 0")
|
||||
<< ("\t\r\n\f\v " + QByteArray::number(LL::min())) << 0 << LL::min() << true;
|
||||
|
||||
// Hex with prefix:
|
||||
QTest::newRow("max 0x base 0")
|
||||
<< ("0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
|
||||
QTest::newRow("max +0x base 0")
|
||||
<< ("+0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
|
||||
QTest::newRow("max space 0x base 0")
|
||||
<< ("\t\r\n\f\v 0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
|
||||
QTest::newRow("max space +0x base 0")
|
||||
<< ("\t\r\n\f\v +0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
|
||||
QByteArray big = QByteArray::number(LL::min(), 16);
|
||||
big.insert(1, "0x"); // after sign
|
||||
QTest::newRow("min hex prefix") << big << 16 << LL::min() << true;
|
||||
QTest::newRow("min 0x base 0") << big << 0 << LL::min() << true;
|
||||
big.prepend("\t\r\n\f\v ");
|
||||
QTest::newRow("min space hex prefix") << big << 16 << LL::min() << true;
|
||||
QTest::newRow("min space 0x base 0") << big << 0 << LL::min() << true;
|
||||
|
||||
// Octal with prefix:
|
||||
QTest::newRow("max octal base 0")
|
||||
<< ('0' + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
|
||||
QTest::newRow("max +octal base 0")
|
||||
<< ("+0" + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
|
||||
QTest::newRow("max space octal base 0")
|
||||
<< ("\t\r\n\f\v 0" + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
|
||||
QTest::newRow("max space +octal base 0")
|
||||
<< ("\t\r\n\f\v +0" + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
|
||||
big = QByteArray::number(LL::min(), 8);
|
||||
big.insert(1, '0'); // after sign
|
||||
QTest::newRow("min octal prefix") << big << 8 << LL::min() << true;
|
||||
QTest::newRow("min octal base 0") << big << 0 << LL::min() << true;
|
||||
big.prepend("\t\r\n\f\v ");
|
||||
QTest::newRow("min space octal prefix") << big << 8 << LL::min() << true;
|
||||
QTest::newRow("min space octal base 0") << big << 0 << LL::min() << true;
|
||||
|
||||
// Values *just* out of range:
|
||||
QTest::newRow("max + 1 dec") << decNext(QByteArray::number(LL::max())) << 10 << 0LL << false;
|
||||
QTest::newRow("max + 1 dec base 0")
|
||||
<< decNext(QByteArray::number(LL::max())) << 0 << 0LL << false;
|
||||
QTest::newRow("min - 1 dec") << decNext(QByteArray::number(LL::min())) << 10 << 0LL << false;
|
||||
QTest::newRow("min - 1 dec base 0")
|
||||
<< decNext(QByteArray::number(LL::min())) << 0 << 0LL << false;
|
||||
// For hex and octal, we know the last digit of min is 0 and skipping its sign gets max+1:
|
||||
big = QByteArray::number(LL::min(), 8);
|
||||
QTest::newRow("max + 1 oct") << big.sliced(1) << 8 << 0LL << false;
|
||||
big[big.size() - 1] = '1';
|
||||
QTest::newRow("min - 1 oct") << big << 8 << 0LL << false;
|
||||
big.insert(1, '0'); // after minus sign
|
||||
QTest::newRow("min - 1 octal base 0") << big << 0 << 0LL << false;
|
||||
big = QByteArray::number(LL::min(), 16);
|
||||
QTest::newRow("max + 1 hex") << big.sliced(1) << 16 << 0LL << false;
|
||||
big[big.size() - 1] = '1';
|
||||
QTest::newRow("min - 1 hex") << big << 16 << 0LL << false;
|
||||
big.insert(1, "0x"); // after minus sign
|
||||
QTest::newRow("min - 1, 0x base 0") << big << 0 << 0LL << false;
|
||||
}
|
||||
|
||||
void tst_QByteArray::toLongLong()
|
||||
@ -1749,14 +1843,81 @@ void tst_QByteArray::toULongLong_data()
|
||||
QTest::addColumn<qulonglong>("result");
|
||||
QTest::addColumn<bool>("ok");
|
||||
|
||||
QTest::newRow("null") << QByteArray() << 10 << (qulonglong)0 << false;
|
||||
QTest::newRow("empty") << QByteArray("") << 10 << (qulonglong)0 << false;
|
||||
QTest::newRow("out of base bound") << QByteArray("c") << 10 << (qulonglong)0 << false;
|
||||
QTest::newRow("null") << QByteArray() << 10 << 0ULL << false;
|
||||
QTest::newRow("empty") << QByteArray("") << 10 << 0ULL << false;
|
||||
QTest::newRow("out of base bound") << QByteArray("c") << 10 << 0ULL << false;
|
||||
|
||||
QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << qulonglong(100) << true;
|
||||
QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << qulonglong(100) << true;
|
||||
QTest::newRow("leading junk") << QByteArray("x100") << 10 << qulonglong(0) << false;
|
||||
QTest::newRow("trailing junk") << QByteArray("100x") << 10 << qulonglong(0) << false;
|
||||
QTest::newRow("in range dec")
|
||||
<< QByteArray("7679359922672374856") << 10 << 7679359922672374856ULL << true;
|
||||
QTest::newRow("in range hex")
|
||||
<< QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448ULL << true;
|
||||
QTest::newRow("in range hex prefix")
|
||||
<< QByteArray("0x6A929129A5421448") << 16 << 0x6A929129A5421448ULL << true;
|
||||
|
||||
QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << 100ULL << true;
|
||||
QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << 100ULL << true;
|
||||
QTest::newRow("leading plus") << QByteArray("+100") << 10 << 100ULL << true;
|
||||
QTest::newRow("space after plus") << QByteArray("+ 12") << 10 << 0ULL << false;
|
||||
QTest::newRow("leading minus") << QByteArray("-100") << 10 << 0ULL << false;
|
||||
QTest::newRow("leading junk") << QByteArray("x100") << 10 << 0ULL << false;
|
||||
QTest::newRow("trailing junk") << QByteArray("100x") << 10 << 0ULL << false;
|
||||
|
||||
QTest::newRow("dec, base 0") << QByteArray("9876543210") << 0 << 9876543210ULL << true;
|
||||
QTest::newRow("hex, base 0") << QByteArray("0x9876543210") << 0 << 0x9876543210ULL << true;
|
||||
QTest::newRow("oct, base 0") << QByteArray("07654321234567") << 0 << 07654321234567ULL << true;
|
||||
QTest::newRow("base 3") << QByteArray("12012") << 3 << 140ULL << true;
|
||||
|
||||
// Boundary values, first in every base:
|
||||
using ULL = std::numeric_limits<qulonglong>;
|
||||
for (int b = 0; b <= 36; ++b) {
|
||||
if (b == 1) // bases 0 and 2 through 36 are allowed
|
||||
++b;
|
||||
QTest::addRow("max base %d", b)
|
||||
<< QByteArray::number(ULL::max(), b ? b : 10) << b << ULL::max() << true;
|
||||
}
|
||||
// Check leading zeros don't hit any buffer-too-big problems:
|
||||
QTest::newRow("many-0 max dec")
|
||||
<< (QByteArray(512, '0') + QByteArray::number(ULL::max())) << 10 << ULL::max() << true;
|
||||
|
||||
// Special bases (and let's include some leading space, too !), first decimal:
|
||||
QTest::newRow("max dec, base 0") << QByteArray::number(ULL::max()) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max space dec")
|
||||
<< ("\t\r\n\f\v " + QByteArray::number(ULL::max())) << 10 << ULL::max() << true;
|
||||
QTest::newRow("max space dec, base 0")
|
||||
<< ("\t\r\n\f\v " + QByteArray::number(ULL::max())) << 0 << ULL::max() << true;
|
||||
|
||||
// Hex with prefix:
|
||||
QTest::newRow("max 0x base 0")
|
||||
<< ("0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max +0x base 0")
|
||||
<< ("+0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max space 0x base 0")
|
||||
<< ("\t\r\n\f\v 0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max space +0x base 0")
|
||||
<< ("\t\r\n\f\v +0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
|
||||
|
||||
// Octal with prefix:
|
||||
QTest::newRow("max octal base 0")
|
||||
<< ('0' + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max +octal base 0")
|
||||
<< ("+0" + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max space octal base 0")
|
||||
<< ("\t\r\n\f\v 0" + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
|
||||
QTest::newRow("max space +octal base 0")
|
||||
<< ("\t\r\n\f\v +0" + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
|
||||
|
||||
// Values *just* out of range:
|
||||
QTest::newRow("max + 1 dec") << decNext(QByteArray::number(ULL::max())) << 10 << 0ULL << false;
|
||||
QTest::newRow("max + 1 dec base 0")
|
||||
<< decNext(QByteArray::number(ULL::max())) << 0 << 0ULL << false;
|
||||
auto big = QByteArray::number(ULL::max(), 8).replace('7', '0');
|
||||
// Number of bits is a power of two, so not a multiple of three; so (only)
|
||||
// first digit of max wasn't 7:
|
||||
big[0] += 1;
|
||||
QTest::newRow("max + 1 oct") << big << 8 << 0ULL << false;
|
||||
// Number of bits is a multiple of four, so every digit of max is 'f'.
|
||||
big = '1' + QByteArray::number(ULL::max(), 16).replace('f', '0');
|
||||
QTest::newRow("max + 1 hex") << big << 16 << 0ULL << false;
|
||||
}
|
||||
|
||||
void tst_QByteArray::toULongLong()
|
||||
|
@ -1319,6 +1319,9 @@ void tst_QLocale::long_long_conversion_data()
|
||||
QTest::newRow("C 12345,67") << QString("C") << "12345,67" << false << (qlonglong) 0;
|
||||
QTest::newRow("C 123456,7") << QString("C") << "123456,7" << false << (qlonglong) 0;
|
||||
QTest::newRow("C 1,234,567") << QString("C") << "1,234,567" << true << (qlonglong) 1234567;
|
||||
using LL = std::numeric_limits<qlonglong>;
|
||||
QTest::newRow("C LLONG_MIN") << QString("C") << QString::number(LL::min()) << true << LL::min();
|
||||
QTest::newRow("C LLONG_MAX") << QString("C") << QString::number(LL::max()) << true << LL::max();
|
||||
|
||||
QTest::newRow("de_DE 1") << QString("de_DE") << "1" << true << (qlonglong) 1;
|
||||
QTest::newRow("de_DE 1.") << QString("de_DE") << "1." << false << (qlonglong) 0;
|
||||
|
@ -3897,7 +3897,7 @@ void tst_QString::toLong()
|
||||
void tst_QString::toULongLong()
|
||||
{
|
||||
QString str;
|
||||
bool ok;
|
||||
bool ok = true;
|
||||
|
||||
QCOMPARE(str.toULongLong(), Q_UINT64_C(0));
|
||||
QCOMPARE(str.toULongLong(&ok), Q_UINT64_C(0));
|
||||
@ -3917,6 +3917,15 @@ void tst_QString::toULongLong()
|
||||
QCOMPARE( str.toULongLong( 0 ), Q_UINT64_C(0) );
|
||||
QCOMPARE( str.toULongLong( &ok ), Q_UINT64_C(0) );
|
||||
QVERIFY( !ok );
|
||||
|
||||
// Check limits round-trip in every base:
|
||||
using ULL = std::numeric_limits<qulonglong>;
|
||||
for (int b = 0; b <= 36; ++b) {
|
||||
if (b == 1) // 0 and 2 through 36 are valid bases
|
||||
++b;
|
||||
QCOMPARE(QString::number(ULL::max(), b ? b : 10).toULongLong(&ok, b), ULL::max());
|
||||
QVERIFY(ok);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QString::toLongLong()
|
||||
@ -3969,6 +3978,71 @@ void tst_QString::toLongLong()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check bounds.
|
||||
// First in every base, with no prefix:
|
||||
using LL = std::numeric_limits<qlonglong>;
|
||||
for (int b = 0; b <= 36; ++b) {
|
||||
if (b == 1) // 0 and 2 through 36 are valid bases
|
||||
++b;
|
||||
QCOMPARE(QString::number(LL::max(), b ? b : 10).toLongLong(&ok, b), LL::max());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(QString::number(LL::min(), b ? b : 10).toLongLong(&ok, b), LL::min());
|
||||
QVERIFY(ok);
|
||||
}
|
||||
|
||||
// Then in base 16 or 0 with 0x prefix:
|
||||
auto big = QString::number(LL::min(), 16);
|
||||
big.insert(1, u"0x"); // after the minus sign
|
||||
big.prepend(u"\t\r\n\f\v ");
|
||||
QCOMPARE(big.toLongLong(&ok, 16), LL::min());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::min());
|
||||
QVERIFY(ok);
|
||||
big = QString::number(LL::max(), 16);
|
||||
big.prepend(u"\t\r\n\f\v 0x");
|
||||
QCOMPARE(big.toLongLong(&ok, 16), LL::max());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::max());
|
||||
QVERIFY(ok);
|
||||
big.insert(6, u'+');
|
||||
QCOMPARE(big.toLongLong(&ok, 16), LL::max());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::max());
|
||||
QVERIFY(ok);
|
||||
|
||||
// Next octal:
|
||||
big = QString::number(LL::min(), 8);
|
||||
big.insert(1, u'0'); // after the minus sign
|
||||
big.prepend(u"\t\r\n\f\v ");
|
||||
QCOMPARE(big.toLongLong(&ok, 8), LL::min());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::min());
|
||||
QVERIFY(ok);
|
||||
big = QString::number(LL::max(), 8);
|
||||
big.prepend(u"\t\r\n\f\v 0");
|
||||
QCOMPARE(big.toLongLong(&ok, 8), LL::max());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::max());
|
||||
QVERIFY(ok);
|
||||
big.insert(6, u'+');
|
||||
QCOMPARE(big.toLongLong(&ok, 8), LL::max());
|
||||
QVERIFY(ok);
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::max());
|
||||
QVERIFY(ok);
|
||||
|
||||
// Finally decimal for base 0:
|
||||
big = QString::number(LL::min(), 10);
|
||||
big.prepend(u"\t\r\n\f\v ");
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::min());
|
||||
QVERIFY(ok);
|
||||
big = QString::number(LL::max(), 10);
|
||||
big.prepend(u"\t\r\n\f\v ");
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::max());
|
||||
QVERIFY(ok);
|
||||
big.insert(6, u'+');
|
||||
QCOMPARE(big.toLongLong(&ok, 0), LL::max());
|
||||
QVERIFY(ok);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user