gramods
Loading...
Searching...
No Matches
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
27BEGIN_NAMESPACE_GMCORE;
28
31
35namespace 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
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
253 : public std::ostream {
254
255public:
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
284private:
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
309END_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