Line data Source code
1 : #ifndef __PHOTOS_LOG_CLASS_HEADER__
2 : #define __PHOTOS_LOG_CLASS_HEADER__
3 :
4 : /**
5 : * This file contains class for logging and filtering output.
6 : * This header file also includes a debug macro which
7 : * tracks any possible memory leaks within the program.
8 : *
9 : * @author Tomasz Przedzinski
10 : * @date 14 November 2009
11 : */
12 :
13 : #include <iostream>
14 : #include <string>
15 : #include <sstream>
16 : #include <stdlib.h>
17 : #include <list>
18 : #include "Photos.h"
19 : // TEMPORARY
20 : #include "f_Init.h"
21 :
22 : using std::stringstream;
23 : using std::string;
24 : using std::streambuf;
25 : using std::ostream;
26 : using std::list;
27 : using std::cout;
28 : using std::endl;
29 :
30 : namespace Photospp
31 : {
32 :
33 : extern void (*PHOERR)(int,const char*,double);
34 : extern void (*PHOREP)();
35 :
36 : class Log
37 : {
38 : public:
39 : /** Shows the summary of all messages. */
40 : static void Summary();
41 :
42 : /** Shows the summary at the end of the program. */
43 : static void SummaryAtExit() { atexit(Summary); }
44 :
45 : /** Adds the decay to the counter. The type is:
46 : 0 - gun, 1 - no mothers & grandmothers, 2 - no mothers, 3 - ok. */
47 : static void AddDecay(int type);
48 :
49 : /** Four logging entries. Usage:
50 : Log::Info()<<"Logging some info: "<<8<<" > "<<7.9<<endl;
51 : Use Log::Info(false) if You don't want the message to be counted.*/
52 : static ostream& Debug(unsigned short int code=0, bool count=true);
53 : static ostream& Info(bool count=true);
54 : static ostream& Warning(bool count=true);
55 : static ostream& Error(bool count=true);
56 :
57 : /** Turns off or on particular types of messages
58 : By default, only debugging messages are turned off. */
59 : static void LogInfo (bool flag=true) { iAction=flag; }
60 : static void LogWarning(bool flag=true) { wAction=flag; }
61 : static void LogError (bool flag=true) { eAction=flag; }
62 :
63 : static void LogAll (bool flag=true) { iAction=wAction=eAction=flag; dRangeS=0; dRangeE=65535; }
64 :
65 : // TEMPORARY
66 : static void LogPhlupa(int from, int to) { phlupy_.ipoinm=from; phlupy_.ipoin=to; }
67 :
68 : /** Sets the range of debug codes that will be printed.
69 : By default, the debug messages are turned off. */
70 : static void LogDebug(unsigned short s=0,unsigned short e=65535) { dRangeS=s; dRangeE=e; }
71 :
72 : /** Asserts logical value. If the assertion fails, the default message or 'text'
73 : will be printed and the program will terminate.
74 : Program termination can be suppressed by Log::IgnoreFailedAsserts(); */
75 : static void Assert(bool check, char *text=NULL);
76 :
77 : /** Terminates the program with added default message or 'text'.
78 : It can be suppressed by Log::IgnoreFatal(); */
79 : static void Fatal(string text, unsigned short int code=0);
80 : static void Fatal(unsigned short int code=0) { Fatal(NULL,code); }
81 :
82 : /** Redirects output to log. Redirection can be done for a block of code
83 : or for one function only. Redirection can be turned off by using
84 : Log::IgnoreRedirection(); If the target is one of the log streams
85 : (for example): Log::RedirectOutput( someFunction, Log::Info() );
86 : You can turn the function's messages off by turning the apropriate
87 : log entries off. The redirected code will still be executed,
88 : only messages are redirected. */
89 : static void RedirectOutput(void (*func)(), ostream& where=*out);
90 : static void RedirectOutput(ostream& where=*out);
91 : /** WARNING! If You're redirecting more than one function, do not forget
92 : to use RevertOutput() afterwards. */
93 0 : static void RevertOutput() { std::cout.rdbuf(bCout); std::cerr.rdbuf(bCerr); }
94 :
95 : /** Do not exit when Log::Assert() check is false.
96 : The number of failed asserts will be listed in the summary. */
97 : static void IgnoreFailedAssert(bool flag=true) { asAction=!flag; }
98 :
99 : /** Ignores redirections of functions' output.
100 : The function will still be called in a normal way. */
101 : static void IgnoreRedirection(bool flag=true) { rAction=!flag; }
102 :
103 : /** Do not exit when Log::Fatal() with the code within the provided range is called.
104 : The number of ignored fatal errors will be listed in the summary. */
105 : static void IgnoreFatal(unsigned short s=0,unsigned short e=65535) { faRangeS=s; faRangeE=e; }
106 :
107 : /** Change the output of the logged messages.
108 : Log::SetOutput(cerr); //changes the output to cerr
109 : Log::SetOutput(new ofstream("log.txt")); //changes the output to a file "log.txt" */
110 : static void SetOutput(ostream *newOut) { out=newOut; }
111 : static void SetOutput(ostream &newOut) { out=&newOut; }
112 :
113 : /** Change the limit of warnings that will be displayed. Set to 0 for no limit. */
114 : static void SetWarningLimit(int x) { warnLimit=x; }
115 :
116 : /** Warnings on errors from internal part of PHOTOS (originally in F77) */
117 : static void PHOERR(int IMES,const char *TEXT,double DATA);
118 :
119 : /** Final report of warnings from internal part of PHOTOS (originally in F77) */
120 : static void PHOREP();
121 :
122 : protected:
123 : static streambuf *bCout,*bCerr;
124 : static ostream *out;
125 : static stringstream buf;
126 : static int warnLimit;
127 : static int decays[4];
128 : static int dCount,dRangeS,dRangeE,faCount,faRangeS,faRangeE;
129 : static int iCount, wCount, eCount, asCount, asFailedCount;
130 : static bool iAction,wAction,eAction,asAction,rAction;
131 : /**
132 : Memory leak tracking section. Compile with #define _LOG_DEBUG_MODE_ to turn it on.
133 : WARNING! Increases execution time significantly. Usefull only for debug purposes.
134 : */
135 : protected:
136 : typedef struct
137 : {
138 : unsigned long address;
139 : unsigned long size;
140 : char file[64];
141 : unsigned long line;
142 : } Pointer;
143 : static list<Pointer*> *PointerList;
144 : public:
145 : #ifdef _LOG_DEBUG_MODE_
146 : static void NewPointer(unsigned long address, unsigned long size, const char *file, unsigned long line)
147 : {
148 : if(!PointerList)
149 : {
150 : PointerList = new list<Pointer *>();
151 : atexit(PrintAllocatedPointers);
152 : }
153 : Pointer *info = new Pointer();
154 : info->address = address;
155 : info->size = size;
156 : info->line = line;
157 : strncpy(info->file, file, 63);
158 : PointerList->push_front(info);
159 : }
160 : static void DeletePointer(unsigned long address)
161 : {
162 : if(!PointerList) return;
163 : for(list<Pointer*>::iterator i = PointerList->begin(); i!=PointerList->end(); i++)
164 : {
165 : if((*i)->address == address)
166 : {
167 : PointerList->remove((*i));
168 : break;
169 : }
170 : }
171 : }
172 : static bool PointerCompare(Pointer *one, Pointer *two)
173 : {
174 : int eq = strcmp(one->file,two->file);
175 : if(eq<0) return true;
176 : else if(eq>0) return false;
177 : return (one->line <= two->line);
178 : }
179 : static void PrintAllocatedPointers()
180 : {
181 : if(!PointerList) return;
182 : int pointers=0,buf=0;
183 : unsigned long total=0;
184 : char *lastS=" ";
185 : unsigned int lastL=0;
186 : if(PointerList->size()==0)
187 : {
188 : cout<<"----------------------------UNFREED MEMORY POINTERS----------------------------\n";
189 : cout<<" ... NONE ...\n";
190 : cout<<"-------------------------------------------------------------------------------\n";
191 : return;
192 : }
193 : PointerList->sort(PointerCompare);
194 : cout<<"---------------------------UNFREED MEMORY POINTERS---------------------------\n";
195 : for(list<Pointer*>::iterator i = PointerList->begin(); i!=PointerList->end(); i++)
196 : {
197 : total+=(*i)->size;
198 : ++pointers;
199 : if(strcmp(lastS,(*i)->file)==0)
200 : {
201 : if(lastL==(*i)->line)
202 : {
203 : printf("%56s%10lub (%lu)\n"," ",(*i)->size,(*i)->address);
204 : continue;
205 : }
206 : }
207 : lastS=(*i)->file;
208 : lastL=(*i)->line;
209 : printf("%s%n:",(*i)->file,&buf);
210 : printf("%-*lu%10lub (%lu)\n",55-buf,(*i)->line,(*i)->size,(*i)->address);
211 : }
212 : cout<<endl<<total<<"\tbytes"<<endl;
213 : cout<<pointers<<"\tpointers"<<endl;
214 : cout<<"-------------------------------------------------------------------------------\n";
215 : };
216 : #endif //_LOG_DEBUG_MODE_
217 : };
218 :
219 : #ifdef _LOG_DEBUG_MODE_
220 :
221 : /**
222 : Redeclare new and delete to use the tracking feature.
223 : To use __FILE__ and __LINE__ macro efficiently this header file
224 : should be included in all separately compiled libraries.
225 : */
226 :
227 : inline void* operator new(long unsigned int size, const char *filename, int line)
228 : {
229 : void *ptr = (void *)malloc(size);
230 : Photos::Log::NewPointer((unsigned long)ptr, size, filename, line);
231 : return(ptr);
232 : }
233 :
234 : inline void operator delete(void *p)
235 : {
236 : Photos::Log::DeletePointer((unsigned long)p);
237 : free(p);
238 : }
239 :
240 : #define new new(__FILE__, __LINE__)
241 :
242 : #endif //_LOG_DEBUG_MODE_
243 :
244 : } // namespace Photospp
245 : #endif
|