initial commit

This commit is contained in:
janis 2022-06-20 00:17:58 +01:00
commit 2719942c9e
5 changed files with 280 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.cache/
target/
compile_commands.json

14
Alloy.toml Normal file
View file

@ -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"]

93
include/journal.hpp Normal file
View file

@ -0,0 +1,93 @@
#pragma once
#include <format>
#include <string_view>
namespace journal {
namespace __detail {
enum LogVerbosity {
Trace,
Debug,
Info,
Warn,
Error,
};
constexpr auto to_string(const LogVerbosity& verbosity) -> std::string;
template <typename... Args>
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 <typename... Args>
inline constexpr auto trace(std::string_view fmt, Args... args) -> void {
__detail::log(__detail::LogVerbosity::Trace, fmt, args...);
}
#else
template <typename... Args>
inline constexpr auto trace(std::string_view fmt, Args... args) -> void {}
#endif
#ifdef JOURNAL_DEBUG
template <typename... Args>
inline constexpr auto debug(std::string_view fmt, Args... args) -> void {
__detail::log(__detail::LogVerbosity::Debug, fmt, args...);
}
#else
template <typename... Args>
inline constexpr auto debug(std::string_view fmt, Args... args) -> void {}
#endif
#ifdef JOURNAL_INFO
template <typename... Args>
inline constexpr auto info(std::string_view fmt, Args... args) -> void {
__detail::log(__detail::LogVerbosity::Info, fmt, args...);
}
#else
template <typename... Args>
inline constexpr auto info(std::string_view fmt, Args... args) -> void {}
#endif
#ifdef JOURNAL_WARN
template <typename... Args>
inline constexpr auto warn(std::string_view fmt, Args... args) -> void {
__detail::log(__detail::LogVerbosity::Warn, fmt, args...);
}
#else
template <typename... Args>
inline constexpr auto warn(std::string_view fmt, Args... args) -> void {}
#endif
#ifdef JOURNAL_ERROR
template <typename... Args>
inline constexpr auto error(std::string_view fmt, Args... args) -> void {
__detail::log(__detail::LogVerbosity::Error, fmt, args...);
}
#else
template <typename... Args>
inline constexpr auto error(std::string_view fmt, Args... args) -> void {}
#endif
} // namespace journal

157
src/journal.cc Normal file
View file

@ -0,0 +1,157 @@
#include "journal.hpp"
#include <compare>
#include <concepts>
#include <cstdio>
#include <iostream>
#include <memory>
#include <mutex>
#include <optional>
#include <string_view>
#include <type_traits>
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 <typename T> class Mutex {
std::mutex mutex;
T inner;
public:
template <typename U>
Mutex(U &&value) requires(std::assignable_from<U, T>)
: inner(std::move(value)) {}
Mutex() requires(std::default_initializable<T>) : inner(T{}) {}
auto ref() -> std::pair<Lock, const T &> {
return {std::move(scoped_lock()), inner};
}
auto mut() -> std::pair<Lock, T &> {
return {std::move(scoped_lock()), inner};
}
auto operator->() -> T& {
return inner;
}
auto scoped_lock() -> Lock { return Lock(mutex); }
auto unique_lock() -> std::unique_lock<std::mutex> {
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<std::underlying_type_t<decltype(inner)>>(inner) <=>
static_cast<std::underlying_type_t<decltype(rhs.inner)>>(rhs.inner);
}
};
struct Sink {
std::shared_ptr<std::ostream> stream;
Verbosity min_verbosity;
Verbosity max_verbosity;
Sink(std::shared_ptr<std::ostream>&& stream)
: stream(std::move(stream)), min_verbosity(journal::__detail::LogVerbosity::Trace),
max_verbosity(journal::__detail::LogVerbosity::Error) {}
Sink(std::shared_ptr<std::ostream>&& stream, const Verbosity &min,
const Verbosity &max)
: stream(std::move(stream)),min_verbosity(min), max_verbosity(max) {}
Sink(std::shared_ptr<std::ostream>&& 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<Sink> 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::ostream>(&std::cout, [](auto&& _) {});
sinks.emplace_back(std::move(out));
}
};
static mutex::Mutex<std::unique_ptr<Journal>> 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

13
src/main.cc Normal file
View file

@ -0,0 +1,13 @@
#include <stdio.h>
#include "journal.hpp"
#include <iostream>
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;
}