HighMap library (C++)
Loading...
Searching...
No Matches
logger.hpp
Go to the documentation of this file.
1/* Copyright (c) 2023 Otto Link. Distributed under the terms of the GNU General
2 Public License. The full license is in the file LICENSE, distributed with
3 this software. */
4
13#pragma once
14
15#include <iostream>
16#include <string>
17#include <string_view>
18
19#include <concepts>
20#include <format>
21#include <source_location>
22
23#ifndef HIGHMAP_ENABLE_LOGS
24#define HIGHMAP_ENABLE_LOGS 1
25#endif
26
27#ifndef HIGHMAP_LOG_LEVEL_WIDTH
28#define HIGHMAP_LOG_LEVEL_WIDTH 5
29#endif
30
31#ifndef HIGHMAP_LOG_FILE_WIDTH
32#define HIGHMAP_LOG_FILE_WIDTH 24
33#endif
34
35namespace hmap::log
36{
37
38#if !HIGHMAP_ENABLE_LOGS
39
40template <typename... Args> inline void trace([[maybe_unused]] Args &&...args)
41{
42}
43
44template <typename... Args> inline void info([[maybe_unused]] Args &&...args)
45{
46}
47
48template <typename... Args> inline void warn([[maybe_unused]] Args &&...args)
49{
50}
51
52template <typename... Args> inline void error([[maybe_unused]] Args &&...args)
53{
54}
55
56#else
57
58template <typename... Args> struct format_string_with_loc
59{
60 std::format_string<Args...> fmt;
61 std::source_location loc;
62
63 template <typename S>
64 requires std::constructible_from<std::format_string<Args...>, const S &>
66 const S &s,
67 const std::source_location &l = std::source_location::current())
68 : fmt(s), loc(l)
69 {
70 }
71};
72
73namespace detail
74{
75
76enum class Level
77{
78 Trace,
79 Info,
80 Warn,
81 Error
82};
83
84inline const char *level_to_string(Level level)
85{
86 switch (level)
87 {
88 case Level::Trace: return "trace";
89 case Level::Info: return "info";
90 case Level::Warn: return "warn";
91 case Level::Error: return "error";
92 }
93 return "info";
94}
95
96constexpr std::string_view get_filename(std::string_view path)
97{
98 const size_t pos = path.find_last_of("/\\");
99 return (pos == std::string_view::npos) ? path : path.substr(pos + 1);
100}
101
102inline std::string format_fixed_width(std::string_view str, size_t width)
103{
104 if (width == 0) return std::string(str);
105 if (str.length() > width)
106 {
107 if (width <= 3) return std::string(str.substr(0, width));
108 return std::string(str.substr(0, width - 3)) + "...";
109 }
110 std::string res(str);
111 res.append(width - str.length(), ' ');
112 return res;
113}
114
115inline void log_impl(Level level,
116 std::string_view msg,
117 const std::source_location &loc)
118{
119 std::ostream &out = (level == Level::Warn || level == Level::Error)
120 ? std::cerr
121 : std::cout;
122 out << "hmap " << "["
123 << format_fixed_width(level_to_string(level), HIGHMAP_LOG_LEVEL_WIDTH)
124 << "] ["
125 << format_fixed_width(get_filename(loc.file_name()),
126 HIGHMAP_LOG_FILE_WIDTH)
127 << ":" << loc.line() << "] " << msg << std::endl;
128}
129
130} // namespace detail
131
132// -----------------------------------------------------------------------------
133// trace
134// -----------------------------------------------------------------------------
135
136template <typename... Args>
137inline void trace(format_string_with_loc<std::type_identity_t<Args>...> fl,
138 Args &&...args)
139{
140 std::string msg = std::vformat(fl.fmt.get(), std::make_format_args(args...));
142}
143
144inline void trace(
145 std::string_view message,
146 const std::source_location &loc = std::source_location::current())
147{
149}
150
151template <typename... Args>
152inline void trace(const std::source_location &loc,
153 std::format_string<Args...> fmt,
154 Args &&...args)
155{
156 std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
158}
159
160inline void trace(const std::source_location &loc, std::string_view message)
161{
163}
164
165// -----------------------------------------------------------------------------
166// info
167// -----------------------------------------------------------------------------
168
169template <typename... Args>
170inline void info(format_string_with_loc<std::type_identity_t<Args>...> fl,
171 Args &&...args)
172{
173 std::string msg = std::vformat(fl.fmt.get(), std::make_format_args(args...));
175}
176
177inline void info(
178 std::string_view message,
179 const std::source_location &loc = std::source_location::current())
180{
182}
183
184template <typename... Args>
185inline void info(const std::source_location &loc,
186 std::format_string<Args...> fmt,
187 Args &&...args)
188{
189 std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
191}
192
193inline void info(const std::source_location &loc, std::string_view message)
194{
196}
197
198// -----------------------------------------------------------------------------
199// warn
200// -----------------------------------------------------------------------------
201
202template <typename... Args>
203inline void warn(format_string_with_loc<std::type_identity_t<Args>...> fl,
204 Args &&...args)
205{
206 std::string msg = std::vformat(fl.fmt.get(), std::make_format_args(args...));
208}
209
210inline void warn(
211 std::string_view message,
212 const std::source_location &loc = std::source_location::current())
213{
215}
216
217template <typename... Args>
218inline void warn(const std::source_location &loc,
219 std::format_string<Args...> fmt,
220 Args &&...args)
221{
222 std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
224}
225
226inline void warn(const std::source_location &loc, std::string_view message)
227{
229}
230
231// -----------------------------------------------------------------------------
232// error
233// -----------------------------------------------------------------------------
234
235template <typename... Args>
236inline void error(format_string_with_loc<std::type_identity_t<Args>...> fl,
237 Args &&...args)
238{
239 std::string msg = std::vformat(fl.fmt.get(), std::make_format_args(args...));
241}
242
243inline void error(
244 std::string_view message,
245 const std::source_location &loc = std::source_location::current())
246{
248}
249
250template <typename... Args>
251inline void error(const std::source_location &loc,
252 std::format_string<Args...> fmt,
253 Args &&...args)
254{
255 std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
257}
258
259inline void error(const std::source_location &loc, std::string_view message)
260{
262}
263
264#endif
265
266} // namespace hmap::log
void log_impl(Level level, std::string_view msg, const std::source_location &loc)
Definition logger.hpp:115
std::string format_fixed_width(std::string_view str, size_t width)
Definition logger.hpp:102
constexpr std::string_view get_filename(std::string_view path)
Definition logger.hpp:96
Level
Definition logger.hpp:77
const char * level_to_string(Level level)
Definition logger.hpp:84
Definition logger.hpp:36
void info(Args &&...args)
Definition logger.hpp:44
void warn(Args &&...args)
Definition logger.hpp:48
void trace(Args &&...args)
Definition logger.hpp:40
void error(Args &&...args)
Definition logger.hpp:52
Definition logger.hpp:59
std::format_string< Args... > fmt
Definition logger.hpp:60
consteval format_string_with_loc(const S &s, const std::source_location &l=std::source_location::current())
Definition logger.hpp:65
std::source_location loc
Definition logger.hpp:61