From 5e6fa3dbc5abc765c60463fa101692bf40c6055b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 19 Dec 2024 10:36:04 +0100 Subject: [PATCH] QTest::toString(QCbor-type): port from const char* to unique_ptr This is more robust and lessens the impedance mismatch as seen by the old code using std::unique_ptr(expr).get(). The new code isn't impedance-mismatch-free, either (UP{qstrdup(qba.data())}), but short of writing a small string class whose internal buffer can be release()ed to comply with the archaic QTest::toString() new[]'ed const char* return value, there's not much we can do about it atm. Also separate the internal from the "public" stuff in QCborValueFormatter by adding private: and public: sections. Pick-to: 6.8 Change-Id: I09a2ad1a75bb9eab3d01f2b5b60afc2d762da384 Reviewed-by: Thiago Macieira (cherry picked from commit d9264ee65d6f24e1008b08494b1472a54ac01940) Reviewed-by: Qt Cherry-pick Bot --- src/testlib/qtesttostring.h | 65 ++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/src/testlib/qtesttostring.h b/src/testlib/qtesttostring.h index 417be70bbc1..e8ada71f9ea 100644 --- a/src/testlib/qtesttostring.h +++ b/src/testlib/qtesttostring.h @@ -32,7 +32,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE @@ -312,46 +312,53 @@ template<> inline char *toString(const QPartialOrdering &o) namespace Internal { struct QCborValueFormatter { +private: + using UP = std::unique_ptr; enum { BufferLen = 256 }; - static char *formatSimpleType(QCborSimpleType st) + + static UP createBuffer() { return q20::make_unique_for_overwrite(BufferLen); } + + static UP formatSimpleType(QCborSimpleType st) { - char *buf = new char[BufferLen]; - std::snprintf(buf, BufferLen, "QCborValue(QCborSimpleType(%d))", int(st)); + auto buf = createBuffer(); + std::snprintf(buf.get(), BufferLen, "QCborValue(QCborSimpleType(%d))", int(st)); return buf; } - static char *formatTag(QCborTag tag, const QCborValue &taggedValue) + static UP formatTag(QCborTag tag, const QCborValue &taggedValue) { + auto buf = createBuffer(); const std::unique_ptr hold(format(taggedValue)); - char *buf = new char[BufferLen]; - std::snprintf(buf, BufferLen, "QCborValue(QCborTag(%llu), %s)", + std::snprintf(buf.get(), BufferLen, "QCborValue(QCborTag(%llu), %s)", qToUnderlying(tag), hold.get()); return buf; } - static char *innerFormat(QCborValue::Type t, const char *str) + static UP innerFormat(QCborValue::Type t, const UP &str) { static const QMetaEnum typeEnum = []() { int idx = QCborValue::staticMetaObject.indexOfEnumerator("Type"); return QCborValue::staticMetaObject.enumerator(idx); }(); - char *buf = new char[BufferLen]; + auto buf = createBuffer(); const char *typeName = typeEnum.valueToKey(t); if (typeName) - std::snprintf(buf, BufferLen, "QCborValue(%s, %s)", typeName, str); + std::snprintf(buf.get(), BufferLen, "QCborValue(%s, %s)", typeName, str ? str.get() : ""); else - std::snprintf(buf, BufferLen, "QCborValue()", t); + std::snprintf(buf.get(), BufferLen, "QCborValue()", t); return buf; } - template static char *format(QCborValue::Type type, const T &t) + template static UP format(QCborValue::Type type, const T &t) { const std::unique_ptr hold(QTest::toString(t)); - return innerFormat(type, hold.get()); + return innerFormat(type, hold); } - static char *format(const QCborValue &v) +public: + + static UP format(const QCborValue &v) { switch (v.type()) { case QCborValue::Integer: @@ -361,21 +368,21 @@ struct QCborValueFormatter case QCborValue::String: return format(v.type(), v.toString()); case QCborValue::Array: - return innerFormat(v.type(), std::unique_ptr(format(v.toArray())).get()); + return innerFormat(v.type(), format(v.toArray())); case QCborValue::Map: - return innerFormat(v.type(), std::unique_ptr(format(v.toMap())).get()); + return innerFormat(v.type(), format(v.toMap())); case QCborValue::Tag: return formatTag(v.tag(), v.taggedValue()); case QCborValue::SimpleType: break; case QCborValue::True: - return qstrdup("QCborValue(true)"); + return UP{qstrdup("QCborValue(true)")}; case QCborValue::False: - return qstrdup("QCborValue(false)"); + return UP{qstrdup("QCborValue(false)")}; case QCborValue::Null: - return qstrdup("QCborValue(nullptr)"); + return UP{qstrdup("QCborValue(nullptr)")}; case QCborValue::Undefined: - return qstrdup("QCborValue()"); + return UP{qstrdup("QCborValue()")}; case QCborValue::Double: return format(v.type(), v.toDouble()); case QCborValue::DateTime: @@ -385,15 +392,15 @@ struct QCborValueFormatter case QCborValue::Uuid: return format(v.type(), v.toUuid()); case QCborValue::Invalid: - return qstrdup("QCborValue()"); + return UP{qstrdup("QCborValue()")}; } if (v.isSimpleType()) return formatSimpleType(v.toSimpleType()); - return innerFormat(v.type(), ""); + return innerFormat(v.type(), nullptr); } - static char *format(const QCborArray &a) + static UP format(const QCborArray &a) { QByteArray out(1, '['); const char *comma = ""; @@ -404,10 +411,10 @@ struct QCborValueFormatter comma = ", "; } out += ']'; - return qstrdup(out.constData()); + return UP{qstrdup(out.constData())}; } - static char *format(const QCborMap &m) + static UP format(const QCborMap &m) { QByteArray out(1, '{'); const char *comma = ""; @@ -421,14 +428,14 @@ struct QCborValueFormatter comma = ", "; } out += '}'; - return qstrdup(out.constData()); + return UP{qstrdup(out.constData())}; } }; } template<> inline char *toString(const QCborValue &v) { - return Internal::QCborValueFormatter::format(v); + return Internal::QCborValueFormatter::format(v).release(); } template<> inline char *toString(const QCborValueRef &v) @@ -438,12 +445,12 @@ template<> inline char *toString(const QCborValueRef &v) template<> inline char *toString(const QCborArray &a) { - return Internal::QCborValueFormatter::format(a); + return Internal::QCborValueFormatter::format(a).release(); } template<> inline char *toString(const QCborMap &m) { - return Internal::QCborValueFormatter::format(m); + return Internal::QCborValueFormatter::format(m).release(); } template char *toString(std::chrono::duration dur)