gramods
Console.hh
1 
8 #ifndef GRAMODS_CORE_CONSOLE
9 #define GRAMODS_CORE_CONSOLE
10 
11 #include <gmCore/config.hh>
12 
13 #include <gmCore/ConsoleLevel.hh>
14 #include <gmCore/MessageSink.hh>
15 
16 #include <gmCore/export.hh>
17 
18 #include <memory>
19 #include <vector>
20 #include <sstream>
21 
22 #include <iostream>
23 #include <string>
24 #include <algorithm>
25 #include <mutex>
26 
27 BEGIN_NAMESPACE_GMCORE;
28 
31 
35 namespace detail {
36  constexpr bool is_path_sep(char c) {
37  return c == '/' || c == '\\';
38  }
39 
40  constexpr const char* strip_path(const char* path) {
41  auto lastname = path;
42  for (auto p = path ; *p ; ++p) {
43  if (is_path_sep(*p) && *(p+1)) lastname = p+1;
44  }
45  return lastname;
46  }
47 
48  struct basename_impl {
49  constexpr basename_impl(const char* begin, const char* end)
50  : _begin(begin), _end(end) {}
51 
52  void write(std::ostream& os) const {
53  os.write(_begin, _end - _begin);
54  }
55 
56  std::string as_string() const {
57  return std::string(_begin, _end);
58  }
59 
60  const char* const _begin;
61  const char* const _end;
62  };
63 
64  inline std::ostream& operator<<(std::ostream& os, const basename_impl& bi) {
65  bi.write(os);
66  return os;
67  }
68 
69  inline std::string to_string(const basename_impl& bi) {
70  return bi.as_string();
71  }
72 
73  constexpr const char* last_dot_of(const char* p) {
74  const char* last_dot = nullptr;
75  for ( ; *p ; ++p) {
76  if (*p == '.')
77  last_dot = p;
78  }
79  return last_dot ? last_dot : p;
80  }
81 }
82 
167 #ifdef NDEBUG
168 
169 # define GM_ERR(TAG, MSG) \
170  gramods::gmCore::Console \
171  (gramods::gmCore::ConsoleLevel::Error, \
172  TAG) << MSG << std::endl
173 
174 # define GM_WRN(TAG, MSG) \
175  gramods::gmCore::Console \
176  (gramods::gmCore::ConsoleLevel::Warning, \
177  TAG) << MSG << std::endl
178 
179 # define GM_INF(TAG, MSG) \
180  gramods::gmCore::Console \
181  (gramods::gmCore::ConsoleLevel::Information, \
182  TAG) << MSG << std::endl
183 
184 # define GM_DBG1(TAG, MSG) \
185  gramods::gmCore::Console \
186  (gramods::gmCore::ConsoleLevel::Debug1, \
187  TAG) << MSG << std::endl
188 
189 # define GM_DBG2(TAG, MSG) \
190  gramods::gmCore::Console \
191  (gramods::gmCore::ConsoleLevel::Debug2, \
192  TAG) << MSG << std::endl
193 
194 # define GM_DBG3(TAG, MSG) \
195  gramods::gmCore::Console \
196  (gramods::gmCore::ConsoleLevel::Debug3, \
197  TAG) << MSG << std::endl
198 
199 #else // if NDEBUG else
200 
203 #ifdef gramods_STRIP_PATH_FROM_FILE
204 #define GM_FILE gmCore::detail::strip_path(__FILE__)
205 #else
206 #define GM_FILE __FILE__
207 #endif
208 
209 # define GM_ERR(TAG, MSG) \
210  gramods::gmCore::Console \
211  (gramods::gmCore::ConsoleLevel::Error, \
212  TAG, GM_FILE, __LINE__, __func__) \
213  << MSG << std::endl
214 
215 # define GM_WRN(TAG, MSG) \
216  gramods::gmCore::Console \
217  (gramods::gmCore::ConsoleLevel::Warning, \
218  TAG, GM_FILE, __LINE__, __func__) \
219  << MSG << std::endl
220 
221 # define GM_INF(TAG, MSG) \
222  gramods::gmCore::Console \
223  (gramods::gmCore::ConsoleLevel::Information, \
224  TAG, GM_FILE, __LINE__, __func__) \
225  << MSG << std::endl
226 
227 # define GM_DBG1(TAG, MSG) \
228  gramods::gmCore::Console \
229  (gramods::gmCore::ConsoleLevel::Debug1, \
230  TAG, GM_FILE, __LINE__, __func__) \
231  << MSG << std::endl
232 
233 # define GM_DBG2(TAG, MSG) \
234  gramods::gmCore::Console \
235  (gramods::gmCore::ConsoleLevel::Debug2, \
236  TAG, GM_FILE, __LINE__, __func__) \
237  << MSG << std::endl
238 
239 # define GM_DBG3(TAG, MSG) \
240  gramods::gmCore::Console \
241  (gramods::gmCore::ConsoleLevel::Debug3, \
242  TAG, GM_FILE, __LINE__, __func__) \
243  << MSG << std::endl
244 
245 #endif // if NDEBUG else endif
246 
252 struct Console
253  : public std::ostream {
254 
255 public:
256 
257  Console(ConsoleLevel level, std::string tag,
258  std::string file, int line, std::string function)
259  : std::ostream(&buffer),
260  buffer(getBuffer(level, tag, file, line, function)) {}
261 
262  Console(ConsoleLevel level, std::string tag)
263  : std::ostream(&buffer),
264  buffer(getBuffer(level, tag)) {}
265 
266  static void addSink(std::shared_ptr<MessageSink> ms) {
267  std::lock_guard<std::mutex> guard(lock);
268  message_sinks.push_back(ms);
269  }
270 
271  static void removeSink(std::shared_ptr<MessageSink> ms) {
272  std::lock_guard<std::mutex> guard(lock);
273  message_sinks.erase(std::remove(message_sinks.begin(), message_sinks.end(), ms),
274  message_sinks.end());
275  }
276 
277  static void removeAllSinks() {
278  std::lock_guard<std::mutex> guard(lock);
279  message_sinks.clear();
280  }
281 
282  static MessageSink *getDefaultSink();
283 
284 private:
285 
286  class ConsoleBuffer
287  : public std::stringbuf {
288  std::vector<std::shared_ptr<MessageSink>> sinks;
289  MessageSink::Message message_template;
290  public:
291  ConsoleBuffer(std::vector<std::shared_ptr<MessageSink>> sinks,
293  : sinks(sinks),
294  message_template(msg) {}
295  virtual int sync();
296  };
297 
298  static ConsoleBuffer getBuffer(ConsoleLevel level, std::string tag);
299 
300  static ConsoleBuffer getBuffer(ConsoleLevel level, std::string tag,
301  std::string file, int line, std::string function);
302 
303  static gmCore_API std::vector<std::shared_ptr<MessageSink>> message_sinks;
304 
305  ConsoleBuffer buffer;
306  static gmCore_API std::mutex lock;
307 };
308 
309 END_NAMESPACE_GMCORE;
310 
311 #endif
This is the base type for back-ends taking care of information sent to the Console class.
Definition: MessageSink.hh:23
Console for easier handling of runtime and debugging information.
Definition: Console.hh:253
Definition: MessageSink.hh:27