pxar
 All Classes Namespaces Functions Variables Typedefs Friends
log.h
1 
5 #ifndef PXAR_LOG_H
6 #define PXAR_LOG_H
7 
9 #if ((defined WIN32) && (defined __CINT__))
10 typedef unsigned int uint32_t;
11 typedef unsigned int DWORD;
12 #include <Windows4Root.h>
13 #else
14 #if (defined WIN32)
15 typedef unsigned int uint32_t;
16 #include <Windows.h>
17 #else
18 #include <sys/time.h>
19 #include <stdint.h>
20 #endif //WIN32
21 #endif //WIN32 && CINT
22 
23 #ifdef WIN32
24 #define __func__ __FUNCTION__
25 #endif // WIN32
26 
27 #include <sstream>
28 #include <iomanip>
29 #include <cstdio>
30 #include <string.h>
31 
32 
33 namespace pxar {
34 
35  enum TLogLevel {
36  logQUIET,
37  logCRITICAL,
38  logERROR,
39  logWARNING,
40  logINFO,
41  logDEBUG,
42  logDEBUGAPI,
43  logDEBUGHAL,
44  logDEBUGRPC,
45  logDEBUGPIPES,
46  logINTERFACE
47  };
48 
49  template <typename T>
50  class pxarLog {
51  public:
52  pxarLog();
53  virtual ~pxarLog();
54  std::ostringstream& Get(TLogLevel level = logINFO, std::string file = "", std::string function = "", uint32_t line = 0);
55  public:
56  static TLogLevel& ReportingLevel();
57  static std::string ToString(TLogLevel level);
58  static TLogLevel FromString(const std::string& level);
59  protected:
60  std::ostringstream os;
61  private:
62  pxarLog(const pxarLog&);
63  pxarLog& operator =(const pxarLog&);
64  std::string NowTime();
65  };
66 
67  template <typename T>
69 
70 
71 #ifdef WIN32
72 
73  template <typename T>
74  std::string pxarLog<T>::NowTime(){
75  const int MAX_LEN = 200;
76  char buffer[MAX_LEN];
77  if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0,
78  "HH':'mm':'ss", buffer, MAX_LEN) == 0)
79  return "Error in NowTime()";
80 
81  char result[100] = {0};
82  static DWORD first = GetTickCount();
83  std::sprintf(result, "%s.%03ld", buffer, static_cast<long>(GetTickCount() - first) % 1000);
84  return result;
85 }
86 
87 #else
88 
89  template <typename T>
90  std::string pxarLog<T>::NowTime() {
91  char buffer[11];
92  time_t t;
93  time(&t);
94  tm r = * localtime(&t);
95  strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
96  struct timeval tv;
97  gettimeofday(&tv, 0);
98  char result[100] = {0};
99  std::sprintf(result, "%s.%03ld", buffer, static_cast<long>(tv.tv_usec) / 1000);
100  return result;
101  }
102 
103 #endif //WIN32
104 
105  template <typename T>
106  std::ostringstream& pxarLog<T>::Get(TLogLevel level, std::string file, std::string function, uint32_t line) {
107  os << "[" << NowTime() << "] ";
108  os << std::setw(8) << ToString(level) << ": ";
109 
110  // For debug levels we want also function name and line number printed:
111  if (level != logINFO && level != logQUIET && level != logDEBUGRPC && level != logWARNING && level != logDEBUGPIPES)
112  os << "<" << file << "/" << function << ":L" << line << "> ";
113  else if(level == logDEBUGRPC)
114  os << "\"" << function << "\" ";
115 
116  return os;
117  }
118 
119  template <typename T>
120  pxarLog<T>::~pxarLog() {
121  os << std::endl;
122  T::Output(os.str());
123  }
124 
125  template <typename T>
126  TLogLevel& pxarLog<T>::ReportingLevel() {
127  static TLogLevel reportingLevel = logINFO;
128  return reportingLevel;
129  }
130 
131  template <typename T>
132  std::string pxarLog<T>::ToString(TLogLevel level) {
133  static const char* const buffer[] = {"QUIET","CRITICAL","ERROR", "WARNING", "INFO", "DEBUG", "DEBUGAPI", "DEBUGHAL", "DEBUGRPC", "DEBUGPIPES", "INTERFACE"};
134  return buffer[level];
135  }
136 
137  template <typename T>
138  TLogLevel pxarLog<T>::FromString(const std::string& level) {
139  if (level == "INTERFACE")
140  return logINTERFACE;
141  if( level == "DEBUGPIPES")
142  return logDEBUGPIPES;
143  if (level == "DEBUGRPC")
144  return logDEBUGRPC;
145  if (level == "DEBUGHAL")
146  return logDEBUGHAL;
147  if (level == "DEBUGAPI")
148  return logDEBUGAPI;
149  if (level == "DEBUG")
150  return logDEBUG;
151  if (level == "INFO")
152  return logINFO;
153  if (level == "WARNING")
154  return logWARNING;
155  if (level == "ERROR")
156  return logERROR;
157  if (level == "CRITICAL")
158  return logCRITICAL;
159  if (level == "QUIET")
160  return logQUIET;
161  pxarLog<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using WARNING level as default.";
162  return logWARNING;
163  }
164 
165 
167  {
168  public:
169  static FILE*& Stream();
170  static bool& Duplicate();
171  static void Output(const std::string& msg);
172  };
173 
174  inline bool& SetLogOutput::Duplicate()
175  {
176  static bool duplic = false;
177  return duplic;
178  }
179 
180  inline FILE*& SetLogOutput::Stream()
181  {
182  static FILE* pStream = stderr;
183  return pStream;
184  }
185 
186  inline void SetLogOutput::Output(const std::string& msg)
187  {
188  FILE* pStream = Stream();
189  if (!pStream)
190  return;
191  // Check if duplication to stderr is needed:
192  if (Duplicate() && pStream != stderr)
193  fprintf(stderr, "%s", msg.c_str());
194  fprintf(pStream, "%s", msg.c_str());
195  fflush(pStream);
196  }
197 
198 typedef pxarLog<SetLogOutput> Log;
199 
200 #define __FILE_NAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
201 
202 #define IFLOG(level) \
203  if (level > pxar::Log::ReportingLevel())
204 
205 #define LOG(level) \
206  if (level > pxar::Log::ReportingLevel() || !pxar::SetLogOutput::Stream()) ; \
207  else pxar::Log().Get(level,__FILE_NAME__,__func__,__LINE__)
208 
209 } //namespace pxar
210 
211 #endif /* PXAR_LOG_H */