Allow printf style for qCDebug, qCWarning, qCCritical macros
Add support for using qCDebug and friends in the 'printf style' way. This allows an almost mechanical conversion of existing qDebug, qWarning, qCritical macros, and allows avoiding the size overhead the streaming style incurs (mostly due to inlined QDebug code). To handle this gracefully we require variadic macros (part of C++11/C99). For compilers not supporting variadic macros we fall back to checking the category in QMessageLogger. [ChangeLog][QtCore][Logging] Allow qCDebug macros to be used in a printf style. Change-Id: I5a8fb135dca504e1d621bb67bf4b2a50c73d41b9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
b152b425f7
commit
b8a38a6737
@ -52,3 +52,7 @@
|
||||
}
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
QLoggingCategory &category();
|
||||
//! [2]
|
||||
|
@ -128,6 +128,27 @@ oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
|
||||
//![12]
|
||||
}
|
||||
|
||||
{
|
||||
//![13]
|
||||
QLoggingCategory category("qt.driver.usb");
|
||||
qCDebug(category, "a debug message logged into category %s", category.categoryName());
|
||||
//![13]
|
||||
}
|
||||
|
||||
{
|
||||
//![14]
|
||||
QLoggingCategory category("qt.driver.usb");
|
||||
qCWarning(category, "a warning message logged into category %s", category.categoryName());
|
||||
//![14]
|
||||
}
|
||||
|
||||
{
|
||||
//![15]
|
||||
QLoggingCategory category("qt.driver.usb");
|
||||
qCCritical(category, "a critical message logged into category %s", category.categoryName());
|
||||
//![15]
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,10 @@
|
||||
#include "qvarlengtharray.h"
|
||||
#include "qdebug.h"
|
||||
#include "qmutex.h"
|
||||
#include "qloggingcategory.h"
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#include "qcoreapplication.h"
|
||||
#include "qthread.h"
|
||||
#include "qloggingcategory.h"
|
||||
#include "private/qloggingregistry_p.h"
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
@ -270,6 +270,74 @@ void QMessageLogger::debug(const char *msg, ...) const
|
||||
qt_message_fatal(QtDebugMsg, context, message);
|
||||
}
|
||||
|
||||
/*!
|
||||
\typedef QMessageLogger::CategoryFunction
|
||||
|
||||
This is a typedef for a pointer to a function with the following
|
||||
signature:
|
||||
|
||||
\snippet code/qlogging/qlogging.cpp 2
|
||||
|
||||
A function which this signature is generated by Q_DECLARE_LOGGING_CATEGORY,
|
||||
Q_LOGGING_CATEGORY.
|
||||
|
||||
\since 5.3
|
||||
*/
|
||||
|
||||
/*!
|
||||
Logs a debug message specified with format \a msg for the context \a cat.
|
||||
Additional parameters, specified by \a msg, may be used.
|
||||
|
||||
\since 5.3
|
||||
\sa qCDebug()
|
||||
*/
|
||||
void QMessageLogger::debug(const QLoggingCategory &cat, const char *msg, ...) const
|
||||
{
|
||||
if (!cat.isDebugEnabled())
|
||||
return;
|
||||
|
||||
QMessageLogContext ctxt;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
QString message;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg); // use variable arg list
|
||||
qt_message(QtDebugMsg, ctxt, msg, ap, message);
|
||||
va_end(ap);
|
||||
|
||||
if (isFatal(QtDebugMsg))
|
||||
qt_message_fatal(QtDebugMsg, ctxt, message);
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a debug message specified with format \a msg for the context returned
|
||||
by \a catFunc. Additional parameters, specified by \a msg, may be used.
|
||||
|
||||
\since 5.3
|
||||
\sa qCDebug()
|
||||
*/
|
||||
void QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc,
|
||||
const char *msg, ...) const
|
||||
{
|
||||
const QLoggingCategory &cat = (*catFunc)();
|
||||
|
||||
QMessageLogContext ctxt;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
QString message;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg); // use variable arg list
|
||||
qt_message(QtDebugMsg, ctxt, msg, ap, message);
|
||||
va_end(ap);
|
||||
|
||||
if (isFatal(QtDebugMsg))
|
||||
qt_message_fatal(QtDebugMsg, ctxt, message);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
/*!
|
||||
@ -285,6 +353,36 @@ QDebug QMessageLogger::debug() const
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a debug message into category \a cat using a QDebug stream.
|
||||
|
||||
\since 5.3
|
||||
\sa qCDebug(), QDebug
|
||||
*/
|
||||
QDebug QMessageLogger::debug(const QLoggingCategory &cat) const
|
||||
{
|
||||
QDebug dbg = QDebug(QtDebugMsg);
|
||||
if (!cat.isDebugEnabled())
|
||||
dbg.stream->message_output = false;
|
||||
|
||||
QMessageLogContext &ctxt = dbg.stream->context;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a debug message into category returned by \a catFunc using a QDebug stream.
|
||||
|
||||
\since 5.3
|
||||
\sa qCDebug(), QDebug
|
||||
*/
|
||||
QDebug QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc) const
|
||||
{
|
||||
return debug((*catFunc)());
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
@ -319,9 +417,65 @@ void QMessageLogger::warning(const char *msg, ...) const
|
||||
qt_message_fatal(QtWarningMsg, context, message);
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a warning message specified with format \a msg for the context \a cat.
|
||||
Additional parameters, specified by \a msg, may be used.
|
||||
|
||||
\since 5.3
|
||||
\sa qCWarning()
|
||||
*/
|
||||
void QMessageLogger::warning(const QLoggingCategory &cat, const char *msg, ...) const
|
||||
{
|
||||
if (!cat.isWarningEnabled())
|
||||
return;
|
||||
|
||||
QMessageLogContext ctxt;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
QString message;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg); // use variable arg list
|
||||
qt_message(QtWarningMsg, ctxt, msg, ap, message);
|
||||
va_end(ap);
|
||||
|
||||
if (isFatal(QtWarningMsg))
|
||||
qt_message_fatal(QtWarningMsg, ctxt, message);
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a warning message specified with format \a msg for the context returned
|
||||
by \a catFunc. Additional parameters, specified by \a msg, may be used.
|
||||
|
||||
\since 5.3
|
||||
\sa qCWarning()
|
||||
*/
|
||||
void QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc,
|
||||
const char *msg, ...) const
|
||||
{
|
||||
const QLoggingCategory &cat = (*catFunc)();
|
||||
if (!cat.isWarningEnabled())
|
||||
return;
|
||||
|
||||
QMessageLogContext ctxt;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
QString message;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg); // use variable arg list
|
||||
qt_message(QtWarningMsg, ctxt, msg, ap, message);
|
||||
va_end(ap);
|
||||
|
||||
if (isFatal(QtWarningMsg))
|
||||
qt_message_fatal(QtWarningMsg, ctxt, message);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
/*!
|
||||
Logs a debug message using a QDebug stream
|
||||
Logs a warning message using a QDebug stream
|
||||
|
||||
\sa qWarning(), QDebug
|
||||
*/
|
||||
@ -332,6 +486,36 @@ QDebug QMessageLogger::warning() const
|
||||
ctxt.copy(context);
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a warning message into category \a cat using a QDebug stream.
|
||||
|
||||
\sa qCWarning(), QDebug
|
||||
*/
|
||||
QDebug QMessageLogger::warning(const QLoggingCategory &cat) const
|
||||
{
|
||||
QDebug dbg = QDebug(QtWarningMsg);
|
||||
if (!cat.isWarningEnabled())
|
||||
dbg.stream->message_output = false;
|
||||
|
||||
QMessageLogContext &ctxt = dbg.stream->context;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a warning message into category returned by \a catFunc using a QDebug stream.
|
||||
|
||||
\since 5.3
|
||||
\sa qCWarning(), QDebug
|
||||
*/
|
||||
QDebug QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc) const
|
||||
{
|
||||
return warning((*catFunc)());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#undef qCritical
|
||||
@ -355,6 +539,62 @@ void QMessageLogger::critical(const char *msg, ...) const
|
||||
qt_message_fatal(QtCriticalMsg, context, message);
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a critical message specified with format \a msg for the context \a cat.
|
||||
Additional parameters, specified by \a msg, may be used.
|
||||
|
||||
\since 5.3
|
||||
\sa qCCritical()
|
||||
*/
|
||||
void QMessageLogger::critical(const QLoggingCategory &cat, const char *msg, ...) const
|
||||
{
|
||||
if (!cat.isCriticalEnabled())
|
||||
return;
|
||||
|
||||
QMessageLogContext ctxt;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
QString message;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg); // use variable arg list
|
||||
qt_message(QtCriticalMsg, ctxt, msg, ap, message);
|
||||
va_end(ap);
|
||||
|
||||
if (isFatal(QtCriticalMsg))
|
||||
qt_message_fatal(QtCriticalMsg, ctxt, message);
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a critical message specified with format \a msg for the context returned
|
||||
by \a catFunc. Additional parameters, specified by \a msg, may be used.
|
||||
|
||||
\since 5.3
|
||||
\sa qCCritical()
|
||||
*/
|
||||
void QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc,
|
||||
const char *msg, ...) const
|
||||
{
|
||||
const QLoggingCategory &cat = (*catFunc)();
|
||||
if (!cat.isCriticalEnabled())
|
||||
return;
|
||||
|
||||
QMessageLogContext ctxt;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
QString message;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg); // use variable arg list
|
||||
qt_message(QtCriticalMsg, ctxt, msg, ap, message);
|
||||
va_end(ap);
|
||||
|
||||
if (isFatal(QtCriticalMsg))
|
||||
qt_message_fatal(QtCriticalMsg, ctxt, message);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
/*!
|
||||
Logs a critical message using a QDebug stream
|
||||
@ -368,6 +608,37 @@ QDebug QMessageLogger::critical() const
|
||||
ctxt.copy(context);
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a critical message into category \a cat using a QDebug stream.
|
||||
|
||||
\since 5.3
|
||||
\sa qCCritical(), QDebug
|
||||
*/
|
||||
QDebug QMessageLogger::critical(const QLoggingCategory &cat) const
|
||||
{
|
||||
QDebug dbg = QDebug(QtCriticalMsg);
|
||||
if (!cat.isCriticalEnabled())
|
||||
dbg.stream->message_output = false;
|
||||
|
||||
QMessageLogContext &ctxt = dbg.stream->context;
|
||||
ctxt.copy(context);
|
||||
ctxt.category = cat.categoryName();
|
||||
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/*!
|
||||
Logs a critical message into category returned by \a catFunc using a QDebug stream.
|
||||
|
||||
\since 5.3
|
||||
\sa qCCritical(), QDebug
|
||||
*/
|
||||
QDebug QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc) const
|
||||
{
|
||||
return critical((*catFunc)());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#undef qFatal
|
||||
|
@ -82,6 +82,8 @@ private:
|
||||
friend class QDebug;
|
||||
};
|
||||
|
||||
class QLoggingCategory;
|
||||
|
||||
class Q_CORE_EXPORT QMessageLogger
|
||||
{
|
||||
Q_DISABLE_COPY(QMessageLogger)
|
||||
@ -98,6 +100,15 @@ public:
|
||||
void warning(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
|
||||
void critical(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
|
||||
|
||||
typedef QLoggingCategory &(*CategoryFunction)();
|
||||
|
||||
void debug(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
||||
void debug(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
||||
void warning(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
||||
void warning(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
||||
void critical(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
||||
void critical(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
||||
|
||||
#ifndef Q_CC_MSVC
|
||||
Q_NORETURN
|
||||
#endif
|
||||
@ -105,8 +116,14 @@ public:
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug debug() const;
|
||||
QDebug debug(const QLoggingCategory &cat) const;
|
||||
QDebug debug(CategoryFunction catFunc) const;
|
||||
QDebug warning() const;
|
||||
QDebug warning(const QLoggingCategory &cat) const;
|
||||
QDebug warning(CategoryFunction catFunc) const;
|
||||
QDebug critical() const;
|
||||
QDebug critical(const QLoggingCategory &cat) const;
|
||||
QDebug critical(CategoryFunction catFunc) const;
|
||||
|
||||
QNoDebug noDebug() const Q_DECL_NOTHROW;
|
||||
#endif // QT_NO_DEBUG_STREAM
|
||||
|
@ -325,6 +325,25 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
\sa qDebug()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCDebug(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\since 5.3
|
||||
|
||||
Logs a debug message \a message in the logging category \a category.
|
||||
\a message might contain place holders that are replaced by additional
|
||||
arguments, similar to the C printf() function.
|
||||
|
||||
Example:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 13
|
||||
|
||||
\note Arguments might not be processed if debug output for the category is
|
||||
not enabled, so do not rely on any side effects.
|
||||
|
||||
\sa qDebug()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCWarning(category)
|
||||
\relates QLoggingCategory
|
||||
@ -347,6 +366,25 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
\sa qWarning()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCWarning(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\since 5.3
|
||||
|
||||
Logs a warning message \a message in the logging category \a category.
|
||||
\a message might contain place holders that are replaced by additional
|
||||
arguments, similar to the C printf() function.
|
||||
|
||||
Example:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 14
|
||||
|
||||
\note Arguments might not be processed if warning output for the category is
|
||||
not enabled, so do not rely on any side effects.
|
||||
|
||||
\sa qWarning()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCCritical(category)
|
||||
\relates QLoggingCategory
|
||||
@ -369,6 +407,24 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
\sa qCritical()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCCritical(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\since 5.3
|
||||
|
||||
Logs a critical message \a message in the logging category \a category.
|
||||
\a message might contain place holders that are replaced by additional
|
||||
arguments, similar to the C printf() function.
|
||||
|
||||
Example:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 15
|
||||
|
||||
\note Arguments might not be processed if critical output for the category
|
||||
is not enabled, so do not rely on any side effects.
|
||||
|
||||
\sa qCritical()
|
||||
*/
|
||||
/*!
|
||||
\macro Q_DECLARE_LOGGING_CATEGORY(name)
|
||||
\relates QLoggingCategory
|
||||
|
@ -94,15 +94,26 @@ private:
|
||||
return category; \
|
||||
}
|
||||
|
||||
#define qCDebug(category) \
|
||||
#ifdef Q_COMPILER_VARIADIC_MACROS
|
||||
|
||||
#define qCDebug(category, ...) \
|
||||
for (bool enabled = category().isDebugEnabled(); Q_UNLIKELY(enabled); enabled = false) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug()
|
||||
#define qCWarning(category) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug(__VA_ARGS__)
|
||||
#define qCWarning(category, ...) \
|
||||
for (bool enabled = category().isWarningEnabled(); enabled; enabled = false) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).warning()
|
||||
#define qCCritical(category) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).warning(__VA_ARGS__)
|
||||
#define qCCritical(category, ...) \
|
||||
for (bool enabled = category().isCriticalEnabled(); enabled; enabled = false) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical()
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical(__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
// check for enabled category inside QMessageLogger.
|
||||
#define qCDebug qDebug
|
||||
#define qCWarning qWarning
|
||||
#define qCCritical qCritical
|
||||
|
||||
#endif // Q_COMPILER_VARIADIC_MACROS
|
||||
|
||||
#if defined(QT_NO_DEBUG_OUTPUT)
|
||||
# undef qCDebug
|
||||
|
@ -376,16 +376,22 @@ private slots:
|
||||
buf = QStringLiteral("default.debug: Check debug with no filter active");
|
||||
qCDebug(defaultCategory) << "Check debug with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
qCDebug(defaultCategory, "Check debug with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default warning
|
||||
buf = QStringLiteral("default.warning: Check warning with no filter active");
|
||||
qCWarning(defaultCategory) << "Check warning with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
qCWarning(defaultCategory, "Check warning with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default critical
|
||||
buf = QStringLiteral("default.critical: Check critical with no filter active");
|
||||
qCCritical(defaultCategory) << "Check critical with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
qCCritical(defaultCategory, "Check critical with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
|
||||
QLoggingCategory customCategory("custom");
|
||||
@ -412,6 +418,24 @@ private slots:
|
||||
qCDebug(customCategory) << "Check debug with filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check different macro/category variants
|
||||
buf = QStringLiteral("tst.log.debug: Check debug with no filter active");
|
||||
qCDebug(TST_LOG) << "Check debug with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
qCDebug(TST_LOG, "Check debug with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
buf = QStringLiteral("tst.log.warning: Check warning with no filter active");
|
||||
qCWarning(TST_LOG) << "Check warning with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
qCWarning(TST_LOG, "Check warning with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
buf = QStringLiteral("tst.log.critical: Check critical with no filter active");
|
||||
qCCritical(TST_LOG) << "Check critical with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
qCCritical(TST_LOG, "Check critical with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
|
||||
// reset to default filter
|
||||
QLoggingCategory::installFilter(0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user