1 /* 2 * Copyright (C) 2009, 2010 Nicolas Bonnefon and other contributors 3 * 4 * This file is part of glogg. 5 * 6 * glogg is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * glogg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with glogg. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef __LOG_H__ 21 #define __LOG_H__ 22 23 #include <sstream> 24 #include <string> 25 #include <cstdio> 26 27 // Modify here! 28 //#define FILELOG_MAX_LEVEL logDEBUG 29 30 inline std::string NowTime(); 31 32 enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4}; 33 34 template <typename T> 35 class Log 36 { 37 public: 38 Log(); 39 virtual ~Log(); 40 std::ostringstream& Get(TLogLevel level = logINFO, 41 const std::string& sourceFile = "", int lineNumber = 0); 42 public: 43 static TLogLevel ReportingLevel() { return reportingLevel; } 44 static std::string ToString(TLogLevel level); 45 static TLogLevel FromString(const std::string& level); 46 static void setReportingLevel(TLogLevel level) { reportingLevel = level; } 47 48 template <typename U> friend class Log; 49 50 protected: 51 std::ostringstream os; 52 private: 53 static TLogLevel reportingLevel; 54 55 Log(const Log&); 56 Log& operator =(const Log&); 57 }; 58 59 template <typename T> TLogLevel Log<T>::reportingLevel = logDEBUG4; 60 61 template <typename T> 62 Log<T>::Log() 63 { 64 } 65 66 template <typename T> 67 std::ostringstream& Log<T>::Get(TLogLevel level, 68 const std::string& sourceFile, int lineNumber) 69 { 70 os << "- " << NowTime(); 71 os << " " << ToString(level); 72 os << " " << sourceFile << ":" << lineNumber << ": "; 73 os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t'); 74 return os; 75 } 76 77 template <typename T> 78 Log<T>::~Log() 79 { 80 os << std::endl; 81 T::Output(os.str()); 82 } 83 84 template <typename T> 85 std::string Log<T>::ToString(TLogLevel level) 86 { 87 static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"}; 88 return buffer[level]; 89 } 90 91 template <typename T> 92 TLogLevel Log<T>::FromString(const std::string& level) 93 { 94 if (level == "DEBUG4") 95 return logDEBUG4; 96 if (level == "DEBUG3") 97 return logDEBUG3; 98 if (level == "DEBUG2") 99 return logDEBUG2; 100 if (level == "DEBUG1") 101 return logDEBUG1; 102 if (level == "DEBUG") 103 return logDEBUG; 104 if (level == "INFO") 105 return logINFO; 106 if (level == "WARNING") 107 return logWARNING; 108 if (level == "ERROR") 109 return logERROR; 110 Log<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default."; 111 return logINFO; 112 } 113 114 class Output2FILE 115 { 116 public: 117 static FILE*& Stream(); 118 static void Output(const std::string& msg); 119 }; 120 121 inline FILE*& Output2FILE::Stream() 122 { 123 static FILE* pStream = stderr; 124 return pStream; 125 } 126 127 inline void Output2FILE::Output(const std::string& msg) 128 { 129 FILE* pStream = Stream(); 130 if (!pStream) 131 return; 132 fprintf(pStream, "%s", msg.c_str()); 133 fflush(pStream); 134 } 135 136 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) 137 # if defined (BUILDING_FILELOG_DLL) 138 # define FILELOG_DECLSPEC __declspec (dllexport) 139 # elif defined (USING_FILELOG_DLL) 140 # define FILELOG_DECLSPEC __declspec (dllimport) 141 # else 142 # define FILELOG_DECLSPEC 143 # endif // BUILDING_DBSIMPLE_DLL 144 #else 145 # define FILELOG_DECLSPEC 146 #endif // _WIN32 147 148 //class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {}; 149 typedef Log<Output2FILE> FILELog; 150 151 #ifndef FILELOG_MAX_LEVEL 152 #define FILELOG_MAX_LEVEL logDEBUG 153 #endif 154 155 #define FILE_LOG(level) \ 156 if (level > FILELOG_MAX_LEVEL) ;\ 157 else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \ 158 else FILELog().Get(level, __FILE__, __LINE__) 159 160 #define LOG(level) FILE_LOG(level) 161 162 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) 163 164 #include <windows.h> 165 166 inline std::string NowTime() 167 { 168 const int MAX_LEN = 200; 169 char buffer[MAX_LEN]; 170 if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, 171 "HH':'mm':'ss", buffer, MAX_LEN) == 0) 172 return "Error in NowTime()"; 173 174 char result[100] = {0}; 175 static DWORD first = GetTickCount(); 176 std::sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000); 177 return result; 178 } 179 180 #else 181 182 #include <sys/time.h> 183 184 inline std::string NowTime() 185 { 186 char buffer[11]; 187 time_t t; 188 time(&t); 189 tm r; 190 strftime(buffer, sizeof(buffer), "%T", localtime_r(&t, &r)); 191 struct timeval tv; 192 gettimeofday(&tv, 0); 193 char result[100] = {0}; 194 std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); 195 return result; 196 } 197 198 #endif //WIN32 199 200 #endif //__LOG_H__ 201