Log.h

00001 #ifndef __PHOTOS_LOG_CLASS_HEADER__
00002 #define __PHOTOS_LOG_CLASS_HEADER__
00003 
00004 /**
00005  * This file contains class for logging and filtering output.
00006  * This header file also includes a debug macro which
00007  * tracks any possible memory leaks within the program.
00008  *
00009  * @author Tomasz Przedzinski
00010  * @date 14 November 2009
00011  */
00012 
00013 #include <iostream>
00014 #include <string>
00015 #include <sstream>
00016 #include <stdlib.h>
00017 #include <list>
00018 #include "Photos.h"
00019 // TEMPORARY
00020 #include "f_Init.h"
00021 
00022 using std::stringstream;
00023 using std::string;
00024 using std::streambuf;
00025 using std::ostream;
00026 using std::list;
00027 using std::cout;
00028 using std::endl;
00029 
00030 namespace Photospp
00031 {
00032 
00033 class Log
00034 {
00035 public:
00036         /** Shows the summary of all messages. */
00037         static void Summary();
00038 
00039         /** Shows the summary at the end of the program. */
00040         static void SummaryAtExit()              { atexit(Summary);      }
00041 
00042         /** Adds the decay to the counter. The type is:
00043             0 - gun, 1 - no mothers & grandmothers, 2 - no mothers, 3 - ok. */
00044         static void AddDecay(int type);
00045 
00046         /** Four logging entries. Usage:
00047             Log::Info()<<"Logging some info: "<<8<<" > "<<7.9<<endl;
00048             Use Log::Info(false) if You don't want the message to be counted.*/
00049         static ostream& Debug(unsigned short int code=0, bool count=true);
00050         static ostream& Info(bool count=true);
00051         static ostream& Warning(bool count=true);
00052         static ostream& Error(bool count=true);
00053 
00054         /** Turns off or on particular types of messages
00055             By default, only debugging messages are turned off. */
00056         static void LogInfo   (bool flag=true)  { iAction=flag;         }
00057         static void LogWarning(bool flag=true)  { wAction=flag;         }
00058         static void LogError  (bool flag=true)  { eAction=flag;         }
00059 
00060         static void LogAll    (bool flag=true)  { iAction=wAction=eAction=flag; dRangeS=0; dRangeE=65535; }
00061 
00062         // TEMPORARY
00063         static void LogPhlupa(int from, int to)  { phlupy_.ipoinm=from; phlupy_.ipoin=to; }
00064 
00065         /** Sets the range of debug codes that will be printed.
00066             By default, the debug messages are turned off. */
00067         static void LogDebug(unsigned short s=0,unsigned short e=65535)         { dRangeS=s; dRangeE=e;   }
00068 
00069         /** Asserts logical value. If the assertion fails, the default message or 'text'
00070             will be printed and the program will terminate.
00071             Program termination can be suppressed by Log::IgnoreFailedAsserts(); */
00072         static void Assert(bool check, char *text=NULL);
00073 
00074         /** Terminates the program with added default message or 'text'.
00075             It can be suppressed by Log::IgnoreFatal(); */
00076         static void Fatal(string text, unsigned short int code=0);
00077         static void Fatal(unsigned short int code=0)                            { Fatal(NULL,code);       }
00078 
00079         /** Redirects output to log. Redirection can be done for a block of code
00080             or for one function only. Redirection can be turned off by using
00081             Log::IgnoreRedirection(); If the target is one of the log streams
00082             (for example): Log::RedirectOutput( someFunction, Log::Info() );
00083             You can turn the function's messages off by turning the apropriate
00084             log entries off. The redirected code will still be executed,
00085             only messages are redirected. */
00086         static void RedirectOutput(void (*func)(), ostream& where=*out);
00087         static void RedirectOutput(ostream& where=*out);
00088         /** WARNING! If You're redirecting more than one function, do not forget
00089             to use RevertOutput() afterwards. */
00090         static void RevertOutput()                      { std::cout.rdbuf(bCout); std::cerr.rdbuf(bCerr); }
00091 
00092         /** Do not exit when Log::Assert() check is false.
00093             The number of failed asserts will be listed in the summary. */
00094         static void IgnoreFailedAssert(bool flag=true)                           { asAction=!flag;        }
00095 
00096         /** Ignores redirections of functions' output.
00097             The function will still be called in a normal way. */
00098         static void IgnoreRedirection(bool flag=true)                            { rAction=!flag;         }
00099 
00100         /** Do not exit when Log::Fatal() with the code within the provided range is called.
00101             The number of ignored fatal errors will be listed in the summary. */
00102         static void IgnoreFatal(unsigned short s=0,unsigned short e=65535) { faRangeS=s; faRangeE=e; }
00103 
00104         /** Change the output of the logged messages.
00105             Log::SetOutput(cerr);                    //changes the output to cerr
00106             Log::SetOutput(new ofstream("log.txt")); //changes the output to a file "log.txt" */
00107         static void SetOutput(ostream *newOut)                                    { out=newOut;           }
00108         static void SetOutput(ostream &newOut)                                    { out=&newOut;          }
00109 
00110         /** Change the limit of warnings that will be displayed. Set to 0 for no limit. */
00111         static void SetWarningLimit(int x)                                        { warnLimit=x;          }
00112 
00113 protected:
00114         static streambuf *bCout,*bCerr;
00115         static ostream *out;
00116         static stringstream buf;
00117         static int  warnLimit;
00118         static int  decays[4];
00119         static int  dCount,dRangeS,dRangeE,faCount,faRangeS,faRangeE;
00120         static int  iCount, wCount, eCount, asCount, asFailedCount;
00121         static bool iAction,wAction,eAction,asAction,rAction;
00122 /**
00123         Memory leak tracking section. Compile with #define _LOG_DEBUG_MODE_ to turn it on.
00124         WARNING! Increases execution time significantly. Usefull only for debug purposes.
00125 */
00126 protected:
00127         typedef struct
00128         {
00129                 unsigned long address;
00130                 unsigned long size;
00131                 char  file[64];
00132                 unsigned long line;
00133         } Pointer;
00134         static list<Pointer*> *PointerList;
00135 public:
00136 #ifdef _LOG_DEBUG_MODE_
00137         static void NewPointer(unsigned long address,  unsigned long size,  const char *file, unsigned long line)
00138         {
00139                 if(!PointerList)
00140                 {
00141                         PointerList = new list<Pointer *>();
00142                         atexit(PrintAllocatedPointers);
00143                 }
00144                 Pointer *info = new Pointer();
00145                 info->address = address;
00146                 info->size    = size;
00147                 info->line    = line;
00148                 strncpy(info->file, file, 63);
00149                 PointerList->push_front(info);
00150         }
00151         static void DeletePointer(unsigned long address)
00152         {
00153                 if(!PointerList) return;
00154                 for(list<Pointer*>::iterator i = PointerList->begin(); i!=PointerList->end(); i++)
00155                 {
00156                         if((*i)->address == address)
00157                         {
00158                                 PointerList->remove((*i));
00159                                 break;
00160                         }
00161                 }
00162         }
00163         static bool PointerCompare(Pointer *one, Pointer *two)
00164         {
00165                 int eq = strcmp(one->file,two->file);
00166                 if(eq<0) return true;
00167                 else if(eq>0) return false;
00168                 return (one->line <= two->line);
00169         }
00170         static void PrintAllocatedPointers()
00171         {
00172                 if(!PointerList) return;
00173                 int pointers=0,buf=0;
00174                 unsigned long total=0;
00175                 char *lastS=" ";
00176                 unsigned int lastL=0;
00177                 if(PointerList->size()==0)
00178                 {
00179                         cout<<"----------------------------UNFREED MEMORY POINTERS----------------------------\n";
00180                         cout<<"                                 ... NONE ...\n";
00181                         cout<<"-------------------------------------------------------------------------------\n";
00182                         return;
00183                 }
00184                 PointerList->sort(PointerCompare);
00185                 cout<<"---------------------------UNFREED MEMORY POINTERS---------------------------\n";
00186                 for(list<Pointer*>::iterator i = PointerList->begin(); i!=PointerList->end(); i++)
00187                 {
00188                         total+=(*i)->size;
00189                         ++pointers;
00190                         if(strcmp(lastS,(*i)->file)==0)
00191                         {
00192                                 if(lastL==(*i)->line)
00193                                 {
00194                                         printf("%56s%10lub (%lu)\n"," ",(*i)->size,(*i)->address);
00195                                         continue;
00196                                 }
00197                         }
00198                         lastS=(*i)->file;
00199                         lastL=(*i)->line;
00200                         printf("%s%n:",(*i)->file,&buf);
00201                         printf("%-*lu%10lub (%lu)\n",55-buf,(*i)->line,(*i)->size,(*i)->address);
00202                 }
00203                 cout<<endl<<total<<"\tbytes"<<endl;
00204                 cout<<pointers<<"\tpointers"<<endl;
00205                 cout<<"-------------------------------------------------------------------------------\n";
00206         };
00207 #endif //_LOG_DEBUG_MODE_
00208 };
00209 
00210 #ifdef _LOG_DEBUG_MODE_
00211 
00212 /**
00213     Redeclare new and delete to use the tracking feature.
00214     To use __FILE__ and __LINE__ macro efficiently this header file
00215     should be included in all separately compiled libraries.
00216 */
00217 
00218 inline void* operator new(long unsigned int size, const char *filename, int line)
00219 {
00220         void *ptr = (void *)malloc(size);
00221         Photos::Log::NewPointer((unsigned long)ptr, size, filename, line);
00222         return(ptr);
00223 }
00224 
00225 inline void  operator delete(void *p)
00226 {
00227         Photos::Log::DeletePointer((unsigned long)p);
00228         free(p);
00229 }
00230 
00231 #define new new(__FILE__, __LINE__)
00232 
00233 #endif //_LOG_DEBUG_MODE_
00234 
00235 } // namespace Photospp
00236 #endif
Generated on Sun Oct 20 20:23:56 2013 for C++InterfacetoPHOTOS by  doxygen 1.6.3