QtBase  v6.3.1
qdebug.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifdef QT_NO_DEBUG
42 #undef QT_NO_DEBUG
43 #endif
44 #ifdef qDebug
45 #undef qDebug
46 #endif
47 
48 #include "qdebug.h"
49 #include "private/qdebug_p.h"
50 #include "qmetaobject.h"
51 #include <private/qtextstream_p.h>
52 #include <private/qtools_p.h>
53 #include <ctype.h>
54 
56 
60 
61 /*
62  Returns a human readable representation of the first \a maxSize
63  characters in \a data.
64 */
65 QByteArray QtDebugUtils::toPrintable(const char *data, int len, int maxSize)
66 {
67  if (!data)
68  return "(null)";
69 
71  for (int i = 0; i < qMin(len, maxSize); ++i) {
72  char c = data[i];
73  if (isprint(c)) {
74  out += c;
75  } else {
76  switch (c) {
77  case '\n':
78  out += "\\n";
79  break;
80  case '\r':
81  out += "\\r";
82  break;
83  case '\t':
84  out += "\\t";
85  break;
86  default: {
87  const char buf[] = {
88  '\\',
89  'x',
90  toHexLower(uchar(c) / 16),
91  toHexLower(uchar(c) % 16),
92  0
93  };
94  out += buf;
95  }
96  }
97  }
98  }
99 
100  if (maxSize < len)
101  out += "...";
102 
103  return out;
104 }
105 
106 // This file is needed to force compilation of QDebug into the kernel library.
107 
195 // Has been defined in the header / inlined before Qt 5.4
197 {
198  if (stream && !--stream->ref) {
199  if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
200  stream->buffer.chop(1);
201  if (stream->message_output) {
203  stream->context,
204  stream->buffer);
205  }
206  delete stream;
207  }
208 }
209 
213 void QDebug::putUcs4(uint ucs4)
214 {
215  maybeQuote('\'');
216  if (ucs4 < 0x20) {
217  stream->ts << "\\x" << Qt::hex << ucs4 << Qt::reset;
218  } else if (ucs4 < 0x80) {
219  stream->ts << char(ucs4);
220  } else {
221  if (ucs4 < 0x10000)
222  stream->ts << "\\u" << qSetFieldWidth(4);
223  else
224  stream->ts << "\\U" << qSetFieldWidth(8);
225  stream->ts << Qt::hex << qSetPadChar(QLatin1Char('0')) << ucs4 << Qt::reset;
226  }
227  maybeQuote('\'');
228 }
229 
230 // These two functions return true if the character should be printed by QDebug.
231 // For QByteArray, this is technically identical to US-ASCII isprint();
232 // for QString, we use QChar::isPrint, which requires a full UCS-4 decode.
233 static inline bool isPrintable(uint ucs4)
234 { return QChar::isPrint(ucs4); }
235 static inline bool isPrintable(ushort uc)
236 { return QChar::isPrint(uc); }
237 static inline bool isPrintable(uchar c)
238 { return c >= ' ' && c < 0x7f; }
239 
240 template <typename Char>
241 static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, int length, bool isUnicode = true)
242 {
243  QChar quote(QLatin1Char('"'));
244  d->write(&quote, 1);
245 
246  bool lastWasHexEscape = false;
247  const Char *end = begin + length;
248  for (const Char *p = begin; p != end; ++p) {
249  // check if we need to insert "" to break an hex escape sequence
250  if (Q_UNLIKELY(lastWasHexEscape)) {
251  if (fromHex(*p) != -1) {
252  // yes, insert it
253  QChar quotes[] = { QLatin1Char('"'), QLatin1Char('"') };
254  d->write(quotes, 2);
255  }
256  lastWasHexEscape = false;
257  }
258 
259  if (sizeof(Char) == sizeof(QChar)) {
260  // Surrogate characters are category Cs (Other_Surrogate), so isPrintable = false for them
261  int runLength = 0;
262  while (p + runLength != end &&
263  isPrintable(p[runLength]) && p[runLength] != '\\' && p[runLength] != '"')
264  ++runLength;
265  if (runLength) {
266  d->write(reinterpret_cast<const QChar *>(p), runLength);
267  p += runLength - 1;
268  continue;
269  }
270  } else if (isPrintable(*p) && *p != '\\' && *p != '"') {
271  QChar c = QLatin1Char(*p);
272  d->write(&c, 1);
273  continue;
274  }
275 
276  // print as an escape sequence (maybe, see below for surrogate pairs)
277  int buflen = 2;
278  ushort buf[sizeof "\\U12345678" - 1];
279  buf[0] = '\\';
280 
281  switch (*p) {
282  case '"':
283  case '\\':
284  buf[1] = *p;
285  break;
286  case '\b':
287  buf[1] = 'b';
288  break;
289  case '\f':
290  buf[1] = 'f';
291  break;
292  case '\n':
293  buf[1] = 'n';
294  break;
295  case '\r':
296  buf[1] = 'r';
297  break;
298  case '\t':
299  buf[1] = 't';
300  break;
301  default:
302  if (!isUnicode) {
303  // print as hex escape
304  buf[1] = 'x';
305  buf[2] = toHexUpper(uchar(*p) >> 4);
306  buf[3] = toHexUpper(uchar(*p));
307  buflen = 4;
308  lastWasHexEscape = true;
309  break;
310  }
311  if (QChar::isHighSurrogate(*p)) {
312  if ((p + 1) != end && QChar::isLowSurrogate(p[1])) {
313  // properly-paired surrogates
314  uint ucs4 = QChar::surrogateToUcs4(*p, p[1]);
315  if (isPrintable(ucs4)) {
316  buf[0] = *p;
317  buf[1] = p[1];
318  buflen = 2;
319  } else {
320  buf[1] = 'U';
321  buf[2] = '0'; // toHexUpper(ucs4 >> 32);
322  buf[3] = '0'; // toHexUpper(ucs4 >> 28);
323  buf[4] = toHexUpper(ucs4 >> 20);
324  buf[5] = toHexUpper(ucs4 >> 16);
325  buf[6] = toHexUpper(ucs4 >> 12);
326  buf[7] = toHexUpper(ucs4 >> 8);
327  buf[8] = toHexUpper(ucs4 >> 4);
328  buf[9] = toHexUpper(ucs4);
329  buflen = 10;
330  }
331  ++p;
332  break;
333  }
334  // improperly-paired surrogates, fall through
335  }
336  buf[1] = 'u';
337  buf[2] = toHexUpper(ushort(*p) >> 12);
338  buf[3] = toHexUpper(ushort(*p) >> 8);
339  buf[4] = toHexUpper(*p >> 4);
340  buf[5] = toHexUpper(*p);
341  buflen = 6;
342  }
343  d->write(reinterpret_cast<QChar *>(buf), buflen);
344  }
345 
346  d->write(&quote, 1);
347 }
348 
353 void QDebug::putString(const QChar *begin, size_t length)
354 {
355  if (stream->noQuotes) {
356  // no quotes, write the string directly too (no pretty-printing)
357  // this respects the QTextStream state, though
358  stream->ts.d_ptr->putString(begin, int(length));
359  } else {
360  // we'll reset the QTextStream formatting mechanisms, so save the state
361  QDebugStateSaver saver(*this);
362  stream->ts.d_ptr->params.reset();
363  putEscapedString(stream->ts.d_ptr.data(), reinterpret_cast<const ushort *>(begin), int(length));
364  }
365 }
366 
371 void QDebug::putByteArray(const char *begin, size_t length, Latin1Content content)
372 {
373  if (stream->noQuotes) {
374  // no quotes, write the string directly too (no pretty-printing)
375  // this respects the QTextStream state, though
376  QString string = content == ContainsLatin1 ? QString::fromLatin1(begin, int(length)) : QString::fromUtf8(begin, int(length));
377  stream->ts.d_ptr->putString(string);
378  } else {
379  // we'll reset the QTextStream formatting mechanisms, so save the state
380  QDebugStateSaver saver(*this);
381  stream->ts.d_ptr->params.reset();
382  putEscapedString(stream->ts.d_ptr.data(), reinterpret_cast<const uchar *>(begin),
383  int(length), content == ContainsLatin1);
384  }
385 }
386 
402 {
403  stream->ts.reset();
404  stream->space = true;
405  stream->noQuotes = false;
407  return *this;
408 }
409 
972 {
973 public:
975  : m_stream(stream),
976  m_spaces(stream->space),
977  m_noQuotes(stream->noQuotes),
978  m_verbosity(stream->verbosity),
979  m_streamParams(stream->ts.d_ptr->params)
980  {
981  }
983  {
984  const bool currentSpaces = m_stream->space;
985  if (currentSpaces && !m_spaces)
986  if (m_stream->buffer.endsWith(QLatin1Char(' ')))
987  m_stream->buffer.chop(1);
988 
989  m_stream->space = m_spaces;
990  m_stream->noQuotes = m_noQuotes;
991  m_stream->ts.d_ptr->params = m_streamParams;
992  m_stream->verbosity = m_verbosity;
993 
994  if (!currentSpaces && m_spaces)
995  m_stream->ts << ' ';
996  }
997 
998  QDebug::Stream *m_stream;
999 
1000  // QDebug state
1001  const bool m_spaces;
1002  const bool m_noQuotes;
1003  const int m_verbosity;
1004 
1005  // QTextStream state
1007 };
1008 
1009 
1017  : d(new QDebugStateSaverPrivate(dbg.stream))
1018 {
1019 }
1020 
1028 {
1029  d->restoreState();
1030 }
1031 
1041 {
1042  qt_QMetaEnum_flagDebugOperator<int>(debug, sizeofT, value);
1043 }
1044 
1045 #ifndef QT_NO_QOBJECT
1083 {
1084  QDebugStateSaver saver(dbg);
1085  dbg.nospace();
1086  QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
1087 
1088  const int verbosity = dbg.verbosity();
1089  if (verbosity >= QDebug::DefaultVerbosity) {
1090  if (const char *scope = me.scope())
1091  dbg << scope << u"::";
1092  }
1093 
1094  const char *key = me.valueToKey(value);
1095  const bool scoped = me.isScoped() || verbosity & 1;
1096  if (scoped || !key)
1097  dbg << me.enumName() << (!key ? u"(" : u"::");
1098 
1099  if (key)
1100  dbg << key;
1101  else
1102  dbg << value << ')';
1103 
1104  return dbg;
1105 }
1106 
1137 {
1138  const int verbosity = debug.verbosity();
1139 
1140  QDebugStateSaver saver(debug);
1141  debug.resetFormat();
1142  debug.noquote();
1143  debug.nospace();
1144 
1145  const QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
1146 
1147  const bool classScope = verbosity >= QDebug::DefaultVerbosity;
1148  if (classScope) {
1149  debug << u"QFlags<";
1150 
1151  if (const char *scope = me.scope())
1152  debug << scope << u"::";
1153  }
1154 
1155  const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity;
1156  if (enumScope) {
1157  debug << me.enumName();
1158  if (classScope)
1159  debug << '>';
1160  debug << '(';
1161  }
1162 
1163  debug << me.valueToKeys(value);
1164 
1165  if (enumScope)
1166  debug << ')';
1167 
1168  return debug;
1169 }
1170 #endif // !QT_NO_QOBJECT
1171 
1172 QT_END_NAMESPACE
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:84
static constexpr char32_t surrogateToUcs4(char16_t high, char16_t low) noexcept
Definition: qchar.h:539
constexpr bool isLowSurrogate() const noexcept
Definition: qchar.h:511
bool isPrint() const noexcept
Definition: qchar.h:496
constexpr bool isHighSurrogate() const noexcept
Definition: qchar.h:510
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
QDebug & verbosity(int verbosityLevel)
Definition: qdebug.h:115
~QDebug()
Definition: qdebug.cpp:196
QDebug & maybeQuote(char c='"')
Definition: qdebug.h:125
QDebug & resetFormat()
Definition: qdebug.cpp:401
QDebug & nospace()
Definition: qdebug.h:113
@ MinimumVerbosity
Definition: qdebug.h:118
@ DefaultVerbosity
Definition: qdebug.h:118
QDebug & space()
Definition: qdebug.h:112
Convenience class for custom QDebug operators.
Definition: qdebug.h:176
QDebugStateSaver(QDebug &dbg)
Definition: qdebug.cpp:1016
const QTextStreamPrivate::Params m_streamParams
Definition: qdebug.cpp:1006
QDebug::Stream * m_stream
Definition: qdebug.cpp:998
QDebugStateSaverPrivate(QDebug::Stream *stream)
Definition: qdebug.cpp:974
The QMetaEnum class provides meta-data about an enumerator.
Definition: qmetaobject.h:220
const char * valueToKey(int value) const
bool isScoped() const
const char * enumName() const
const char * scope() const
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
qsizetype fromUtf8(uchar b, OutputPtr &dst, InputPtr &src, InputPtr end)
Q_CORE_EXPORT QByteArray toPrintable(const char *data, int len, int maxSize)
Definition: qdebug.cpp:65
QTextStream & hex(QTextStream &stream)
QTextStream & reset(QTextStream &stream)
constexpr char toHexUpper(uint value) noexcept
Definition: qtools_p.h:60
constexpr char toHexLower(uint value) noexcept
Definition: qtools_p.h:65
constexpr int fromHex(uint c) noexcept
Definition: qtools_p.h:70
#define Q_UNLIKELY(x)
QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, qint64 value, const QMetaObject *meta, const char *name)
Definition: qdebug.cpp:1082
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
Definition: qdebug.cpp:1040
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
Definition: qglobal.h:332
unsigned long long quint64
Definition: qglobal.h:299
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
unsigned short ushort
Definition: qglobal.h:333
Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context, const QString &message)
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLuint64 key
GLuint GLuint end
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
void ** params
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLsizei len
Definition: qopenglext.h:3292
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QT_BEGIN_NAMESPACE typedef char Char
QTextStreamManipulator qSetPadChar(QChar ch)
Definition: qtextstream.h:273
QTextStreamManipulator qSetFieldWidth(int width)
Definition: qtextstream.h:267
QTextStream out(stdout)
[7]
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:165
int indexOfEnumerator(const char *name) const
QMetaEnum enumerator(int index) const