8 #ifndef _QI_DETAIL_LOG_HXX_
9 #define _QI_DETAIL_LOG_HXX_
11 #include <boost/noncopyable.hpp>
12 #include <boost/preprocessor/cat.hpp>
14 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
15 # define _qiLogDebug(...) qi::log::LogStream(qi::LogLevel_Debug, "", __FUNCTION__, 0, __VA_ARGS__).self()
17 # define _qiLogDebug(...) qi::log::LogStream(qi::LogLevel_Debug, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__).self()
20 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
21 # define _qiLogVerbose(...) qi::log::LogStream(qi::LogLevel_Verbose, "", __FUNCTION__, 0, __VA_ARGS__).self()
23 # define _qiLogVerbose(...) qi::log::LogStream(qi::LogLevel_Verbose, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__).self()
26 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
27 # define _qiLogInfo(...) qi::log::LogStream(qi::LogLevel_Info, "", __FUNCTION__, 0, __VA_ARGS__).self()
29 # define _qiLogInfo(...) qi::log::LogStream(qi::LogLevel_Info, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__).self()
32 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
33 # define _qiLogWarning(...) qi::log::LogStream(qi::LogLevel_Warning, "", __FUNCTION__, 0, __VA_ARGS__).self()
35 # define _qiLogWarning(...) qi::log::LogStream(qi::LogLevel_Warning, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__).self()
38 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
39 # define _qiLogError(...) qi::log::LogStream(qi::LogLevel_Error, "", __FUNCTION__, 0, __VA_ARGS__).self()
41 # define _qiLogError(...) qi::log::LogStream(qi::LogLevel_Error, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__).self()
44 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
45 # define _qiLogFatal(...) qi::log::LogStream(qi::LogLevel_Fatal, "", __FUNCTION__, 0, __VA_ARGS__).self()
47 # define _qiLogFatal(...) qi::log::LogStream(qi::LogLevel_Fatal, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__).self()
51 # define _QI_FORMAT_ELEM(_, a, elem) % (elem)
53 # define _QI_LOG_FORMAT(Msg, ...) \
54 QI_CAT(_QI_LOG_FORMAT_HASARG_, _QI_LOG_ISEMPTY(__VA_ARGS__))(Msg, __VA_ARGS__)
56 #define _QI_LOG_FORMAT_HASARG_0(Msg, ...) \
57 boost::str(::qi::log::detail::getFormat(Msg) QI_VAARGS_APPLY(_QI_FORMAT_ELEM, _, __VA_ARGS__ ))
59 #define _QI_LOG_FORMAT_HASARG_1(Msg, ...) Msg
61 #define _QI_SECOND(a, ...) __VA_ARGS__
69 #ifndef _QI_LOG_VARIABLE_SUFFIX
70 # define _QI_LOG_VARIABLE_SUFFIX _x // dummy/default suffix
73 # define _QI_LOG_CATEGORY_GET() BOOST_PP_CAT(_qi_log_category, _QI_LOG_VARIABLE_SUFFIX)
75 #if defined(NO_QI_LOG_DETAILED_CONTEXT) || defined(NDEBUG)
76 # define _QI_LOG_MESSAGE(Type, Message) \
79 if (::qi::log::isVisible(_QI_LOG_CATEGORY_GET(), ::qi::Type)) \
80 ::qi::log::log(::qi::Type, \
81 _QI_LOG_CATEGORY_GET(), \
83 "", __FUNCTION__, 0); \
87 # define _QI_LOG_MESSAGE(Type, Message) \
90 if (::qi::log::isVisible(_QI_LOG_CATEGORY_GET(), ::qi::Type)) \
91 ::qi::log::log(::qi::Type, \
92 _QI_LOG_CATEGORY_GET(), \
94 __FILE__, __FUNCTION__, __LINE__); \
103 # define _QI_LOG_MESSAGE_STREAM(Type, TypeCased, ...) \
104 QI_CAT(_QI_LOG_MESSAGE_STREAM_HASCAT_, _QI_LOG_ISEMPTY( __VA_ARGS__))(Type, TypeCased, __VA_ARGS__)
107 #define _QI_LOG_MESSAGE_STREAM_HASCAT_1(Type, TypeCased, ...) \
108 ::qi::log::isVisible(_QI_LOG_CATEGORY_GET(), ::qi::Type) \
109 && BOOST_PP_CAT(_qiLog, TypeCased)(_QI_LOG_CATEGORY_GET())
113 #define _QI_LOG_MESSAGE_STREAM_HASCAT_0(...) QI_DELAY(_QI_LOG_MESSAGE_STREAM_HASCAT_0) ## _BOUNCE(__VA_ARGS__)
115 #define _QI_LOG_MESSAGE_STREAM_HASCAT_0(...) _QI_LOG_MESSAGE_STREAM_HASCAT_0_BOUNCE(__VA_ARGS__)
119 #define _QI_LOG_MESSAGE_STREAM_HASCAT_0_BOUNCE(Type, TypeCased, cat, ...) \
120 QI_CAT(_QI_LOG_MESSAGE_STREAM_HASCAT_HASFORMAT_, _QI_LOG_ISEMPTY( __VA_ARGS__))(Type, TypeCased, cat, __VA_ARGS__)
124 #define _QI_LOG_MESSAGE_STREAM_HASCAT_HASFORMAT_1(Type, TypeCased, cat, ...) \
125 BOOST_PP_CAT(_qiLog,TypeCased)(cat)
128 #define _QI_LOG_MESSAGE_STREAM_HASCAT_HASFORMAT_0(Type, TypeCased, cat, ...) \
129 BOOST_PP_CAT(_qiLog, TypeCased)(cat, _QI_LOG_FORMAT(__VA_ARGS__))
138 #define _WQI_IS_EMPTY_HELPER___ a,b
139 #define WQI_IS_EMPTY(a,...) QI_CAT_20(QI_LIST_VASIZE,((QI_CAT_22(_WQI_IS_EMPTY_HELPER, QI_CAT_24(QI_CAT_26(_, a), _)))))
141 #define _QI_FIRST_ARG(a, ...) a
142 #define _QI_LOG_ISEMPTY(...) WQI_IS_EMPTY(QI_CAT_18(_, _QI_FIRST_ARG(__VA_ARGS__, 12)))
146 #define _QI_LOG_REVERSE 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0
147 #define _QI_LOG_REVERSEEMPTY 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1
148 #define _QI_LOG_ARGN(a, b, c, d, e, f, g, h, i, N, ...) N
149 #define _QI_LOG_NARG_(dummy, ...) _QI_LOG_ARGN(__VA_ARGS__)
150 #define _QI_LOG_NARG(...) _QI_LOG_NARG_(dummy, ##__VA_ARGS__, _QI_LOG_REVERSE)
151 #define _QI_LOG_ISEMPTY(...) _QI_LOG_NARG_(dummy, ##__VA_ARGS__, _QI_LOG_REVERSEEMPTY)
172 template <
typename T>
214 const std::string &rules);
220 return category && level <= category->
maxLevel;
224 class LogStream:
public std::stringstream, boost::noncopyable
229 const char *
function,
231 const char *category)
233 , _category(category)
236 , _function(function)
242 const char *
function,
247 , _categoryType(category)
249 , _function(function)
255 const char *
function,
257 const char *category,
258 const std::string& message)
260 , _category(category)
263 , _function(function)
272 qi::log::log(_logLevel, _category, this->str().c_str(), _file, _function, _line);
274 qi::log::log(_logLevel, _categoryType, this->str(), _file, _function, _line);
283 const char *_category;
286 const char *_function;
292 #endif // _QI_DETAIL_LOG_HXX_
LogStream(const qi::LogLevel level, const char *file, const char *function, const int line, const char *category)
void setLevel(SubscriberId sub, qi::LogLevel level)
LogStream(const qi::LogLevel level, const char *file, const char *function, const int line, CategoryType category)
bool operator<(bool b, const NullStream &ns)
LogLevel
Log level verbosity.
LogStream(const qi::LogLevel level, const char *file, const char *function, const int line, const char *category, const std::string &message)
unsigned int SubscriberId
Subscriber Identifier.
Category(const std::string &name)
std::vector< qi::LogLevel > levels
std::vector< std::tuple< std::string, qi::LogLevel > > parseFilterRules(const std::string &rules)
void log(const qi::LogLevel verb, const char *category, const char *msg, const char *file="", const char *fct="", const int line=0)
Log function. You should call qiLog* macros instead.
NullStream & operator<<(std::ostream &(*QI_UNUSED(f))(std::ostream &))
NullStream & operator<<(const T &QI_UNUSED(val))
boost::format getFormat(const std::string &s)
bool isVisible(CategoryType category, qi::LogLevel level)
Check if the given combination of category and level is enable.
#define QI_UNUSED(x)
This macro tags a parameter as unused.