Skip to content

Commit

Permalink
QTest::toString(QCbor-type): port from const char* to unique_ptr<char[]>
Browse files Browse the repository at this point in the history
This is more robust and lessens the impedance mismatch as seen by the
old code using std::unique_ptr<char[]>(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 <thiago.macieira@intel.com>
(cherry picked from commit d9264ee)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
  • Loading branch information
marcmutz authored and Qt Cherry-pick Bot committed Dec 26, 2024
1 parent 8fdcda4 commit 5e6fa3d
Showing 1 changed file with 36 additions and 29 deletions.
65 changes: 36 additions & 29 deletions src/testlib/qtesttostring.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include <QtCore/qvariant.h>

#include <cstdio>
#include <memory>
#include <QtCore/q20memory.h>

QT_BEGIN_NAMESPACE

Expand Down Expand Up @@ -312,46 +312,53 @@ template<> inline char *toString(const QPartialOrdering &o)
namespace Internal {
struct QCborValueFormatter
{
private:
using UP = std::unique_ptr<char[]>;
enum { BufferLen = 256 };
static char *formatSimpleType(QCborSimpleType st)

static UP createBuffer() { return q20::make_unique_for_overwrite<char[]>(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<char[]> 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(<unknown type 0x%02x>)", t);
std::snprintf(buf.get(), BufferLen, "QCborValue(<unknown type 0x%02x>)", t);
return buf;
}

template<typename T> static char *format(QCborValue::Type type, const T &t)
template<typename T> static UP format(QCborValue::Type type, const T &t)
{
const std::unique_ptr<char[]> 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:
Expand All @@ -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<char[]>(format(v.toArray())).get());
return innerFormat(v.type(), format(v.toArray()));
case QCborValue::Map:
return innerFormat(v.type(), std::unique_ptr<char[]>(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:
Expand All @@ -385,15 +392,15 @@ struct QCborValueFormatter
case QCborValue::Uuid:
return format(v.type(), v.toUuid());
case QCborValue::Invalid:
return qstrdup("QCborValue(<invalid>)");
return UP{qstrdup("QCborValue(<invalid>)")};
}

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 = "";
Expand All @@ -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 = "";
Expand All @@ -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)
Expand All @@ -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 <typename Rep, typename Period> char *toString(std::chrono::duration<Rep, Period> dur)
Expand Down

0 comments on commit 5e6fa3d

Please sign in to comment.