StormByte C++ Library 0.0.9999
StormByte is a comprehensive, cross-platform C++ library aimed at easing system programming, configuration management, logging, and database handling tasks. This library provides a unified API that abstracts away the complexities and inconsistencies of different platforms (Windows, Linux).
Loading...
Searching...
No Matches
logger.hxx
1#pragma once
2
3#include <StormByte/string.hxx>
4
5#include <memory>
6#include <optional>
7#include <ostream>
8
16namespace StormByte {
25 class STORMBYTE_PUBLIC Logger final {
26 // Friend declarations for manipulators
27 friend STORMBYTE_PUBLIC Logger& humanreadable_number(Logger& logger) noexcept;
28 friend STORMBYTE_PUBLIC Logger& humanreadable_bytes(Logger& logger) noexcept;
29 friend STORMBYTE_PUBLIC Logger& nohumanreadable(Logger& logger) noexcept;
30
31 public:
36 enum class STORMBYTE_PUBLIC Level : unsigned short {
37 LowLevel = 0,
43 Fatal
44 };
45
50 constexpr static std::string LevelToString(const Level& l) noexcept {
51 switch (l) {
52 case Level::LowLevel: return "LowLevel";
53 case Level::Debug: return "Debug";
54 case Level::Warning: return "Warning";
55 case Level::Notice: return "Notice";
56 case Level::Info: return "Info";
57 case Level::Error: return "Error";
58 case Level::Fatal: return "Fatal";
59 default: return "Unknown";
60 }
61 }
62
69 Logger(std::ostream& out, const Level& level = Level::Info, const std::string& format = "[%L] %T") noexcept;
70
75
80
85
90
95
102
103 // Overload for manipulators like std::endl
104 Logger& operator<<(std::ostream& (*manip)(std::ostream&)) noexcept;
105
112 return manip(*this);
113 }
114
121 template <typename T>
122 Logger& operator<<(const T& value) noexcept
123 requires (!std::is_same_v<std::decay_t<T>, Logger& (*)(Logger&) noexcept>) {
124 using DecayedT = std::decay_t<T>;
125
126 if constexpr (std::is_same_v<DecayedT, bool>) {
127 print_message(value ? "true" : "false");
128 }
129 else if constexpr (std::is_integral_v<DecayedT> || std::is_floating_point_v<DecayedT>) {
130 print_message(value);
131 }
132 else if constexpr (std::is_same_v<DecayedT, std::string> || std::is_same_v<DecayedT, const char*>) {
133 print_message(std::string(value));
134 }
135 else if constexpr (std::is_same_v<DecayedT, std::wstring> || std::is_same_v<DecayedT, const wchar_t*>) {
136 print_message(String::UTF8Encode(value));
137 }
138 else if constexpr (std::is_array_v<T> && std::is_same_v<std::remove_extent_t<T>, char>) {
139 print_message(std::string(value));
140 }
141 else {
142 static_assert(!std::is_same_v<T, T>, "Unsupported type for Logger::operator<<");
143 }
144 return *this;
145 }
146
147 private:
148 std::ostream& m_out;
149 Level m_print_level;
150 std::optional<Level> m_current_level;
151 bool m_header_displayed;
152 const std::string m_format;
153 String::Format m_human_readable_format;
154
158 void print_time() const noexcept;
159
163 void print_level() const noexcept;
164
168 void print_header() const noexcept;
169
170 // Overload for numeric types
171 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> && !std::is_same_v<T, wchar_t>>>
172 void print_message(const T& value) noexcept {
173 std::string message;
174 if (m_human_readable_format == String::Format::Raw) {
175 message = std::to_string(value);
176 }
177 else {
178 // Pass raw numeric type (without std::decay_t) to HumanReadable
179 message = String::HumanReadable(value, m_human_readable_format, "en_US.UTF-8");
180 }
181 print_message(message); // Forward to std::string overload
182 }
183
184 // Overload for std::string
185 void print_message(const std::string& message) noexcept;
186
187 // Overload for wchar_t
188 void print_message(const wchar_t& value) noexcept;
189 };
190
191 // Manipulator to enable human-readable number formatting
192 inline STORMBYTE_PUBLIC Logger& humanreadable_number(Logger& logger) noexcept {
193 logger.m_human_readable_format = String::Format::HumanReadableNumber;
194 return logger;
195 }
196
197 // Manipulator to enable human-readable bytes formatting
198 inline STORMBYTE_PUBLIC Logger& humanreadable_bytes(Logger& logger) noexcept {
199 logger.m_human_readable_format = String::Format::HumanReadableBytes;
200 return logger;
201 }
202
203 // Manipulator to disable human-readable formatting (Raw output)
204 inline STORMBYTE_PUBLIC Logger& nohumanreadable(Logger& logger) noexcept {
205 logger.m_human_readable_format = String::Format::Raw;
206 return logger;
207 }
208
209 template <typename Ptr, typename T>
210 Ptr& operator<<(Ptr& logger, const T& value) noexcept
211 requires std::is_same_v<Ptr, std::shared_ptr<Logger>> || std::is_same_v<Ptr, std::unique_ptr<Logger>> {
212 if (logger) {
213 *logger << value; // Forward the call to the underlying Logger instance
214 }
215 return logger;
216 }
217
218 template <typename Ptr>
219 Ptr& operator<<(Ptr& logger, const Logger::Level& level) noexcept
220 requires std::is_same_v<Ptr, std::shared_ptr<Logger>> || std::is_same_v<Ptr, std::unique_ptr<Logger>> {
221 if (logger) {
222 *logger << level; // Forward the Level to the underlying Logger instance
223 }
224 return logger;
225 }
226
227 template <typename Ptr>
228 Ptr& operator<<(Ptr& logger, std::ostream& (*manip)(std::ostream&)) noexcept
229 requires std::is_same_v<Ptr, std::shared_ptr<Logger>> || std::is_same_v<Ptr, std::unique_ptr<Logger>> {
230 if (logger) {
231 *logger << manip; // Forward manipulators like std::endl
232 }
233 return logger;
234 }
235}
A flexible and extensible logging utility.
Definition logger.hxx:25
enum STORMBYTE_PUBLIC Info
Info level.
Definition logger.hxx:41
static constexpr std::string LevelToString(const Level &l) noexcept
Definition logger.hxx:50
enum STORMBYTE_PUBLIC Warning
Warning level.
Definition logger.hxx:39
enum STORMBYTE_PUBLIC Level
Low level debug level.
Definition logger.hxx:36
Logger(std::ostream &out, const Level &level=Level::Info, const std::string &format="[%L] %T") noexcept
enum STORMBYTE_PUBLIC Debug
Debug level.
Definition logger.hxx:38
enum STORMBYTE_PUBLIC Notice
Notice level.
Definition logger.hxx:40
Logger & operator<<(const T &value) noexcept
Definition logger.hxx:122
enum STORMBYTE_PUBLIC Error
Error level.
Definition logger.hxx:42
Main namespace for the StormByte library.
std::conditional_t< is_reference< T >::value, std::expected< std::reference_wrapper< std::remove_reference_t< T > >, std::shared_ptr< E > >, std::expected< T, std::shared_ptr< E > > > Expected
Expected type with support for reference types.
Definition expected.hxx:32