Add deref utilities & use them for log writer
This commit is contained in:
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// @Todo Don't use internal get_stdout_writer, make console module
|
// @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 asl::log::Logger* g_head = &g_default_logger;
|
||||||
|
|
||||||
static constexpr asl::string_view kLevelName[] = {
|
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);
|
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
|
kLevelName[msg.level], // NOLINT
|
||||||
msg.location.file,
|
msg.location.file,
|
||||||
msg.location.line,
|
msg.location.line,
|
||||||
|
@ -39,16 +39,24 @@ public:
|
|||||||
constexpr Logger* next_logger() const { return m_next; }
|
constexpr Logger* next_logger() const { return m_next; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// @Todo Make a deref_as trait & deref utility
|
class DefaultLoggerBase : public Logger
|
||||||
// @Todo Accept writer as box, pointer, reference, or value
|
|
||||||
class DefaultLogger : 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:
|
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>);
|
void register_logger(box<Logger>);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <asl/log/log.hpp>
|
#include <asl/log/log.hpp>
|
||||||
#include <asl/testing/testing.hpp>
|
#include <asl/testing/testing.hpp>
|
||||||
|
#include <asl/string_builder.hpp>
|
||||||
|
|
||||||
ASL_TEST(log)
|
ASL_TEST(log)
|
||||||
{
|
{
|
||||||
@ -8,3 +9,15 @@ ASL_TEST(log)
|
|||||||
ASL_LOG_ERROR("Oh no! {}", 42);
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
27
asl/meta.hpp
27
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> 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_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 : false_type {};
|
||||||
template<typename T> struct _is_ptr_helper<T*> : true_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>
|
template<typename T>
|
||||||
concept is_niche = same_as<un_cvref_t<T>, niche_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
|
} // namespace asl
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "asl/meta.hpp"
|
#include "asl/meta.hpp"
|
||||||
#include "asl/tests/test_types.hpp"
|
#include "asl/tests/test_types.hpp"
|
||||||
|
#include "asl/testing/testing.hpp"
|
||||||
|
#include "asl/box.hpp"
|
||||||
|
|
||||||
struct Struct {};
|
struct Struct {};
|
||||||
union Union {};
|
union Union {};
|
||||||
@ -247,3 +249,41 @@ static_assert(!asl::is_enum<int>);
|
|||||||
static_assert(asl::is_enum<Enum1>);
|
static_assert(asl::is_enum<Enum1>);
|
||||||
static_assert(asl::is_enum<Enum2>);
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user