Skip to content

Commit 8310e70

Browse files
committed
Refactor logging API, add StringViewStream other minor QoL updates and changes
1 parent 3d1f910 commit 8310e70

11 files changed

Lines changed: 410 additions & 80 deletions

File tree

Playground/main.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88

99
using namespace ARLib;
1010
int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv) {
11-
auto console_logger = MUST(ConsoleLogger::create("default"_s, LogLevel::Trace, "%c%m %l test"));
12-
auto file_logger = MUST(FileLogger::create("file"_s, LogLevel::Info, "log.txt"_s));
13-
auto string_logger = MUST(StringLogger::create("buffer"_s, LogLevel::Debug, DefaultLogFormat));
11+
auto console_logger = MUST(ConsoleLogger::create("default"_s, LogLevel::Trace, "%c%m %l%r test"));
12+
auto file_logger = MUST(FileLoggerTs::create("file"_s, LogLevel::Info, "log.txt"_s));
13+
auto string_logger = MUST(StringLogger::create("buffer"_s, LogLevel::Debug, DefaultLogFormat));
1414
Logger::register_logger(console_logger);
1515
Logger::register_logger(file_logger);
1616
Logger::register_logger(string_logger);
17-
for (size_t i = 0; i < 10; i++) {
18-
Logger::log(LogLevel::Info, "Hello from {} {}."_sv, "ARLib", i);
19-
}
17+
for (size_t i = 0; i < 10; i++) { Logger::log_warning("Hello from {} {}."_sv, "ARLib", i); }
2018
auto logger = Logger::get_named_logger("buffer"_sv);
2119
if (logger.is_ok()) { Printer::print("String logger contents: {}", logger.to_ok().as<StringLogger>().output()); }
20+
console_logger->log_info("This is a test log message with value: {}"_sv, 42);
21+
file_logger->log_error("This is an error message with value: {}"_sv, 42);
22+
for (const auto& line : string_logger.as<StringLogger>().lines()) { Printer::print("Logged line: {}", line); }
2223
return 0;
2324
}

include/EnumHelpers.hpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,22 @@ namespace EnumHelpers {
6868
while ((isspace(view[last_idx]) || view[last_idx] == ',') && last_idx > 0) last_idx--;
6969
return view.substringview(0, last_idx + 1);
7070
}
71+
72+
template <Enum T>
73+
constexpr StringView enum_full_string = get_enum_full_string<T>({});
74+
75+
template <Enum T>
76+
constexpr StringView enum_view = strip_trailing_commas(enum_full_string<T>);
77+
78+
template <Enum T>
79+
constexpr size_t enum_count = count_enum_values(enum_view<T>);
80+
7181
template <Enum T>
72-
requires(!get_enum_full_string<T>({}).empty())
82+
requires(!enum_full_string<T>.empty())
7383
struct EnumArrayProvider<T> {
7484
constexpr static auto construct_enum_array(TagType<T>) {
75-
constexpr StringView view = strip_trailing_commas(get_enum_full_string<T>({}));
76-
Array<Pair<StringView, T>, count_enum_values(view)> enum_map_l;
85+
constexpr StringView view = enum_view<T>;
86+
Array<Pair<StringView, T>, enum_count<T>> enum_map_l;
7787
UnderlyingTypeT<T> current_val{};
7888
auto get_pair = [&view, &current_val](size_t first_idx, size_t second_idx) {
7989
constexpr bool Signed = IsSigned<UnderlyingTypeT<T>>;
@@ -115,9 +125,9 @@ namespace EnumHelpers {
115125
};
116126
template <Enum T>
117127
constexpr auto construct_enum_map(
118-
const Array<Pair<StringView, T>, count_enum_values(strip_trailing_commas(get_enum_full_string<T>({})))>& enum_array
128+
const Array<Pair<StringView, T>, enum_count<T>>& enum_array
119129
) {
120-
constexpr size_t sz = count_enum_values(strip_trailing_commas(get_enum_full_string<T>({})));
130+
constexpr size_t sz = enum_count<T>;
121131
EnumStrHashMap<T, sz> map;
122132
for (const auto& [k, v] : enum_array) {
123133
const bool inserted = map.insert(v, k);

include/Iterator.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ class IteratorBase {
1818
constexpr IteratorBase(IteratorBase<T>&& other) noexcept : m_current(other.m_current) { other.m_current = nullptr; }
1919

2020
public:
21+
constexpr const T* const ptr() const { return m_current; }
2122
constexpr bool operator==(const IteratorBase<T>& other) const { return m_current == other.m_current; }
2223
constexpr bool operator!=(const IteratorBase<T>& other) const { return m_current != other.m_current; }
2324
constexpr bool operator<(const IteratorBase<T>& other) { return m_current < other.m_current; }
2425
constexpr bool operator>(const IteratorBase<T>& other) { return m_current > other.m_current; }
2526
};
26-
// for some godforsaken reason
27-
#define m_current IteratorBase<T>::m_current
2827
template <typename T>
2928
class Iterator final : public IteratorBase<T> {
29+
using IteratorBase<T>::m_current;
3030
public:
31-
explicit Iterator(T* start) : IteratorBase<T>(start) {}
31+
constexpr explicit Iterator(T* start) : IteratorBase<T>(start) {}
3232
Iterator(const Iterator<T>& other) : IteratorBase<T>(other) {}
3333
Iterator(Iterator<T>&& other) noexcept : IteratorBase<T>(other) {}
3434
T& operator*() { return *m_current; }
@@ -74,6 +74,7 @@ class Iterator final : public IteratorBase<T> {
7474
};
7575
template <typename Ct>
7676
class ConstIterator final : public IteratorBase<typename AddConst<Ct>::type> {
77+
using IteratorBase<typename AddConst<Ct>::type>::m_current;
7778

7879
public:
7980
using T = AddConstT<Ct>;
@@ -125,6 +126,7 @@ class ConstIterator final : public IteratorBase<typename AddConst<Ct>::type> {
125126
};
126127
template <typename T>
127128
class ReverseIterator final : public IteratorBase<T> {
129+
using IteratorBase<T>::m_current;
128130
public:
129131
explicit ReverseIterator(T* end) : IteratorBase<T>(end) {}
130132
ReverseIterator(const ReverseIterator<T>& other) : IteratorBase<T>(other.m_current) {}
@@ -168,6 +170,7 @@ class ReverseIterator final : public IteratorBase<T> {
168170
template <typename Ct>
169171
class ConstReverseIterator final : public IteratorBase<typename AddConst<Ct>::type> {
170172
using T = typename AddConst<Ct>::type;
173+
using IteratorBase<T>::m_current;
171174

172175
public:
173176
explicit ConstReverseIterator(T* end) : IteratorBase<T>(end) {}
@@ -211,7 +214,6 @@ class ConstReverseIterator final : public IteratorBase<typename AddConst<Ct>::ty
211214
}
212215
ConstReverseIterator<Ct> operator-(Integral auto offset) { return { m_current + offset }; }
213216
};
214-
#undef m_current
215217
template <typename T, ComparatorType CMP, typename = EnableIfT<IsNonboolIntegral<T>>>
216218
class LoopIterator {
217219
T m_current;

include/Logger.hpp

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ constexpr static inline uint8_t _newline_buffer[]{ '\n' };
1212
constexpr static inline Span<const uint8_t> _newline_span{ _newline_buffer };
1313
MAKE_FANCY_ENUM(LogLevel, uint8_t, Critical = 5, Error = 4, Warning = 3, Info = 2, Debug = 1, Trace = 0);
1414
MAKE_FANCY_ENUM(LoggingError, uint8_t, FormatError, OutputError, OpenStreamError, LoggerNotFoundError);
15-
constexpr StringView DefaultLogFormat = "%c[%n|%l - %u][%t]%r %m";
15+
constexpr StringView DefaultLogFormat = "%c[%n|%l - %u][%t]%r %m";
1616
constexpr StringView DefaultLogFileFormat = "[%n|%l - %u][%t] %m";
1717
class LoggingFormat {
18-
enum class LoggingFormatSpecifier {
18+
enum class LoggingFormatSpecifier : uint8_t {
1919
Message,
2020
LogLevel,
21+
LogLevelShort,
2122
Timestamp,
2223
ThreadId,
2324
DefaultColor,
@@ -32,21 +33,61 @@ class LoggingFormat {
3233
static Result<LoggingFormat, LoggingError> from_string(StringView format);
3334
String format_message(StringView message, LogLevel level, StringView logger_name) const;
3435
};
36+
#ifdef __INTELLISENSE__
37+
constexpr bool is_intellisense = true;
38+
#else
39+
constexpr bool is_intellisense = false;
40+
#endif
41+
template <typename... Args>
42+
using LoggerStringParam = ConditionalT<is_intellisense, StringView, FormatString<sizeof...(Args)>>;
43+
44+
template <typename T>
45+
concept LoggingPrintable = Printable<RemoveReferenceT<T>>;
3546
class LoggingBackend {
3647
String m_name;
3748
LogLevel m_level;
3849
LoggingFormat m_format;
3950
friend class LoggingBackendTs;
51+
friend class Logger;
52+
public:
53+
using LogResult = DiscardResult<LoggingError>;
4054
protected:
4155
String format_message(StringView message, LogLevel level) const;
42-
protected:
4356
LoggingBackend(String name, LogLevel level, LoggingFormat format) :
4457
m_name{ name }, m_level{ level }, m_format{ format } {}
58+
virtual LogResult log(LogLevel level, StringView message) = 0;
4559
public:
46-
using LogResult = DiscardResult<LoggingError>;
4760
constexpr bool should_log(LogLevel level) const { return level >= m_level; }
4861
const String& name() const { return m_name; }
49-
virtual LogResult log(LogLevel level, StringView message) = 0;
62+
template <LoggingPrintable... Args>
63+
LogResult log(LogLevel level, LoggerStringParam<Args...> str, Args&&... args) {
64+
auto formatted_string = Printer::format(move(str), Forward<Args>(args)...);
65+
return log(level, formatted_string);
66+
}
67+
template <LoggingPrintable... Args>
68+
LogResult log_critical(LoggerStringParam<Args...> str, Args&&... args) {
69+
return log(LogLevel::Critical, move(str), Forward<Args>(args)...);
70+
}
71+
template <LoggingPrintable... Args>
72+
LogResult log_error(LoggerStringParam<Args...> str, Args&&... args) {
73+
return log(LogLevel::Error, move(str), Forward<Args>(args)...);
74+
}
75+
template <LoggingPrintable... Args>
76+
LogResult log_warning(LoggerStringParam<Args...> str, Args&&... args) {
77+
return log(LogLevel::Warning, move(str), Forward<Args>(args)...);
78+
}
79+
template <LoggingPrintable... Args>
80+
LogResult log_info(LoggerStringParam<Args...> str, Args&&... args) {
81+
return log(LogLevel::Info, move(str), Forward<Args>(args)...);
82+
}
83+
template <LoggingPrintable... Args>
84+
LogResult log_debug(LoggerStringParam<Args...> str, Args&&... args) {
85+
return log(LogLevel::Debug, move(str), Forward<Args>(args)...);
86+
}
87+
template <LoggingPrintable... Args>
88+
LogResult log_trace(LoggerStringParam<Args...> str, Args&&... args) {
89+
return log(LogLevel::Trace, move(str), Forward<Args>(args)...);
90+
}
5091
virtual bool supports_color() { return false; }
5192
virtual ~LoggingBackend() = default;
5293
};
@@ -154,8 +195,9 @@ class FileLogger : public StreamLogger<FileStream> {
154195
};
155196
class BufferedFileLogger : public StreamLogger<BufferedFileStream> {
156197
String m_file_path;
157-
BufferedFileLogger(String name, LogLevel level, LoggingFormat format, String file_path, BufferedFileStream&& stream) :
158-
StreamLogger<BufferedFileStream>{ name, level, format, move(stream) }, m_file_path{ move(file_path) } {}
198+
BufferedFileLogger(
199+
String name, LogLevel level, LoggingFormat format, String file_path, BufferedFileStream&& stream
200+
) : StreamLogger<BufferedFileStream>{ name, level, format, move(stream) }, m_file_path{ move(file_path) } {}
159201
public:
160202
static Result<SharedPtr<LoggingBackend>, LoggingError>
161203
create(String name, LogLevel level, String file_path, StringView format = DefaultLogFileFormat) {
@@ -179,12 +221,12 @@ class StringLogger : public StreamLogger<StringStream> {
179221
};
180222
}
181223
String output() const { return m_stream->str(); }
224+
auto lines() const { return StringViewStream{ *m_stream }.lines_view(); }
182225
};
183226
class FileLoggerTs : public StreamLoggerTs<FileStream> {
184227
String m_file_path;
185228
FileLoggerTs(String name, LogLevel level, LoggingFormat format, String file_path, FileStream&& stream) :
186-
StreamLoggerTs<FileStream>{ name, level, format, move(stream) }, m_file_path{ move(file_path) } {
187-
}
229+
StreamLoggerTs<FileStream>{ name, level, format, move(stream) }, m_file_path{ move(file_path) } {}
188230
public:
189231
static Result<SharedPtr<LoggingBackend>, LoggingError>
190232
create(String name, LogLevel level, String file_path, StringView format = DefaultLogFileFormat) {
@@ -247,30 +289,23 @@ class Logger {
247289
}
248290
public:
249291
static void register_logger(SharedPtr<LoggingBackend> backend) {
250-
auto name_copy = backend->name();
292+
String name_copy = backend->name();
251293
store().add_backend(move(name_copy), move(backend));
252294
}
253295
static LoggingStorage::ResultType get_named_logger(StringView name);
254296
static LoggingStorage::ResultType get_default_logger();
255-
#ifdef __INTELLISENSE__
256-
#define LOGGER_STRING_PARAM_TYPE StringView
257-
#else
258-
#define LOGGER_STRING_PARAM_TYPE FormatString<sizeof...(Args)>
259-
#endif
260-
template <typename... Args>
261-
requires(... && Printable<RemoveReferenceT<Args>>)
297+
template <LoggingPrintable... Args>
262298
static LoggingBackend::LogResult
263-
log(StringView logger_name, LogLevel level, LOGGER_STRING_PARAM_TYPE str, Args&&... args) {
299+
log(StringView logger_name, LogLevel level, LoggerStringParam<Args...> str, Args&&... args) {
264300
auto formatted_string = Printer::format(move(str), Forward<Args>(args)...);
265301
if (auto it = store().get(logger_name); it.is_ok()) {
266302
auto backend = it.to_ok();
267303
TRY(backend->log(level, formatted_string));
268304
}
269305
return {};
270306
}
271-
template <typename... Args>
272-
requires(... && Printable<RemoveReferenceT<Args>>)
273-
static LoggingBackend::LogResult log(LogLevel level, LOGGER_STRING_PARAM_TYPE str, Args&&... args) {
307+
template <LoggingPrintable... Args>
308+
static LoggingBackend::LogResult log(LogLevel level, LoggerStringParam<Args...> str, Args&&... args) {
274309
auto formatted_string = Printer::format(move(str), Forward<Args>(args)...);
275310
auto& sync_store = Logger::store();
276311
return sync_store.m_store.with_lock(
@@ -280,5 +315,29 @@ class Logger {
280315
}
281316
);
282317
}
318+
template <LoggingPrintable... Args>
319+
static LoggingBackend::LogResult log_critical(LoggerStringParam<Args...> str, Args&&... args) {
320+
return log(LogLevel::Critical, move(str), Forward<Args>(args)...);
321+
}
322+
template <LoggingPrintable... Args>
323+
static LoggingBackend::LogResult log_error(LoggerStringParam<Args...> str, Args&&... args) {
324+
return log(LogLevel::Error, move(str), Forward<Args>(args)...);
325+
}
326+
template <LoggingPrintable... Args>
327+
static LoggingBackend::LogResult log_warning(LoggerStringParam<Args...> str, Args&&... args) {
328+
return log(LogLevel::Warning, move(str), Forward<Args>(args)...);
329+
}
330+
template <LoggingPrintable... Args>
331+
static LoggingBackend::LogResult log_info(LoggerStringParam<Args...> str, Args&&... args) {
332+
return log(LogLevel::Info, move(str), Forward<Args>(args)...);
333+
}
334+
template <LoggingPrintable... Args>
335+
static LoggingBackend::LogResult log_debug(LoggerStringParam<Args...> str, Args&&... args) {
336+
return log(LogLevel::Debug, move(str), Forward<Args>(args)...);
337+
}
338+
template <LoggingPrintable... Args>
339+
static LoggingBackend::LogResult log_trace(LoggerStringParam<Args...> str, Args&&... args) {
340+
return log(LogLevel::Trace, move(str), Forward<Args>(args)...);
341+
}
283342
};
284343
} // namespace ARLib

include/Stream.hpp

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ struct CharacterStream : public BaseStream {
5252
LinesIterator begin() const;
5353
LinesIterator end() const;
5454
};
55-
virtual Lines lines() & = 0;
56-
virtual Lines lines() && = 0;
55+
virtual Lines lines() & = 0;
56+
virtual Lines lines() && = 0;
5757
virtual DiscardResult<FileError> open() { return DefaultOk{}; }
5858
virtual Result<size_t> write_string(StringView buffer) = 0;
5959
virtual Result<String> read_string() = 0;
@@ -127,6 +127,7 @@ class BufferedFileStream : public FileStream {
127127
class StringStream : public CharacterStream {
128128
size_t m_pos{ 0 };
129129
String m_buffer;
130+
friend class StringViewStream;
130131
public:
131132
StringStream() = default;
132133
StringStream(String buffer) : m_buffer{ move(buffer) } {}
@@ -149,4 +150,67 @@ class StringStream : public CharacterStream {
149150
bool is_open() const override { return true; }
150151
virtual ~StringStream() = default;
151152
};
153+
class StringViewStream : public CharacterStream {
154+
size_t m_pos{ 0 };
155+
StringView m_view;
156+
public:
157+
class LinesViewIterator {
158+
MaybeOwned<StringViewStream> m_stream;
159+
bool m_eof_reached{ false };
160+
bool m_end{ false };
161+
StringView m_current_line{};
162+
public:
163+
LinesViewIterator(MaybeOwned<StringViewStream> stream, bool end = false);
164+
StringView operator*();
165+
LinesViewIterator& operator++();
166+
LinesViewIterator operator++(int);
167+
bool operator==(const LinesViewIterator& other) const;
168+
bool operator!=(const LinesViewIterator& other) const;
169+
};
170+
class LinesView {
171+
MaybeOwned<StringViewStream> m_stream;
172+
public:
173+
LinesView(StringViewStream& stream) :
174+
m_stream{ MaybeOwned<StringViewStream>::template lended<StringViewStream>(stream) } {
175+
if (auto& fs = *m_stream; !fs.is_open()) { fs.open(); }
176+
}
177+
LinesView(StringViewStream&& stream) :
178+
m_stream{
179+
MaybeOwned<StringViewStream>::template owned<StringViewStream>(Forward<StringViewStream>(stream))
180+
} {
181+
if (auto& fs = *m_stream; !fs.is_open()) { fs.open(); }
182+
}
183+
LinesViewIterator begin();
184+
LinesViewIterator end();
185+
LinesViewIterator begin() const;
186+
LinesViewIterator end() const;
187+
};
188+
StringViewStream() = default;
189+
StringViewStream(const StringStream& stream) : m_pos{ stream.m_pos }, m_view{ stream.m_buffer } {}
190+
StringViewStream(StringView view) : m_view{ move(view) } {}
191+
StringViewStream(const String& str) : m_view{ str.view() } {}
192+
Result<size_t> write(Span<const uint8_t> buffer) override;
193+
Result<size_t> write(Span<const char> buffer) override;
194+
Result<size_t> write(StringView view) override;
195+
Result<Vector<uint8_t>> read(size_t n) override;
196+
Result<Vector<uint8_t>> read() override;
197+
Result<size_t> write_string(StringView buffer) override;
198+
Result<String> read_string() override;
199+
Result<String> read_line(bool& eof_reached) override;
200+
Result<StringView> read_string_view();
201+
Result<StringView> read_line_view(bool& eof_reached);
202+
Lines lines() & override { return Lines{ *this }; }
203+
Lines lines() && override { return Lines{ move(*this) }; }
204+
LinesView lines_view() & { return LinesView{ *this }; }
205+
LinesView lines_view() && { return LinesView{ move(*this) }; }
206+
size_t pos() const override { return m_pos; }
207+
size_t seek(size_t pos) override {
208+
m_pos = pos;
209+
return m_pos;
210+
}
211+
StringView view() const { return m_view; }
212+
String str() const { return m_view.str(); }
213+
bool is_open() const override { return true; }
214+
virtual ~StringViewStream() = default;
215+
};
152216
} // namespace ARLib

0 commit comments

Comments
 (0)