00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdmisc.h"
00027
00028 #ifdef NL_OS_WINDOWS
00029 #include <process.h>
00030 #include <windows.h>
00031 #else
00032 #include <unistd.h>
00033 #endif
00034
00035 #include <time.h>
00036 #include <stdarg.h>
00037
00038 #include "nel/misc/displayer.h"
00039 #include "nel/misc/log.h"
00040 #include "nel/misc/debug.h"
00041 #include "nel/misc/path.h"
00042
00043 using namespace std;
00044
00045
00046 namespace NLMISC
00047 {
00048
00049 string *CLog::_ProcessName = NULL;
00050
00051 CLog::CLog( TLogType logType) : _LogType (logType), _Line(-1), _FileName(NULL), _Mutex("LOG"+toString((uint)logType)), _PosSet(false)
00052 {
00053 }
00054
00055 void CLog::setDefaultProcessName ()
00056 {
00057 #ifdef NL_OS_WINDOWS
00058 if (_ProcessName == NULL)
00059 {
00060 _ProcessName = new string;
00061 }
00062
00063 if ((*_ProcessName).empty())
00064 {
00065 char name[1024];
00066 GetModuleFileName (NULL, name, 1023);
00067 (*_ProcessName) = CFile::getFilename(name);
00068 }
00069 #endif
00070 }
00071
00072 void CLog::setProcessName (const std::string &processName)
00073 {
00074 if (_ProcessName == NULL)
00075 {
00076 _ProcessName = new string;
00077 }
00078
00079 *_ProcessName = processName;
00080 }
00081
00082 void CLog::setPosition (sint line, char *filename)
00083 {
00084 if ( !noDisplayer() )
00085 {
00086 _Mutex.enter();
00087 _PosSet++;
00088 _Line = line;
00089 _FileName = filename;
00090 }
00091 }
00092
00094 void CLog::unsetPosition()
00095 {
00096 nlassert( !noDisplayer() );
00097
00098 if ( _PosSet > 0 )
00099 {
00100 _FileName = NULL;
00101 _Line = -1;
00102 _PosSet--;
00103 _Mutex.leave();
00104 }
00105 }
00106
00107
00108 void CLog::addDisplayer (IDisplayer *displayer, bool bypassFilter)
00109 {
00110 if (displayer == NULL)
00111 {
00112 nlwarning ("Trying to add a NULL displayer");
00113 return;
00114 }
00115
00116 if (bypassFilter)
00117 {
00118 CDisplayers::iterator idi = std::find (_BypassFilterDisplayers.begin (), _BypassFilterDisplayers.end (), displayer);
00119 if (idi == _BypassFilterDisplayers.end ())
00120 {
00121 _BypassFilterDisplayers.push_back (displayer);
00122 }
00123 else
00124 {
00125 nlwarning ("Couldn't add the displayer, it was already added");
00126 }
00127 }
00128 else
00129 {
00130 CDisplayers::iterator idi = std::find (_Displayers.begin (), _Displayers.end (), displayer);
00131 if (idi == _Displayers.end ())
00132 {
00133 _Displayers.push_back (displayer);
00134 }
00135 else
00136 {
00137 nlwarning ("Couldn't add the displayer, it was already added");
00138 }
00139 }
00140 }
00141
00142 void CLog::removeDisplayer (IDisplayer *displayer)
00143 {
00144 if (displayer == NULL)
00145 {
00146 nlwarning ("Trying to remove a NULL displayer");
00147 return;
00148 }
00149
00150 CDisplayers::iterator idi = std::find (_Displayers.begin (), _Displayers.end (), displayer);
00151 if (idi != _Displayers.end ())
00152 {
00153 _Displayers.erase (idi);
00154 }
00155
00156 idi = std::find (_BypassFilterDisplayers.begin (), _BypassFilterDisplayers.end (), displayer);
00157 if (idi != _BypassFilterDisplayers.end ())
00158 {
00159 _BypassFilterDisplayers.erase (idi);
00160 }
00161
00162 }
00163
00164 void CLog::removeDisplayer (const char *displayerName)
00165 {
00166 if (displayerName == NULL || displayerName[0] == '\0')
00167 {
00168 nlwarning ("Trying to remove an empty displayer name");
00169 return;
00170 }
00171
00172 CDisplayers::iterator idi;
00173 for (idi = _Displayers.begin (); idi != _Displayers.end ();)
00174 {
00175 if ((*idi)->DisplayerName == displayerName)
00176 {
00177 idi = _Displayers.erase (idi);
00178 }
00179 else
00180 {
00181 idi++;
00182 }
00183 }
00184
00185 for (idi = _BypassFilterDisplayers.begin (); idi != _BypassFilterDisplayers.end ();)
00186 {
00187 if ((*idi)->DisplayerName == displayerName)
00188 {
00189 idi = _BypassFilterDisplayers.erase (idi);
00190 }
00191 else
00192 {
00193 idi++;
00194 }
00195 }
00196 }
00197
00198 IDisplayer *CLog::getDisplayer (const char *displayerName)
00199 {
00200 if (displayerName == NULL || displayerName[0] == '\0')
00201 {
00202 nlwarning ("Trying to get an empty displayer name");
00203 return NULL;
00204 }
00205
00206 CDisplayers::iterator idi;
00207 for (idi = _Displayers.begin (); idi != _Displayers.end (); idi++)
00208 {
00209 if ((*idi)->DisplayerName == displayerName)
00210 {
00211 return *idi;
00212 }
00213 }
00214 for (idi = _BypassFilterDisplayers.begin (); idi != _BypassFilterDisplayers.end (); idi++)
00215 {
00216 if ((*idi)->DisplayerName == displayerName)
00217 {
00218 return *idi;
00219 }
00220 }
00221 return NULL;
00222 }
00223
00224
00225
00226
00227 bool CLog::attached(IDisplayer *displayer) const
00228 {
00229 return (find( _Displayers.begin(), _Displayers.end(), displayer ) != _Displayers.end()) ||
00230 (find( _BypassFilterDisplayers.begin(), _BypassFilterDisplayers.end(), displayer ) != _BypassFilterDisplayers.end());
00231 }
00232
00233 static string TempString;
00234 static TDisplayInfo TempArgs;
00235
00236
00237 void CLog::displayString (const char *str)
00238 {
00239 const char *disp = NULL;
00240 TDisplayInfo localargs, *args = NULL;
00241
00242 setDefaultProcessName ();
00243
00244 if(strchr(str,'\n') == NULL)
00245 {
00246 if (TempString.empty())
00247 {
00248 time (&TempArgs.Date);
00249 TempArgs.LogType = _LogType;
00250 TempArgs.ProcessName = *_ProcessName;
00251 TempArgs.ThreadId = getThreadId();
00252 TempArgs.Filename = _FileName;
00253 TempArgs.Line = _Line;
00254 TempArgs.CallstackAndLog = "";
00255
00256 TempString = str;
00257 }
00258 else
00259 {
00260 TempString += str;
00261 }
00262 return;
00263 }
00264 else
00265 {
00266 if (TempString.empty())
00267 {
00268 time (&localargs.Date);
00269 localargs.LogType = _LogType;
00270 localargs.ProcessName = *_ProcessName;
00271 localargs.ThreadId = getThreadId();
00272 localargs.Filename = _FileName;
00273 localargs.Line = _Line;
00274 localargs.CallstackAndLog = "";
00275
00276 disp = str;
00277 args = &localargs;
00278 }
00279 else
00280 {
00281 TempString += str;
00282 disp = TempString.c_str();
00283 args = &TempArgs;
00284 }
00285 }
00286
00287
00288 for (CDisplayers::iterator idi=_BypassFilterDisplayers.begin(); idi!=_BypassFilterDisplayers.end(); idi++ )
00289 {
00290 (*idi)->display( *args, disp );
00291 }
00292
00293
00294 if(args->LogType == LOG_ERROR || args->LogType == LOG_ASSERT)
00295 {
00296 getCallStackAndLog (args->CallstackAndLog, 4);
00297 }
00298
00299 if (passFilter (disp))
00300 {
00301
00302 for (CDisplayers::iterator idi=_Displayers.begin(); idi!=_Displayers.end(); idi++ )
00303 {
00304 (*idi)->display( *args, disp );
00305 }
00306 }
00307 TempString = "";
00308 unsetPosition();
00309 }
00310
00311
00312
00313
00314
00315 void CLog::displayNL (const char *format, ...)
00316 {
00317 if ( noDisplayer() )
00318 {
00319 return;
00320 }
00321
00322 char *str;
00323 NLMISC_CONVERT_VARGS (str, format, 256);
00324
00325 if (strlen(str)<256-1)
00326 strcat (str, "\n");
00327 else
00328 str[256-2] = '\n';
00329
00330 displayString (str);
00331 }
00332
00333
00334
00335
00336 void CLog::display (const char *format, ...)
00337 {
00338 if ( noDisplayer() )
00339 {
00340 return;
00341 }
00342
00343 char *str;
00344 NLMISC_CONVERT_VARGS (str, format, 256);
00345
00346 displayString (str);
00347 }
00348
00349
00350 void CLog::displayRawString (const char *str)
00351 {
00352 const char *disp = NULL;
00353 TDisplayInfo localargs, *args = NULL;
00354
00355 setDefaultProcessName ();
00356
00357 if(strchr(str,'\n') == NULL)
00358 {
00359 if (TempString.empty())
00360 {
00361 localargs.Date = 0;
00362 localargs.LogType = CLog::LOG_NO;
00363 localargs.ProcessName = "";
00364 localargs.ThreadId = 0;
00365 localargs.Filename = NULL;
00366 localargs.Line = -1;
00367 localargs.CallstackAndLog = "";
00368
00369 TempString = str;
00370 }
00371 else
00372 {
00373 TempString += str;
00374 }
00375 return;
00376 }
00377 else
00378 {
00379 if (TempString.empty())
00380 {
00381 localargs.Date = 0;
00382 localargs.LogType = CLog::LOG_NO;
00383 localargs.ProcessName = "";
00384 localargs.ThreadId = 0;
00385 localargs.Filename = NULL;
00386 localargs.Line = -1;
00387 localargs.CallstackAndLog = "";
00388
00389 disp = str;
00390 args = &localargs;
00391 }
00392 else
00393 {
00394 TempString += str;
00395 disp = TempString.c_str();
00396 args = &TempArgs;
00397 }
00398 }
00399
00400
00401 for (CDisplayers::iterator idi=_BypassFilterDisplayers.begin(); idi!=_BypassFilterDisplayers.end(); idi++ )
00402 {
00403 (*idi)->display( *args, disp );
00404 }
00405
00406
00407 if(args->LogType == LOG_ERROR || args->LogType == LOG_ASSERT)
00408 {
00409 getCallStackAndLog (args->CallstackAndLog, 4);
00410 }
00411
00412 if ( passFilter( disp ) )
00413 {
00414
00415 for ( CDisplayers::iterator idi=_Displayers.begin(); idi!=_Displayers.end(); idi++ )
00416 {
00417 (*idi)->display( *args, disp );
00418 }
00419 }
00420 TempString = "";
00421 unsetPosition();
00422 }
00423
00424
00425
00426
00427 void CLog::displayRawNL( const char *format, ... )
00428 {
00429 if ( noDisplayer() )
00430 {
00431 return;
00432 }
00433
00434 char *str;
00435 NLMISC_CONVERT_VARGS (str, format, 256);
00436
00437 if (strlen(str)<256-1)
00438 strcat (str, "\n");
00439 else
00440 str[256-2] = '\n';
00441
00442 displayRawString(str);
00443 }
00444
00445
00446
00447
00448 void CLog::displayRaw( const char *format, ... )
00449 {
00450 if ( noDisplayer() )
00451 {
00452 return;
00453 }
00454
00455 char *str;
00456 NLMISC_CONVERT_VARGS (str, format, 256);
00457
00458 displayRawString(str);
00459 }
00460
00461
00462 void CLog::forceDisplayRaw (const char *format, ...)
00463 {
00464 if ( noDisplayer() )
00465 {
00466 return;
00467 }
00468
00469 char *str;
00470 NLMISC_CONVERT_VARGS (str, format, 256);
00471
00472 TDisplayInfo args;
00473
00474
00475 for ( CDisplayers::iterator idi=_Displayers.begin(); idi!=_Displayers.end(); idi++ )
00476 {
00477 (*idi)->display( args, str );
00478 }
00479 }
00480
00481
00482
00483
00484
00485
00486 bool CLog::passFilter( const char *filter )
00487 {
00488 bool yes = _PositiveFilter.empty();
00489
00490 bool found;
00491 list<string>::iterator ilf;
00492
00493
00494 for ( ilf=_PositiveFilter.begin(); ilf!=_PositiveFilter.end(); ++ilf )
00495 {
00496 found = ( strstr( filter, (*ilf).c_str() ) != NULL );
00497 if ( found )
00498 {
00499 yes = true;
00500 break;
00501 }
00502
00503 }
00504 if ( ! yes )
00505 {
00506 return false;
00507 }
00508
00509
00510 for ( ilf=_NegativeFilter.begin(); ilf!=_NegativeFilter.end(); ++ilf )
00511 {
00512 found = ( strstr( filter, (*ilf).c_str() ) != NULL );
00513 if ( found )
00514 {
00515 return false;
00516 }
00517 }
00518 return true;
00519 }
00520
00521
00522
00523
00524
00525 void CLog::removeFilter( const char *filterstr )
00526 {
00527 if (filterstr == NULL)
00528 {
00529 _PositiveFilter.clear();
00530 _NegativeFilter.clear();
00531
00532 }
00533 else
00534 {
00535 _PositiveFilter.remove( filterstr );
00536 _NegativeFilter.remove( filterstr );
00537
00538 }
00539 }
00540
00541 void CLog::displayFilter( CLog &log )
00542 {
00543 std::list<std::string>::iterator it;
00544 log.displayNL ("Positive Filter(s):");
00545 for (it = _PositiveFilter.begin (); it != _PositiveFilter.end (); it++)
00546 {
00547 log.displayNL ("'%s'", (*it).c_str());
00548 }
00549 log.displayNL ("Negative Filter(s):");
00550 for (it = _NegativeFilter.begin (); it != _NegativeFilter.end (); it++)
00551 {
00552 log.displayNL ("'%s'", (*it).c_str());
00553 }
00554 }
00555
00556 void CLog::addPositiveFilter( const char *filterstr )
00557 {
00558
00559 _PositiveFilter.push_back( filterstr );
00560 }
00561
00562 void CLog::addNegativeFilter( const char *filterstr )
00563 {
00564
00565 _NegativeFilter.push_back( filterstr );
00566 }
00567
00568 void CLog::resetFilters()
00569 {
00570
00571 _PositiveFilter.clear();
00572 _NegativeFilter.clear();
00573 }
00574
00575 }
00576