From 2719942c9eb1e4a397cd16febc50e61b8a510841 Mon Sep 17 00:00:00 2001 From: janis Date: Mon, 20 Jun 2022 00:17:58 +0100 Subject: [PATCH] initial commit --- .gitignore | 3 + Alloy.toml | 14 ++++ include/journal.hpp | 93 ++++++++++++++++++++++++++ src/journal.cc | 157 ++++++++++++++++++++++++++++++++++++++++++++ src/main.cc | 13 ++++ 5 files changed, 280 insertions(+) create mode 100644 .gitignore create mode 100644 Alloy.toml create mode 100644 include/journal.hpp create mode 100644 src/journal.cc create mode 100644 src/main.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6df8e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.cache/ +target/ +compile_commands.json diff --git a/Alloy.toml b/Alloy.toml new file mode 100644 index 0000000..5aa6c3f --- /dev/null +++ b/Alloy.toml @@ -0,0 +1,14 @@ +[package] +name = "journal" +authors = [] +standard = "c++20" +version = "0.1.0" + +[lib] +name = "libjournal" +cc-flags = ["-DJOURNAL_ALL"] + +[[bin]] +name = "journal" +cc-flags = ["-DJOURNAL_ALL", "-gcodeview", "-g"] +ld-flags = ["-g", "-gcodeview"] \ No newline at end of file diff --git a/include/journal.hpp b/include/journal.hpp new file mode 100644 index 0000000..81ead34 --- /dev/null +++ b/include/journal.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include + +namespace journal { + +namespace __detail { + +enum LogVerbosity { + Trace, + Debug, + Info, + Warn, + Error, +}; + +constexpr auto to_string(const LogVerbosity& verbosity) -> std::string; + +template +inline constexpr auto log(const LogVerbosity &verbosity, std::string_view fmt, + Args... args) -> void { + const auto msg = std::vformat(fmt, std::make_format_args( args...)); + log_internal(verbosity, msg); +} + +auto log_internal(const LogVerbosity &verbosity, + const std::string &msg) -> void; +} // namespace __detail + +using __detail::LogVerbosity; + +auto init_stdout(const LogVerbosity& min = LogVerbosity::Info) -> void; + +#ifdef JOURNAL_ALL +#define JOURNAL_TRACE +#define JOURNAL_DEBUG +#define JOURNAL_INFO +#define JOURNAL_WARN +#define JOURNAL_ERROR +#endif + +#ifdef JOURNAL_TRACE +template +inline constexpr auto trace(std::string_view fmt, Args... args) -> void { + __detail::log(__detail::LogVerbosity::Trace, fmt, args...); +} +#else +template +inline constexpr auto trace(std::string_view fmt, Args... args) -> void {} +#endif + +#ifdef JOURNAL_DEBUG +template +inline constexpr auto debug(std::string_view fmt, Args... args) -> void { + __detail::log(__detail::LogVerbosity::Debug, fmt, args...); +} +#else +template +inline constexpr auto debug(std::string_view fmt, Args... args) -> void {} +#endif + +#ifdef JOURNAL_INFO +template +inline constexpr auto info(std::string_view fmt, Args... args) -> void { + __detail::log(__detail::LogVerbosity::Info, fmt, args...); +} +#else +template +inline constexpr auto info(std::string_view fmt, Args... args) -> void {} +#endif + +#ifdef JOURNAL_WARN +template +inline constexpr auto warn(std::string_view fmt, Args... args) -> void { + __detail::log(__detail::LogVerbosity::Warn, fmt, args...); +} +#else +template +inline constexpr auto warn(std::string_view fmt, Args... args) -> void {} +#endif + +#ifdef JOURNAL_ERROR +template +inline constexpr auto error(std::string_view fmt, Args... args) -> void { + __detail::log(__detail::LogVerbosity::Error, fmt, args...); +} +#else +template +inline constexpr auto error(std::string_view fmt, Args... args) -> void {} +#endif + +} // namespace journal \ No newline at end of file diff --git a/src/journal.cc b/src/journal.cc new file mode 100644 index 0000000..aae733e --- /dev/null +++ b/src/journal.cc @@ -0,0 +1,157 @@ +#include "journal.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace journal { +namespace mutex { +class Lock { + std::mutex &mutex; + bool moved = false; + +public: + Lock(Lock &rhs) = delete; + Lock(std::mutex &mutex) : mutex(mutex) { mutex.lock(); + }; + Lock(Lock &&rhs) : mutex(rhs.mutex) { rhs.moved = true; + }; + auto operator=(Lock &rhs) = delete; + ~Lock() { + if (!moved) { + mutex.unlock(); + } + } +}; + +template class Mutex { + std::mutex mutex; + T inner; + +public: + template + Mutex(U &&value) requires(std::assignable_from) + : inner(std::move(value)) {} + Mutex() requires(std::default_initializable) : inner(T{}) {} + + auto ref() -> std::pair { + return {std::move(scoped_lock()), inner}; + } + auto mut() -> std::pair { + return {std::move(scoped_lock()), inner}; + } + + auto operator->() -> T& { + return inner; + } + + auto scoped_lock() -> Lock { return Lock(mutex); } + + auto unique_lock() -> std::unique_lock { + return std::unique_lock(mutex); + } + + auto lock() -> void { mutex.lock(); } + + auto try_lock() -> bool { return mutex.try_lock(); } + + auto unlock() -> void { mutex.unlock(); } +}; +} // namespace mutex + +namespace __detail { + +constexpr auto to_string(const LogVerbosity& verbosity) -> std::string { + switch (verbosity) { + case LogVerbosity::Trace: + return "Trace"; + case LogVerbosity::Debug: + return "Debug"; + case LogVerbosity::Info: + return "Info"; + case LogVerbosity::Warn: + return "Warn"; + case LogVerbosity::Error: + return "Error"; + } +} + +struct Verbosity { + journal::__detail::LogVerbosity inner; + + Verbosity(journal::__detail::LogVerbosity &&value) : inner(value) {} + Verbosity(const journal::__detail::LogVerbosity &value) : inner(value) {} + + auto operator<=>(const Verbosity &rhs) -> std::strong_ordering { + return static_cast>(inner) <=> + static_cast>(rhs.inner); + } +}; + +struct Sink { + std::shared_ptr stream; + Verbosity min_verbosity; + Verbosity max_verbosity; + + Sink(std::shared_ptr&& stream) + : stream(std::move(stream)), min_verbosity(journal::__detail::LogVerbosity::Trace), + max_verbosity(journal::__detail::LogVerbosity::Error) {} + Sink(std::shared_ptr&& stream, const Verbosity &min, + const Verbosity &max) + : stream(std::move(stream)),min_verbosity(min), max_verbosity(max) {} + Sink(std::shared_ptr&& stream, const Verbosity &min) + : stream(std::move(stream)),min_verbosity(min), max_verbosity(journal::__detail::Error) {} + + auto operator<<(std::string_view msg) { (*stream) << msg; } +}; + +class Journal { + std::vector sinks; + +public: +Journal() {} + auto log(const Verbosity &verbosity, std::string_view msg) { + for (auto &&sink : sinks) { + if (verbosity >= sink.min_verbosity && verbosity <= sink.max_verbosity) { + sink << std::format("[{: <5}] {}\n", to_string(verbosity.inner), msg); + } + } + } + + auto + add_std_out(const Verbosity &min = journal::__detail::LogVerbosity::Info) { + auto out = std::shared_ptr(&std::cout, [](auto&& _) {}); + sinks.emplace_back(std::move(out)); + } +}; + +static mutex::Mutex> global_journal; + +auto log_internal(const LogVerbosity &verbosity, + const std::string &msg) + -> void { + auto &&[lock, ref] = global_journal.ref(); + + ref->log(verbosity, msg); +} +} // namespace __detail + +auto init() { + auto &&[lock, ref] = __detail::global_journal.mut(); + if (!ref.get()) { + ref = std::make_unique<__detail::Journal>(); + } +} + +auto init_stdout(const LogVerbosity &min) -> void { + init(); + auto &&[lock, ref] = __detail::global_journal.mut(); + ref->add_std_out(); +} +} // namespace journal diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..7b32b3c --- /dev/null +++ b/src/main.cc @@ -0,0 +1,13 @@ +#include +#include "journal.hpp" +#include + +int main(int argc, const char* argv[]) { + std::cin.get(); + journal::init_stdout(); + printf("Hello, Alloy!\n"); + journal::info("some info!"); + journal::error("something went wrong!"); + journal::trace("just some very verbose stuff here"); + return 1; +} \ No newline at end of file