StdLog.h
Go to the documentation of this file.
00001 /*
00002  * StdLog.h
00003  *
00004  * Standard implementation of CLog for non-realtime logging to the console and to file.
00005  *
00006  *  Created on: Jul 30, 2009
00007  *      Author: Erik Schuitema
00008  */
00009 
00010 #ifndef STDLOG_H_
00011 #define STDLOG_H_
00012 
00013 #include <iostream>
00014 #include <sstream>
00015 #include <fstream>
00016 #include <streambuf>
00017 #include <iomanip>
00018 #include "Log.h"
00019 
00020 #ifdef _WIN32
00021 #include <windows.h>
00022 #include <win32_compat.h>
00023 #endif
00024 
00025 #ifdef __APPLE__
00026 #include <mach/clock.h>
00027 #include <mach/mach.h>
00028 #endif
00029 
00030 class CStdStringbuf: public std::stringbuf
00031 {
00032         protected:
00033                 pthread_mutex_t *mGlobalLogLock;
00034                 bool            mOutputToConsole;
00035                 bool            mOutputToFile;
00036                 bool            mTimeStamping;
00037                 std::string     mHeaderText;
00038                 std::string mSystemHeader;
00039                 int                     mHeaderColor;
00040                 int                     mMessageColor;
00041                 FILE            *mFileOut;
00042 #ifdef _WIN32
00043                 HANDLE          mConsoleHandle;
00044 #endif
00045 
00046                 // sync(): synchronize the content of the buffer with the designated output
00047                 virtual int sync()
00048                 {
00049                         // Lock globally if desired. This makes sure that the log line is not interrupted by other logging threads.
00050                         if (mGlobalLogLock != NULL)
00051                                 pthread_mutex_lock(mGlobalLogLock);
00052 
00053                         if (mOutputToConsole || mOutputToFile)
00054                         {
00055                                 // See basic_stringbuf::str() for similar code. However, in that code, I couldn't understand the use of egptr():
00056                                 // "The current egptr() may not be the actual string end."
00057 
00058                                 if (this->pptr())
00059                                 {
00060                                         int len = (int)(this->pptr() - this->pbase());
00061                                         if (len > 0)
00062                                         {
00063                                                 // Null-terminate the string before outputting it (this is necessary)
00064 #if defined(_MSC_VER) || defined(__APPLE__)
00065                                                 if (this->pptr() == this->epptr())
00066                                                         len--;
00067 #else
00068                                                 if (len > (int)_M_string.capacity() - 1)
00069                                                         len = _M_string.capacity() - 1;
00070 #endif
00071                                                 // Writing in the 'unused' space of the buffer shouldn't do any harm
00072                                                 // so we don't have to back it up
00073                                                 this->pbase()[len] = '\0';
00074 
00075                                                 // Call rt_printf and/or rt_fprintf to output the temp buffer, preceded by the header text
00076                                                 if (mOutputToConsole)
00077                                                 {
00078                                                         // Set header color
00079 #ifdef _WIN32
00080                                                         SetConsoleTextAttribute(mConsoleHandle, mHeaderColor);
00081 #else
00082                                                         printf("\033[%dm", mHeaderColor);
00083 #endif
00084                                                         // Print header
00085                                                         fputs(mHeaderText.c_str(), stdout);
00086                                                         // Reset all console attributes (because it may contain other attributes besides color that are not reset when setting new color)
00087 #ifdef _WIN32
00088                                                         SetConsoleTextAttribute(mConsoleHandle, FOREGROUND_GRAY);
00089 #else
00090                                                         printf("\033[0m");      // reset all attributes
00091 #endif
00092                                                         // write time of sending if desired
00093                                                         if (mTimeStamping)
00094                                                         {
00095                                                                 timespec absTime;
00096                                                                 #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
00097                                                                 clock_serv_t cclock;
00098                                                                 mach_timespec_t mts;
00099                                                                 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
00100                                                                 clock_get_time(cclock, &mts);
00101                                                                 mach_port_deallocate(mach_task_self(), cclock);
00102                                                                 absTime.tv_sec = mts.tv_sec;
00103                                                                 absTime.tv_nsec = mts.tv_nsec;
00104                                                                 
00105                                                                 #else
00106                                                                 clock_gettime(CLOCK_REALTIME, &absTime);
00107                                                                 #endif
00108                                                                 printf("[TS:%llu] ", absTime.tv_sec*(long long int)(1E9) + absTime.tv_nsec);
00109                                                         }
00110                                                         // Set message color
00111 #ifdef _WIN32
00112                                                         SetConsoleTextAttribute(mConsoleHandle, mMessageColor);
00113 #else
00114                                                         printf("\033[%dm", mMessageColor);
00115 #endif
00116                                                         // Print message
00117                                                         fputs(this->mSystemHeader.c_str(), stdout);
00118                                                         fputs(this->pbase(), stdout);
00119                                                         // Reset all console attributes
00120 #ifdef _WIN32
00121                                                         SetConsoleTextAttribute(mConsoleHandle, FOREGROUND_GRAY);
00122 #else
00123                                                         printf("\033[0m");      // reset all attributes
00124 #endif
00125                                                 }
00126                                                 if (mOutputToFile && mFileOut != NULL)
00127                                                 {
00128                                                         fputs(mHeaderText.c_str(), mFileOut);
00129                                                         fputs(this->pbase(), mFileOut);
00130                                                 }
00131 
00132                                                 // Adjust the write buffer pointers. This effectively empties the buffer.
00133 #if defined(__APPLE__) || defined(_MSC_VER)
00134                                                 setg(pbase(), pbase(), epptr());
00135                                                 setp(pbase(), epptr());
00136 #else
00137                                                 _M_sync(const_cast<char_type*>(_M_string.data()), 0, 0);
00138 #endif
00139                                         }
00140                                 }
00141                         }
00142                         int result = std::stringbuf::sync();
00143 
00144                         // Unlock if desired
00145                         if (mGlobalLogLock != NULL)
00146                                 pthread_mutex_unlock(mGlobalLogLock);
00147 
00148                         return result;
00149                 }
00150 
00151         public:
00152                 CStdStringbuf(pthread_mutex_t *globalLogLock=NULL):
00153                         mGlobalLogLock(globalLogLock),
00154                         mOutputToConsole(true),
00155                         mOutputToFile(false),
00156                         mTimeStamping(false),
00157                         mHeaderColor(0),
00158                         mMessageColor(0),
00159                         mFileOut(NULL)
00160                 {
00161 #ifdef _WIN32
00162                         mConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
00163 #endif
00164                 }
00165 
00166                 ~CStdStringbuf()
00167                 {
00168                         // Force a last sync. Disable the locking mechanism, because the logfactory might destroy itself, and its locking mutex!
00169                         mGlobalLogLock = NULL;
00170                         sync();
00171                         // Force file closure
00172                         enableFileOutput(false);
00173                 }
00174 
00175                 void    enableConsoleOutput(bool bEnabled)                                      {mOutputToConsole = bEnabled;}
00176                 void    enableFileOutput(bool bEnabled, const std::string& filename="")
00177                 {
00178                         if (bEnabled)
00179                         {       // Open file
00180                                 // First close the old one if existent
00181                                 if (mFileOut != NULL)
00182                                 {
00183                                         // First, empty our internal buffer to the file buffer using sync()
00184                                         sync();
00185                                         // Then, close the file (which will flush its own buffer to disc)
00186                                         fclose(mFileOut);
00187                                 }
00188                                 mFileOut = fopen(filename.c_str(), "wt");
00189                         }
00190                         else
00191                         {       // Close file
00192                                 if (mFileOut != NULL)
00193                                 {
00194                                         // First, empty our internal buffer to the file buffer using sync()
00195                                         sync();
00196                                         // Then, close the file (which will flush its own buffer to disc)
00197                                         fclose(mFileOut);
00198                                         mFileOut = NULL;
00199                                 }
00200                         }
00201 
00202                         if (bEnabled && mFileOut == NULL)
00203                         {
00204                                 std::cerr << "Unable to enable file output" << std::endl;
00205                                 mOutputToFile   = false;
00206                         }
00207                         else
00208                                 mOutputToFile   = bEnabled;
00209                 }
00210                 void    flushFileOutput()
00211                 {
00212                         if (mOutputToFile)
00213                                 if (mFileOut != NULL)
00214                                         fflush(mFileOut);
00215                 }
00216                 void    enableTimeStamping(bool enabled)                                        {mTimeStamping  = enabled;}
00217                 void    setHeaderText(const std::string &headerText)            {mHeaderText    = headerText;}
00218                 std::string& headerText()                                                                       {return mHeaderText;}
00219                 void    setHeaderColor(int headerColor)                                         {mHeaderColor   = headerColor;}
00220                 void    setMessageColor(int messageColor)                                       {mMessageColor  = messageColor;}
00221                 void  setSystemHeader(const std::string &text) { mSystemHeader = text;}
00222 };
00223 
00224 class CStdLogStream : public CLogStream
00225 {
00226         protected:
00227                 CStdStringbuf mBuffer;
00228 
00229         public:
00230                 CStdLogStream(pthread_mutex_t *globalLogLock=NULL):
00231                         CLogStream(&mBuffer),
00232                         mBuffer(globalLogLock)
00233                 {
00234                 }
00235 
00236                 void    flushFileOutput()                                                                       {mBuffer.flushFileOutput();}
00237                 void    enableConsoleOutput(bool bEnabled)                                      {return mBuffer.enableConsoleOutput(bEnabled);}
00238                 // mBuffer.enableFileOutput closes files locally, so it can return NULL to the log factory.
00239                 FILE*   enableFileOutput(bool bEnabled, const std::string& filename="") {mBuffer.enableFileOutput(bEnabled, filename); return NULL;}
00240                 void    enableTimeStamping(bool enabled)                                        {mBuffer.enableTimeStamping(enabled);}
00241                 void    setHeaderText(const std::string &headerText)            {mBuffer.setHeaderText(headerText);}
00242                 std::string& headerText()                                                                       {return mBuffer.headerText();}
00243                 void    setHeaderColor(int headerColor)                                         {mBuffer.setHeaderColor(headerColor);}
00244                 void    setMessageColor(int messageColor)                                       {mBuffer.setMessageColor(messageColor);}
00245                 void  setSystemHeader(const std::string &text) { mBuffer.setSystemHeader(text); }
00246 
00247 };
00248 
00249 class CStdLog: public CLog
00250 {
00251         protected:
00252                 CStdLogStream   mCout;
00253                 CStdLogStream   mCerr;
00254                 CStdLogStream   mCcustom[LOG_MAX_CUSTOMLOGS];
00255 
00256         public:
00257                 CLogStream&     cout()                                          {return mCout;}
00258                 CLogStream&     cerr()                                          {return mCerr;}
00259                 CLogStream&     ccustom(const int index)        {return mCcustom[index];}
00260 };
00261 
00262 #endif /* STDLOG_H_ */


threemxl
Author(s):
autogenerated on Fri Aug 28 2015 13:21:08