Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
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
00047 virtual int sync()
00048 {
00049
00050 if (mGlobalLogLock != NULL)
00051 pthread_mutex_lock(mGlobalLogLock);
00052
00053 if (mOutputToConsole || mOutputToFile)
00054 {
00055
00056
00057
00058 if (this->pptr())
00059 {
00060 int len = (int)(this->pptr() - this->pbase());
00061 if (len > 0)
00062 {
00063
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
00072
00073 this->pbase()[len] = '\0';
00074
00075
00076 if (mOutputToConsole)
00077 {
00078
00079 #ifdef _WIN32
00080 SetConsoleTextAttribute(mConsoleHandle, mHeaderColor);
00081 #else
00082 printf("\033[%dm", mHeaderColor);
00083 #endif
00084
00085 fputs(mHeaderText.c_str(), stdout);
00086
00087 #ifdef _WIN32
00088 SetConsoleTextAttribute(mConsoleHandle, FOREGROUND_GRAY);
00089 #else
00090 printf("\033[0m");
00091 #endif
00092
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
00111 #ifdef _WIN32
00112 SetConsoleTextAttribute(mConsoleHandle, mMessageColor);
00113 #else
00114 printf("\033[%dm", mMessageColor);
00115 #endif
00116
00117 fputs(this->mSystemHeader.c_str(), stdout);
00118 fputs(this->pbase(), stdout);
00119
00120 #ifdef _WIN32
00121 SetConsoleTextAttribute(mConsoleHandle, FOREGROUND_GRAY);
00122 #else
00123 printf("\033[0m");
00124 #endif
00125 }
00126 if (mOutputToFile && mFileOut != NULL)
00127 {
00128 fputs(mHeaderText.c_str(), mFileOut);
00129 fputs(this->pbase(), mFileOut);
00130 }
00131
00132
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
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
00169 mGlobalLogLock = NULL;
00170 sync();
00171
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 {
00180
00181 if (mFileOut != NULL)
00182 {
00183
00184 sync();
00185
00186 fclose(mFileOut);
00187 }
00188 mFileOut = fopen(filename.c_str(), "wt");
00189 }
00190 else
00191 {
00192 if (mFileOut != NULL)
00193 {
00194
00195 sync();
00196
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
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