summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qdebug.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qdebug.h')
-rw-r--r--src/corelib/io/qdebug.h158
1 files changed, 132 insertions, 26 deletions
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 64b4ac37c9..4797bcd169 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -11,15 +11,20 @@
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qtextstream.h>
+#include <QtCore/qtypes.h>
#include <QtCore/qstring.h>
#include <QtCore/qcontiguouscache.h>
#include <QtCore/qsharedpointer.h>
// all these have already been included by various headers above, but don't rely on indirect includes:
-#include <vector>
+#include <chrono>
#include <list>
#include <map>
+#include <optional>
+#include <string>
+#include <string_view>
#include <utility>
+#include <vector>
#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
# include <QtCore/qlist.h>
@@ -65,12 +70,15 @@ class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
QT7_ONLY(Q_CORE_EXPORT) void putUcs4(uint ucs4);
QT7_ONLY(Q_CORE_EXPORT) void putString(const QChar *begin, size_t length);
QT7_ONLY(Q_CORE_EXPORT) void putByteArray(const char *begin, size_t length, Latin1Content content);
+ QT7_ONLY(Q_CORE_EXPORT) void putTimeUnit(qint64 num, qint64 den);
+ QT7_ONLY(Q_CORE_EXPORT) void putInt128(const void *i);
+ QT7_ONLY(Q_CORE_EXPORT) void putUInt128(const void *i);
public:
explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
explicit QDebug(QString *string) : stream(new Stream(string)) {}
explicit QDebug(QtMsgType t) : stream(new Stream(t)) {}
QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
- QDebug(QDebug &&other) noexcept : stream{qExchange(other.stream, nullptr)} {}
+ QDebug(QDebug &&other) noexcept : stream{std::exchange(other.stream, nullptr)} {}
inline QDebug &operator=(const QDebug &other);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QDebug)
~QDebug();
@@ -89,6 +97,9 @@ public:
bool autoInsertSpaces() const { return stream->space; }
void setAutoInsertSpaces(bool b) { stream->space = b; }
+ [[nodiscard]] bool quoteStrings() const noexcept { return !stream->noQuotes; }
+ void setQuoteStrings(bool b) { stream->noQuotes = !b; }
+
inline QDebug &quote() { stream->noQuotes = false; return *this; }
inline QDebug &noquote() { stream->noQuotes = true; return *this; }
inline QDebug &maybeQuote(char c = '"') { if (!stream->noQuotes) stream->ts << c; return *this; }
@@ -98,7 +109,7 @@ public:
inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
- inline QDebug &operator<<(char16_t t) { return *this << QChar(ushort(t)); }
+ inline QDebug &operator<<(char16_t t) { return *this << QChar(t); }
inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
@@ -106,11 +117,12 @@ public:
inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
+ inline QDebug &operator<<(qfloat16 t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
inline QDebug &operator<<(const char16_t *t) { stream->ts << QStringView(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(), size_t(t.size())); return maybeSpace(); }
inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
inline QDebug &operator<<(QUtf8StringView s) { putByteArray(reinterpret_cast<const char*>(s.data()), s.size(), ContainsBinary); return maybeSpace(); }
inline QDebug &operator<<(QLatin1StringView t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
@@ -118,6 +130,7 @@ public:
inline QDebug &operator<<(QByteArrayView t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
+ inline QDebug &operator<<(std::nullopt_t) { stream->ts << "nullopt"; return maybeSpace(); }
inline QDebug &operator<<(QTextStreamFunction f) {
stream->ts << f;
return *this;
@@ -126,6 +139,89 @@ public:
inline QDebug &operator<<(QTextStreamManipulator m)
{ stream->ts << m; return *this; }
+#ifdef Q_QDOC
+ template <typename Char, typename...Args>
+ QDebug &operator<<(const std::basic_string<Char, Args...> &s);
+
+ template <typename Char, typename...Args>
+ QDebug &operator<<(std::basic_string_view<Char, Args...> s);
+#else
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char, Args...> &s)
+ { return *this << QUtf8StringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char, Args...> s)
+ { return *this << QUtf8StringView(s); }
+
+#ifdef __cpp_char8_t
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char8_t, Args...> &s)
+ { return *this << QUtf8StringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char8_t, Args...> s)
+ { return *this << QUtf8StringView(s); }
+#endif // __cpp_char8_t
+
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char16_t, Args...> &s)
+ { return *this << QStringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char16_t, Args...> s)
+ { return *this << QStringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<wchar_t, Args...> &s)
+ {
+ if constexpr (sizeof(wchar_t) == 2)
+ return *this << QStringView(s);
+ else
+ return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
+ }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<wchar_t, Args...> s)
+ {
+ if constexpr (sizeof(wchar_t) == 2)
+ return *this << QStringView(s);
+ else
+ return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
+ }
+
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char32_t, Args...> &s)
+ { return *this << QString::fromUcs4(s.data(), s.size()); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char32_t, Args...> s)
+ { return *this << QString::fromUcs4(s.data(), s.size()); }
+#endif // !Q_QDOC
+
+ template <typename Rep, typename Period>
+ QDebug &operator<<(std::chrono::duration<Rep, Period> duration)
+ {
+ stream->ts << duration.count();
+ putTimeUnit(Period::num, Period::den);
+ return maybeSpace();
+ }
+
+#ifdef QT_SUPPORTS_INT128
+private:
+ // Constrained templates so they only match q(u)int128 without conversions.
+ // Also keeps these operators out of the ABI.
+ template <typename T>
+ using if_qint128 = std::enable_if_t<std::is_same_v<T, qint128>, bool>;
+ template <typename T>
+ using if_quint128 = std::enable_if_t<std::is_same_v<T, quint128>, bool>;
+public:
+ template <typename T, if_qint128<T> = true>
+ QDebug &operator<<(T i128) { putInt128(&i128); return maybeSpace(); }
+ template <typename T, if_quint128<T> = true>
+ QDebug &operator<<(T u128) { putUInt128(&u128); return maybeSpace(); }
+#endif // QT_SUPPORTS_INT128
+
template <typename T>
static QString toString(T &&object)
{
@@ -139,10 +235,12 @@ public:
Q_DECLARE_SHARED(QDebug)
class QDebugStateSaverPrivate;
-class Q_CORE_EXPORT QDebugStateSaver
+class QDebugStateSaver
{
public:
+ Q_NODISCARD_CTOR Q_CORE_EXPORT
QDebugStateSaver(QDebug &dbg);
+ Q_CORE_EXPORT
~QDebugStateSaver();
private:
Q_DISABLE_COPY(QDebugStateSaver)
@@ -215,72 +313,83 @@ template<typename Container, typename ...T>
using QDebugIfHasDebugStreamContainer =
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDebug, Container, T>...>, QDebug>;
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
template<typename T>
inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec)
{
- return QtPrivate::printSequentialContainer(debug, "QList", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "QList", vec);
}
template<typename T, qsizetype P>
inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QVarLengthArray<T, P> &vec)
{
- return QtPrivate::printSequentialContainer(debug, "QVarLengthArray", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "QVarLengthArray", vec);
}
template <typename T, typename Alloc>
inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
{
- return QtPrivate::printSequentialContainer(debug, "std::vector", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::vector", vec);
}
template <typename T, typename Alloc>
inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::list<T, Alloc> &vec)
{
- return QtPrivate::printSequentialContainer(debug, "std::list", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::list", vec);
}
template <typename T>
inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, std::initializer_list<T> list)
{
- return QtPrivate::printSequentialContainer(debug, "std::initializer_list", list);
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::initializer_list", list);
}
template <typename Key, typename T, typename Compare, typename Alloc>
inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
{
- return QtPrivate::printSequentialContainer(debug, "std::map", map); // yes, sequential: *it is std::pair
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::map", map); // yes, sequential: *it is std::pair
}
template <typename Key, typename T, typename Compare, typename Alloc>
inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
{
- return QtPrivate::printSequentialContainer(debug, "std::multimap", map); // yes, sequential: *it is std::pair
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map); // yes, sequential: *it is std::pair
}
template <class Key, class T>
inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
{
- return QtPrivate::printAssociativeContainer(debug, "QMap", map);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QMap", map);
}
template <class Key, class T>
inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
{
- return QtPrivate::printAssociativeContainer(debug, "QMultiMap", map);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiMap", map);
}
template <class Key, class T>
inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
{
- return QtPrivate::printAssociativeContainer(debug, "QHash", hash);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QHash", hash);
}
template <class Key, class T>
inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
{
- return QtPrivate::printAssociativeContainer(debug, "QMultiHash", hash);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash);
+}
+
+template <class T>
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::optional<T> &opt)
+{
+ const QDebugStateSaver saver(debug);
+ if (!opt)
+ debug.nospace() << std::nullopt;
+ else
+ debug.nospace() << "std::optional(" << *opt << ')';
+ return debug;
}
template <class T1, class T2>
@@ -294,7 +403,7 @@ inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T
template <typename T>
inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set)
{
- return QtPrivate::printSequentialContainer(debug, "QSet", set);
+ return QtPrivate::printSequentialContainer(std::move(debug), "QSet", set);
}
template <class T>
@@ -302,7 +411,7 @@ inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QContiguousCache
{
const QDebugStateSaver saver(debug);
debug.nospace() << "QContiguousCache(";
- for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
+ for (qsizetype i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
debug << cache[i];
if (i != cache.lastIndex())
debug << ", ";
@@ -346,15 +455,12 @@ template <typename T>
QDebug operator<<(QDebug debug, const QSet<T> &set);
template <class T1, class T2>
-QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair);
-
-template <class T1, class T2>
QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair);
template <typename T>
QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache);
-#endif // Q_CLANG_QDOC
+#endif // Q_QDOC
template <class T>
inline QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr)
@@ -383,7 +489,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
debug.resetFormat();
debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
bool needSeparator = false;
- for (uint i = 0; i < sizeofT * 8; ++i) {
+ for (size_t i = 0; i < sizeofT * 8; ++i) {
if (value & (Int(1) << i)) {
if (needSeparator)
debug << '|';
@@ -465,7 +571,7 @@ inline QDebug operator<<(QDebug debug, QKeyCombination combination)
return debug;
}
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
// We provide QDebug stream operators for commonly used Core Foundation
// and Core Graphics types, as well as NSObject. Additional CF/CG types
@@ -544,7 +650,7 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF
#undef QT_FORWARD_DECLARE_CG_TYPE
#undef QT_FORWARD_DECLARE_MUTABLE_CG_TYPE
-#endif // Q_OS_MAC
+#endif // Q_OS_DARWIN
QT_END_NAMESPACE