summaryrefslogtreecommitdiff
path: root/src/logger.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/logger.cc')
-rw-r--r--src/logger.cc125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/logger.cc b/src/logger.cc
new file mode 100644
index 0000000..e6198da
--- /dev/null
+++ b/src/logger.cc
@@ -0,0 +1,125 @@
+#include "logger.hh"
+
+#include <cstdint>
+#include <format>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <utility>
+
+namespace logger {
+
+namespace {
+
+class BaseLogger : public Logger {
+ protected:
+ enum class Level : uint8_t {
+ kError,
+ kWarning,
+ kInfo,
+ kDebug,
+ };
+
+ public:
+ void err(std::string_view message) final { write(Level::kError, message); }
+
+ void warn(std::string_view message) final { write(Level::kWarning, message); }
+
+ void info(std::string_view message) final { write(Level::kInfo, message); }
+
+#ifndef NDEBUG
+ void dbg(std::string_view message) final { write(Level::kDebug, message); }
+#endif
+
+ protected:
+ BaseLogger() = default;
+
+ virtual void write(Level level, std::string_view message) = 0;
+};
+
+class NoopLogger : public BaseLogger {
+ public:
+ NoopLogger() = default;
+
+ protected:
+ void write(Level /* level */, std::string_view /* message */) override {}
+};
+
+class StderrLogger : public BaseLogger {
+ public:
+ explicit StderrLogger(bool verbose) : verbose_(verbose) {}
+
+ protected:
+ void write(Level level, std::string_view message) override {
+ switch (level) {
+ case Level::kError:
+ std::cerr << "Error: ";
+ break;
+ case Level::kWarning:
+ std::cerr << "Warning: ";
+ break;
+ case Level::kInfo:
+ if (!verbose_)
+ return;
+ std::cerr << "Info: ";
+ break;
+ case Level::kDebug:
+ if (!verbose_)
+ return;
+ std::cerr << "Debug: ";
+ break;
+ }
+ std::cerr << message << '\n';
+ }
+
+ private:
+ bool const verbose_;
+};
+
+class PrefixLogger : public Logger {
+ public:
+ PrefixLogger(Logger& logger, std::string prefix)
+ : logger_(logger), prefix_(std::move(prefix)) {}
+
+ void err(std::string_view message) override {
+ logger_.err(std::format("{}: {}", prefix_, message));
+ }
+
+ void warn(std::string_view message) override {
+ logger_.warn(std::format("{}: {}", prefix_, message));
+ }
+
+ void info(std::string_view message) override {
+ logger_.info(std::format("{}: {}", prefix_, message));
+ }
+
+#ifndef NDEBUG
+ void dbg(std::string_view message) override {
+ logger_.dbg(std::format("{}: {}", prefix_, message));
+ }
+#endif
+
+ private:
+ Logger& logger_;
+ std::string prefix_;
+};
+
+} // namespace
+
+[[nodiscard]]
+std::unique_ptr<Logger> noop() {
+ return std::make_unique<NoopLogger>();
+}
+
+[[nodiscard]]
+std::unique_ptr<Logger> stderr(bool verbose) {
+ return std::make_unique<StderrLogger>(verbose);
+}
+
+[[nodiscard]]
+std::unique_ptr<Logger> prefix(Logger& logger, std::string prefix) {
+ return std::make_unique<PrefixLogger>(logger, std::move(prefix));
+}
+
+} // namespace logger