diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-02-04 00:37:08 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-02-04 00:37:08 +0100 |
commit | 3d5a45b283d2a59211f9e24f100b95169375213d (patch) | |
tree | 2180c31100324076f7ff862009190564c0296b58 /asl | |
parent | f2b1af8d3f23ff47b343cef8feef6e25ff5377e4 (diff) |
Add deref utilities & use them for log writer
Diffstat (limited to 'asl')
-rw-r--r-- | asl/log/log.cpp | 6 | ||||
-rw-r--r-- | asl/log/log.hpp | 20 | ||||
-rw-r--r-- | asl/log/log_tests.cpp | 13 | ||||
-rw-r--r-- | asl/meta.hpp | 27 | ||||
-rw-r--r-- | asl/tests/meta_tests.cpp | 40 |
5 files changed, 97 insertions, 9 deletions
diff --git a/asl/log/log.cpp b/asl/log/log.cpp index cd5d287..af31a84 100644 --- a/asl/log/log.cpp +++ b/asl/log/log.cpp @@ -4,7 +4,7 @@ // @Todo Don't use internal get_stdout_writer, make console module -static asl::log::DefaultLogger g_default_logger{asl::print_internals::get_stdout_writer()}; +static asl::log::DefaultLogger<asl::Writer*> g_default_logger{asl::print_internals::get_stdout_writer()}; static asl::log::Logger* g_head = &g_default_logger; static constexpr asl::string_view kLevelName[] = { @@ -20,9 +20,9 @@ void asl::log::register_logger(box<Logger> logger_box) logger->m_next = exchange(g_head, logger); } -void asl::log::DefaultLogger::log(const message& msg) +void asl::log::DefaultLoggerBase::log_inner(Writer& writer, const message& msg) { - asl::format(m_writer, "[{}] {}:{}: {}\n", + asl::format(&writer, "[{}] {}:{}: {}\n", kLevelName[msg.level], // NOLINT msg.location.file, msg.location.line, diff --git a/asl/log/log.hpp b/asl/log/log.hpp index f2e3a47..7445cf6 100644 --- a/asl/log/log.hpp +++ b/asl/log/log.hpp @@ -39,16 +39,24 @@ public: 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 +class DefaultLoggerBase : public Logger { - Writer* m_writer; +protected: + static void log_inner(Writer&, const message&); +}; + +template<derefs_as<Writer> W> +class DefaultLogger : public DefaultLoggerBase +{ + W m_writer; public: - explicit constexpr DefaultLogger(Writer* writer) : m_writer{writer} {} + explicit constexpr DefaultLogger(W&& writer) : m_writer{ASL_FWD(writer)} {} - void log(const message&) override; + constexpr void log(const message& m) override + { + log_inner(deref<Writer>(m_writer), m); + } }; void register_logger(box<Logger>); diff --git a/asl/log/log_tests.cpp b/asl/log/log_tests.cpp index 01e8fd7..4ab83e8 100644 --- a/asl/log/log_tests.cpp +++ b/asl/log/log_tests.cpp @@ -1,5 +1,6 @@ #include <asl/log/log.hpp> #include <asl/testing/testing.hpp> +#include <asl/string_builder.hpp> ASL_TEST(log) { @@ -8,3 +9,15 @@ ASL_TEST(log) ASL_LOG_ERROR("Oh no! {}", 42); } +static asl::StringWriter g_string_writer{}; + +ASL_TEST(custom_writer) +{ + asl::log::register_logger<asl::log::DefaultLogger<asl::StringWriter<>&>>(g_string_writer); + + ASL_LOG_INFO("Hello"); + auto sv = g_string_writer.as_string_view(); + + ASL_TEST_EXPECT(sv == "[ INFO ] asl/log/log_tests.cpp:18: Hello\n"); +} + diff --git a/asl/meta.hpp b/asl/meta.hpp index 9909be6..a464e36 100644 --- a/asl/meta.hpp +++ b/asl/meta.hpp @@ -117,6 +117,8 @@ template<typename T> struct _is_ref_helper<T&> { static constexpr bool l = true template<typename T> struct _is_ref_helper<T&&> { static constexpr bool l = false; static constexpr bool r = true; }; template<typename T> concept is_ref = _is_ref_helper<T>::l || _is_ref_helper<T>::r; +template<typename T> concept is_rref = _is_ref_helper<T>::r; +template<typename T> concept is_lref = _is_ref_helper<T>::l; template<typename T> struct _is_ptr_helper : false_type {}; template<typename T> struct _is_ptr_helper<T*> : true_type {}; @@ -218,4 +220,29 @@ concept has_niche = constructible_from<T, niche_t> && equality_comparable_with<T template<typename T> concept is_niche = same_as<un_cvref_t<T>, niche_t>; +template<typename T, typename U> +concept _derefs_with_indirection_as = requires(T& t) +{ + *t; + requires convertible_from<U&, decltype(*t)>; +}; + +template<typename T, typename U> +concept _derefs_reference_as = is_ref<T> && convertible_from<U&, T>; + +template<typename T, typename U> +concept _derefs_value_as = !is_ref<T> && convertible_from<U&, T&>; + +template<typename U, _derefs_with_indirection_as<U> T> +constexpr U& deref(T&& t) { return static_cast<U&>(*t); } + +template<typename U, _derefs_reference_as<U> T> +constexpr U& deref(T&& t) { return static_cast<U&>(t); } + +template<typename U, _derefs_value_as<U> T> +constexpr U& deref(T&& t) { return static_cast<U&>(t); } + +template<typename T, typename U> +concept derefs_as = _derefs_with_indirection_as<T, U> || _derefs_reference_as<T, U> || _derefs_value_as<T, U>; + } // namespace asl diff --git a/asl/tests/meta_tests.cpp b/asl/tests/meta_tests.cpp index f01258a..5026327 100644 --- a/asl/tests/meta_tests.cpp +++ b/asl/tests/meta_tests.cpp @@ -1,5 +1,7 @@ #include "asl/meta.hpp" #include "asl/tests/test_types.hpp" +#include "asl/testing/testing.hpp" +#include "asl/box.hpp" struct Struct {}; union Union {}; @@ -247,3 +249,41 @@ static_assert(!asl::is_enum<int>); static_assert(asl::is_enum<Enum1>); static_assert(asl::is_enum<Enum2>); +static_assert(asl::derefs_as<int, int>); +static_assert(asl::derefs_as<int*, int>); +static_assert(asl::derefs_as<int&, int>); +static_assert(asl::derefs_as<asl::box<int>, int>); + +static_assert(asl::derefs_as<Derived, Base>); +static_assert(asl::derefs_as<Derived*, Base>); +static_assert(asl::derefs_as<Derived&, Base>); +static_assert(asl::derefs_as<asl::box<Derived>, Base>); + +static void wants_int(int) {} +static void wants_base(Base&) {} +static void wants_base_ptr(Base*) {} + +ASL_TEST(deref) +{ + int a = 4; + auto b = asl::make_box<int>(5); + + wants_int(asl::deref<int>(5)); + wants_int(asl::deref<int>(a)); + wants_int(asl::deref<int>(&a)); + wants_int(asl::deref<int>(b)); + + Derived c{}; + auto d = asl::make_box<Derived>(); + + wants_base(asl::deref<Base>(Derived{})); + wants_base(asl::deref<Base>(c)); + wants_base(asl::deref<Base>(&c)); + wants_base(asl::deref<Base>(d)); + + wants_base_ptr(&asl::deref<Base>(Derived{})); + wants_base_ptr(&asl::deref<Base>(c)); + wants_base_ptr(&asl::deref<Base>(&c)); + wants_base_ptr(&asl::deref<Base>(d)); +} + |