Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2013 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_NAMESPACE
57 :
58 :
59 : class Q_CORE_EXPORT QDebug
60 : {
61 : friend class QMessageLogger;
62 : friend class QDebugStateSaverPrivate;
63 0 : struct Stream {
64 : Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
65 : Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
66 : Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true) {}
67 : QTextStream ts;
68 : QString buffer;
69 : int ref;
70 : QtMsgType type;
71 : bool space;
72 : bool message_output;
73 : QMessageLogContext context;
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 0 : inline ~QDebug() {
82 0 : if (!--stream->ref) {
83 0 : if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
84 0 : stream->buffer.chop(1);
85 0 : if (stream->message_output) {
86 : QT_TRY {
87 : qt_message_output(stream->type,
88 : stream->context,
89 0 : stream->buffer);
90 0 : } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ }
91 : }
92 0 : delete stream;
93 : }
94 0 : }
95 : inline void swap(QDebug &other) { qSwap(stream, other.stream); }
96 :
97 : inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
98 : inline QDebug &nospace() { stream->space = false; return *this; }
99 0 : inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
100 :
101 : bool autoInsertSpaces() const { return stream->space; }
102 : void setAutoInsertSpaces(bool b) { stream->space = b; }
103 :
104 : inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
105 0 : inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
106 : inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
107 : inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
108 : inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
109 : inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
110 : inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
111 : inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
112 : inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
113 : inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
114 : inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
115 : inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
116 : inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
117 0 : inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
118 0 : inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
119 : inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
120 : inline QDebug &operator<<(QLatin1String t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
121 : inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
122 : inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
123 : inline QDebug &operator<<(QTextStreamFunction f) {
124 : stream->ts << f;
125 : return *this;
126 : }
127 :
128 : inline QDebug &operator<<(QTextStreamManipulator m)
129 : { stream->ts << m; return *this; }
130 : };
131 :
132 : Q_DECLARE_SHARED(QDebug)
133 :
134 : class QDebugStateSaverPrivate;
135 : class Q_CORE_EXPORT QDebugStateSaver
136 : {
137 : public:
138 : QDebugStateSaver(QDebug &dbg);
139 : ~QDebugStateSaver();
140 : private:
141 : Q_DISABLE_COPY(QDebugStateSaver)
142 : QScopedPointer<QDebugStateSaverPrivate> d;
143 : };
144 :
145 : class QNoDebug
146 : {
147 : public:
148 : inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
149 : inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
150 : inline QNoDebug &space() { return *this; }
151 : inline QNoDebug &nospace() { return *this; }
152 : inline QNoDebug &maybeSpace() { return *this; }
153 :
154 : template<typename T>
155 : inline QNoDebug &operator<<(const T &) { return *this; }
156 : };
157 :
158 : inline QDebug &QDebug::operator=(const QDebug &other)
159 : {
160 : if (this != &other) {
161 : QDebug copy(other);
162 : qSwap(stream, copy.stream);
163 : }
164 : return *this;
165 : }
166 :
167 : #if defined(FORCE_UREF)
168 : template <class T>
169 : inline QDebug &operator<<(QDebug debug, const QList<T> &list)
170 : #else
171 : template <class T>
172 : inline QDebug operator<<(QDebug debug, const QList<T> &list)
173 : #endif
174 : {
175 : const bool oldSetting = debug.autoInsertSpaces();
176 : debug.nospace() << '(';
177 : for (typename QList<T>::size_type i = 0; i < list.count(); ++i) {
178 : if (i)
179 : debug << ", ";
180 : debug << list.at(i);
181 : }
182 : debug << ')';
183 : debug.setAutoInsertSpaces(oldSetting);
184 : return debug.maybeSpace();
185 : }
186 :
187 : #if defined(FORCE_UREF)
188 : template <typename T>
189 : inline QDebug &operator<<(QDebug debug, const QVector<T> &vec)
190 : #else
191 : template <typename T>
192 : inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
193 : #endif
194 : {
195 : const bool oldSetting = debug.autoInsertSpaces();
196 : debug.nospace() << "QVector";
197 : debug.setAutoInsertSpaces(oldSetting);
198 : return operator<<(debug, vec.toList());
199 : }
200 :
201 : #if defined(FORCE_UREF)
202 : template <class aKey, class aT>
203 : inline QDebug &operator<<(QDebug debug, const QMap<aKey, aT> &map)
204 : #else
205 : template <class aKey, class aT>
206 : inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
207 : #endif
208 : {
209 : const bool oldSetting = debug.autoInsertSpaces();
210 : debug.nospace() << "QMap(";
211 : for (typename QMap<aKey, aT>::const_iterator it = map.constBegin();
212 : it != map.constEnd(); ++it) {
213 : debug << '(' << it.key() << ", " << it.value() << ')';
214 : }
215 : debug << ')';
216 : debug.setAutoInsertSpaces(oldSetting);
217 : return debug.maybeSpace();
218 : }
219 :
220 : #if defined(FORCE_UREF)
221 : template <class aKey, class aT>
222 : inline QDebug &operator<<(QDebug debug, const QHash<aKey, aT> &hash)
223 : #else
224 : template <class aKey, class aT>
225 : inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
226 : #endif
227 : {
228 : const bool oldSetting = debug.autoInsertSpaces();
229 : debug.nospace() << "QHash(";
230 : for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin();
231 : it != hash.constEnd(); ++it)
232 : debug << '(' << it.key() << ", " << it.value() << ')';
233 : debug << ')';
234 : debug.setAutoInsertSpaces(oldSetting);
235 : return debug.maybeSpace();
236 : }
237 :
238 : #if defined(FORCE_UREF)
239 : template <class T1, class T2>
240 : inline QDebug &operator<<(QDebug debug, const QPair<T1, T2> &pair)
241 : #else
242 : template <class T1, class T2>
243 : inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
244 : #endif
245 : {
246 : const bool oldSetting = debug.autoInsertSpaces();
247 : debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
248 : debug.setAutoInsertSpaces(oldSetting);
249 : return debug.maybeSpace();
250 : }
251 :
252 : template <typename T>
253 : inline QDebug operator<<(QDebug debug, const QSet<T> &set)
254 : {
255 : const bool oldSetting = debug.autoInsertSpaces();
256 : debug.nospace() << "QSet";
257 : debug.setAutoInsertSpaces(oldSetting);
258 : return operator<<(debug, set.toList());
259 : }
260 :
261 : #if defined(FORCE_UREF)
262 : template <class T>
263 : inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
264 : #else
265 : template <class T>
266 : inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
267 : #endif
268 : {
269 : const bool oldSetting = debug.autoInsertSpaces();
270 : debug.nospace() << "QContiguousCache(";
271 : for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
272 : debug << cache[i];
273 : if (i != cache.lastIndex())
274 : debug << ", ";
275 : }
276 : debug << ')';
277 : debug.setAutoInsertSpaces(oldSetting);
278 : return debug.maybeSpace();
279 : }
280 :
281 : #if defined(FORCE_UREF)
282 : template <class T>
283 : inline QDebug &operator<<(QDebug debug, const QFlags<T> &flags)
284 : #else
285 : template <class T>
286 : inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
287 : #endif
288 : {
289 : const bool oldSetting = debug.autoInsertSpaces();
290 : debug.nospace() << "QFlags(";
291 : bool needSeparator = false;
292 : for (uint i = 0; i < sizeof(T) * 8; ++i) {
293 : if (flags.testFlag(T(1 << i))) {
294 : if (needSeparator)
295 : debug.nospace() << '|';
296 : else
297 : needSeparator = true;
298 : debug.nospace() << "0x" << QByteArray::number(typename QFlags<T>::Int(1) << i, 16).constData();
299 : }
300 : }
301 : debug << ')';
302 : debug.setAutoInsertSpaces(oldSetting);
303 : return debug.maybeSpace();
304 : }
305 :
306 : QT_END_NAMESPACE
307 :
308 : #endif // QDEBUG_H
|