QtMiscUtils: add isAsciiPrintable() helper

- isAsciiPrintable: borrowed the logic from isPrintable(uchar) in
  qdebug.cpp, now isPrintable(uchar) calls isAsciiPrintable

- Replace ::isspace() with ascii_isspace() from qlocale_p.h

Functions from ctype.h have a couple of issues:
- they're locale-dependent, which isn't what's required here, the code
  is only interested in ASCII
- their args should be representable as uchar or EOF otherwise it's
  undefined behavior

An Early-Warning could use something like:
grep -rP "\b(isalnum|isalpha|isblank|iscntrl|isdigit|islower|isgraph|\
         "isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper)\b"

Pick-to: 6.5
Task-number: QTBUG-111262
Change-Id: I1f47f41bd56735297078ff0d0ddc2ebf999abf8b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2023-03-15 17:27:21 +02:00
parent d184c66ad5
commit f6b780b583
6 changed files with 26 additions and 24 deletions

View File

@ -14,13 +14,10 @@
#include "qmetaobject.h"
#include <private/qtextstream_p.h>
#include <private/qtools_p.h>
#include <ctype.h>
QT_BEGIN_NAMESPACE
using QtMiscUtils::toHexUpper;
using QtMiscUtils::toHexLower;
using QtMiscUtils::fromHex;
using namespace QtMiscUtils;
/*
Returns a human readable representation of the first \a maxSize
@ -35,7 +32,7 @@ QByteArray QtDebugUtils::toPrintable(const char *data, qint64 len, qsizetype max
QByteArray out;
for (qsizetype i = 0; i < qMin(len, maxSize); ++i) {
char c = data[i];
if (isprint(c)) {
if (isAsciiPrintable(c)) {
out += c;
} else {
switch (c) {
@ -198,7 +195,7 @@ void QDebug::putUcs4(uint ucs4)
static inline bool isPrintable(char32_t ucs4) { return QChar::isPrint(ucs4); }
static inline bool isPrintable(char16_t uc) { return QChar::isPrint(uc); }
static inline bool isPrintable(uchar c)
{ return c >= ' ' && c < 0x7f; }
{ return isAsciiPrintable(c); }
template <typename Char>
static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, size_t length, bool isUnicode = true)

View File

@ -10,16 +10,14 @@
#include "qstringlist.h"
#include "qdir.h"
#include "private/qbytearray_p.h"
#include "private/qtools_p.h"
#include <algorithm>
#ifdef QIODEVICE_DEBUG
# include <ctype.h>
#endif
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
[[maybe_unused]]
static void debugBinaryString(const char *input, qint64 maxlen)
@ -38,7 +36,7 @@ static void debugBinaryString(const char *input, qint64 maxlen)
for (qsizetype j = tmp.size(); j < 16 + 1; ++j)
printf(" ");
for (qsizetype j = 0; j < tmp.size(); ++j)
printf("%c", isprint(int(uchar(tmp[j]))) ? tmp[j] : '.');
printf("%c", isAsciiPrintable(tmp[j]) ? tmp[j] : '.');
tmp.clear();
}
}
@ -1011,7 +1009,7 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
*data = c;
#if defined QIODEVICE_DEBUG
printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this,
int(c), isprint(c) ? c : '?');
int(c), isAsciiPrintable(c) ? c : '?');
#endif
if (d->buffer.isEmpty())
readData(data, 0);
@ -1792,7 +1790,7 @@ void QIODevice::ungetChar(char c)
}
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::ungetChar(0x%hhx '%c')\n", this, c, isprint(c) ? c : '?');
printf("%p QIODevice::ungetChar(0x%hhx '%c')\n", this, c, isAsciiPrintable(c) ? c : '?');
#endif
d->buffer.ungetChar(c);

View File

@ -101,6 +101,11 @@ constexpr inline int caseCompareAscii(char lhs, char rhs) noexcept
return int(uchar(lhsLower)) - int(uchar(rhsLower));
}
constexpr inline int isAsciiPrintable(char32_t ch) noexcept
{
return ch >= ' ' && ch < 0x7f;
}
constexpr inline int qt_lencmp(qsizetype lhs, qsizetype rhs) noexcept
{
return lhs == rhs ? 0 :

View File

@ -11,8 +11,8 @@
#include <qloggingcategory.h>
#include <qrgba64.h>
#include <qvariant.h>
#include <ctype.h>
#include <private/qlocale_p.h>
#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
@ -41,7 +41,7 @@ static int read_pbm_int(QIODevice *d, bool *ok)
for (;;) {
if (!d->getChar(&c)) // end of file
break;
digit = isdigit((uchar) c);
digit = QtMiscUtils::isAsciiDigit(c);
if (val != -1) {
if (digit) {
const int cValue = c - '0';
@ -59,7 +59,7 @@ static int read_pbm_int(QIODevice *d, bool *ok)
}
if (digit) // first digit
val = c - '0';
else if (isspace((uchar) c))
else if (ascii_isspace(c))
continue;
else if (c == '#')
discard_pbm_line(d);
@ -77,7 +77,7 @@ static bool read_pbm_header(QIODevice *device, char& type, int& w, int& h, int&
if (device->read(buf, 3) != 3) // read P[1-6]<white-space>
return false;
if (!(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])))
if (!(buf[0] == 'P' && QtMiscUtils::isAsciiDigit(buf[1]) && ascii_isspace(buf[2])))
return false;
type = buf[1];

View File

@ -96,12 +96,14 @@
#include <qtgui_tracepoints_p.h>
#include <ctype.h>
#include <private/qtools_p.h>
#include <limits>
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
using namespace QtMiscUtils;
// Helper macro for static functions to check on the existence of the application class.
#define CHECK_QAPP_INSTANCE(...) \
@ -263,13 +265,13 @@ static inline int nextGeometryToken(const QByteArray &a, int &pos, char *op)
*op = a.at(pos);
if (*op == '+' || *op == '-' || *op == 'x')
pos++;
else if (isdigit(*op))
else if (isAsciiDigit(*op))
*op = 'x'; // If it starts with a digit, it is supposed to be a width specification.
else
return -1;
const int numberPos = pos;
for ( ; pos < size && isdigit(a.at(pos)); ++pos) ;
for ( ; pos < size && isAsciiDigit(a.at(pos)); ++pos) ;
bool ok;
const int result = a.mid(numberPos, pos - numberPos).toInt(&ok);

View File

@ -7,8 +7,8 @@
#include <QtTest/private/qtestlog_p.h>
#include <QtTest/private/qteamcitylogger_p.h>
#include <QtCore/qbytearray.h>
#include <private/qlocale_p.h>
#include <cctype>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
@ -235,7 +235,7 @@ void QTeamCityLogger::tcEscapedString(QTestCharBuffer *buf, const char *str) con
swallowSpace = false;
break;
default:
if (std::isspace(ch)) {
if (ascii_isspace(ch)) {
if (swallowSpace)
continue;
swallowSpace = true;
@ -252,7 +252,7 @@ void QTeamCityLogger::tcEscapedString(QTestCharBuffer *buf, const char *str) con
Q_ASSERT(p[-1] == ' ');
--p;
}
Q_ASSERT(p == buf->data() || !std::isspace(p[-1]));
Q_ASSERT(p == buf->data() || !ascii_isspace(p[-1]));
*p = '\0';
}