summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2024-07-18 22:57:10 +0200
committerMarc Mutz <marc.mutz@qt.io>2024-07-23 02:59:53 +0200
commitb57fac818b7fe028dc61f1196cfda397233edffe (patch)
tree1a932bf3b7ead2e883ec6325de3af7d332a7d359
parentb892b39a7a6c50eb5bbf03f0c9f01bdd07756f13 (diff)
Long live QDebug::toBytes()!
I've seen over and over again how test authors are plagued by the impedance mismatch between their 8-bit actual data and the result of QString::toString() being in UTF-16. They invariably ditch their 8-bit inputs and go to QString, but the mere fact that they start out with 8-bit input and then run into problems means we have a gaping API hole here. QTest::toString() also suffers from this. So add the option to a) construct a QDebug object over a QByteArray (already supported by underlying QTextStream) and b) to stream into QByteArray like toString() streams into QString. Finally, make QTest::toString() use the new toBytes() function instead of the old toString() one. This saves 1% (91122→90248) in tst_tostring exeutable size on optimized Linux AMD64 GCC 9 builds. [ChangeLog][QtCore][QDebug] Added ctor from QByteArray* and a static toBytes() function. Change-Id: I2b021513d6427a1a961f39e751eaf4faaf527ba8 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qdebug.cpp22
-rw-r--r--src/corelib/io/qdebug.h11
-rw-r--r--src/testlib/qtesttostring.h2
3 files changed, 34 insertions, 1 deletions
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 600b8b13b80..1c6aecaaabb 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1000,6 +1000,8 @@ QDebug &QDebug::resetFormat()
\since 6.0
\include qdebug-toString.qdocinc
+
+ \sa toBytes()
*/
/*! \internal */
@@ -1014,6 +1016,26 @@ QString QDebug::toStringImpl(StreamTypeErased s, const void *obj)
}
/*!
+ \fn template <class T> QByteArray QDebug::toBytes(const T &object)
+ \since 6.9
+
+ This is equivalent to \c{QDebug::toString(object).toUtf8()}, but more efficient.
+
+ \sa toString()
+*/
+
+/*! \internal */
+QByteArray QDebug::toBytesImpl(StreamTypeErased s, const void *obj)
+{
+ QByteArray result;
+ {
+ QDebug d(&result);
+ s(d.nospace(), obj);
+ }
+ return result;
+}
+
+/*!
\fn template <class T> QDebug operator<<(QDebug debug, const QList<T> &list)
\relates QDebug
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index fe3c66180c3..ab1f53afe77 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -51,6 +51,9 @@ class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
explicit Stream(QString *string)
: ts(string, WriteOnly)
{}
+ explicit Stream(QByteArray *ba)
+ : ts(ba, WriteOnly)
+ {}
explicit Stream(QtMsgType t)
: ts(&buffer, WriteOnly),
type(t),
@@ -78,6 +81,7 @@ class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
public:
explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
explicit QDebug(QString *string) : stream(new Stream(string)) {}
+ explicit QDebug(QByteArray *bytes) : stream(new Stream(bytes)) {}
explicit QDebug(QtMsgType t) : stream(new Stream(t)) {}
QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
QDebug(QDebug &&other) noexcept : stream{std::exchange(other.stream, nullptr)} {}
@@ -232,12 +236,19 @@ private:
}
using StreamTypeErased = void(*)(QDebug&, const void*);
QT7_ONLY(Q_CORE_EXPORT) static QString toStringImpl(StreamTypeErased s, const void *obj);
+ QT7_ONLY(Q_CORE_EXPORT) static QByteArray toBytesImpl(StreamTypeErased s, const void *obj);
public:
template <typename T>
static QString toString(const T &object)
{
return toStringImpl(&streamTypeErased<T>, &object);
}
+
+ template <typename T>
+ static QByteArray toBytes(const T &object)
+ {
+ return toBytesImpl(&streamTypeErased<T>, &object);
+ }
};
Q_DECLARE_SHARED(QDebug)
diff --git a/src/testlib/qtesttostring.h b/src/testlib/qtesttostring.h
index 903392697d6..bcd70501f67 100644
--- a/src/testlib/qtesttostring.h
+++ b/src/testlib/qtesttostring.h
@@ -55,7 +55,7 @@ inline typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value && !std::is_e
char *result = nullptr;
#ifndef QT_NO_DEBUG_STREAM
if constexpr (QTypeTraits::has_ostream_operator_v<QDebug, T>) {
- result = qstrdup(QDebug::toString(t).toUtf8().constData());
+ result = qstrdup(QDebug::toBytes(t).constData());
} else {
static_assert(!QMetaTypeId2<T>::IsBuiltIn,
"Built-in type must implement debug streaming operator "