// 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 */