summaryrefslogtreecommitdiff
path: root/asl/log/log.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'asl/log/log.hpp')
-rw-r--r--asl/log/log.hpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/asl/log/log.hpp b/asl/log/log.hpp
index e69de29..a6b8f03 100644
--- a/asl/log/log.hpp
+++ b/asl/log/log.hpp
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <asl/format.hpp>
+#include <asl/utility.hpp>
+#include <asl/box.hpp>
+
+namespace asl::log
+{
+
+enum level : uint8_t
+{
+ kDebug = 0,
+ kInfo,
+ kWarning,
+ kError,
+};
+
+struct message
+{
+ level level;
+ string_view message;
+ source_location location;
+};
+
+// @Todo Write and use an intrusive doubly-linked list
+class Logger
+{
+ Logger* m_next{};
+
+public:
+ Logger() = default;
+ ASL_DEFAULT_COPY_MOVE(Logger);
+ virtual ~Logger() = default;
+
+ virtual void log(const message&) = 0;
+
+ friend void register_logger(box<Logger>);
+
+ constexpr Logger* next_logger() const { return m_next; }
+};
+
+// @Todo Make a deref_as trait & deref utility
+// @Todo Accept writer as box, pointer, reference, or value
+class DefaultLogger : public Logger
+{
+ Writer* m_writer;
+
+public:
+ explicit constexpr DefaultLogger(Writer* writer) : m_writer{writer} {}
+
+ void log(const message&) override;
+};
+
+void register_logger(box<Logger>);
+
+// @Todo Add a way to remove loggers (including all)
+
+template<typename T, typename... Args>
+requires constructible_from<T, Args&&...> && convertible_from<Logger*, T*>
+void register_logger(Args&&... args)
+{
+ register_logger(make_box<T>(ASL_FWD(args)...));
+}
+
+void log_inner(level l, string_view fmt, span<const format_internals::type_erased_arg> args, const source_location& sl);
+
+template<formattable... Args>
+void log(level l, const source_location& sl, string_view fmt, const Args&... args)
+{
+ format_internals::type_erased_arg type_erased_args[] = {
+ format_internals::type_erased_arg(args)...
+ };
+ log_inner(l, fmt, type_erased_args, sl);
+}
+
+} // namespace asl::log
+
+// @Todo Compile-time configuration of logging
+
+#define ASL_LOG_DEBUG(...) ::asl::log::log(::asl::log::kDebug, ::asl::source_location{}, __VA_ARGS__)
+#define ASL_LOG_INFO(...) ::asl::log::log(::asl::log::kInfo, ::asl::source_location{}, __VA_ARGS__)
+#define ASL_LOG_WARNING(...) ::asl::log::log(::asl::log::kWarning, ::asl::source_location{}, __VA_ARGS__)
+#define ASL_LOG_ERROR(...) ::asl::log::log(::asl::log::kError, ::asl::source_location{}, __VA_ARGS__)