Adaptagrams
topology_log.h
1 /*
2  * vim: ts=4 sw=4 et tw=0 wm=0
3  *
4  * libtopology - Classes used in generating and managing topology constraints.
5  *
6  * Copyright (C) 2007-2008 Monash University
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  * See the file LICENSE.LGPL distributed with the library.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  *
18 */
19 
20 /*
21 Logging code from DJJ article: http://www.ddj.com/cpp/201804215.
22 
23 Title: Logging In C++
24 Author: Petru Marginean
25 Keywords: OCT07 C++
26 Description: Unpublished source code accompanying the article by Petru Marginean, in which he presents a C++ logging framework that is typesafe, thread-safe, and portable.
27  */
28 #ifndef __TOPOLOGY_LOG_H__
29 #define __TOPOLOGY_LOG_H__
30 
31 #include <sstream>
32 #include <string>
33 #include <cstdio>
34 #include <iomanip>
35 
36 namespace topology {
37 inline std::string NowTime();
38 
39 enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
40 
41 template <typename T>
42 class Log
43 {
44 public:
45  Log();
46  virtual ~Log();
47  std::ostringstream& Get(TLogLevel level = logINFO);
48  void flush();
49 public:
50  static TLogLevel& ReportingLevel();
51  static std::string ToString(TLogLevel level);
52  static TLogLevel FromString(const std::string& level);
53 protected:
54  std::ostringstream os;
55 private:
56  Log(const Log&);
57  Log& operator =(const Log&);
58 };
59 
60 template <typename T>
61 Log<T>::Log()
62 {
63 }
64 
65 template <typename T>
66 std::ostringstream& Log<T>::Get(TLogLevel level)
67 {
68  os << "- " << NowTime();
69  os << " " << ToString(level) << ": ";
70  os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
71  return os;
72 }
73 
74 template <typename T>
75 void Log<T>::flush()
76 {
77  os << std::endl;
78  T::Output(os.str());
79 }
80 template <typename T>
81 Log<T>::~Log()
82 {
83  flush();
84 }
85 
86 template <typename T>
87 TLogLevel& Log<T>::ReportingLevel()
88 {
89  static TLogLevel reportingLevel = logDEBUG4;
90  return reportingLevel;
91 }
92 
93 template <typename T>
94 std::string Log<T>::ToString(TLogLevel level)
95 {
96  static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"};
97  return buffer[level];
98 }
99 
100 template <typename T>
101 TLogLevel Log<T>::FromString(const std::string& level)
102 {
103  if (level == "DEBUG4")
104  return logDEBUG4;
105  if (level == "DEBUG3")
106  return logDEBUG3;
107  if (level == "DEBUG2")
108  return logDEBUG2;
109  if (level == "DEBUG1")
110  return logDEBUG1;
111  if (level == "DEBUG")
112  return logDEBUG;
113  if (level == "INFO")
114  return logINFO;
115  if (level == "WARNING")
116  return logWARNING;
117  if (level == "ERROR")
118  return logERROR;
119  Log<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default.";
120  return logINFO;
121 }
122 
123 class Output2FILE
124 {
125 public:
126  static FILE*& Stream();
127  static void Output(const std::string& msg);
128 };
129 
130 inline FILE*& Output2FILE::Stream()
131 {
132  static FILE* pStream = stderr;
133  return pStream;
134 }
135 
136 inline void Output2FILE::Output(const std::string& msg)
137 {
138  FILE* pStream = Stream();
139  if (!pStream)
140  return;
141  fprintf(pStream, "%s", msg.c_str());
142  fflush(pStream);
143 }
144 
145 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
146 # if defined (BUILDING_FILELOG_DLL)
147 # define FILELOG_DECLSPEC __declspec (dllexport)
148 # elif defined (USING_FILELOG_DLL)
149 # define FILELOG_DECLSPEC __declspec (dllimport)
150 # else
151 # define FILELOG_DECLSPEC
152 # endif // BUILDING_DBSIMPLE_DLL
153 #else
154 # define FILELOG_DECLSPEC
155 #endif // _WIN32
156 
157 class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {};
158 //typedef Log<Output2FILE> FILELog;
159 
160 #ifndef FILELOG_MAX_LEVEL
161 #define FILELOG_MAX_LEVEL logDEBUG4
162 #endif
163 
164 #define FILE_LOG(level) \
165  if (level > FILELOG_MAX_LEVEL) ;\
166  else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \
167  else FILELog().Get(level)
168 
169 #define FLUSH_LOG(level) \
170  if (level > FILELOG_MAX_LEVEL) ;\
171  else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \
172  else FILELog().flush()
173 
174 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
175 
176 #include <windows.h>
177 
178 inline std::string NowTime()
179 {
180  const int MAX_LEN = 200;
181  char buffer[MAX_LEN];
182  if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0,
183  "HH':'mm':'ss", buffer, MAX_LEN) == 0)
184  return "Error in NowTime()";
185 
186  static DWORD first = GetTickCount();
187  std::stringstream result;
188  result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)(GetTickCount() - first) % 1000);
189  return result.str();
190 }
191 
192 #else
193 
194 #include <sys/time.h>
195 
196 inline std::string NowTime()
197 {
198  char buffer[11];
199  time_t t;
200  time(&t);
201  tm r;
202  strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
203  struct timeval tv;
204  gettimeofday(&tv, 0);
205  std::stringstream result;
206  result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)tv.tv_usec / 1000);
207  return result.str();
208 }
209 
210 #endif //WIN32
211 } // namespace topology
212 #endif //__TOPOLOGY_LOG_H__
libtopology: Extensions for topology preservation for libcola and libavoid libraries.
Definition: shape.h:41