C++ Utilities
Loading...
Searching...
No Matches
log.h
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: 2025 Nessan Fitzmaurice <nzznfitz+gh@icloud.com>
3// SPDX-License-Identifier: MIT
4
8
9#include <iostream>
10#include <string>
11#include <format>
12
14#ifdef DEBUG
15 #define DBG(...) MAKE_MESSAGE("DBG", __VA_ARGS__).dispatch()
16#else
17 #define DBG(...) void(0)
18#endif
19
21#ifndef NO_LOGS
22 #define LOG(...) MAKE_MESSAGE("LOG", __VA_ARGS__).dispatch()
23#else
24 #define LOG(...) void(0)
25#endif
26
28#define MAKE_MESSAGE(type, ...) \
29 utilities::message { __func__, __FILE__, __LINE__, type __VA_OPT__(, std::format(__VA_ARGS__)) }
30
31namespace utilities {
32
36class message {
37public:
41 using handler_type = void(const message&);
42
44 static handler_type*& handler() { return c_handler; }
45
49 static void use_default_handler() { c_handler = default_handler; }
50
54 inline static std::ostream* stream = &std::cout;
55
59 message(std::string_view func, std::string_view path, std::size_t line, std::string_view type,
60 std::string_view payload = "") :
61 m_function{func}, m_filename{filename(path)}, m_line{line}, m_type{type}, m_payload{payload}
62 {
63 // Empty body.
64 }
65
67 std::string to_string() const
68 {
69 auto retval = std::format("[{}] function '{}' ({}, line {})", m_type, m_function, m_filename, m_line);
70 if (!m_payload.empty()) {
71 retval += ": ";
72 retval += m_payload;
73 }
74 return retval;
75 }
76
78 void dispatch() const { c_handler(*this); }
79
81 static void default_handler(const message& message) { *stream << message.to_string() << std::endl; }
82
84 static std::string filename(std::string_view path)
85 {
86 char sep = '/';
87#ifdef _WIN32
88 sep = '\\';
89#endif
90 auto i = path.rfind(sep, path.length());
91 if (i != std::string::npos) return std::string{path.substr(i + 1, path.length() - i)};
92 return "";
93 }
94
95private:
96 std::string m_function; // Function/method where the message originated from.
97 std::string m_filename; // Filename where the message originated from (just the filename not the path).
98 std::size_t m_line; // Line in the file where the message originated.
99 std::string m_type; // The type of this message e.g. "DEBUG".
100 std::string m_payload; // Any user supplied string that goes with this message.
101
102 // User can set the a handler for all messages -- the default just prints the message to the default stream.
103 inline static handler_type* c_handler = default_handler;
104};
105
106} // namespace utilities
void dispatch() const
Dispatch this message to the message handler.
Definition log.h:78
message(std::string_view func, std::string_view path, std::size_t line, std::string_view type, std::string_view payload="")
Constructor for message objects.
Definition log.h:59
static std::string filename(std::string_view path)
Reduce a full path to just the filename.
Definition log.h:84
static void default_handler(const message &message)
The default message handler just prints the message to the default stream.
Definition log.h:81
void(const message &) handler_type
Messages are handled by a function with this signature – there is just one handler at a time.
Definition log.h:41
static void use_default_handler()
Class method that sets the message handler back to the default value.
Definition log.h:49
static handler_type *& handler()
Class method that lets you set a custom message handling function.
Definition log.h:44
static std::ostream * stream
The stream used by the default message handler.
Definition log.h:54
std::string to_string() const
Returns the whole message as a string e.g. "[DEBUG] 'foobar' foo.cpp line 25: x = 10,...
Definition log.h:67
The namespace for the utilities library.
Definition formatter.h:14
constexpr auto type()
Returns a string representing an object's "type" as the compiler/preprocessor sees.
Definition type.h:17