QtMiscUtils: add some more character helpers

isHexDigit, isOctalDigit, isAsciiDigit, isAsciiLower, isAsciiUpper,
isAsciiLetterOrNumber.

This de-duplicates some code through out.

Rename two local lambdas that were called "isAsciiLetterOrNumber" to not
conflict with the method in QtMiscUtils.

Change-Id: I5b631f95b9f109136d19515f7e20b8e2fbca3d43
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 498f3452285aa44580e1d03baeec126d475f8401)
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Ahmad Samir 2023-01-17 20:54:52 +02:00 committed by Friedemann Kleint
parent 19db73bd8b
commit 967609ad49
19 changed files with 141 additions and 130 deletions

View File

@ -66,6 +66,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
struct QConfFileCustomFormat struct QConfFileCustomFormat
{ {
@ -515,8 +516,7 @@ void QSettingsPrivate::iniEscapedKey(const QString &key, QByteArray &result)
if (ch == '/') { if (ch == '/') {
result += '\\'; result += '\\';
} else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') } else if (isAsciiLetterOrNumber(ch) || ch == '_' || ch == '-' || ch == '.') {
|| ch == '_' || ch == '-' || ch == '.') {
result += (char)ch; result += (char)ch;
} else if (ch <= 0xFF) { } else if (ch <= 0xFF) {
result += '%'; result += '%';
@ -608,10 +608,7 @@ void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result)
if (ch == ';' || ch == ',' || ch == '=') if (ch == ';' || ch == ',' || ch == '=')
needsQuotes = true; needsQuotes = true;
if (escapeNextIfDigit if (escapeNextIfDigit && isHexDigit(ch)) {
&& ((ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= 'f')
|| (ch >= 'A' && ch <= 'F'))) {
result += "\\x" + QByteArray::number(ch, 16); result += "\\x" + QByteArray::number(ch, 16);
continue; continue;
} }
@ -754,9 +751,9 @@ StNormal:
goto end; goto end;
ch = str.at(i); ch = str.at(i);
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) if (isHexDigit(ch))
goto StHexEscape; goto StHexEscape;
} else if (ch >= '0' && ch <= '7') { } else if (isOctalDigit(ch)) {
escapeVal = ch - '0'; escapeVal = ch - '0';
goto StOctEscape; goto StOctEscape;
} else if (ch == '\n' || ch == '\r') { } else if (ch == '\n' || ch == '\r') {

View File

@ -402,10 +402,12 @@
#include "private/qipaddress_p.h" #include "private/qipaddress_p.h"
#include "qurlquery.h" #include "qurlquery.h"
#include "private/qdir_p.h" #include "private/qdir_p.h"
#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
// in qstring.cpp: // in qstring.cpp:
void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept; void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept;
@ -413,7 +415,7 @@ void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept;
inline static bool isHex(char c) inline static bool isHex(char c)
{ {
c |= 0x20; c |= 0x20;
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); return isAsciiDigit(c) || (c >= 'a' && c <= 'f');
} }
static inline QString ftpScheme() static inline QString ftpScheme()
@ -964,14 +966,14 @@ inline bool QUrlPrivate::setScheme(const QString &value, qsizetype len, bool doS
qsizetype needsLowercasing = -1; qsizetype needsLowercasing = -1;
const ushort *p = reinterpret_cast<const ushort *>(value.data()); const ushort *p = reinterpret_cast<const ushort *>(value.data());
for (qsizetype i = 0; i < len; ++i) { for (qsizetype i = 0; i < len; ++i) {
if (p[i] >= 'a' && p[i] <= 'z') if (isAsciiLower(p[i]))
continue; continue;
if (p[i] >= 'A' && p[i] <= 'Z') { if (isAsciiUpper(p[i])) {
needsLowercasing = i; needsLowercasing = i;
continue; continue;
} }
if (i) { if (i) {
if (p[i] >= '0' && p[i] <= '9') if (isAsciiDigit(p[i]))
continue; continue;
if (p[i] == '+' || p[i] == '-' || p[i] == '.') if (p[i] == '+' || p[i] == '-' || p[i] == '.')
continue; continue;
@ -992,7 +994,7 @@ inline bool QUrlPrivate::setScheme(const QString &value, qsizetype len, bool doS
QChar *schemeData = scheme.data(); // force detaching here QChar *schemeData = scheme.data(); // force detaching here
for (qsizetype i = needsLowercasing; i >= 0; --i) { for (qsizetype i = needsLowercasing; i >= 0; --i) {
ushort c = schemeData[i].unicode(); ushort c = schemeData[i].unicode();
if (c >= 'A' && c <= 'Z') if (isAsciiUpper(c))
schemeData[i] = QChar(c + 0x20); schemeData[i] = QChar(c + 0x20);
} }
} }
@ -1044,7 +1046,7 @@ inline void QUrlPrivate::setAuthority(const QString &auth, qsizetype from, qsize
unsigned long x = 0; unsigned long x = 0;
for (qsizetype i = colonIndex + 1; i < end; ++i) { for (qsizetype i = colonIndex + 1; i < end; ++i) {
ushort c = auth.at(i).unicode(); ushort c = auth.at(i).unicode();
if (c >= '0' && c <= '9') { if (isAsciiDigit(c)) {
x *= 10; x *= 10;
x += c - '0'; x += c - '0';
} else { } else {
@ -1186,9 +1188,7 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
const QChar *const origBegin = begin; const QChar *const origBegin = begin;
if (begin[3].unicode() != '.') if (begin[3].unicode() != '.')
return &begin[3]; return &begin[3];
if ((begin[2].unicode() >= 'A' && begin[2].unicode() <= 'F') || if (isHexDigit(begin[2].unicode())) {
(begin[2].unicode() >= 'a' && begin[2].unicode() <= 'f') ||
(begin[2].unicode() >= '0' && begin[2].unicode() <= '9')) {
// this is so unlikely that we'll just go down the slow path // this is so unlikely that we'll just go down the slow path
// decode the whole string, skipping the "[vH." and "]" which we already know to be there // decode the whole string, skipping the "[vH." and "]" which we already know to be there
host += QStringView(begin, 4); host += QStringView(begin, 4);
@ -1207,11 +1207,7 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
} }
for ( ; begin != end; ++begin) { for ( ; begin != end; ++begin) {
if (begin->unicode() >= 'A' && begin->unicode() <= 'Z') if (isAsciiLetterOrNumber(begin->unicode()))
host += *begin;
else if (begin->unicode() >= 'a' && begin->unicode() <= 'z')
host += *begin;
else if (begin->unicode() >= '0' && begin->unicode() <= '9')
host += *begin; host += *begin;
else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != nullptr) else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != nullptr)
host += *begin; host += *begin;

View File

@ -23,11 +23,14 @@
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
#include <private/qobject_p.h> // For QObjectPrivate::Connection #include <private/qobject_p.h> // For QObjectPrivate::Connection
#endif #endif
#include <private/qtools_p.h>
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
// ### TODO - QTBUG-87869: wrap in a proper Q_NAMESPACE and use scoped enums, to avoid name clashes // ### TODO - QTBUG-87869: wrap in a proper Q_NAMESPACE and use scoped enums, to avoid name clashes
using namespace QtMiscUtils;
enum PropertyFlags { enum PropertyFlags {
Invalid = 0x00000000, Invalid = 0x00000000,
Readable = 0x00000001, Readable = 0x00000001,
@ -265,11 +268,7 @@ enum { MetaObjectPrivateFieldCount = sizeof(QMetaObjectPrivate) / sizeof(int) };
// mirrored in moc's utils.h // mirrored in moc's utils.h
static inline bool is_ident_char(char s) static inline bool is_ident_char(char s)
{ {
return ((s >= 'a' && s <= 'z') return isAsciiLetterOrNumber(s) || s == '_';
|| (s >= 'A' && s <= 'Z')
|| (s >= '0' && s <= '9')
|| s == '_'
);
} }
static inline bool is_space(char s) static inline bool is_space(char s)

View File

@ -13,10 +13,12 @@
#include <qendian.h> #include <qendian.h>
#include <private/qoffsetstringarray_p.h> #include <private/qoffsetstringarray_p.h>
#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
// in the same order as Type! // in the same order as Type!
static constexpr auto magicRuleTypes = qOffsetStringArray( static constexpr auto magicRuleTypes = qOffsetStringArray(
@ -156,11 +158,11 @@ static inline QByteArray makePattern(const QByteArray &value)
continue; continue;
} }
*data++ = c; *data++ = c;
} else if (*p >= '0' && *p <= '7') { // oct (\\7, or \\77, or \\377) } else if (isOctalDigit(*p)) { // oct (\\7, or \\77, or \\377)
char c = *p - '0'; char c = *p - '0';
if (p + 1 < e && p[1] >= '0' && p[1] <= '7') { if (p + 1 < e && isOctalDigit(p[1])) {
c = (c << 3) + *(++p) - '0'; c = (c << 3) + *(++p) - '0';
if (p + 1 < e && p[1] >= '0' && p[1] <= '7' && p[-1] <= '3') if (p + 1 < e && isOctalDigit(p[1]) && p[-1] <= '3')
c = (c << 3) + *(++p) - '0'; c = (c << 3) + *(++p) - '0';
} }
*data++ = c; *data++ = c;

View File

@ -11,6 +11,7 @@
#include "private/qstringconverter_p.h" #include "private/qstringconverter_p.h"
#include "private/qcborvalue_p.h" #include "private/qcborvalue_p.h"
#include "private/qnumeric_p.h" #include "private/qnumeric_p.h"
#include <private/qtools_p.h>
//#define PARSER_DEBUG //#define PARSER_DEBUG
#ifdef PARSER_DEBUG #ifdef PARSER_DEBUG
@ -28,6 +29,8 @@ static const int nestingLimit = 1024;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
// error strings for the JSON parser // error strings for the JSON parser
#define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred") #define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred")
#define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object") #define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object")
@ -693,14 +696,14 @@ bool Parser::parseNumber()
if (json < end && *json == '0') { if (json < end && *json == '0') {
++json; ++json;
} else { } else {
while (json < end && *json >= '0' && *json <= '9') while (json < end && isAsciiDigit(*json))
++json; ++json;
} }
// frac = decimal-point 1*DIGIT // frac = decimal-point 1*DIGIT
if (json < end && *json == '.') { if (json < end && *json == '.') {
++json; ++json;
while (json < end && *json >= '0' && *json <= '9') { while (json < end && isAsciiDigit(*json)) {
isInt = isInt && *json == '0'; isInt = isInt && *json == '0';
++json; ++json;
} }
@ -712,7 +715,7 @@ bool Parser::parseNumber()
++json; ++json;
if (json < end && (*json == '-' || *json == '+')) if (json < end && (*json == '-' || *json == '+'))
++json; ++json;
while (json < end && *json >= '0' && *json <= '9') while (json < end && isAsciiDigit(*json))
++json; ++json;
} }

View File

@ -196,6 +196,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
#include "qnumeric.h" #include "qnumeric.h"
#include "qvarlengtharray.h" #include "qvarlengtharray.h"
#include <private/qdebug_p.h> #include <private/qdebug_p.h>
#include <private/qtools_p.h>
#include <locale.h> #include <locale.h>
#include "private/qlocale_p.h" #include "private/qlocale_p.h"
@ -245,6 +246,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
//------------------------------------------------------------------- //-------------------------------------------------------------------
@ -1686,7 +1688,7 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
int ndigits = 0; int ndigits = 0;
while (getChar(&dig)) { while (getChar(&dig)) {
int n = dig.toLower().unicode(); int n = dig.toLower().unicode();
if (n >= '0' && n <= '7') { if (isOctalDigit(n)) {
val *= 8; val *= 8;
val += n - '0'; val += n - '0';
} else { } else {

View File

@ -16,6 +16,7 @@
#include <qcoreapplication.h> #include <qcoreapplication.h>
#include <private/qoffsetstringarray_p.h> #include <private/qoffsetstringarray_p.h>
#include <private/qtools_p.h>
#include <iterator> #include <iterator>
#include "qxmlstream_p.h" #include "qxmlstream_p.h"
@ -26,6 +27,7 @@ QT_BEGIN_NAMESPACE
using namespace QtPrivate; using namespace QtPrivate;
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
enum { StreamEOF = ~0U }; enum { StreamEOF = ~0U };
@ -1731,9 +1733,7 @@ void QXmlStreamReaderPrivate::checkPublicLiteral(QStringView publicId)
case '$': case '_': case '%': case '\'': case '\"': case '$': case '_': case '%': case '\'': case '\"':
continue; continue;
default: default:
if ((c >= 'a' && c <= 'z') if (isAsciiLetterOrNumber(c))
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9'))
continue; continue;
} }
break; break;

View File

@ -5,8 +5,12 @@
#include "qxmlutils_p.h" #include "qxmlutils_p.h"
#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
/* TODO: /* TODO:
* - isNameChar() doesn't have to be public, it's only needed in * - isNameChar() doesn't have to be public, it's only needed in
* qdom.cpp -- refactor fixedXmlName() to use isNCName() * qdom.cpp -- refactor fixedXmlName() to use isNCName()
@ -197,16 +201,12 @@ bool QXmlUtils::isEncName(QStringView encName)
if (encName.isEmpty()) if (encName.isEmpty())
return false; return false;
const auto first = encName.front().unicode(); const auto first = encName.front().unicode();
if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z'))) if (!(isAsciiLower(first) || isAsciiUpper(first)))
return false; return false;
for (QChar ch : encName.mid(1)) { for (QChar ch : encName.mid(1)) {
const auto cp = ch.unicode(); const auto cp = ch.unicode();
if ((cp >= 'a' && cp <= 'z') if (isAsciiLetterOrNumber(cp) || cp == '.' || cp == '_' || cp == '-')
|| (cp >= 'A' && cp <= 'Z')
|| (cp >= '0' && cp <= '9')
|| cp == '.' || cp == '_' || cp == '-') {
continue; continue;
}
return false; return false;
} }
return true; return true;
@ -285,12 +285,8 @@ bool QXmlUtils::isPublicID(QStringView candidate)
for (QChar ch : candidate) { for (QChar ch : candidate) {
const ushort cp = ch.unicode(); const ushort cp = ch.unicode();
if ((cp >= 'a' && cp <= 'z') if (isAsciiLetterOrNumber(cp))
|| (cp >= 'A' && cp <= 'Z')
|| (cp >= '0' && cp <= '9'))
{
continue; continue;
}
switch (cp) switch (cp)
{ {

View File

@ -22,6 +22,7 @@ QT_WARNING_DISABLE_GCC("-Wfree-nonheap-object") // false positive tracking
#include "qlocale.h" #include "qlocale.h"
#include "qlocale_p.h" #include "qlocale_p.h"
#include "qlocale_tools_p.h" #include "qlocale_tools_p.h"
#include <private/qtools_p.h>
#if QT_CONFIG(datetimeparser) #if QT_CONFIG(datetimeparser)
#include "private/qdatetimeparser_p.h" #include "private/qdatetimeparser_p.h"
#endif #endif
@ -60,6 +61,7 @@ QT_IMPL_METATYPE_EXTERN_TAGGED(QSystemLocale::CurrencyToStringArgument,
#endif #endif
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
#ifndef QT_NO_SYSTEMLOCALE #ifndef QT_NO_SYSTEMLOCALE
Q_CONSTINIT static QSystemLocale *_systemLocale = nullptr; Q_CONSTINIT static QSystemLocale *_systemLocale = nullptr;
@ -542,7 +544,7 @@ static bool validTag(QStringView tag)
// Is tag is a non-empty sequence of ASCII letters and/or digits ? // Is tag is a non-empty sequence of ASCII letters and/or digits ?
for (QChar uc : tag) { for (QChar uc : tag) {
const char16_t ch = uc.unicode(); const char16_t ch = uc.unicode();
if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))) if (!isAsciiLetterOrNumber(ch))
return false; return false;
} }
return tag.size() > 0; return tag.size() > 0;
@ -2603,11 +2605,6 @@ QString QLocale::exponential() const
return d->m_data->exponentSeparator(); return d->m_data->exponentSeparator();
} }
static bool qIsUpper(char c)
{
return c >= 'A' && c <= 'Z';
}
/*! /*!
\overload \overload
Returns a string representing the floating-point number \a f. Returns a string representing the floating-point number \a f.
@ -2645,7 +2642,7 @@ static bool qIsUpper(char c)
QString QLocale::toString(double f, char format, int precision) const QString QLocale::toString(double f, char format, int precision) const
{ {
QLocaleData::DoubleForm form = QLocaleData::DFDecimal; QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
uint flags = qIsUpper(format) ? QLocaleData::CapitalEorX : 0; uint flags = isAsciiUpper(format) ? QLocaleData::CapitalEorX : 0;
switch (QtMiscUtils::toAsciiLower(format)) { switch (QtMiscUtils::toAsciiLower(format)) {
case 'f': case 'f':
@ -4023,7 +4020,7 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
const QStringView in = str.mid(i, str.at(i).isHighSurrogate() ? 2 : 1); const QStringView in = str.mid(i, str.at(i).isHighSurrogate() ? 2 : 1);
char c = numericToCLocale(in); char c = numericToCLocale(in);
if (c >= '0' && c <= '9') { if (isAsciiDigit(c)) {
switch (state) { switch (state) {
case Whole: case Whole:
// Nothing special to do (unless we want to check grouping sizes). // Nothing special to do (unless we want to check grouping sizes).

View File

@ -7,6 +7,7 @@
#include "qlocale_p.h" #include "qlocale_p.h"
#include "qstring.h" #include "qstring.h"
#include <private/qtools_p.h>
#include <private/qnumeric_p.h> #include <private/qnumeric_p.h>
#include <ctype.h> #include <ctype.h>
@ -37,6 +38,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
QT_CLOCALE_HOLDER QT_CLOCALE_HOLDER
void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
@ -371,7 +374,7 @@ static auto scanPrefix(const char *p, const char *stop, int base)
const char *next; const char *next;
int base; int base;
}; };
if (p < stop && *p >= '0' && *p <= '9') { if (p < stop && isAsciiDigit(*p)) {
if (*p == '0') { if (*p == '0') {
const char *x_or_b = p + 1; const char *x_or_b = p + 1;
if (x_or_b < stop) { if (x_or_b < stop) {

View File

@ -74,6 +74,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
const char16_t QString::_empty = 0; const char16_t QString::_empty = 0;
@ -86,16 +87,6 @@ enum StringComparisonMode {
CompareStringsForOrdering CompareStringsForOrdering
}; };
inline bool qIsUpper(char ch)
{
return ch >= 'A' && ch <= 'Z';
}
inline bool qIsDigit(char ch)
{
return ch >= '0' && ch <= '9';
}
template <typename Pointer> template <typename Pointer>
char32_t foldCaseHelper(Pointer ch, Pointer start) = delete; char32_t foldCaseHelper(Pointer ch, Pointer start) = delete;
@ -1350,13 +1341,6 @@ static int ucstrncmp(const char16_t *a, const char *b, size_t l)
return 0; return 0;
} }
constexpr int lencmp(qsizetype lhs, qsizetype rhs) noexcept
{
return lhs == rhs ? 0 :
lhs > rhs ? 1 :
/* else */ -1 ;
}
// Unicode case-sensitive equality // Unicode case-sensitive equality
template <typename Char2> template <typename Char2>
static bool ucstreq(const char16_t *a, size_t alen, const Char2 *b, size_t blen) static bool ucstreq(const char16_t *a, size_t alen, const Char2 *b, size_t blen)
@ -1380,7 +1364,7 @@ static int ucstrcmp(const char16_t *a, size_t alen, const Char2 *b, size_t blen)
} }
const size_t l = qMin(alen, blen); const size_t l = qMin(alen, blen);
int cmp = ucstrncmp<CompareStringsForOrdering>(a, b, l); int cmp = ucstrncmp<CompareStringsForOrdering>(a, b, l);
return cmp ? cmp : lencmp(alen, blen); return cmp ? cmp : qt_lencmp(alen, blen);
} }
static constexpr uchar latin1Lower[256] = { static constexpr uchar latin1Lower[256] = {
@ -1419,7 +1403,7 @@ static int latin1nicmp(const char *lhsChar, qsizetype lSize, const char *rhsChar
if (int res = latin1Lower[lhs[i]] - latin1Lower[rhs[i]]) if (int res = latin1Lower[lhs[i]] - latin1Lower[rhs[i]])
return res; return res;
} }
return lencmp(lSize, rSize); return qt_lencmp(lSize, rSize);
} }
bool QtPrivate::equalStrings(QStringView lhs, QStringView rhs) noexcept bool QtPrivate::equalStrings(QStringView lhs, QStringView rhs) noexcept
@ -1564,12 +1548,12 @@ int QtPrivate::compareStrings(QLatin1StringView lhs, QStringView rhs, Qt::CaseSe
int QtPrivate::compareStrings(QLatin1StringView lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs) noexcept int QtPrivate::compareStrings(QLatin1StringView lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs) noexcept
{ {
if (lhs.isEmpty()) if (lhs.isEmpty())
return lencmp(qsizetype(0), rhs.size()); return qt_lencmp(qsizetype(0), rhs.size());
if (cs == Qt::CaseInsensitive) if (cs == Qt::CaseInsensitive)
return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size()); return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
const auto l = std::min(lhs.size(), rhs.size()); const auto l = std::min(lhs.size(), rhs.size());
int r = memcmp(lhs.data(), rhs.data(), l); int r = memcmp(lhs.data(), rhs.data(), l);
return r ? r : lencmp(lhs.size(), rhs.size()); return r ? r : qt_lencmp(lhs.size(), rhs.size());
} }
/*! /*!
@ -6881,7 +6865,7 @@ static uint parse_flag_characters(const char * &c) noexcept
static int parse_field_width(const char *&c, qsizetype size) static int parse_field_width(const char *&c, qsizetype size)
{ {
Q_ASSERT(qIsDigit(*c)); Q_ASSERT(isAsciiDigit(*c));
const char *const stop = c + size; const char *const stop = c + size;
// can't be negative - started with a digit // can't be negative - started with a digit
@ -6891,7 +6875,7 @@ static int parse_field_width(const char *&c, qsizetype size)
if (used <= 0) if (used <= 0)
return false; return false;
// preserve Qt 5.5 behavior of consuming all digits, no matter how many // preserve Qt 5.5 behavior of consuming all digits, no matter how many
while (c < stop && qIsDigit(*c)) while (c < stop && isAsciiDigit(*c))
++c; ++c;
return result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0; return result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0;
} }
@ -6981,7 +6965,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
// Parse field width // Parse field width
int width = -1; // -1 means unspecified int width = -1; // -1 means unspecified
if (qIsDigit(*c)) { if (isAsciiDigit(*c)) {
width = parse_field_width(c, formatEnd - c); width = parse_field_width(c, formatEnd - c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least } else if (*c == '*') { // can't parse this in another function, not portably, at least
width = va_arg(ap, int); width = va_arg(ap, int);
@ -7000,7 +6984,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
if (*c == '.') { if (*c == '.') {
++c; ++c;
precision = 0; precision = 0;
if (qIsDigit(*c)) { if (isAsciiDigit(*c)) {
precision = parse_field_width(c, formatEnd - c); precision = parse_field_width(c, formatEnd - c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least } else if (*c == '*') { // can't parse this in another function, not portably, at least
precision = va_arg(ap, int); precision = va_arg(ap, int);
@ -7061,7 +7045,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
default: u = 0; break; default: u = 0; break;
} }
if (qIsUpper(*c)) if (isAsciiUpper(*c))
flags |= QLocaleData::CapitalEorX; flags |= QLocaleData::CapitalEorX;
int base = 10; int base = 10;
@ -7092,7 +7076,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
else else
d = va_arg(ap, double); d = va_arg(ap, double);
if (qIsUpper(*c)) if (isAsciiUpper(*c))
flags |= QLocaleData::CapitalEorX; flags |= QLocaleData::CapitalEorX;
QLocaleData::DoubleForm form = QLocaleData::DFDecimal; QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
@ -7738,7 +7722,7 @@ QString QString::number(double n, char format, int precision)
break; break;
} }
return qdtoBasicLatin(n, form, precision, qIsUpper(format)); return qdtoBasicLatin(n, form, precision, isAsciiUpper(format));
} }
namespace { namespace {
@ -8605,7 +8589,7 @@ QString QString::arg(double a, int fieldWidth, char format, int precision, QChar
if (fillChar == u'0') if (fillChar == u'0')
flags |= QLocaleData::ZeroPadded; flags |= QLocaleData::ZeroPadded;
if (qIsUpper(format)) if (isAsciiUpper(format))
flags |= QLocaleData::CapitalEorX; flags |= QLocaleData::CapitalEorX;
QLocaleData::DoubleForm form = QLocaleData::DFDecimal; QLocaleData::DoubleForm form = QLocaleData::DFDecimal;

View File

@ -31,6 +31,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
static_assert(std::is_nothrow_move_constructible_v<QStringEncoder>); static_assert(std::is_nothrow_move_constructible_v<QStringEncoder>);
static_assert(std::is_nothrow_move_assignable_v<QStringEncoder>); static_assert(std::is_nothrow_move_assignable_v<QStringEncoder>);
static_assert(std::is_nothrow_move_constructible_v<QStringDecoder>); static_assert(std::is_nothrow_move_constructible_v<QStringDecoder>);
@ -890,22 +892,15 @@ int QUtf8::compareUtf8(QByteArrayView utf8, QLatin1StringView s, Qt::CaseSensiti
return (end1 > src1) - (end2 > src2); return (end1 > src1) - (end2 > src2);
} }
static inline int lencmp(qsizetype lhs, qsizetype rhs) noexcept
{
return lhs == rhs ? 0 :
lhs > rhs ? 1 :
/* else */ -1 ;
}
int QUtf8::compareUtf8(QByteArrayView lhs, QByteArrayView rhs, Qt::CaseSensitivity cs) noexcept int QUtf8::compareUtf8(QByteArrayView lhs, QByteArrayView rhs, Qt::CaseSensitivity cs) noexcept
{ {
if (lhs.isEmpty()) if (lhs.isEmpty())
return lencmp(0, rhs.size()); return qt_lencmp(0, rhs.size());
if (cs == Qt::CaseSensitive) { if (cs == Qt::CaseSensitive) {
const auto l = std::min(lhs.size(), rhs.size()); const auto l = std::min(lhs.size(), rhs.size());
int r = memcmp(lhs.data(), rhs.data(), l); int r = memcmp(lhs.data(), rhs.data(), l);
return r ? r : lencmp(lhs.size(), rhs.size()); return r ? r : qt_lencmp(lhs.size(), rhs.size());
} }
char32_t uc1 = QChar::Null; char32_t uc1 = QChar::Null;

View File

@ -8,6 +8,7 @@
#include "qtimezoneprivate_data_p.h" #include "qtimezoneprivate_data_p.h"
#include <private/qnumeric_p.h> #include <private/qnumeric_p.h>
#include <private/qtools_p.h>
#include <qdatastream.h> #include <qdatastream.h>
#include <qdebug.h> #include <qdebug.h>
@ -15,6 +16,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
/* /*
Static utilities for looking up Windows ID tables Static utilities for looking up Windows ID tables
*/ */
@ -597,12 +600,12 @@ bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
} else if (ch == '-') { } else if (ch == '-') {
if (sectionLength == 0) if (sectionLength == 0)
return false; // violates (4) return false; // violates (4)
} else if (!(ch >= 'a' && ch <= 'z') } else if (!isAsciiLower(ch)
&& !(ch >= 'A' && ch <= 'Z') && !isAsciiUpper(ch)
&& !(ch == '_') && !(ch == '_')
&& !(ch == '.') && !(ch == '.')
// Should ideally check these only happen as an offset: // Should ideally check these only happen as an offset:
&& !(ch >= '0' && ch <= '9') && !isAsciiDigit(ch)
&& !(ch == '+') && !(ch == '+')
&& !(ch == ':')) { && !(ch == ':')) {
return false; // violates (2) return false; // violates (2)

View File

@ -31,6 +31,13 @@ constexpr inline char toHexLower(uint value) noexcept
return "0123456789abcdef"[value & 0xF]; return "0123456789abcdef"[value & 0xF];
} }
[[nodiscard]] constexpr inline int isHexDigit(char32_t c) noexcept
{
return (c >= '0' && c <= '9')
|| (c >= 'A' && c <= 'F')
|| (c >= 'a' && c <= 'f');
}
constexpr inline int fromHex(uint c) noexcept constexpr inline int fromHex(uint c) noexcept
{ {
return ((c >= '0') && (c <= '9')) ? int(c - '0') : return ((c >= '0') && (c <= '9')) ? int(c - '0') :
@ -44,19 +51,44 @@ constexpr inline char toOct(uint value) noexcept
return char('0' + (value & 0x7)); return char('0' + (value & 0x7));
} }
[[nodiscard]] constexpr inline int isOctalDigit(char32_t c) noexcept
{
return c >= '0' && c <= '7';
}
constexpr inline int fromOct(uint c) noexcept constexpr inline int fromOct(uint c) noexcept
{ {
return ((c >= '0') && (c <= '7')) ? int(c - '0') : -1; return isOctalDigit(c) ? int(c - '0') : -1;
}
[[nodiscard]] constexpr inline bool isAsciiDigit(char32_t c) noexcept
{
return c >= '0' && c <= '9';
}
constexpr inline bool isAsciiUpper(char32_t c) noexcept
{
return c >= 'A' && c <= 'Z';
}
constexpr inline bool isAsciiLower(char32_t c) noexcept
{
return c >= 'a' && c <= 'z';
}
constexpr inline bool isAsciiLetterOrNumber(char32_t c) noexcept
{
return isAsciiDigit(c) || isAsciiLower(c) || isAsciiUpper(c);
} }
constexpr inline char toAsciiLower(char ch) noexcept constexpr inline char toAsciiLower(char ch) noexcept
{ {
return (ch >= 'A' && ch <= 'Z') ? ch - 'A' + 'a' : ch; return isAsciiUpper(ch) ? ch - 'A' + 'a' : ch;
} }
constexpr inline char toAsciiUpper(char ch) noexcept constexpr inline char toAsciiUpper(char ch) noexcept
{ {
return (ch >= 'a' && ch <= 'z') ? ch - 'a' + 'A' : ch; return isAsciiLower(ch) ? ch - 'a' + 'A' : ch;
} }
constexpr inline int caseCompareAscii(char lhs, char rhs) noexcept constexpr inline int caseCompareAscii(char lhs, char rhs) noexcept
@ -66,7 +98,12 @@ constexpr inline int caseCompareAscii(char lhs, char rhs) noexcept
return int(uchar(lhsLower)) - int(uchar(rhsLower)); return int(uchar(lhsLower)) - int(uchar(rhsLower));
} }
constexpr inline int qt_lencmp(qsizetype lhs, qsizetype rhs) noexcept
{
return lhs == rhs ? 0 :
lhs > rhs ? 1 :
/* else */ -1 ;
}
} }
// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. // We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size.

View File

@ -7,6 +7,7 @@
#include <QtCore/qlist.h> #include <QtCore/qlist.h>
#include <QtCore/qstringlist.h> #include <QtCore/qstringlist.h>
#include <private/qtools_p.h>
#include "qdbusargument.h" #include "qdbusargument.h"
#include "qdbusunixfiledescriptor.h" #include "qdbusunixfiledescriptor.h"
@ -16,29 +17,24 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
static inline bool isValidCharacterNoDash(QChar c) static inline bool isValidCharacterNoDash(QChar c)
{ {
ushort u = c.unicode(); ushort u = c.unicode();
return (u >= 'a' && u <= 'z') return isAsciiLetterOrNumber(u) || (u == '_');
|| (u >= 'A' && u <= 'Z')
|| (u >= '0' && u <= '9')
|| (u == '_');
} }
static inline bool isValidCharacter(QChar c) static inline bool isValidCharacter(QChar c)
{ {
ushort u = c.unicode(); ushort u = c.unicode();
return (u >= 'a' && u <= 'z') return isAsciiLetterOrNumber(u)
|| (u >= 'A' && u <= 'Z')
|| (u >= '0' && u <= '9')
|| (u == '_') || (u == '-'); || (u == '_') || (u == '-');
} }
static inline bool isValidNumber(QChar c) static inline bool isValidNumber(QChar c)
{ {
ushort u = c.unicode(); return (isAsciiDigit(c.toLatin1()));
return (u >= '0' && u <= '9');
} }
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED

View File

@ -16,6 +16,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
Q_DECLARE_LOGGING_CATEGORY(lcImageIo) Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
/***************************************************************************** /*****************************************************************************
@ -54,11 +56,9 @@ static bool read_xbm_header(QIODevice *device, int& w, int& h)
} }
auto parseDefine = [] (const char *buf, int len) -> int { auto parseDefine = [] (const char *buf, int len) -> int {
auto isAsciiLetterOrNumber = [] (char ch) -> bool { auto checkChar = [] (char ch) -> bool {
return (ch >= '0' && ch <= '9') || return isAsciiLetterOrNumber(ch)
(ch >= 'A' && ch <= 'Z') || || ch == '_' || ch == '.';
(ch >= 'a' && ch <= 'z') ||
ch == '_' || ch == '.';
}; };
auto isAsciiSpace = [] (char ch) -> bool { auto isAsciiSpace = [] (char ch) -> bool {
return ch == ' ' || ch == '\t'; return ch == ' ' || ch == '\t';
@ -70,7 +70,7 @@ static bool read_xbm_header(QIODevice *device, int& w, int& h)
int index = defineLen; int index = defineLen;
while (buf[index] && isAsciiSpace(buf[index])) while (buf[index] && isAsciiSpace(buf[index]))
++index; ++index;
while (buf[index] && isAsciiLetterOrNumber(buf[index])) while (buf[index] && checkChar(buf[index]))
++index; ++index;
while (buf[index] && isAsciiSpace(buf[index])) while (buf[index] && isAsciiSpace(buf[index]))
++index; ++index;

View File

@ -15,12 +15,15 @@
#include <private/qcolor_p.h> #include <private/qcolor_p.h>
#include <private/qduplicatetracker_p.h> // for easier std::pmr detection #include <private/qduplicatetracker_p.h> // for easier std::pmr detection
#include <private/qtools_p.h>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
Q_DECLARE_LOGGING_CATEGORY(lcImageIo) Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
static quint64 xpmHash(const QString &str) static quint64 xpmHash(const QString &str)
@ -736,15 +739,13 @@ static QString fbname(const QString &fileName) // get file basename (sort of)
int i = qMax(s.lastIndexOf(u'/'), s.lastIndexOf(u'\\')); int i = qMax(s.lastIndexOf(u'/'), s.lastIndexOf(u'\\'));
if (i < 0) if (i < 0)
i = 0; i = 0;
auto isAsciiLetterOrNumber = [](QChar ch) -> bool { auto checkChar = [](QChar ch) -> bool {
return (ch.unicode() >= '0' && ch.unicode() <= '9') || uchar uc = ch.unicode();
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') || return isAsciiLetterOrNumber(uc) || uc == '_';
(ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
ch.unicode() == '_';
}; };
int start = -1; int start = -1;
for (; i < s.size(); ++i) { for (; i < s.size(); ++i) {
if (isAsciiLetterOrNumber(s.at(i))) { if (checkChar(s.at(i))) {
start = i; start = i;
} else if (start > 0) } else if (start > 0)
break; break;

View File

@ -21,6 +21,7 @@
#include "QtCore/qcoreapplication.h" #include "QtCore/qcoreapplication.h"
#include <QtCore/private/qthread_p.h> #include <QtCore/private/qthread_p.h>
#include <QtCore/private/qtools_p.h>
#include "qnetworkcookiejar.h" #include "qnetworkcookiejar.h"
#include "qnetconmonitor_p.h" #include "qnetconmonitor_p.h"
@ -32,6 +33,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
class QNetworkProxy; class QNetworkProxy;
@ -1720,8 +1722,8 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe
QByteArray v = q->rawHeader(header); QByteArray v = q->rawHeader(header);
if (v.size() == 3 if (v.size() == 3
&& v[0] == '1' && v[0] == '1'
&& v[1] >= '0' && v[1] <= '9' && isAsciiDigit(v[1])
&& v[2] >= '0' && v[2] <= '9') && isAsciiDigit(v[2]))
continue; continue;
} }

View File

@ -8,11 +8,14 @@
#include <QtCore/qdatetime.h> #include <QtCore/qdatetime.h>
#include <QtCore/qlist.h> #include <QtCore/qlist.h>
#include <QDebug> #include <QDebug>
#include <private/qtools_p.h>
#include <limits> #include <limits>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace QtMiscUtils;
typedef QMap<QByteArray, QByteArray> OidNameMap; typedef QMap<QByteArray, QByteArray> OidNameMap;
static OidNameMap createOidMap() static OidNameMap createOidMap()
{ {
@ -213,11 +216,6 @@ QDateTime QAsn1Element::toDateTime() const
// QDateTime::fromString is lenient and accepts +- signs in front // QDateTime::fromString is lenient and accepts +- signs in front
// of the year; but ASN.1 doesn't allow them. // of the year; but ASN.1 doesn't allow them.
const auto isAsciiDigit = [](char c)
{
return c >= '0' && c <= '9';
};
if (!isAsciiDigit(mValue[0])) if (!isAsciiDigit(mValue[0]))
return result; return result;