// NeL - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#ifndef NL_LOG_H
#define NL_LOG_H
#include "types_nl.h"
#include "mutex.h"
#include
#include
namespace NLMISC
{
class IDisplayer;
/**
* When display() is called, the logger builds a string and sends it to its attached displayers.
* The positive filters, if any, are applied first, then the negative filters.
* See the nldebug/nlinfo... macros in debug.h.
*
* \ref log_howto
* \author Vianney Lecroart, Olivier Cado
* \author Nevrax France
* \date 2001
*/
class CLog {
public:
typedef enum { LOG_NO=0, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG, LOG_STAT, LOG_ASSERT, LOG_UNKNOWN } TLogType;
// Debug information
struct TDisplayInfo
{
TDisplayInfo() : Date(0), LogType(CLog::LOG_NO), ThreadId(0), FileName(NULL), Line(-1), FuncName(NULL) {}
time_t Date;
TLogType LogType;
std::string ProcessName;
size_t ThreadId;
const char *FileName;
sint Line;
const char *FuncName;
std::string CallstackAndLog; // contains the callstack and a log with not filter of N last line (only in error/assert log type)
};
CLog (TLogType logType = LOG_NO);
/// Add a new displayer in the log. You have to create the displayer, remove it and delete it when you have finish with it.
/// For example, in a 3dDisplayer, you can add the displayer when you want, and the displayer displays the string if the 3d
/// screen is available and do nothing otherwise. In this case, if you want, you could leave the displayer all the time.
void addDisplayer (IDisplayer *displayer, bool bypassFilter = false);
/// Return the first displayer selected by his name
IDisplayer *getDisplayer (const char *displayerName);
/// Remove a displayer. If the displayer doesn't work in a specific time, you could remove it.
void removeDisplayer (IDisplayer *displayer);
/// Remove a displayer using his name
void removeDisplayer (const char *displayerName);
/// Returns true if the specified displayer is attached to the log object
bool attached (IDisplayer *displayer) const;
/// Returns true if no displayer is attached
bool noDisplayer () const { return _Displayers.empty() && _BypassFilterDisplayers.empty(); }
/// Set the name of the process
static void setProcessName (const std::string &processName);
/// Find the process name if nobody call setProcessName before
static void setDefaultProcessName ();
/// If !noDisplayer(), sets line and file parameters, and enters the mutex. If !noDisplayer(), don't forget to call display...() after, to release the mutex.
void setPosition (sint line, const char *fileName, const char *funcName = NULL);
#ifdef NL_OS_WINDOWS
#define CHECK_TYPES2(__a,__b) \
inline __a(const char *fmt) { __b(fmt); } \
template __a(const char *fmt, A a) { _check(a); __b(fmt, a); } \
template __a(const char *fmt, A a, B b) { _check(a); _check(b); __b(fmt, a, b); } \
template __a(const char *fmt, A a, B b, C c) { _check(a); _check(b); _check(c); __b(fmt, a, b, c); } \
template __a(const char *fmt, A a, B b, C c, D d) { _check(a); _check(b); _check(c); _check(d); __b(fmt, a, b, c, d); } \
template __a(const char *fmt, A a, B b, C c, D d, E e) { _check(a); _check(b); _check(c); _check(d); _check(e); __b(fmt, a, b, c, d, e); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); __b(fmt, a, b, c, d, e, f); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); __b(fmt, a, b, c, d, e, f, g); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); __b(fmt, a, b, c, d, e, f, g, h); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); __b(fmt, a, b, c, d, e, f, g, h, i); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); __b(fmt, a, b, c, d, e, f, g, h, i, j); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); __b(fmt, a, b, c, d, e, f, g, h, i, j, k); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t, U u) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); _check(u); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t, U u, V v) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); _check(u); _check(v); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t, U u, V v, W w) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); _check(u); _check(v); _check(w); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t, U u, V v, W w, X x) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); _check(u); _check(v); _check(w); _check(x); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t, U u, V v, W w, X x, Y y) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); _check(u); _check(v); _check(w); _check(x); _check(y); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y); } \
template __a(const char *fmt, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p, Q q, R r, S s, T t, U u, V v, W w, X x, Y y, Z z) { _check(a); _check(b); _check(c); _check(d); _check(e); _check(f); _check(g); _check(h); _check(i); _check(j); _check(k); _check(l); _check(m); _check(n); _check(o); _check(p); _check(q); _check(r); _check(s); _check(t); _check(u); _check(v); _check(w); _check(x); _check(y); _check(z); __b(fmt, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z); }
/// Display a string in decorated and final new line form to all attached displayers. Call setPosition() before. Releases the mutex.
void _displayNL (const char *format, ...);
CHECK_TYPES2(void displayNL, _displayNL)
/// Display a string in decorated form to all attached displayers. Call setPosition() before. Releases the mutex.
void _display (const char *format, ...);
CHECK_TYPES2(void display, _display)
/// Display a string with a final new line to all attached displayers. Call setPosition() before. Releases the mutex.
void _displayRawNL (const char *format, ...);
CHECK_TYPES2(void displayRawNL, _displayRawNL)
/// Display a string (and nothing more) to all attached displayers. Call setPosition() before. Releases the mutex.
void _displayRaw (const char *format, ...);
CHECK_TYPES2(void displayRaw, _displayRaw)
/// Display a raw text to the normal displayer but without filtering
/// It's used by the Memdisplayer (little hack to work)
void _forceDisplayRaw (const char *format, ...);
CHECK_TYPES2(void forceDisplayRaw, _forceDisplayRaw)
#else
/// Display a string in decorated and final new line form to all attached displayers. Call setPosition() before. Releases the mutex.
void displayNL (const char *format, ...);
/// Display a string in decorated form to all attached displayers. Call setPosition() before. Releases the mutex.
void display (const char *format, ...);
/// Display a string with a final new line to all attached displayers. Call setPosition() before. Releases the mutex.
void displayRawNL (const char *format, ...);
/// Display a string (and nothing more) to all attached displayers. Call setPosition() before. Releases the mutex.
void displayRaw (const char *format, ...);
/// Display a raw text to the normal displayer but without filtering
/// It's used by the Memdisplayer (little hack to work)
void forceDisplayRaw (const char *format, ...);
#endif
/// Adds a positive filter. Tells the logger to log only the lines that contain filterstr
void addPositiveFilter( const char *filterstr );
/// Adds a negative filter. Tells the logger to discard the lines that contain filterstr
void addNegativeFilter( const char *filterstr );
/// Reset both filters
void resetFilters();
/// Removes a filter by name (in both filters).
void removeFilter( const char *filterstr = NULL);
/// Displays the list of filter into a log
void displayFilter( CLog &log );
/// Do not call this unless you know why you're doing it, it kills the debug/log system!
static void releaseProcessName();
protected:
/// Symetric to setPosition(). Automatically called by display...(). Do not call if noDisplayer().
void unsetPosition();
/// Returns true if the string must be logged, according to the current filter
bool passFilter( const char *filter );
TLogType _LogType;
static std::string *_ProcessName;
const char *_FileName;
sint _Line;
const char *_FuncName;
typedef std::list CDisplayers;
CDisplayers _Displayers;
CDisplayers _BypassFilterDisplayers; // these displayers always log info (by pass filter system)
CMutex _Mutex;
uint32 _PosSet;
/// "Discard" filter
std::list _NegativeFilter;
/// "Crop" filter
std::list _PositiveFilter;
/// Display a string in decorated form to all attached displayers.
void displayString (const char *str);
/// Display a Raw string to all attached displayers.
void displayRawString (const char *str);
std::string TempString;
TDisplayInfo TempArgs;
};
} // NLMISC
#endif // NL_LOG_H
/* End of log.h */