2001-10-14 18:38:45 +04:00
|
|
|
#ifndef CLOG_H
|
|
|
|
#define CLOG_H
|
|
|
|
|
2002-06-19 15:23:49 +04:00
|
|
|
#include "common.h"
|
|
|
|
#include <stdarg.h>
|
2001-10-14 18:38:45 +04:00
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Logging facility
|
|
|
|
/*!
|
|
|
|
The logging class; all console output should go through this class.
|
|
|
|
It supports multithread safe operation, several message priority levels,
|
|
|
|
filtering by priority, and output redirection. The macros log() and
|
|
|
|
clog() provide convenient access.
|
|
|
|
*/
|
2001-10-14 18:38:45 +04:00
|
|
|
class CLog {
|
2002-04-29 18:40:01 +04:00
|
|
|
public:
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Log levels
|
|
|
|
/*!
|
|
|
|
The logging priority levels in order of highest to lowest priority.
|
|
|
|
*/
|
|
|
|
enum ELevel {
|
|
|
|
kFATAL, //!< For fatal errors
|
|
|
|
kERROR, //!< For serious errors
|
|
|
|
kWARNING, //!< For minor errors and warnings
|
|
|
|
kNOTE, //!< For messages about notable events
|
|
|
|
kINFO, //!< For informational messages
|
|
|
|
kDEBUG, //!< For important debugging messages
|
|
|
|
kDEBUG1, //!< For more detailed debugging messages
|
|
|
|
kDEBUG2 //!< For even more detailed debugging messages
|
2002-06-03 22:53:18 +04:00
|
|
|
};
|
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Outputter function.
|
|
|
|
/*!
|
|
|
|
Type of outputter function. The outputter should write \c message,
|
|
|
|
which has the given \c priority, to a log and return true. Or it can
|
|
|
|
return false to let CLog use the default outputter.
|
|
|
|
*/
|
|
|
|
typedef bool (*Outputter)(int priority, const char* message);
|
2002-06-09 01:48:00 +04:00
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Locking function
|
|
|
|
/*!
|
|
|
|
Type of lock/unlock function. If \c lock is true then block other
|
|
|
|
threads that try to lock until this thread unlocks. If \c lock is
|
|
|
|
false then unlock and allow another (waiting) thread to lock.
|
|
|
|
*/
|
2002-05-31 18:25:26 +04:00
|
|
|
typedef void (*Lock)(bool lock);
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! @name manipulators
|
|
|
|
//@{
|
2002-05-31 18:25:26 +04:00
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Set the function used to write the log
|
|
|
|
/*!
|
|
|
|
Sets the function used to write to the log. The outputter function
|
|
|
|
is called with the formatted string to write and the priority level.
|
|
|
|
CLog will have already filtered messages below the current filter
|
|
|
|
priority. A NULL outputter means to use the default which is to print
|
|
|
|
to stderr. Note that the outputter should not call CLog methods but,
|
|
|
|
if it does, the current lock function must permit recursive locks.
|
|
|
|
*/
|
2001-11-19 03:33:36 +03:00
|
|
|
static void setOutputter(Outputter);
|
2002-05-31 18:25:26 +04:00
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Set the lock/unlock function
|
|
|
|
/*!
|
|
|
|
Set the lock/unlock function. Use setLock(NULL) to remove the
|
|
|
|
locking function. There is no default lock function; do not call
|
|
|
|
CLog from multiple threads unless a working lock function has been
|
|
|
|
installed.
|
|
|
|
*/
|
2002-05-31 18:25:26 +04:00
|
|
|
static void setLock(Lock);
|
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//! Set the minimum priority filter.
|
|
|
|
/*!
|
|
|
|
Set the filter. Messages below this priority are discarded.
|
|
|
|
The default priority is 4 (INFO) (unless built without NDEBUG
|
|
|
|
in which case it's 5 (DEBUG)). The default can be overridden
|
|
|
|
by setting the SYN_LOG_PRI env var to "FATAL", "ERROR", etc.
|
|
|
|
setFilter(const char*) returns true if the priority \c name was
|
|
|
|
recognized; if \c name is NULL then it simply returns true.
|
|
|
|
*/
|
2002-06-03 20:36:45 +04:00
|
|
|
static bool setFilter(const char* name);
|
2002-05-31 18:25:26 +04:00
|
|
|
static void setFilter(int);
|
2002-07-26 22:28:18 +04:00
|
|
|
|
|
|
|
//@}
|
|
|
|
//! @name accessors
|
|
|
|
//@{
|
|
|
|
|
|
|
|
//! Print a log message
|
|
|
|
/*!
|
|
|
|
Print a log message using the printf-like \c format and arguments.
|
|
|
|
*/
|
|
|
|
static void print(const char* format, ...);
|
|
|
|
|
|
|
|
//! Print a log message
|
|
|
|
/*!
|
|
|
|
Print a log message using the printf-like \c format and arguments
|
|
|
|
preceded by the filename and line number.
|
|
|
|
*/
|
|
|
|
static void printt(const char* file, int line,
|
|
|
|
const char* format, ...);
|
|
|
|
|
|
|
|
//! Get the function used to write the log
|
|
|
|
static Outputter getOutputter();
|
|
|
|
|
|
|
|
//! Get the lock/unlock function
|
|
|
|
/*!
|
|
|
|
Get the lock/unlock function. Note that the lock function is
|
|
|
|
used when retrieving the lock function.
|
|
|
|
*/
|
|
|
|
static Lock getLock();
|
|
|
|
|
|
|
|
//! Get the minimum priority level.
|
2002-05-31 18:25:26 +04:00
|
|
|
static int getFilter();
|
2001-10-14 18:38:45 +04:00
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
//@}
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
private:
|
2002-05-31 18:25:26 +04:00
|
|
|
class CHoldLock {
|
|
|
|
public:
|
2002-06-01 23:26:11 +04:00
|
|
|
CHoldLock(Lock lock) : m_lock(lock) { m_lock(true); }
|
2002-05-31 18:25:26 +04:00
|
|
|
~CHoldLock() { m_lock(false); }
|
|
|
|
|
|
|
|
private:
|
2002-06-01 23:26:11 +04:00
|
|
|
Lock m_lock;
|
2002-05-31 18:25:26 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static void dummyLock(bool);
|
|
|
|
static int getMaxPriority();
|
2001-11-19 03:33:36 +03:00
|
|
|
static void output(int priority, char* msg);
|
2002-06-19 15:23:49 +04:00
|
|
|
#if WINDOWS_LIKE
|
2002-05-22 21:01:17 +04:00
|
|
|
static void openConsole();
|
|
|
|
#endif
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
private:
|
2001-11-19 03:33:36 +03:00
|
|
|
static Outputter s_outputter;
|
2002-05-31 18:25:26 +04:00
|
|
|
static Lock s_lock;
|
|
|
|
static int s_maxPriority;
|
2001-10-14 18:38:45 +04:00
|
|
|
};
|
|
|
|
|
2002-07-26 22:28:18 +04:00
|
|
|
/*!
|
|
|
|
\def log(arg)
|
|
|
|
Write to the log. Because macros cannot accept variable arguments, this
|
|
|
|
should be invoked like so:
|
|
|
|
\code
|
|
|
|
log((CLOG_XXX "%d and %d are %s", x, y, x == y ? "equal" : "not equal"));
|
|
|
|
\endcode
|
|
|
|
In particular, notice the double open and close parentheses. Also note
|
|
|
|
that there is no comma after the \c CLOG_XXX. The \c XXX should be
|
|
|
|
replaced by one of enumerants in \c CLog::ELevel without the leading
|
|
|
|
\c k. For example, \c CLOG_INFO. The special \c CLOG_PRINT level will
|
|
|
|
not be filtered and is never prefixed by the filename and line number.
|
|
|
|
|
|
|
|
If \c NOLOGGING is defined during the build then this macro expands to
|
|
|
|
nothing. If \c NDEBUG is defined during the build then it expands to a
|
|
|
|
call to CLog::print. Otherwise it expands to a call to CLog::printt,
|
|
|
|
which includes the filename and line number.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\def logc(expr, arg)
|
|
|
|
Write to the log if and only if expr is true. Because macros cannot accept
|
|
|
|
variable arguments, this should be invoked like so:
|
|
|
|
\code
|
|
|
|
clog(x == y, (CLOG_XXX "%d and %d are equal", x, y));
|
|
|
|
\endcode
|
|
|
|
In particular, notice the parentheses around everything after the boolean
|
|
|
|
expression. Also note that there is no comma after the \c CLOG_XXX.
|
|
|
|
The \c XXX should be replaced by one of enumerants in \c CLog::ELevel
|
|
|
|
without the leading \c k. For example, \c CLOG_INFO. The special
|
|
|
|
\c CLOG_PRINT level will not be filtered and is never prefixed by the
|
|
|
|
filename and line number.
|
|
|
|
|
|
|
|
If \c NOLOGGING is defined during the build then this macro expands to
|
|
|
|
nothing. If \c NDEBUG is defined during the build then it expands to a
|
|
|
|
call to CLog::print. Otherwise it expands to a call to CLog::printt,
|
|
|
|
which includes the filename and line number.
|
|
|
|
*/
|
|
|
|
|
2001-10-14 18:38:45 +04:00
|
|
|
#if defined(NOLOGGING)
|
|
|
|
#define log(_a1)
|
2001-10-14 22:29:43 +04:00
|
|
|
#define logc(_a1, _a2)
|
2001-10-14 18:38:45 +04:00
|
|
|
#define CLOG_TRACE
|
|
|
|
#elif defined(NDEBUG)
|
|
|
|
#define log(_a1) CLog::print _a1
|
2001-10-14 22:29:43 +04:00
|
|
|
#define logc(_a1, _a2) if (_a1) CLog::print _a2
|
2001-10-14 18:38:45 +04:00
|
|
|
#define CLOG_TRACE
|
|
|
|
#else
|
|
|
|
#define log(_a1) CLog::printt _a1
|
2001-10-14 22:29:43 +04:00
|
|
|
#define logc(_a1, _a2) if (_a1) CLog::printt _a2
|
2001-10-14 18:38:45 +04:00
|
|
|
#define CLOG_TRACE __FILE__, __LINE__,
|
|
|
|
#endif
|
|
|
|
|
2002-06-03 20:36:45 +04:00
|
|
|
#define CLOG_PRINT CLOG_TRACE "%z\057"
|
2001-10-14 18:38:45 +04:00
|
|
|
#define CLOG_CRIT CLOG_TRACE "%z\060"
|
|
|
|
#define CLOG_ERR CLOG_TRACE "%z\061"
|
|
|
|
#define CLOG_WARN CLOG_TRACE "%z\062"
|
|
|
|
#define CLOG_NOTE CLOG_TRACE "%z\063"
|
|
|
|
#define CLOG_INFO CLOG_TRACE "%z\064"
|
|
|
|
#define CLOG_DEBUG CLOG_TRACE "%z\065"
|
2002-04-27 22:49:03 +04:00
|
|
|
#define CLOG_DEBUG1 CLOG_TRACE "%z\066"
|
|
|
|
#define CLOG_DEBUG2 CLOG_TRACE "%z\067"
|
2001-10-14 18:38:45 +04:00
|
|
|
|
|
|
|
#endif
|