source: trunk/src/corelib/io/qdebug.h@ 604

Last change on this file since 604 was 604, checked in by Dmitry A. Kuminov, 15 years ago

corelib: Added qDebugFmt() and qDebugFmtHex() debug stream modifiers to ease formatting of integers in debug printing.

File size: 11.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
56QT_BEGIN_HEADER
57
58QT_BEGIN_NAMESPACE
59
60QT_MODULE(Core)
61
62class 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;
75public:
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
126class QNoDebug
127{
128public:
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#ifndef QT_NO_MEMBER_TEMPLATES
141 template<typename T>
142 inline QNoDebug &operator<<(const T &) { return *this; }
143#endif
144};
145
146Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); }
147
148inline QDebug &QDebug::operator=(const QDebug &other)
149{
150 if (this != &other) {
151 QDebug copy(other);
152 qSwap(stream, copy.stream);
153 }
154 return *this;
155}
156
157#if defined(FORCE_UREF)
158template <class T>
159inline QDebug &operator<<(QDebug debug, const QList<T> &list)
160#else
161template <class T>
162inline QDebug operator<<(QDebug debug, const QList<T> &list)
163#endif
164{
165 debug.nospace() << '(';
166 for (Q_TYPENAME QList<T>::size_type i = 0; i < list.count(); ++i) {
167 if (i)
168 debug << ", ";
169 debug << list.at(i);
170 }
171 debug << ')';
172 return debug.space();
173}
174
175#if defined(FORCE_UREF)
176template <typename T>
177inline QDebug &operator<<(QDebug debug, const QVector<T> &vec)
178#else
179template <typename T>
180inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
181#endif
182{
183 debug.nospace() << "QVector";
184 return operator<<(debug, vec.toList());
185}
186
187#if defined(FORCE_UREF)
188template <class aKey, class aT>
189inline QDebug &operator<<(QDebug debug, const QMap<aKey, aT> &map)
190#else
191template <class aKey, class aT>
192inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
193#endif
194{
195 debug.nospace() << "QMap(";
196 for (typename QMap<aKey, aT>::const_iterator it = map.constBegin();
197 it != map.constEnd(); ++it) {
198 debug << '(' << it.key() << ", " << it.value() << ')';
199 }
200 debug << ')';
201 return debug.space();
202}
203
204#if defined(FORCE_UREF)
205template <class aKey, class aT>
206inline QDebug &operator<<(QDebug debug, const QHash<aKey, aT> &hash)
207#else
208template <class aKey, class aT>
209inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
210#endif
211{
212 debug.nospace() << "QHash(";
213 for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin();
214 it != hash.constEnd(); ++it)
215 debug << '(' << it.key() << ", " << it.value() << ')';
216 debug << ')';
217 return debug.space();
218}
219
220#if defined(FORCE_UREF)
221template <class T1, class T2>
222inline QDebug &operator<<(QDebug debug, const QPair<T1, T2> &pair)
223#else
224template <class T1, class T2>
225inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
226#endif
227{
228 debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
229 return debug.space();
230}
231
232template <typename T>
233inline QDebug operator<<(QDebug debug, const QSet<T> &set)
234{
235 debug.nospace() << "QSet";
236 return operator<<(debug, set.toList());
237}
238
239#if defined(FORCE_UREF)
240template <class T>
241inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
242#else
243template <class T>
244inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
245#endif
246{
247 debug.nospace() << "QContiguousCache(";
248 for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
249 debug << cache[i];
250 if (i != cache.lastIndex())
251 debug << ", ";
252 }
253 debug << ')';
254 return debug.space();
255}
256
257template <class T>
258struct QDebugFmt
259{
260 QDebugFmt(const char *fmt, const T &val) : format(fmt), value(val) {};
261 const char *format;
262 const T &value;
263};
264
265template <class T>
266inline QDebugFmt<T> qDebugFmt(const char *fmt, const T &val)
267{
268 return QDebugFmt<T>(fmt, val);
269}
270
271inline QDebugFmt<char> qDebugFmtHex(const char &val) { return qDebugFmt("0x%02X", val); }
272inline QDebugFmt<char> qDebugFmtHex(const uchar &val) { return qDebugFmtHex(reinterpret_cast<const char &>(val)); }
273inline QDebugFmt<short> qDebugFmtHex(const short &val) { return qDebugFmt("0x%04X", val); }
274inline QDebugFmt<short> qDebugFmtHex(const ushort &val) { return qDebugFmtHex(reinterpret_cast<const short &>(val)); }
275inline QDebugFmt<int> qDebugFmtHex(const int &val) { return qDebugFmt("0x%08X", val); }
276inline QDebugFmt<int> qDebugFmtHex(const uint &val) { return qDebugFmtHex(reinterpret_cast<const int &>(val)); }
277inline QDebugFmt<long> qDebugFmtHex(const long &val) { return qDebugFmt("0x%08lX", val); }
278inline QDebugFmt<long> qDebugFmtHex(const ulong &val) { return qDebugFmtHex(reinterpret_cast<const long &>(val)); }
279
280#if defined(FORCE_UREF)
281template <class T>
282inline QDebug &operator<<(QDebug debug, const QDebugFmt<T> &fmt)
283#else
284template <class T>
285inline QDebug operator<<(QDebug debug, const QDebugFmt<T> &fmt)
286#endif
287{
288 debug << QString().sprintf(fmt.format, fmt.value).toAscii().constData();
289 return debug;
290}
291
292#if !defined(QT_NO_DEBUG_STREAM)
293Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); }
294
295#else // QT_NO_DEBUG_STREAM
296#undef qDebug
297inline QNoDebug qDebug() { return QNoDebug(); }
298#define qDebug QT_NO_QDEBUG_MACRO
299
300#ifdef QT_NO_MEMBER_TEMPLATES
301template<typename T>
302inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; }
303#endif
304
305#endif
306
307#if !defined(QT_NO_WARNING_OUTPUT)
308Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); }
309#else
310#undef qWarning
311inline QNoDebug qWarning() { return QNoDebug(); }
312#define qWarning QT_NO_QWARNING_MACRO
313#endif
314
315QT_END_NAMESPACE
316
317QT_END_HEADER
318
319#endif // QDEBUG_H
Note: See TracBrowser for help on using the repository browser.