Do the same for qDebug of QByteArray and QLatin1String
QLatin1String are actually Unicode, so print them with \uXXXX sequences. QByteArray are binary (arbitrary), so print as hex. Since hex escape sequences in C are not limited in length (\x00000F is a valid hex sequence), we need to insert "" if the next character is a valid hex digit. [ChangeLog][QtCore][QDebug] Similarly, printing of QByteArrays whenever "noquote" is not active now prints the arrays in a format consumable in C++, with all non-printable characters printed in hex escape sequences. Change-Id: Ibd0c1a97cbac98610c65c1091bfbcf5581c835db Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
parent
2c01d402e1
commit
62b752b3a2
@ -46,6 +46,7 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using QtMiscUtils::toHexUpper;
|
using QtMiscUtils::toHexUpper;
|
||||||
|
using QtMiscUtils::fromHex;
|
||||||
|
|
||||||
// This file is needed to force compilation of QDebug into the kernel library.
|
// This file is needed to force compilation of QDebug into the kernel library.
|
||||||
|
|
||||||
@ -173,13 +174,24 @@ void QDebug::putUcs4(uint ucs4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, int length)
|
static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, int length, bool isUnicode = true)
|
||||||
{
|
{
|
||||||
QChar quote(QLatin1Char('"'));
|
QChar quote(QLatin1Char('"'));
|
||||||
d->write("e, 1);
|
d->write("e, 1);
|
||||||
|
|
||||||
|
bool lastWasHexEscape = false;
|
||||||
const Char *end = begin + length;
|
const Char *end = begin + length;
|
||||||
for (const Char *p = begin; p != end; ++p) {
|
for (const Char *p = begin; p != end; ++p) {
|
||||||
|
// check if we need to insert "" to break an hex escape sequence
|
||||||
|
if (Q_UNLIKELY(lastWasHexEscape)) {
|
||||||
|
if (fromHex(*p) != -1) {
|
||||||
|
// yes, insert it
|
||||||
|
QChar quotes[] = { QLatin1Char('"'), QLatin1Char('"') };
|
||||||
|
d->write(quotes, 2);
|
||||||
|
}
|
||||||
|
lastWasHexEscape = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sizeof(Char) == sizeof(QChar)) {
|
if (sizeof(Char) == sizeof(QChar)) {
|
||||||
int runLength = 0;
|
int runLength = 0;
|
||||||
while (p + runLength != end &&
|
while (p + runLength != end &&
|
||||||
@ -190,6 +202,10 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
|
|||||||
p += runLength - 1;
|
p += runLength - 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (*p < 0x7f && *p >= 0x20 && *p != '\\' && *p != '"') {
|
||||||
|
QChar c = QLatin1Char(*p);
|
||||||
|
d->write(&c, 1);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print as an escape sequence
|
// print as an escape sequence
|
||||||
@ -218,6 +234,15 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
|
|||||||
buf[1] = 't';
|
buf[1] = 't';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (!isUnicode) {
|
||||||
|
// print as hex escape
|
||||||
|
buf[1] = 'x';
|
||||||
|
buf[2] = toHexUpper(uchar(*p) >> 4);
|
||||||
|
buf[3] = toHexUpper(uchar(*p));
|
||||||
|
buflen = 4;
|
||||||
|
lastWasHexEscape = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (QChar::isHighSurrogate(*p)) {
|
if (QChar::isHighSurrogate(*p)) {
|
||||||
if ((p + 1) != end && QChar::isLowSurrogate(p[1])) {
|
if ((p + 1) != end && QChar::isLowSurrogate(p[1])) {
|
||||||
// properly-paired surrogates
|
// properly-paired surrogates
|
||||||
@ -272,6 +297,26 @@ void QDebug::putString(const QChar *begin, size_t length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Duplicated from QtTest::toPrettyCString().
|
||||||
|
*/
|
||||||
|
void QDebug::putByteArray(const char *begin, size_t length, Latin1Content content)
|
||||||
|
{
|
||||||
|
if (stream->testFlag(Stream::NoQuotes)) {
|
||||||
|
// no quotes, write the string directly too (no pretty-printing)
|
||||||
|
// this respects the QTextStream state, though
|
||||||
|
QString string = content == ContainsLatin1 ? QString::fromLatin1(begin, length) : QString::fromUtf8(begin, length);
|
||||||
|
stream->ts.d_ptr->putString(string);
|
||||||
|
} else {
|
||||||
|
// we'll reset the QTextStream formatting mechanisms, so save the state
|
||||||
|
QDebugStateSaver saver(*this);
|
||||||
|
stream->ts.d_ptr->params.reset();
|
||||||
|
putEscapedString(stream->ts.d_ptr.data(), reinterpret_cast<const uchar *>(begin),
|
||||||
|
length, content == ContainsLatin1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QDebug::swap(QDebug &other)
|
\fn QDebug::swap(QDebug &other)
|
||||||
\since 5.0
|
\since 5.0
|
||||||
|
@ -77,8 +77,11 @@ class Q_CORE_EXPORT QDebug
|
|||||||
int flags;
|
int flags;
|
||||||
} *stream;
|
} *stream;
|
||||||
|
|
||||||
|
enum Latin1Content { ContainsBinary = 0, ContainsLatin1 };
|
||||||
|
|
||||||
void putUcs4(uint ucs4);
|
void putUcs4(uint ucs4);
|
||||||
void putString(const QChar *begin, size_t length);
|
void putString(const QChar *begin, size_t length);
|
||||||
|
void putByteArray(const char *begin, size_t length, Latin1Content content);
|
||||||
public:
|
public:
|
||||||
inline QDebug(QIODevice *device) : stream(new Stream(device)) {}
|
inline QDebug(QIODevice *device) : stream(new Stream(device)) {}
|
||||||
inline QDebug(QString *string) : stream(new Stream(string)) {}
|
inline QDebug(QString *string) : stream(new Stream(string)) {}
|
||||||
@ -121,8 +124,8 @@ public:
|
|||||||
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
|
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
|
||||||
inline QDebug &operator<<(const QString & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
|
inline QDebug &operator<<(const QString & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
|
||||||
inline QDebug &operator<<(const QStringRef & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
|
inline QDebug &operator<<(const QStringRef & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
|
||||||
inline QDebug &operator<<(QLatin1String t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
|
inline QDebug &operator<<(QLatin1String t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
|
||||||
inline QDebug &operator<<(const QByteArray & t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
|
inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
|
||||||
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
|
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
|
||||||
#ifdef Q_COMPILER_NULLPTR
|
#ifdef Q_COMPILER_NULLPTR
|
||||||
inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
|
inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
|
||||||
|
@ -490,6 +490,28 @@ void tst_QDebug::qDebugQByteArray() const
|
|||||||
QCOMPARE(QString::fromLatin1(s_file), file);
|
QCOMPARE(QString::fromLatin1(s_file), file);
|
||||||
QCOMPARE(s_line, line);
|
QCOMPARE(s_line, line);
|
||||||
QCOMPARE(QString::fromLatin1(s_function), function);
|
QCOMPARE(QString::fromLatin1(s_function), function);
|
||||||
|
|
||||||
|
/* simpler tests from now on */
|
||||||
|
QByteArray ba = "\"Hello\"";
|
||||||
|
qDebug() << ba;
|
||||||
|
QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
|
||||||
|
|
||||||
|
qDebug().noquote().nospace() << ba;
|
||||||
|
QCOMPARE(s_msg, QString::fromLatin1(ba));
|
||||||
|
|
||||||
|
qDebug().noquote().nospace() << qSetFieldWidth(8) << ba;
|
||||||
|
QCOMPARE(s_msg, " " + QString::fromLatin1(ba));
|
||||||
|
|
||||||
|
ba = "\nSm\xC3\xB8rg\xC3\xA5sbord\\";
|
||||||
|
qDebug().noquote().nospace() << ba;
|
||||||
|
QCOMPARE(s_msg, QString::fromUtf8(ba));
|
||||||
|
|
||||||
|
qDebug() << ba;
|
||||||
|
QCOMPARE(s_msg, QString("\"\\nSm\\xC3\\xB8rg\\xC3\\xA5sbord\\\\\""));
|
||||||
|
|
||||||
|
// ensure that it closes hex escape sequences correctly
|
||||||
|
qDebug() << QByteArray("\377FFFF");
|
||||||
|
QCOMPARE(s_msg, QString("\"\\xFF\"\"FFFF\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TestEnum {
|
enum TestEnum {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user