File indexing completed on 2025-09-16 09:04:24
0001
0002
0003
0004
0005 #ifndef QDEBUG_H
0006 #define QDEBUG_H
0007
0008 #if 0
0009 #pragma qt_class(QtDebug)
0010 #endif
0011
0012 #include <QtCore/qcompare.h>
0013 #include <QtCore/qcontainerfwd.h>
0014 #include <QtCore/qfloat16.h>
0015 #include <QtCore/qtextstream.h>
0016 #include <QtCore/qttypetraits.h>
0017 #include <QtCore/qtypes.h>
0018 #include <QtCore/qstring.h>
0019 #include <QtCore/qcontiguouscache.h>
0020 #include <QtCore/qsharedpointer.h>
0021
0022
0023 #include <array>
0024 #include <chrono>
0025 #include <list>
0026 #include <map>
0027 #include <memory>
0028 #include <optional>
0029 #include <string>
0030 #include <string_view>
0031 #include <set>
0032 #include <tuple>
0033 #include <QtCore/q20type_traits.h>
0034 #include <utility>
0035 #include <unordered_map>
0036 #include <unordered_set>
0037 #include <vector>
0038
0039 #if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
0040 # include <QtCore/qlist.h>
0041 # include <QtCore/qmap.h>
0042 # include <QtCore/qset.h>
0043 # include <QtCore/qvarlengtharray.h>
0044 #endif
0045
0046 QT_BEGIN_NAMESPACE
0047
0048 class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
0049 {
0050 friend class QMessageLogger;
0051 friend class QDebugStateSaver;
0052 friend class QDebugStateSaverPrivate;
0053 struct Stream {
0054 enum { VerbosityShift = 29, VerbosityMask = 0x7 };
0055
0056 explicit Stream(QIODevice *device)
0057 : ts(device)
0058 {}
0059 explicit Stream(QString *string)
0060 : ts(string, WriteOnly)
0061 {}
0062 explicit Stream(QByteArray *ba)
0063 : ts(ba, WriteOnly)
0064 {}
0065 explicit Stream(QtMsgType t)
0066 : ts(&buffer, WriteOnly),
0067 type(t),
0068 message_output(true)
0069 {}
0070 QTextStream ts;
0071 QString buffer;
0072 int ref = 1;
0073 QtMsgType type = QtDebugMsg;
0074 bool space = true;
0075 bool noQuotes = false;
0076 bool message_output = false;
0077 int verbosity = DefaultVerbosity;
0078 QMessageLogContext context;
0079 } *stream;
0080
0081 enum Latin1Content { ContainsBinary = 0, ContainsLatin1 };
0082
0083 QT7_ONLY(Q_CORE_EXPORT) void putUcs4(uint ucs4);
0084 QT7_ONLY(Q_CORE_EXPORT) void putString(const QChar *begin, size_t length);
0085 QT7_ONLY(Q_CORE_EXPORT) void putByteArray(const char *begin, size_t length, Latin1Content content);
0086 QT7_ONLY(Q_CORE_EXPORT) void putTimeUnit(qint64 num, qint64 den);
0087 QT7_ONLY(Q_CORE_EXPORT) void putInt128(const void *i);
0088 QT7_ONLY(Q_CORE_EXPORT) void putUInt128(const void *i);
0089 QT7_ONLY(Q_CORE_EXPORT) void putQtOrdering(QtOrderingPrivate::QtOrderingTypeFlag flags,
0090 Qt::partial_ordering order);
0091
0092 template <typename...Ts>
0093 using if_streamable = std::enable_if_t<
0094 std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, Ts>...>
0095 , bool>;
0096 public:
0097 explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
0098 explicit QDebug(QString *string) : stream(new Stream(string)) {}
0099 explicit QDebug(QByteArray *bytes) : stream(new Stream(bytes)) {}
0100 explicit QDebug(QtMsgType t) : stream(new Stream(t)) {}
0101 QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
0102 QDebug(QDebug &&other) noexcept : stream{std::exchange(other.stream, nullptr)} {}
0103 inline QDebug &operator=(const QDebug &other);
0104 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QDebug)
0105 ~QDebug();
0106 void swap(QDebug &other) noexcept { qt_ptr_swap(stream, other.stream); }
0107
0108 QT7_ONLY(Q_CORE_EXPORT) QDebug &resetFormat();
0109
0110 inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
0111 inline QDebug &nospace() { stream->space = false; return *this; }
0112 inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
0113 inline QDebug &verbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; return *this; }
0114 int verbosity() const { return stream->verbosity; }
0115 void setVerbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; }
0116 enum VerbosityLevel { MinimumVerbosity = 0, DefaultVerbosity = 2, MaximumVerbosity = 7 };
0117
0118 bool autoInsertSpaces() const { return stream->space; }
0119 void setAutoInsertSpaces(bool b) { stream->space = b; }
0120
0121 [[nodiscard]] bool quoteStrings() const noexcept { return !stream->noQuotes; }
0122 void setQuoteStrings(bool b) { stream->noQuotes = !b; }
0123
0124 inline QDebug "e() { stream->noQuotes = false; return *this; }
0125 inline QDebug &noquote() { stream->noQuotes = true; return *this; }
0126 inline QDebug &maybeQuote(char c = '"') { if (!stream->noQuotes) stream->ts << c; return *this; }
0127
0128 inline QDebug &operator<<(QChar t) { putUcs4(t.unicode()); return maybeSpace(); }
0129 inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
0130 inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
0131 inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
0132 inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
0133 inline QDebug &operator<<(char16_t t) { return *this << QChar(t); }
0134 inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
0135 inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
0136 inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
0137 inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
0138 inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
0139 inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
0140 inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
0141 inline QDebug &operator<<(qfloat16 t) { stream->ts << t; return maybeSpace(); }
0142 inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
0143 inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
0144 inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
0145 inline QDebug &operator<<(const char16_t *t) { stream->ts << QStringView(t); return maybeSpace(); }
0146 inline QDebug &operator<<(const QString & t) { putString(t.constData(), size_t(t.size())); return maybeSpace(); }
0147 inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
0148 inline QDebug &operator<<(QUtf8StringView s) { putByteArray(reinterpret_cast<const char*>(s.data()), s.size(), ContainsBinary); return maybeSpace(); }
0149 inline QDebug &operator<<(QLatin1StringView t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
0150 inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
0151 inline QDebug &operator<<(QByteArrayView t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
0152 inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
0153 inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
0154 inline QDebug &operator<<(std::nullopt_t) { stream->ts << "nullopt"; return maybeSpace(); }
0155 inline QDebug &operator<<(QTextStreamFunction f) {
0156 stream->ts << f;
0157 return *this;
0158 }
0159
0160 inline QDebug &operator<<(QTextStreamManipulator m)
0161 { stream->ts << m; return *this; }
0162
0163 #ifdef Q_QDOC
0164 template <typename Char, typename...Args>
0165 QDebug &operator<<(const std::basic_string<Char, Args...> &s);
0166
0167 template <typename Char, typename...Args>
0168 QDebug &operator<<(std::basic_string_view<Char, Args...> s);
0169 #else
0170 template <typename...Args>
0171 QDebug &operator<<(const std::basic_string<char, Args...> &s)
0172 { return *this << QUtf8StringView(s); }
0173
0174 template <typename...Args>
0175 QDebug &operator<<(std::basic_string_view<char, Args...> s)
0176 { return *this << QUtf8StringView(s); }
0177
0178 #ifdef __cpp_char8_t
0179 template <typename...Args>
0180 QDebug &operator<<(const std::basic_string<char8_t, Args...> &s)
0181 { return *this << QUtf8StringView(s); }
0182
0183 template <typename...Args>
0184 QDebug &operator<<(std::basic_string_view<char8_t, Args...> s)
0185 { return *this << QUtf8StringView(s); }
0186 #endif
0187
0188 template <typename...Args>
0189 QDebug &operator<<(const std::basic_string<char16_t, Args...> &s)
0190 { return *this << QStringView(s); }
0191
0192 template <typename...Args>
0193 QDebug &operator<<(std::basic_string_view<char16_t, Args...> s)
0194 { return *this << QStringView(s); }
0195
0196 template <typename...Args>
0197 QDebug &operator<<(const std::basic_string<wchar_t, Args...> &s)
0198 {
0199 if constexpr (sizeof(wchar_t) == 2)
0200 return *this << QStringView(s);
0201 else
0202 return *this << QString::fromWCharArray(s.data(), s.size());
0203 }
0204
0205 template <typename...Args>
0206 QDebug &operator<<(std::basic_string_view<wchar_t, Args...> s)
0207 {
0208 if constexpr (sizeof(wchar_t) == 2)
0209 return *this << QStringView(s);
0210 else
0211 return *this << QString::fromWCharArray(s.data(), s.size());
0212 }
0213
0214 template <typename...Args>
0215 QDebug &operator<<(const std::basic_string<char32_t, Args...> &s)
0216 { return *this << QString::fromUcs4(s.data(), s.size()); }
0217
0218 template <typename...Args>
0219 QDebug &operator<<(std::basic_string_view<char32_t, Args...> s)
0220 { return *this << QString::fromUcs4(s.data(), s.size()); }
0221 #endif
0222
0223 template <typename Rep, typename Period>
0224 QDebug &operator<<(std::chrono::duration<Rep, Period> duration)
0225 {
0226 stream->ts << duration.count();
0227 putTimeUnit(Period::num, Period::den);
0228 return maybeSpace();
0229 }
0230
0231 #ifdef QT_SUPPORTS_INT128
0232 private:
0233
0234
0235 template <typename T>
0236 using if_qint128 = std::enable_if_t<std::is_same_v<T, qint128>, bool>;
0237 template <typename T>
0238 using if_quint128 = std::enable_if_t<std::is_same_v<T, quint128>, bool>;
0239 public:
0240 template <typename T, if_qint128<T> = true>
0241 QDebug &operator<<(T i128) { putInt128(&i128); return maybeSpace(); }
0242 template <typename T, if_quint128<T> = true>
0243 QDebug &operator<<(T u128) { putUInt128(&u128); return maybeSpace(); }
0244 #endif
0245
0246 private:
0247 template <typename T>
0248 static void streamTypeErased(QDebug &d, const void *obj)
0249 {
0250 d << *static_cast<const T*>(obj);
0251 }
0252 using StreamTypeErased = void(*)(QDebug&, const void*);
0253 QT7_ONLY(Q_CORE_EXPORT) static QString toStringImpl(StreamTypeErased s, const void *obj);
0254 QT7_ONLY(Q_CORE_EXPORT) static QByteArray toBytesImpl(StreamTypeErased s, const void *obj);
0255 QT7_ONLY(Q_CORE_EXPORT) QDebug &putTupleLikeImplImpl(const char *ns, const char *what, size_t n,
0256 StreamTypeErased *ops, const void **data);
0257
0258 template <typename TupleLike, size_t...Is>
0259 QDebug &putTupleLikeImpl(const char *ns, const char *what, const TupleLike &t,
0260 std::index_sequence<Is...>)
0261 {
0262 if constexpr (sizeof...(Is)) {
0263 StreamTypeErased ops[] = {
0264 &streamTypeErased<q20::remove_cvref_t<std::tuple_element_t<Is, TupleLike>>>...
0265 };
0266 const void *data[] = {
0267 std::addressof(std::get<Is>(t))...
0268 };
0269 return putTupleLikeImplImpl(ns, what, sizeof...(Is), ops, data);
0270 } else {
0271 return putTupleLikeImplImpl(ns, what, 0, nullptr, nullptr);
0272 }
0273 }
0274
0275 template <typename TupleLike>
0276 QDebug &putTupleLike(const char *ns, const char *what, const TupleLike &t)
0277 {
0278 using Indexes = std::make_index_sequence<std::tuple_size_v<TupleLike>>;
0279 return putTupleLikeImpl(ns, what, t, Indexes{});
0280 }
0281 public:
0282 template <typename T>
0283 static QString toString(const T &object)
0284 {
0285 return toStringImpl(&streamTypeErased<T>, std::addressof(object));
0286 }
0287
0288 template <typename T>
0289 static QByteArray toBytes(const T &object)
0290 {
0291 return toBytesImpl(&streamTypeErased<T>, std::addressof(object));
0292 }
0293
0294 template <typename...Ts, if_streamable<Ts...> = true>
0295 QDebug &operator<<(const std::tuple<Ts...> &t)
0296 {
0297 return putTupleLike("std", "tuple", t);
0298 }
0299
0300 template <typename T, if_streamable<T> = true>
0301 QDebug &operator<<(const std::optional<T> &o)
0302 {
0303 if (!o)
0304 return *this << std::nullopt;
0305 StreamTypeErased s = &streamTypeErased<std::remove_cv_t<T>>;
0306 const void *d = std::addressof(*o);
0307 return putTupleLikeImplImpl("std", "optional", 1, &s, &d);
0308 }
0309
0310 private:
0311 template <typename T>
0312 using if_ordering_type = std::enable_if_t<QtOrderingPrivate::is_ordering_type_v<T>, bool>;
0313
0314 template <typename T, if_ordering_type<T> = true>
0315 friend QDebug operator<<(QDebug debug, T t)
0316 {
0317 debug.putQtOrdering(QtOrderingPrivate::orderingFlagsFor(t), Qt::partial_ordering(t));
0318 return debug;
0319 }
0320 };
0321
0322 Q_DECLARE_SHARED(QDebug)
0323
0324 class QDebugStateSaverPrivate;
0325 class QDebugStateSaver
0326 {
0327 public:
0328 Q_NODISCARD_CTOR Q_CORE_EXPORT
0329 QDebugStateSaver(QDebug &dbg);
0330 Q_CORE_EXPORT
0331 ~QDebugStateSaver();
0332 private:
0333 Q_DISABLE_COPY(QDebugStateSaver)
0334 std::unique_ptr<QDebugStateSaverPrivate> d;
0335 };
0336
0337 class QNoDebug
0338 {
0339 public:
0340 inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
0341 inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
0342 inline QNoDebug &space() { return *this; }
0343 inline QNoDebug &nospace() { return *this; }
0344 inline QNoDebug &maybeSpace() { return *this; }
0345 inline QNoDebug "e() { return *this; }
0346 inline QNoDebug &noquote() { return *this; }
0347 inline QNoDebug &maybeQuote(const char = '"') { return *this; }
0348 inline QNoDebug &verbosity(int) { return *this; }
0349
0350 template<typename T>
0351 inline QNoDebug &operator<<(const T &) { return *this; }
0352 };
0353
0354 inline QDebug &QDebug::operator=(const QDebug &other)
0355 {
0356 QDebug{other}.swap(*this);
0357 return *this;
0358 }
0359
0360 namespace QtPrivate {
0361
0362 template <typename SequentialContainer>
0363 inline QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
0364 {
0365 const QDebugStateSaver saver(debug);
0366 debug.nospace() << which << '(';
0367 typename SequentialContainer::const_iterator it = c.begin(), end = c.end();
0368 if (it != end) {
0369 debug << *it;
0370 ++it;
0371 }
0372 while (it != end) {
0373 debug << ", " << *it;
0374 ++it;
0375 }
0376 debug << ')';
0377 return debug;
0378 }
0379
0380 template <typename AssociativeContainer>
0381 inline QDebug printAssociativeContainer(QDebug debug, const char *which, const AssociativeContainer &c)
0382 {
0383 const QDebugStateSaver saver(debug);
0384 debug.nospace() << which << "(";
0385 for (typename AssociativeContainer::const_iterator it = c.constBegin();
0386 it != c.constEnd(); ++it) {
0387 debug << '(' << it.key() << ", " << it.value() << ')';
0388 }
0389 debug << ')';
0390 return debug;
0391 }
0392
0393 }
0394
0395 template<typename ...T>
0396 using QDebugIfHasDebugStream =
0397 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, T>...>, QDebug>;
0398
0399 template<typename Container, typename ...T>
0400 using QDebugIfHasDebugStreamContainer =
0401 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDebug, Container, T>...>, QDebug>;
0402
0403 #ifndef Q_QDOC
0404
0405 template<typename T>
0406 inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec)
0407 {
0408 return QtPrivate::printSequentialContainer(std::move(debug), "QList", vec);
0409 }
0410
0411 template<typename T, qsizetype P>
0412 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QVarLengthArray<T, P> &vec)
0413 {
0414 return QtPrivate::printSequentialContainer(std::move(debug), "QVarLengthArray", vec);
0415 }
0416
0417 template <typename T, typename Alloc>
0418 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
0419 {
0420 return QtPrivate::printSequentialContainer(std::move(debug), "std::vector", vec);
0421 }
0422
0423 template <typename T, std::size_t N>
0424 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::array<T, N> &array)
0425 {
0426 return QtPrivate::printSequentialContainer(std::move(debug), "std::array", array);
0427 }
0428
0429 template <typename T, typename Alloc>
0430 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::list<T, Alloc> &vec)
0431 {
0432 return QtPrivate::printSequentialContainer(std::move(debug), "std::list", vec);
0433 }
0434
0435 template <typename T>
0436 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, std::initializer_list<T> list)
0437 {
0438 return QtPrivate::printSequentialContainer(std::move(debug), "std::initializer_list", list);
0439 }
0440
0441 template <typename Key, typename T, typename Compare, typename Alloc>
0442 inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
0443 {
0444 return QtPrivate::printSequentialContainer(std::move(debug), "std::map", map);
0445 }
0446
0447 template <typename Key, typename T, typename Compare, typename Alloc>
0448 inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
0449 {
0450 return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map);
0451 }
0452
0453 template <typename Key, typename Compare, typename Alloc>
0454 inline QDebugIfHasDebugStream<Key> operator<<(QDebug debug, const std::multiset<Key, Compare, Alloc> &multiset)
0455 {
0456 return QtPrivate::printSequentialContainer(std::move(debug), "std::multiset", multiset);
0457 }
0458
0459 template <typename Key, typename Compare, typename Alloc>
0460 inline QDebugIfHasDebugStream<Key> operator<<(QDebug debug, const std::set<Key, Compare, Alloc> &set)
0461 {
0462 return QtPrivate::printSequentialContainer(std::move(debug), "std::set", set);
0463 }
0464
0465 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
0466 inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::unordered_map<Key, T, Hash, KeyEqual, Alloc> &unordered_map)
0467 {
0468 return QtPrivate::printSequentialContainer(std::move(debug), "std::unordered_map", unordered_map);
0469 }
0470
0471 template <typename Key, typename Hash, typename KeyEqual, typename Alloc>
0472 inline QDebugIfHasDebugStream<Key> operator<<(QDebug debug, const std::unordered_set<Key, Hash, KeyEqual, Alloc> &unordered_set)
0473 {
0474 return QtPrivate::printSequentialContainer(std::move(debug), "std::unordered_set", unordered_set);
0475 }
0476
0477 template <class Key, class T>
0478 inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
0479 {
0480 return QtPrivate::printAssociativeContainer(std::move(debug), "QMap", map);
0481 }
0482
0483 template <class Key, class T>
0484 inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
0485 {
0486 return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiMap", map);
0487 }
0488
0489 template <class Key, class T>
0490 inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
0491 {
0492 return QtPrivate::printAssociativeContainer(std::move(debug), "QHash", hash);
0493 }
0494
0495 template <class Key, class T>
0496 inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
0497 {
0498 return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash);
0499 }
0500
0501 template <class T1, class T2>
0502 inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T1, T2> &pair)
0503 {
0504 const QDebugStateSaver saver(debug);
0505 debug.nospace() << "std::pair(" << pair.first << ", " << pair.second << ')';
0506 return debug;
0507 }
0508
0509 template <typename T>
0510 inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set)
0511 {
0512 return QtPrivate::printSequentialContainer(std::move(debug), "QSet", set);
0513 }
0514
0515 template <class T>
0516 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QContiguousCache<T> &cache)
0517 {
0518 const QDebugStateSaver saver(debug);
0519 debug.nospace() << "QContiguousCache(";
0520 for (qsizetype i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
0521 debug << cache[i];
0522 if (i != cache.lastIndex())
0523 debug << ", ";
0524 }
0525 debug << ')';
0526 return debug;
0527 }
0528
0529 #else
0530 template <class T>
0531 QDebug operator<<(QDebug debug, const QList<T> &list);
0532
0533 template <class T, qsizetype P>
0534 QDebug operator<<(QDebug debug, const QVarLengthArray<T, P> &array);
0535
0536 template <typename T, typename Alloc>
0537 QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec);
0538
0539 template <typename T, std::size_t N>
0540 QDebug operator<<(QDebug debug, const std::array<T, N> &array);
0541
0542 template <typename T, typename Alloc>
0543 QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec);
0544
0545 template <typename Key, typename T, typename Compare, typename Alloc>
0546 QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map);
0547
0548 template <typename Key, typename T, typename Compare, typename Alloc>
0549 QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map);
0550
0551 template <class Key, class T>
0552 QDebug operator<<(QDebug debug, const QMap<Key, T> &map);
0553
0554 template <class Key, class T>
0555 QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map);
0556
0557 template <class Key, class T>
0558 QDebug operator<<(QDebug debug, const QHash<Key, T> &hash);
0559
0560 template <class Key, class T>
0561 QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash);
0562
0563 template <typename T>
0564 QDebug operator<<(QDebug debug, const QSet<T> &set);
0565
0566 template <class T1, class T2>
0567 QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair);
0568
0569 template <typename T>
0570 QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache);
0571
0572 template <typename Key, typename Compare, typename Alloc>
0573 QDebug operator<<(QDebug debug, const std::multiset<Key, Compare, Alloc> &multiset);
0574
0575 template <typename Key, typename Compare, typename Alloc>
0576 QDebug operator<<(QDebug debug, const std::set<Key, Compare, Alloc> &set);
0577
0578 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
0579 QDebug operator<<(QDebug debug, const std::unordered_map<Key, T, Hash, KeyEqual, Alloc> &unordered_map);
0580
0581 template <typename Key, typename Hash, typename KeyEqual, typename Alloc>
0582 QDebug operator<<(QDebug debug, const std::unordered_set<Key, Hash, KeyEqual, Alloc> &unordered_set);
0583
0584 #endif
0585
0586 template <class T>
0587 inline QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr)
0588 {
0589 QDebugStateSaver saver(debug);
0590 debug.nospace() << "QSharedPointer(" << ptr.data() << ")";
0591 return debug;
0592 }
0593
0594 template <typename T, typename Tag> class QTaggedPointer;
0595
0596 template <typename T, typename Tag>
0597 inline QDebug operator<<(QDebug debug, const QTaggedPointer<T, Tag> &ptr)
0598 {
0599 QDebugStateSaver saver(debug);
0600 debug.nospace() << "QTaggedPointer(" << ptr.pointer() << ", " << ptr.tag() << ")";
0601 return debug;
0602 }
0603
0604 Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, qint64 value, const QMetaObject *meta, const char *name);
0605 Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name);
0606 Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value);
0607 Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value);
0608
0609 template <typename Int>
0610 void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
0611 {
0612 static_assert(std::is_unsigned_v<Int>,
0613 "Cast value to an unsigned type before calling this function");
0614 const QDebugStateSaver saver(debug);
0615 debug.resetFormat();
0616 debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
0617 bool needSeparator = false;
0618 for (size_t i = 0; i < sizeofT * 8; ++i) {
0619 if (value & (Int(1) << i)) {
0620 if (needSeparator)
0621 debug << '|';
0622 else
0623 needSeparator = true;
0624 debug << (Int(1) << i);
0625 }
0626 }
0627 debug << ')';
0628 }
0629
0630 template <class Flags,
0631 std::enable_if_t<QtPrivate::IsQFlags<Flags>::value, bool> = true>
0632 inline QDebug operator<<(QDebug debug, Flags flags)
0633 {
0634 using T = typename Flags::enum_type;
0635 using UInt = typename QIntegerForSizeof<T>::Unsigned;
0636 #if !defined(QT_NO_QOBJECT)
0637 if constexpr (QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<Flags>::Value) {
0638
0639
0640 using Int = std::conditional_t<QtPrivate::IsQEnumHelper<Flags>::Value, UInt,
0641 std::underlying_type_t<T>>;
0642 const QMetaObject *obj = qt_getEnumMetaObject(T());
0643 const char *name = qt_getEnumName(T());
0644 return qt_QMetaEnum_flagDebugOperator(debug, Int(flags.toInt()), obj, name);
0645 } else
0646 #endif
0647 {
0648 qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), UInt(flags.toInt()));
0649 return debug;
0650 }
0651 }
0652
0653 #ifdef Q_QDOC
0654 template <typename T>
0655 QDebug operator<<(QDebug debug, const QFlags<T> &flags);
0656 #endif
0657
0658 #if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC)
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669 namespace QtPrivate {
0670 template <typename T, bool IsEnum = std::is_enum_v<T>, bool = sizeof(T) <= sizeof(quint64)>
0671 struct EnumHasQFlag { static constexpr bool Value = false; };
0672 template <typename T> struct EnumHasQFlag<T, true, true> : QtPrivate::IsQEnumHelper<QFlags<T>> {};
0673
0674 template <typename T, bool IsEnum = std::is_enum_v<T>, bool HasQFlag = EnumHasQFlag<T>::Value>
0675 struct EnumHasQEnum { static constexpr bool Value = false; };
0676 template <typename T> struct EnumHasQEnum<T, true, false> : QtPrivate::IsQEnumHelper<T> {};
0677 }
0678
0679 template <typename T>
0680 std::enable_if_t<QtPrivate::EnumHasQFlag<T>::Value, QDebug>
0681 operator<<(QDebug debug, T flag)
0682 {
0683 return debug << QFlags(flag);
0684 }
0685
0686 template<typename T>
0687 std::enable_if_t<QtPrivate::EnumHasQEnum<T>::Value, QDebug>
0688 operator<<(QDebug dbg, T value)
0689 {
0690 const QMetaObject *obj = qt_getEnumMetaObject(value);
0691 const char *name = qt_getEnumName(value);
0692 return qt_QMetaEnum_debugOperator(dbg, static_cast<typename std::underlying_type<T>::type>(value), obj, name);
0693 }
0694 #endif
0695
0696 inline QDebug operator<<(QDebug debug, QKeyCombination combination)
0697 {
0698 QDebugStateSaver saver(debug);
0699 debug.nospace() << "QKeyCombination("
0700 << combination.keyboardModifiers()
0701 << ", "
0702 << combination.key()
0703 << ")";
0704 return debug;
0705 }
0706
0707 #ifdef Q_OS_DARWIN
0708
0709
0710
0711
0712
0713 #define QT_FOR_EACH_CORE_FOUNDATION_TYPE(F) \
0714 F(CFArray) \
0715 F(CFURL) \
0716 F(CFData) \
0717 F(CFNumber) \
0718 F(CFDictionary) \
0719 F(CFLocale) \
0720 F(CFDate) \
0721 F(CFBoolean) \
0722 F(CFTimeZone) \
0723
0724 #define QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(F) \
0725 F(CFError) \
0726 F(CFBundle) \
0727
0728 #define QT_FOR_EACH_CORE_GRAPHICS_TYPE(F) \
0729 F(CGPath) \
0730
0731 #define QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(F) \
0732 F(CGColorSpace) \
0733 F(CGImage) \
0734 F(CGFont) \
0735 F(CGColor) \
0736
0737 #define QT_FORWARD_DECLARE_CF_TYPE(type) Q_FORWARD_DECLARE_CF_TYPE(type);
0738 #define QT_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type);
0739 #define QT_FORWARD_DECLARE_CG_TYPE(type) Q_FORWARD_DECLARE_CG_TYPE(type);
0740 #define QT_FORWARD_DECLARE_MUTABLE_CG_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(type);
0741
0742 QT_END_NAMESPACE
0743 Q_FORWARD_DECLARE_CF_TYPE(CFString);
0744 struct objc_object;
0745 Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
0746 QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_CF_TYPE)
0747 QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_MUTABLE_CF_TYPE)
0748 QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_CG_TYPE)
0749 QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_MUTABLE_CG_TYPE)
0750 QT_BEGIN_NAMESPACE
0751
0752 #define QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
0753 Q_CORE_EXPORT QDebug operator<<(QDebug, CFType##Ref);
0754
0755 #define Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
0756 QDebug operator<<(QDebug debug, CFType##Ref ref) \
0757 { \
0758 if (!ref) \
0759 return debug << QT_STRINGIFY(CFType) "Ref(0x0)"; \
0760 if (CFStringRef description = CFCopyDescription(ref)) { \
0761 QDebugStateSaver saver(debug); \
0762 debug.noquote() << description; \
0763 CFRelease(description); \
0764 } \
0765 return debug; \
0766 }
0767
0768
0769 #if defined(__OBJC__)
0770 Q_CORE_EXPORT QDebug operator<<(QDebug, id);
0771 #endif
0772 Q_CORE_EXPORT QDebug operator<<(QDebug, objc_object *);
0773 Q_CORE_EXPORT QDebug operator<<(QDebug, const NSObject *);
0774 Q_CORE_EXPORT QDebug operator<<(QDebug, CFStringRef);
0775
0776 QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0777 QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0778 QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0779 QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0780
0781 #undef QT_FORWARD_DECLARE_CF_TYPE
0782 #undef QT_FORWARD_DECLARE_MUTABLE_CF_TYPE
0783 #undef QT_FORWARD_DECLARE_CG_TYPE
0784 #undef QT_FORWARD_DECLARE_MUTABLE_CG_TYPE
0785
0786 #endif
0787
0788 QT_END_NAMESPACE
0789
0790 #endif