00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004
00005 #include <time.h>
00006 #include "CSLog.h"
00007 using namespace std;
00008
00009 LogMap CSLog::mMap;
00010 std::string CSLog::mDebugLevelString[]={
00011 ((std::string) "Message"),
00012 ((std::string) "Debug"),
00013 ((std::string) "Info"),
00014 ((std::string) "Warning"),
00015 ((std::string) "Error"),
00016 ((std::string) "None")
00017 };
00018
00019 CSLog::CSLog(const std::string &identifier)
00020 : mIdentifier(identifier)
00021 {
00022 mLogFilename = mIdentifier + ".log";
00023 mTrackClassName = "";
00024 mTrackMethodName = "";
00025 for (int i=0; i < MAX_METHOD_DEPTH; i++)
00026 {
00027 mCurrentMethod[i] = "";
00028 mCurrentClass[i] = "";
00029 }
00030 mLogLevel = LOG_LEVEL_ERROR;
00031 mDebugType = LOG_TYPE_HIGHER_LEVEL;
00032 mFileState = false;
00033 mDebugFile = 0;
00034 mFunctionDepth = 0;
00035 mFunctionTracking = false;
00036 mShortMessage = false;
00037 printInternal(-1, "--- LOG STARTING ---");
00038 }
00039
00040 CSLog::~CSLog()
00041 {
00042 closeFile();
00043 }
00044
00045 bool CSLog::openFile()
00046 {
00047 closeFile();
00048 mDebugFile = fopen(mLogFilename.c_str(), "a");
00049 if (mDebugFile == 0)
00050 {
00051 return false;
00052 }
00053
00054 if (setvbuf(mDebugFile, NULL, _IONBF, 0 ) != 0 )
00055 {
00056
00057
00058 }
00059
00060 mFileState = true;
00061 return true;
00062 }
00063
00064 bool CSLog::closeFile()
00065 {
00066 if (mDebugFile == 0)
00067 {
00068 mFileState = false;
00069 return true;
00070 }
00071 fflush(mDebugFile);
00072 fclose(mDebugFile);
00073
00074 mFileState = false;
00075 mDebugFile = 0;
00076 return true;
00077 }
00078
00079 bool CSLog::printInternal(int level, const std::string &text)
00080 {
00081 if ((level < mLogLevel) && (level != -1))
00082 {
00083 return true;
00084 }
00085
00086 if ((mTrackClassName.length() != 0) && (level != -1))
00087 {
00088 int result = mTrackClassName.compare(0, mTrackClassName.length(), mCurrentClass[mFunctionDepth], 0, mTrackClassName.length());
00089 if ( result != 0)
00090 {
00091 return true;
00092 }
00093 }
00094
00095 if ((mTrackMethodName.length() != 0) && (level != -1))
00096 {
00097 int result = mTrackMethodName.compare(0, mTrackMethodName.length(), mCurrentMethod[mFunctionDepth], 0, mTrackMethodName.length());
00098 if (result != 0)
00099 {
00100 return true;
00101 }
00102 }
00103 if (level > LOG_LEVEL_NONE)
00104 {
00105 level = LOG_LEVEL_NONE;
00106 }
00107
00108 std::string out;
00109 if (!mShortMessage)
00110 {
00111 static char depth[MAX_METHOD_DEPTH];
00112 int i;
00113 for (i=0; ((i<mFunctionDepth) && (i < MAX_METHOD_DEPTH-1)); i++)
00114 {
00115 depth[i] = ' ';
00116 }
00117 depth[i]=0;
00118
00119 struct tm *newtime;
00120 static char ctime[80];
00121 time_t aclock;
00122 time( &aclock );
00123 newtime = localtime( &aclock );
00124
00125
00126
00127 sprintf(ctime, "%s", asctime(newtime));
00128
00129 ctime[strlen(ctime) - 1] = 0;
00130 out = depth + ((std::string)"---") + "\n";
00131 out = out + depth + "|" + ((std::string)ctime);
00132
00133 if (mCurrentClass[mFunctionDepth].length() != 0)
00134 {
00135 out = out + " -> " + mCurrentClass[mFunctionDepth] + "::";
00136 }
00137 else
00138 {
00139 ;
00140 }
00141 if (mCurrentMethod[mFunctionDepth].length() != 0)
00142 {
00143 if (mCurrentClass[mFunctionDepth].length() == 0)
00144 {
00145 out = out + " -> UnkownClass::";
00146 }
00147 out = out + mCurrentMethod[mFunctionDepth] + "()\n";
00148 }
00149 else
00150 {
00151 ;
00152 out = out + "\n";
00153 }
00154
00155
00156 out = out + depth + "|" + mDebugLevelString[level+1]+ ": "+text + "\n";
00157 out = out + depth + "---" + "\n";
00158 }
00159 else
00160 {
00161
00162 if (mCurrentClass[mFunctionDepth].length() != 0)
00163 {
00164 out = mCurrentClass[mFunctionDepth] + "::";
00165 }
00166 if (mCurrentMethod[mFunctionDepth].length() != 0)
00167 {
00168 out = out + mCurrentMethod[mFunctionDepth] + "()";
00169 }
00170 out = out + ": "+text + "\n";
00171
00172 }
00173
00174 bool fileError = openFile();
00175 if (fileError)
00176 {
00177 fprintf(mDebugFile, out.c_str());
00178 closeFile();
00179 }
00180 fprintf(stderr, out.c_str());
00181
00182 CSLogCallbacks::iterator iter = mCallbacks.begin();
00183 while (iter != mCallbacks.end())
00184 {
00185 CSLogCallback *callback = *iter;
00186 callback->printLog(text);
00187 iter++;
00188 }
00189 return fileError;
00190 }
00191
00192 CSLog *CSLog::getInstance(const std::string &identifier)
00193 {
00194 CSLog *instance = 0;
00195 try
00196 {
00197 LogMap::iterator iter = mMap.find(identifier);
00198 if (iter != mMap.end())
00199 {
00200 instance = iter->second;
00201 }
00202 else
00203 {
00204 instance = new CSLog(identifier);
00205 mMap.insert(LogMap::value_type(identifier, instance));
00206 }
00207 }
00208 catch (...)
00209 {
00210 }
00211 return instance;
00212 }
00213
00214 void CSLog::deleteInstance(const std::string &identifier)
00215 {
00216 CSLog *instance = 0;
00217 LogMap::iterator iter = mMap.find(identifier);
00218 if (iter != mMap.end())
00219 {
00220 instance = iter->second;
00221 delete(instance);
00222 mMap.erase(iter);
00223 }
00224 }
00225
00226 void CSLog::print(int level, const std::string &text)
00227 {
00228 printInternal(level, text);
00229 }
00230
00231 void CSLog::print(int level, const std::string &text, long value)
00232 {
00233 std::string newText;
00234 static char valueText[80];
00235 sprintf(valueText, "%i", value);
00236 newText = text + valueText;
00237 print(level, newText);
00238 }
00239
00240 void CSLog::print(int level, const std::string &text, int value)
00241 {
00242 std::string newText;
00243 static char valueText[80];
00244 sprintf(valueText, "%i", value);
00245 newText = text + valueText;
00246 print(level, newText);
00247 }
00248
00249 void CSLog::print(int level, const std::string &text, float value)
00250 {
00251 std::string newText;
00252 static char valueText[80];
00253 sprintf(valueText, "%f", value);
00254 newText = text + valueText;
00255 print(level, newText);
00256 }
00257
00258 void CSLog::startFunction(const std::string &methodName, const std::string &className)
00259 {
00260 mFunctionDepth++;
00261 mCurrentMethod[mFunctionDepth] = methodName;
00262 mCurrentClass[mFunctionDepth] = className;
00263 if (mFunctionTracking)
00264 {
00265 #ifdef SDL_TIMING
00266 mCurrentTime[mFunctionDepth] = SDL_GetTicks();
00267 #endif
00268 if (!mShortMessage)
00269 {
00270 printInternal(LOG_LEVEL_DEBUG, ((std::string) "Entering..."));
00271 }
00272 }
00273 }
00274
00275 void CSLog::endFunction()
00276 {
00277 if (!mShortMessage)
00278 {
00279 if (mFunctionTracking)
00280 {
00281 #ifdef SDL_TIMING
00282 long timeBetween = SDL_GetTicks() - mCurrentTime[mFunctionDepth];
00283 mCurrentTime[mFunctionDepth] = 0;
00284 std::string newText;
00285 static char valueText[80];
00286 sprintf(valueText, "Time remaining in Method (ms): %i", timeBetween);
00287 printInternal(LOG_LEVEL_DEBUG, ((std::string) "Exiting... " + valueText));
00288 #else
00289 printInternal(LOG_LEVEL_DEBUG, ((std::string) "Exiting..."));
00290 #endif
00291 }
00292 }
00293 mCurrentMethod[mFunctionDepth] = "";
00294 mCurrentClass[mFunctionDepth] = "";
00295 mFunctionDepth--;
00296 if (mFunctionDepth < 0)
00297 {
00298 mFunctionDepth = 0;
00299 }
00300 }
00301
00302 void CSLog::setDebugType(int type)
00303 {
00304 mDebugType = type;
00305 }
00306
00307 int CSLog::getDebugType()
00308 {
00309 return mDebugType;
00310 }
00311
00312 void CSLog::setDebugLevel(int level)
00313 {
00314 mLogLevel = level;
00315 }
00316
00317 int CSLog::getDebugLevel()
00318 {
00319 return mLogLevel;
00320 }
00321
00322 void CSLog::addCallback(CSLogCallback *callback)
00323 {
00324 removeCallback(callback);
00325 mCallbacks.push_back(callback);
00326 }
00327
00328 void CSLog::removeCallback(CSLogCallback *callback)
00329 {
00330 CSLogCallbacks::iterator iter = mCallbacks.begin();
00331 while ( iter != mCallbacks.end())
00332 {
00333 if ((*iter) == callback)
00334 {
00335 mCallbacks.erase(iter);
00336 iter = mCallbacks.begin();
00337 }
00338 else
00339 {
00340 iter++;
00341 }
00342 }
00343 }