1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #ifndef QDEBUG_H |
43 | #define QDEBUG_H |
44 | |
45 | #include <QtCore/qalgorithms.h> |
46 | #include <QtCore/qhash.h> |
47 | #include <QtCore/qlist.h> |
48 | #include <QtCore/qmap.h> |
49 | #include <QtCore/qpair.h> |
50 | #include <QtCore/qtextstream.h> |
51 | #include <QtCore/qstring.h> |
52 | #include <QtCore/qvector.h> |
53 | #include <QtCore/qset.h> |
54 | #include <QtCore/qcontiguouscache.h> |
55 | |
56 | QT_BEGIN_HEADER |
57 | |
58 | QT_BEGIN_NAMESPACE |
59 | |
60 | QT_MODULE(Core) |
61 | |
62 | class Q_CORE_EXPORT QDebug |
63 | { |
64 | struct Stream { |
65 | Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {} |
66 | Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {} |
67 | Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true) {} |
68 | QTextStream ts; |
69 | QString buffer; |
70 | int ref; |
71 | QtMsgType type; |
72 | bool space; |
73 | bool message_output; |
74 | } *stream; |
75 | public: |
76 | inline QDebug(QIODevice *device) : stream(new Stream(device)) {} |
77 | inline QDebug(QString *string) : stream(new Stream(string)) {} |
78 | inline QDebug(QtMsgType t) : stream(new Stream(t)) {} |
79 | inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; } |
80 | inline QDebug &operator=(const QDebug &other); |
81 | inline ~QDebug() { |
82 | if (!--stream->ref) { |
83 | if(stream->message_output) { |
84 | QT_TRY { |
85 | qt_message_output(stream->type, stream->buffer.toLocal8Bit().data()); |
86 | } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ } |
87 | } |
88 | delete stream; |
89 | } |
90 | } |
91 | inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; } |
92 | inline QDebug &nospace() { stream->space = false; return *this; } |
93 | inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; } |
94 | |
95 | inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); } |
96 | inline QDebug &operator<<(QBool t) { stream->ts << (bool(t != 0) ? "true" : "false" ); return maybeSpace(); } |
97 | inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false" ); return maybeSpace(); } |
98 | inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); } |
99 | inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); } |
100 | inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); } |
101 | inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); } |
102 | inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); } |
103 | inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); } |
104 | inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); } |
105 | inline QDebug &operator<<(qint64 t) |
106 | { stream->ts << QString::number(t); return maybeSpace(); } |
107 | inline QDebug &operator<<(quint64 t) |
108 | { stream->ts << QString::number(t); return maybeSpace(); } |
109 | inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); } |
110 | inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); } |
111 | inline QDebug &operator<<(const char* t) { stream->ts << QString::fromAscii(t); return maybeSpace(); } |
112 | inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); } |
113 | inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); } |
114 | inline QDebug &operator<<(const QLatin1String &t) { stream->ts << '\"' << t.latin1() << '\"'; return maybeSpace(); } |
115 | inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); } |
116 | inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); } |
117 | inline QDebug &operator<<(QTextStreamFunction f) { |
118 | stream->ts << f; |
119 | return *this; |
120 | } |
121 | |
122 | inline QDebug &operator<<(QTextStreamManipulator m) |
123 | { stream->ts << m; return *this; } |
124 | }; |
125 | |
126 | class QNoDebug |
127 | { |
128 | public: |
129 | inline QNoDebug(){} |
130 | inline QNoDebug(const QDebug &){} |
131 | inline ~QNoDebug(){} |
132 | #if !defined( QT_NO_TEXTSTREAM ) |
133 | inline QNoDebug &operator<<(QTextStreamFunction) { return *this; } |
134 | inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; } |
135 | #endif |
136 | inline QNoDebug &space() { return *this; } |
137 | inline QNoDebug &nospace() { return *this; } |
138 | inline QNoDebug &maybeSpace() { return *this; } |
139 | |
140 | template<typename T> |
141 | inline QNoDebug &operator<<(const T &) { return *this; } |
142 | }; |
143 | |
144 | Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); } |
145 | |
146 | inline QDebug &QDebug::operator=(const QDebug &other) |
147 | { |
148 | if (this != &other) { |
149 | QDebug copy(other); |
150 | qSwap(stream, copy.stream); |
151 | } |
152 | return *this; |
153 | } |
154 | |
155 | #if defined(FORCE_UREF) |
156 | template <class T> |
157 | inline QDebug &operator<<(QDebug debug, const QList<T> &list) |
158 | #else |
159 | template <class T> |
160 | inline QDebug operator<<(QDebug debug, const QList<T> &list) |
161 | #endif |
162 | { |
163 | debug.nospace() << '('; |
164 | for (Q_TYPENAME QList<T>::size_type i = 0; i < list.count(); ++i) { |
165 | if (i) |
166 | debug << ", " ; |
167 | debug << list.at(i); |
168 | } |
169 | debug << ')'; |
170 | return debug.space(); |
171 | } |
172 | |
173 | #if defined(FORCE_UREF) |
174 | template <typename T> |
175 | inline QDebug &operator<<(QDebug debug, const QVector<T> &vec) |
176 | #else |
177 | template <typename T> |
178 | inline QDebug operator<<(QDebug debug, const QVector<T> &vec) |
179 | #endif |
180 | { |
181 | debug.nospace() << "QVector" ; |
182 | return operator<<(debug, vec.toList()); |
183 | } |
184 | |
185 | #if defined(FORCE_UREF) |
186 | template <class aKey, class aT> |
187 | inline QDebug &operator<<(QDebug debug, const QMap<aKey, aT> &map) |
188 | #else |
189 | template <class aKey, class aT> |
190 | inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map) |
191 | #endif |
192 | { |
193 | debug.nospace() << "QMap(" ; |
194 | for (typename QMap<aKey, aT>::const_iterator it = map.constBegin(); |
195 | it != map.constEnd(); ++it) { |
196 | debug << '(' << it.key() << ", " << it.value() << ')'; |
197 | } |
198 | debug << ')'; |
199 | return debug.space(); |
200 | } |
201 | |
202 | #if defined(FORCE_UREF) |
203 | template <class aKey, class aT> |
204 | inline QDebug &operator<<(QDebug debug, const QHash<aKey, aT> &hash) |
205 | #else |
206 | template <class aKey, class aT> |
207 | inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash) |
208 | #endif |
209 | { |
210 | debug.nospace() << "QHash(" ; |
211 | for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin(); |
212 | it != hash.constEnd(); ++it) |
213 | debug << '(' << it.key() << ", " << it.value() << ')'; |
214 | debug << ')'; |
215 | return debug.space(); |
216 | } |
217 | |
218 | #if defined(FORCE_UREF) |
219 | template <class T1, class T2> |
220 | inline QDebug &operator<<(QDebug debug, const QPair<T1, T2> &pair) |
221 | #else |
222 | template <class T1, class T2> |
223 | inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair) |
224 | #endif |
225 | { |
226 | debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')'; |
227 | return debug.space(); |
228 | } |
229 | |
230 | template <typename T> |
231 | inline QDebug operator<<(QDebug debug, const QSet<T> &set) |
232 | { |
233 | debug.nospace() << "QSet" ; |
234 | return operator<<(debug, set.toList()); |
235 | } |
236 | |
237 | #if defined(FORCE_UREF) |
238 | template <class T> |
239 | inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache) |
240 | #else |
241 | template <class T> |
242 | inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) |
243 | #endif |
244 | { |
245 | debug.nospace() << "QContiguousCache(" ; |
246 | for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) { |
247 | debug << cache[i]; |
248 | if (i != cache.lastIndex()) |
249 | debug << ", " ; |
250 | } |
251 | debug << ')'; |
252 | return debug.space(); |
253 | } |
254 | |
255 | #if defined(FORCE_UREF) |
256 | template <class T> |
257 | inline QDebug &operator<<(QDebug debug, const QFlags<T> &flags) |
258 | #else |
259 | template <class T> |
260 | inline QDebug operator<<(QDebug debug, const QFlags<T> &flags) |
261 | #endif |
262 | { |
263 | debug.nospace() << "QFlags(" ; |
264 | bool needSeparator = false; |
265 | for (uint i = 0; i < sizeof(T) * 8; ++i) { |
266 | if (flags.testFlag(T(1 << i))) { |
267 | if (needSeparator) |
268 | debug.nospace() << '|'; |
269 | else |
270 | needSeparator = true; |
271 | debug.nospace() << "0x" << QByteArray::number(T(1 << i), 16).constData(); |
272 | } |
273 | } |
274 | debug << ')'; |
275 | return debug.space(); |
276 | } |
277 | |
278 | #if !defined(QT_NO_DEBUG_STREAM) |
279 | Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } |
280 | |
281 | #else // QT_NO_DEBUG_STREAM |
282 | #undef qDebug |
283 | inline QNoDebug qDebug() { return QNoDebug(); } |
284 | #define qDebug QT_NO_QDEBUG_MACRO |
285 | |
286 | #endif |
287 | |
288 | #if !defined(QT_NO_WARNING_OUTPUT) |
289 | Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); } |
290 | #else |
291 | #undef qWarning |
292 | inline QNoDebug qWarning() { return QNoDebug(); } |
293 | #define qWarning QT_NO_QWARNING_MACRO |
294 | #endif |
295 | |
296 | QT_END_NAMESPACE |
297 | |
298 | QT_END_HEADER |
299 | |
300 | #endif // QDEBUG_H |
301 | |