Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qdebug.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // Copyright (C) 2016 Intel Corporation.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QDEBUG_H
0006 #define QDEBUG_H
0007 
0008 #if 0
0009 #pragma qt_class(QtDebug)
0010 #endif
0011 
0012 #include <QtCore/qcontainerfwd.h>
0013 #include <QtCore/qtextstream.h>
0014 #include <QtCore/qtypes.h>
0015 #include <QtCore/qstring.h>
0016 #include <QtCore/qcontiguouscache.h>
0017 #include <QtCore/qsharedpointer.h>
0018 
0019 // all these have already been included by various headers above, but don't rely on indirect includes:
0020 #include <chrono>
0021 #include <list>
0022 #include <map>
0023 #include <optional>
0024 #include <string>
0025 #include <string_view>
0026 #include <utility>
0027 #include <vector>
0028 
0029 #if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
0030 #  include <QtCore/qlist.h>
0031 #  include <QtCore/qmap.h>
0032 #  include <QtCore/qset.h>
0033 #  include <QtCore/qvarlengtharray.h>
0034 #endif
0035 
0036 QT_BEGIN_NAMESPACE
0037 
0038 class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
0039 {
0040     friend class QMessageLogger;
0041     friend class QDebugStateSaver;
0042     friend class QDebugStateSaverPrivate;
0043     struct Stream {
0044         enum { VerbosityShift = 29, VerbosityMask = 0x7 };
0045 
0046         Stream(QIODevice *device)
0047             : ts(device)
0048         {}
0049         Stream(QString *string)
0050             : ts(string, WriteOnly)
0051         {}
0052         Stream(QtMsgType t)
0053             : ts(&buffer, WriteOnly),
0054               type(t),
0055               message_output(true)
0056         {}
0057         QTextStream ts;
0058         QString buffer;
0059         int ref = 1;
0060         QtMsgType type = QtDebugMsg;
0061         bool space = true;
0062         bool noQuotes = false;
0063         bool message_output = false;
0064         int verbosity = DefaultVerbosity;
0065         QMessageLogContext context;
0066     } *stream;
0067 
0068     enum Latin1Content { ContainsBinary = 0, ContainsLatin1 };
0069 
0070     QT7_ONLY(Q_CORE_EXPORT) void putUcs4(uint ucs4);
0071     QT7_ONLY(Q_CORE_EXPORT) void putString(const QChar *begin, size_t length);
0072     QT7_ONLY(Q_CORE_EXPORT) void putByteArray(const char *begin, size_t length, Latin1Content content);
0073     QT7_ONLY(Q_CORE_EXPORT) void putTimeUnit(qint64 num, qint64 den);
0074     QT7_ONLY(Q_CORE_EXPORT) void putInt128(const void *i);
0075     QT7_ONLY(Q_CORE_EXPORT) void putUInt128(const void *i);
0076 public:
0077     explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
0078     explicit QDebug(QString *string) : stream(new Stream(string)) {}
0079     explicit QDebug(QtMsgType t) : stream(new Stream(t)) {}
0080     QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
0081     QDebug(QDebug &&other) noexcept : stream{std::exchange(other.stream, nullptr)} {}
0082     inline QDebug &operator=(const QDebug &other);
0083     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QDebug)
0084     ~QDebug();
0085     void swap(QDebug &other) noexcept { qt_ptr_swap(stream, other.stream); }
0086 
0087     QT7_ONLY(Q_CORE_EXPORT) QDebug &resetFormat();
0088 
0089     inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
0090     inline QDebug &nospace() { stream->space = false; return *this; }
0091     inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
0092     inline QDebug &verbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; return *this; }
0093     int verbosity() const { return stream->verbosity; }
0094     void setVerbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; }
0095     enum VerbosityLevel { MinimumVerbosity = 0, DefaultVerbosity = 2, MaximumVerbosity = 7 };
0096 
0097     bool autoInsertSpaces() const { return stream->space; }
0098     void setAutoInsertSpaces(bool b) { stream->space = b; }
0099 
0100     [[nodiscard]] bool quoteStrings() const noexcept { return !stream->noQuotes; }
0101     void setQuoteStrings(bool b) { stream->noQuotes = !b; }
0102 
0103     inline QDebug &quote() { stream->noQuotes = false; return *this; }
0104     inline QDebug &noquote() { stream->noQuotes = true; return *this; }
0105     inline QDebug &maybeQuote(char c = '"') { if (!stream->noQuotes) stream->ts << c; return *this; }
0106 
0107     inline QDebug &operator<<(QChar t) { putUcs4(t.unicode()); return maybeSpace(); }
0108     inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
0109     inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
0110     inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
0111     inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
0112     inline QDebug &operator<<(char16_t t) { return *this << QChar(t); }
0113     inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
0114     inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
0115     inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
0116     inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
0117     inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
0118     inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
0119     inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
0120     inline QDebug &operator<<(qfloat16 t) { stream->ts << t; return maybeSpace(); }
0121     inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
0122     inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
0123     inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
0124     inline QDebug &operator<<(const char16_t *t)  { stream->ts << QStringView(t); return maybeSpace(); }
0125     inline QDebug &operator<<(const QString & t) { putString(t.constData(), size_t(t.size())); return maybeSpace(); }
0126     inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
0127     inline QDebug &operator<<(QUtf8StringView s) { putByteArray(reinterpret_cast<const char*>(s.data()), s.size(), ContainsBinary); return maybeSpace(); }
0128     inline QDebug &operator<<(QLatin1StringView t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
0129     inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
0130     inline QDebug &operator<<(QByteArrayView t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
0131     inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
0132     inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
0133     inline QDebug &operator<<(std::nullopt_t) { stream->ts << "nullopt"; return maybeSpace(); }
0134     inline QDebug &operator<<(QTextStreamFunction f) {
0135         stream->ts << f;
0136         return *this;
0137     }
0138 
0139     inline QDebug &operator<<(QTextStreamManipulator m)
0140     { stream->ts << m; return *this; }
0141 
0142 #ifdef Q_QDOC
0143     template <typename Char, typename...Args>
0144     QDebug &operator<<(const std::basic_string<Char, Args...> &s);
0145 
0146     template <typename Char, typename...Args>
0147     QDebug &operator<<(std::basic_string_view<Char, Args...> s);
0148 #else
0149     template <typename...Args>
0150     QDebug &operator<<(const std::basic_string<char, Args...> &s)
0151     { return *this << QUtf8StringView(s); }
0152 
0153     template <typename...Args>
0154     QDebug &operator<<(std::basic_string_view<char, Args...> s)
0155     { return *this << QUtf8StringView(s); }
0156 
0157 #ifdef __cpp_char8_t
0158     template <typename...Args>
0159     QDebug &operator<<(const std::basic_string<char8_t, Args...> &s)
0160     { return *this << QUtf8StringView(s); }
0161 
0162     template <typename...Args>
0163     QDebug &operator<<(std::basic_string_view<char8_t, Args...> s)
0164     { return *this << QUtf8StringView(s); }
0165 #endif // __cpp_char8_t
0166 
0167     template <typename...Args>
0168     QDebug &operator<<(const std::basic_string<char16_t, Args...> &s)
0169     { return *this << QStringView(s); }
0170 
0171     template <typename...Args>
0172     QDebug &operator<<(std::basic_string_view<char16_t, Args...> s)
0173     { return *this << QStringView(s); }
0174 
0175     template <typename...Args>
0176     QDebug &operator<<(const std::basic_string<wchar_t, Args...> &s)
0177     {
0178         if constexpr (sizeof(wchar_t) == 2)
0179             return *this << QStringView(s);
0180         else
0181             return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
0182     }
0183 
0184     template <typename...Args>
0185     QDebug &operator<<(std::basic_string_view<wchar_t, Args...> s)
0186     {
0187         if constexpr (sizeof(wchar_t) == 2)
0188             return *this << QStringView(s);
0189         else
0190             return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
0191     }
0192 
0193     template <typename...Args>
0194     QDebug &operator<<(const std::basic_string<char32_t, Args...> &s)
0195     { return *this << QString::fromUcs4(s.data(), s.size()); }
0196 
0197     template <typename...Args>
0198     QDebug &operator<<(std::basic_string_view<char32_t, Args...> s)
0199     { return *this << QString::fromUcs4(s.data(), s.size()); }
0200 #endif // !Q_QDOC
0201 
0202     template <typename Rep, typename Period>
0203     QDebug &operator<<(std::chrono::duration<Rep, Period> duration)
0204     {
0205         stream->ts << duration.count();
0206         putTimeUnit(Period::num, Period::den);
0207         return maybeSpace();
0208     }
0209 
0210 #ifdef QT_SUPPORTS_INT128
0211 private:
0212     // Constrained templates so they only match q(u)int128 without conversions.
0213     // Also keeps these operators out of the ABI.
0214     template <typename T>
0215     using if_qint128 = std::enable_if_t<std::is_same_v<T, qint128>, bool>;
0216     template <typename T>
0217     using if_quint128 = std::enable_if_t<std::is_same_v<T, quint128>, bool>;
0218 public:
0219     template <typename T, if_qint128<T> = true>
0220     QDebug &operator<<(T i128) { putInt128(&i128); return maybeSpace(); }
0221     template <typename T, if_quint128<T> = true>
0222     QDebug &operator<<(T u128) { putUInt128(&u128); return maybeSpace(); }
0223 #endif // QT_SUPPORTS_INT128
0224 
0225     template <typename T>
0226     static QString toString(T &&object)
0227     {
0228         QString buffer;
0229         QDebug stream(&buffer);
0230         stream.nospace() << std::forward<T>(object);
0231         return buffer;
0232     }
0233 };
0234 
0235 Q_DECLARE_SHARED(QDebug)
0236 
0237 class QDebugStateSaverPrivate;
0238 class QDebugStateSaver
0239 {
0240 public:
0241     Q_NODISCARD_CTOR Q_CORE_EXPORT
0242     QDebugStateSaver(QDebug &dbg);
0243     Q_CORE_EXPORT
0244     ~QDebugStateSaver();
0245 private:
0246     Q_DISABLE_COPY(QDebugStateSaver)
0247     QScopedPointer<QDebugStateSaverPrivate> d;
0248 };
0249 
0250 class QNoDebug
0251 {
0252 public:
0253     inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
0254     inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
0255     inline QNoDebug &space() { return *this; }
0256     inline QNoDebug &nospace() { return *this; }
0257     inline QNoDebug &maybeSpace() { return *this; }
0258     inline QNoDebug &quote() { return *this; }
0259     inline QNoDebug &noquote() { return *this; }
0260     inline QNoDebug &maybeQuote(const char = '"') { return *this; }
0261     inline QNoDebug &verbosity(int) { return *this; }
0262 
0263     template<typename T>
0264     inline QNoDebug &operator<<(const T &) { return *this; }
0265 };
0266 
0267 inline QDebug &QDebug::operator=(const QDebug &other)
0268 {
0269     QDebug{other}.swap(*this);
0270     return *this;
0271 }
0272 
0273 namespace QtPrivate {
0274 
0275 template <typename SequentialContainer>
0276 inline QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
0277 {
0278     const QDebugStateSaver saver(debug);
0279     debug.nospace() << which << '(';
0280     typename SequentialContainer::const_iterator it = c.begin(), end = c.end();
0281     if (it != end) {
0282         debug << *it;
0283         ++it;
0284     }
0285     while (it != end) {
0286         debug << ", " << *it;
0287         ++it;
0288     }
0289     debug << ')';
0290     return debug;
0291 }
0292 
0293 template <typename AssociativeContainer>
0294 inline QDebug printAssociativeContainer(QDebug debug, const char *which, const AssociativeContainer &c)
0295 {
0296     const QDebugStateSaver saver(debug);
0297     debug.nospace() << which << "(";
0298     for (typename AssociativeContainer::const_iterator it = c.constBegin();
0299          it != c.constEnd(); ++it) {
0300         debug << '(' << it.key() << ", " << it.value() << ')';
0301     }
0302     debug << ')';
0303     return debug;
0304 }
0305 
0306 } // namespace QtPrivate
0307 
0308 template<typename ...T>
0309 using QDebugIfHasDebugStream =
0310     std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, T>...>, QDebug>;
0311 
0312 template<typename Container, typename ...T>
0313 using QDebugIfHasDebugStreamContainer =
0314     std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDebug, Container, T>...>, QDebug>;
0315 
0316 #ifndef Q_QDOC
0317 
0318 template<typename T>
0319 inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec)
0320 {
0321     return QtPrivate::printSequentialContainer(std::move(debug), "QList", vec);
0322 }
0323 
0324 template<typename T, qsizetype P>
0325 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QVarLengthArray<T, P> &vec)
0326 {
0327     return QtPrivate::printSequentialContainer(std::move(debug), "QVarLengthArray", vec);
0328 }
0329 
0330 template <typename T, typename Alloc>
0331 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
0332 {
0333     return QtPrivate::printSequentialContainer(std::move(debug), "std::vector", vec);
0334 }
0335 
0336 template <typename T, typename Alloc>
0337 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::list<T, Alloc> &vec)
0338 {
0339     return QtPrivate::printSequentialContainer(std::move(debug), "std::list", vec);
0340 }
0341 
0342 template <typename T>
0343 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, std::initializer_list<T> list)
0344 {
0345     return QtPrivate::printSequentialContainer(std::move(debug), "std::initializer_list", list);
0346 }
0347 
0348 template <typename Key, typename T, typename Compare, typename Alloc>
0349 inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
0350 {
0351     return QtPrivate::printSequentialContainer(std::move(debug), "std::map", map); // yes, sequential: *it is std::pair
0352 }
0353 
0354 template <typename Key, typename T, typename Compare, typename Alloc>
0355 inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
0356 {
0357     return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map); // yes, sequential: *it is std::pair
0358 }
0359 
0360 template <class Key, class T>
0361 inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
0362 {
0363     return QtPrivate::printAssociativeContainer(std::move(debug), "QMap", map);
0364 }
0365 
0366 template <class Key, class T>
0367 inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
0368 {
0369     return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiMap", map);
0370 }
0371 
0372 template <class Key, class T>
0373 inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
0374 {
0375     return QtPrivate::printAssociativeContainer(std::move(debug), "QHash", hash);
0376 }
0377 
0378 template <class Key, class T>
0379 inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
0380 {
0381     return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash);
0382 }
0383 
0384 template <class T>
0385 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::optional<T> &opt)
0386 {
0387     const QDebugStateSaver saver(debug);
0388     if (!opt)
0389         debug.nospace() << std::nullopt;
0390     else
0391         debug.nospace() << "std::optional(" << *opt << ')';
0392     return debug;
0393 }
0394 
0395 template <class T1, class T2>
0396 inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T1, T2> &pair)
0397 {
0398     const QDebugStateSaver saver(debug);
0399     debug.nospace() << "std::pair(" << pair.first << ',' << pair.second << ')';
0400     return debug;
0401 }
0402 
0403 template <typename T>
0404 inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set)
0405 {
0406     return QtPrivate::printSequentialContainer(std::move(debug), "QSet", set);
0407 }
0408 
0409 template <class T>
0410 inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QContiguousCache<T> &cache)
0411 {
0412     const QDebugStateSaver saver(debug);
0413     debug.nospace() << "QContiguousCache(";
0414     for (qsizetype i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
0415         debug << cache[i];
0416         if (i != cache.lastIndex())
0417             debug << ", ";
0418     }
0419     debug << ')';
0420     return debug;
0421 }
0422 
0423 #else
0424 template <class T>
0425 QDebug operator<<(QDebug debug, const QList<T> &list);
0426 
0427 template <class T, qsizetype P>
0428 QDebug operator<<(QDebug debug, const QVarLengthArray<T, P> &array);
0429 
0430 template <typename T, typename Alloc>
0431 QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec);
0432 
0433 template <typename T, typename Alloc>
0434 QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec);
0435 
0436 template <typename Key, typename T, typename Compare, typename Alloc>
0437 QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map);
0438 
0439 template <typename Key, typename T, typename Compare, typename Alloc>
0440 QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map);
0441 
0442 template <class Key, class T>
0443 QDebug operator<<(QDebug debug, const QMap<Key, T> &map);
0444 
0445 template <class Key, class T>
0446 QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map);
0447 
0448 template <class Key, class T>
0449 QDebug operator<<(QDebug debug, const QHash<Key, T> &hash);
0450 
0451 template <class Key, class T>
0452 QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash);
0453 
0454 template <typename T>
0455 QDebug operator<<(QDebug debug, const QSet<T> &set);
0456 
0457 template <class T1, class T2>
0458 QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair);
0459 
0460 template <typename T>
0461 QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache);
0462 
0463 #endif // Q_QDOC
0464 
0465 template <class T>
0466 inline QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr)
0467 {
0468     QDebugStateSaver saver(debug);
0469     debug.nospace() << "QSharedPointer(" << ptr.data() << ")";
0470     return debug;
0471 }
0472 
0473 template <typename T, typename Tag> class QTaggedPointer;
0474 
0475 template <typename T, typename Tag>
0476 inline QDebug operator<<(QDebug debug, const QTaggedPointer<T, Tag> &ptr)
0477 {
0478     QDebugStateSaver saver(debug);
0479     debug.nospace() << "QTaggedPointer(" << ptr.pointer() << ", " << ptr.tag() << ")";
0480     return debug;
0481 }
0482 
0483 Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value);
0484 
0485 template <typename Int>
0486 void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
0487 {
0488     const QDebugStateSaver saver(debug);
0489     debug.resetFormat();
0490     debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
0491     bool needSeparator = false;
0492     for (size_t i = 0; i < sizeofT * 8; ++i) {
0493         if (value & (Int(1) << i)) {
0494             if (needSeparator)
0495                 debug << '|';
0496             else
0497                 needSeparator = true;
0498             debug << (Int(1) << i);
0499         }
0500     }
0501     debug << ')';
0502 }
0503 
0504 #if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC)
0505 Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, qint64 value, const QMetaObject *meta, const char *name);
0506 Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name);
0507 
0508 template<typename T>
0509 typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, QDebug>::type
0510 operator<<(QDebug dbg, T value)
0511 {
0512     const QMetaObject *obj = qt_getEnumMetaObject(value);
0513     const char *name = qt_getEnumName(value);
0514     return qt_QMetaEnum_debugOperator(dbg, static_cast<typename std::underlying_type<T>::type>(value), obj, name);
0515 }
0516 
0517 template<typename T,
0518          typename A = typename std::enable_if<std::is_enum<T>::value, void>::type,
0519          typename B = typename std::enable_if<sizeof(T) <= sizeof(int), void>::type,
0520          typename C = typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value, void>::type,
0521          typename D = typename std::enable_if<QtPrivate::IsQEnumHelper<QFlags<T>>::Value, void>::type>
0522 inline QDebug operator<<(QDebug dbg, T value)
0523 {
0524     typedef QFlags<T> FlagsT;
0525     const QMetaObject *obj = qt_getEnumMetaObject(FlagsT());
0526     const char *name = qt_getEnumName(FlagsT());
0527     return qt_QMetaEnum_debugOperator(dbg, typename FlagsT::Int(value), obj, name);
0528 }
0529 
0530 template <class T>
0531 inline typename std::enable_if<
0532     QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
0533     QDebug>::type
0534 qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
0535 {
0536     const QMetaObject *obj = qt_getEnumMetaObject(T());
0537     const char *name = qt_getEnumName(T());
0538     return qt_QMetaEnum_flagDebugOperator(debug, flags.toInt(), obj, name);
0539 }
0540 
0541 template <class T>
0542 inline typename std::enable_if<
0543     !QtPrivate::IsQEnumHelper<T>::Value && !QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
0544     QDebug>::type
0545 qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
0546 #else // !QT_NO_QOBJECT && !Q_QDOC
0547 template <class T>
0548 inline QDebug qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
0549 #endif
0550 {
0551     qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), typename QFlags<T>::Int(flags));
0552     return debug;
0553 }
0554 
0555 template<typename T>
0556 inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
0557 {
0558     // We have to use an indirection otherwise specialisation of some other overload of the
0559     // operator<< the compiler would try to instantiate QFlags<T> for the std::enable_if
0560     return qt_QMetaEnum_flagDebugOperator_helper(debug, flags);
0561 }
0562 
0563 inline QDebug operator<<(QDebug debug, QKeyCombination combination)
0564 {
0565     QDebugStateSaver saver(debug);
0566     debug.nospace() << "QKeyCombination("
0567                     << combination.keyboardModifiers()
0568                     << ", "
0569                     << combination.key()
0570                     << ")";
0571     return debug;
0572 }
0573 
0574 #ifdef Q_OS_DARWIN
0575 
0576 // We provide QDebug stream operators for commonly used Core Foundation
0577 // and Core Graphics types, as well as NSObject. Additional CF/CG types
0578 // may be added by the user, using Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE.
0579 
0580 #define QT_FOR_EACH_CORE_FOUNDATION_TYPE(F) \
0581     F(CFArray) \
0582     F(CFURL) \
0583     F(CFData) \
0584     F(CFNumber) \
0585     F(CFDictionary) \
0586     F(CFLocale) \
0587     F(CFDate) \
0588     F(CFBoolean) \
0589     F(CFTimeZone) \
0590 
0591 #define QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(F) \
0592     F(CFError) \
0593     F(CFBundle) \
0594 
0595 #define QT_FOR_EACH_CORE_GRAPHICS_TYPE(F) \
0596     F(CGPath) \
0597 
0598 #define QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(F) \
0599     F(CGColorSpace) \
0600     F(CGImage) \
0601     F(CGFont) \
0602     F(CGColor) \
0603 
0604 #define QT_FORWARD_DECLARE_CF_TYPE(type) Q_FORWARD_DECLARE_CF_TYPE(type);
0605 #define QT_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type);
0606 #define QT_FORWARD_DECLARE_CG_TYPE(type) Q_FORWARD_DECLARE_CG_TYPE(type);
0607 #define QT_FORWARD_DECLARE_MUTABLE_CG_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(type);
0608 
0609 QT_END_NAMESPACE
0610 Q_FORWARD_DECLARE_CF_TYPE(CFString);
0611 struct objc_object;
0612 Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
0613 QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_CF_TYPE)
0614 QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_MUTABLE_CF_TYPE)
0615 QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_CG_TYPE)
0616 QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_MUTABLE_CG_TYPE)
0617 QT_BEGIN_NAMESPACE
0618 
0619 #define QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
0620     Q_CORE_EXPORT QDebug operator<<(QDebug, CFType##Ref);
0621 
0622 #define Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
0623     QDebug operator<<(QDebug debug, CFType##Ref ref) \
0624     { \
0625         if (!ref) \
0626             return debug << QT_STRINGIFY(CFType) "Ref(0x0)"; \
0627         if (CFStringRef description = CFCopyDescription(ref)) { \
0628             QDebugStateSaver saver(debug); \
0629             debug.noquote() << description; \
0630             CFRelease(description); \
0631         } \
0632         return debug; \
0633     }
0634 
0635 // Defined in qcore_mac_objc.mm
0636 #if defined(__OBJC__)
0637 Q_CORE_EXPORT QDebug operator<<(QDebug, id);
0638 #endif
0639 Q_CORE_EXPORT QDebug operator<<(QDebug, objc_object *);
0640 Q_CORE_EXPORT QDebug operator<<(QDebug, const NSObject *);
0641 Q_CORE_EXPORT QDebug operator<<(QDebug, CFStringRef);
0642 
0643 QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0644 QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0645 QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0646 QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
0647 
0648 #undef QT_FORWARD_DECLARE_CF_TYPE
0649 #undef QT_FORWARD_DECLARE_MUTABLE_CF_TYPE
0650 #undef QT_FORWARD_DECLARE_CG_TYPE
0651 #undef QT_FORWARD_DECLARE_MUTABLE_CG_TYPE
0652 
0653 #endif // Q_OS_DARWIN
0654 
0655 QT_END_NAMESPACE
0656 
0657 #endif // QDEBUG_H