QAnyStringView: add QDebug stream operator
When QDebug::quoted(), indicates the encoding using the u/u8 prefixes or the _L1 suffix. This is information that might come in handy, and we plan to make it off-switchable (QTBUG-114936). The default should be true, though, for QAnyStringView, because we should confront users with this feature so they learn it exists. For concrete view types, changing the default behavior is probably not a good idea. [ChangeLog][QtCore][QAnyStringView/QDebug] Can now stream QAnyStringView into QDebug. Fixes: QTBUG-114935 Change-Id: Icd5bf700c8b7958e942468b54248487998f262d5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
4443d392e4
commit
b2b5862479
|
|
@ -206,7 +206,7 @@ qt_internal_add_module(Core
|
|||
serialization/qjsonwriter.cpp serialization/qjsonwriter_p.h
|
||||
serialization/qtextstream.cpp serialization/qtextstream.h serialization/qtextstream_p.h
|
||||
serialization/qxmlutils.cpp serialization/qxmlutils_p.h
|
||||
text/qanystringview.h
|
||||
text/qanystringview.cpp text/qanystringview.h
|
||||
text/qbytearray.cpp text/qbytearray.h text/qbytearray_p.h
|
||||
text/qbytearrayalgorithms.h
|
||||
text/qbytearraylist.cpp text/qbytearraylist.h
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
#include "qanystringview.h"
|
||||
#include "qdebug.h"
|
||||
#include "qttypetraits.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QAnyStringView
|
||||
\inmodule QtCore
|
||||
|
|
@ -597,3 +603,47 @@
|
|||
\sa QString::isNull(), QAnyStringView
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QAnyStringView::operator<<(QDebug d, QAnyStringView s)
|
||||
\since 6.7
|
||||
\relates QAnyStringView
|
||||
\relatesalso QDebug
|
||||
|
||||
Outputs \a s to debug stream \a d.
|
||||
|
||||
If \c{d.quotedString()} is \c true, indicates which encoding the string is
|
||||
in. If you just want the string data, use visit() like this:
|
||||
|
||||
\code
|
||||
s.visit([&d) (auto s) { d << s; });
|
||||
\endcode
|
||||
|
||||
\sa QAnyStringView::visit()
|
||||
*/
|
||||
QDebug operator<<(QDebug d, QAnyStringView s)
|
||||
{
|
||||
struct S { const char *prefix, *suffix; };
|
||||
const auto affixes = s.visit([](auto s) {
|
||||
using View = decltype(s);
|
||||
if constexpr (std::is_same_v<View, QLatin1StringView>) {
|
||||
return S{"", "_L1"};
|
||||
} else if constexpr (std::is_same_v<View, QUtf8StringView>) {
|
||||
return S{"u8", ""};
|
||||
} else if constexpr (std::is_same_v<View, QStringView>) {
|
||||
return S{"u", ""};
|
||||
} else {
|
||||
static_assert(QtPrivate::type_dependent_false<View>());
|
||||
}
|
||||
});
|
||||
const QDebugStateSaver saver(d);
|
||||
d.nospace();
|
||||
if (d.quoteStrings())
|
||||
d << affixes.prefix;
|
||||
s.visit([&d](auto s) { d << s; });
|
||||
if (d.quoteStrings())
|
||||
d << affixes.suffix;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -312,6 +312,10 @@ private:
|
|||
{ return QAnyStringView::compare(lhs, rhs) > 0; }
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
Q_CORE_EXPORT friend QDebug operator<<(QDebug d, QAnyStringView s);
|
||||
#endif
|
||||
|
||||
[[nodiscard]] constexpr Tag tag() const noexcept { return Tag{m_size & TypeMask}; }
|
||||
[[nodiscard]] constexpr bool isUtf16() const noexcept { return tag() == Tag::Utf16; }
|
||||
[[nodiscard]] constexpr bool isUtf8() const noexcept { return tag() == Tag::Utf8; }
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QAnyStringView>
|
||||
#include <QChar>
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QStringBuilder>
|
||||
|
|
@ -304,6 +305,7 @@ class tst_QAnyStringView : public QObject
|
|||
private Q_SLOTS:
|
||||
void constExpr() const;
|
||||
void basics() const;
|
||||
void debug() const;
|
||||
void asciiLiteralIsLatin1() const;
|
||||
|
||||
void fromQString() const { fromQStringOrByteArray<QString>(); }
|
||||
|
|
@ -476,6 +478,77 @@ void tst_QAnyStringView::basics() const
|
|||
QVERIFY(!(sv2 != sv1));
|
||||
}
|
||||
|
||||
void tst_QAnyStringView::debug() const
|
||||
{
|
||||
#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
|
||||
# define MAYBE_L1(str) str "_L1"
|
||||
# define VERIFY_L1(s) QVERIFY(s.isLatin1())
|
||||
#else
|
||||
# define MAYBE_L1(str) "u8" str
|
||||
# define VERIFY_L1(s) QVERIFY(s.isUtf8())
|
||||
#endif
|
||||
#define CHECK1(s, mod, expected) do { \
|
||||
QString result; \
|
||||
QDebug(&result) mod << "X"_L1 << s << "Y"_L1; \
|
||||
/* QDebug appends an eager ' ', so trim before comparison */ \
|
||||
/* We use X and Y affixes so we can still check spacing */ \
|
||||
/* around the QAnyStringView itself. */ \
|
||||
QCOMPARE(result.trimmed(), expected); \
|
||||
} while (false)
|
||||
#define CHECK(init, esq, eq, es, e) do { \
|
||||
QAnyStringView s = init; \
|
||||
CHECK1(s, , esq); \
|
||||
CHECK1(s, .nospace(), eq); \
|
||||
CHECK1(s, .noquote(), es); \
|
||||
CHECK1(s, .nospace().noquote(), e); \
|
||||
} while (false)
|
||||
|
||||
CHECK(nullptr,
|
||||
R"("X" u8"" "Y")",
|
||||
R"("X"u8"""Y")",
|
||||
R"(X Y)",
|
||||
R"(XY)");
|
||||
CHECK(QLatin1StringView(nullptr),
|
||||
R"("X" ""_L1 "Y")",
|
||||
R"("X"""_L1"Y")",
|
||||
R"(X Y)",
|
||||
R"(XY)");
|
||||
CHECK(QUtf8StringView(nullptr),
|
||||
R"("X" u8"" "Y")",
|
||||
R"("X"u8"""Y")",
|
||||
R"(X Y)",
|
||||
R"(XY)");
|
||||
CHECK(QStringView(nullptr),
|
||||
R"("X" u"" "Y")",
|
||||
R"("X"u"""Y")",
|
||||
R"(X Y)",
|
||||
R"(XY)");
|
||||
{
|
||||
constexpr QAnyStringView asv = "hello";
|
||||
VERIFY_L1(asv); // ### fails when asv isn't constexpr
|
||||
CHECK(asv,
|
||||
R"("X" )" MAYBE_L1(R"("hello")") R"( "Y")",
|
||||
R"("X")" MAYBE_L1(R"("hello")") R"("Y")",
|
||||
R"(X hello Y)",
|
||||
R"(XhelloY)");
|
||||
}
|
||||
CHECK(u8"hällo",
|
||||
R"("X" u8"h\xC3\xA4llo" "Y")",
|
||||
R"("X"u8"h\xC3\xA4llo""Y")",
|
||||
R"(X hällo Y)",
|
||||
R"(XhälloY)");
|
||||
CHECK(u"hällo",
|
||||
R"("X" u"hällo" "Y")",
|
||||
R"("X"u"hällo""Y")",
|
||||
R"(X hällo Y)",
|
||||
R"(XhälloY)");
|
||||
|
||||
#undef CHECK
|
||||
#undef CHECK1
|
||||
#undef VERIFY_L1
|
||||
#undef MAYBE_L1
|
||||
}
|
||||
|
||||
void tst_QAnyStringView::asciiLiteralIsLatin1() const
|
||||
{
|
||||
#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
|
||||
|
|
|
|||
Loading…
Reference in New Issue