* Logging ported from layover project with minor tweaks.
* Logging test ported over.
* Boost libraries are available.
116 lines
3.8 KiB
C++
116 lines
3.8 KiB
C++
//-----------------------------------------------------------------------------
|
|
// ___ __ _ _
|
|
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Author: Kurt Sassenrath
|
|
// Module: Logging
|
|
//
|
|
// Type traits for massaging various types into something fmt-printable.
|
|
//
|
|
// Copyright (c) 2023 Kurt Sassenrath.
|
|
//
|
|
// License TBD.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef logging_traits_34e410874c0179c6
|
|
#define logging_traits_34e410874c0179c6
|
|
|
|
#include <type_traits>
|
|
#include <memory>
|
|
|
|
namespace parselink {
|
|
namespace logging {
|
|
|
|
// Customization point for printing out the enum name (value) and not the
|
|
// full type. The default prints the type name. An example is provided below.
|
|
//
|
|
// enum class Foo { Bar, Cat };
|
|
// Foo v{Foo::Bar};
|
|
// logger.log<...>("value: {}", v); // logs "value: Foo::Bar"
|
|
// logger.log<...>("value: {}", enum_name_only{v}); // logs "value: Bar"
|
|
template <typename E>
|
|
requires std::is_enum_v<E>
|
|
struct enum_name_only {
|
|
E v;
|
|
};
|
|
|
|
template <typename E>
|
|
enum_name_only(E) -> enum_name_only<E>;
|
|
|
|
// Wrapper for a string that will be colorized as if it's an error, instead of
|
|
// a normal string.
|
|
struct error_str {
|
|
template <std::convertible_to<std::string_view> T>
|
|
error_str(T&& t) : v(std::forward<T>(t)) {}
|
|
std::string_view v;
|
|
};
|
|
|
|
namespace detail {
|
|
|
|
// The following concepts aim to describe both raw and smart pointers in a
|
|
// way that the log formatter can deduce theme (color/format) as well as
|
|
// print the address without libformat's boilerplate (fmt::ptr).
|
|
template <typename T>
|
|
struct is_smart_pointer_type : std::false_type {};
|
|
|
|
template <typename T, typename D>
|
|
struct is_smart_pointer_type<std::unique_ptr<T, D>> : std::true_type {};
|
|
|
|
template <typename T>
|
|
struct is_smart_pointer_type<std::shared_ptr<T>> : std::true_type {};
|
|
|
|
template <typename T>
|
|
concept smart_pointer = is_smart_pointer_type<std::remove_cvref_t<T>>::value;
|
|
|
|
template <typename T>
|
|
using underlying_ptr_type = std::remove_cv_t<
|
|
std::remove_pointer_t<std::decay_t<std::remove_cvref_t<T>>>>;
|
|
|
|
template <typename T>
|
|
concept non_string_pointer =
|
|
std::is_pointer_v<std::decay_t<std::remove_cvref_t<T>>>
|
|
&& !std::is_same_v<underlying_ptr_type<T>, void>
|
|
&& !std::is_same_v<underlying_ptr_type<T>, char>;
|
|
|
|
template <typename T>
|
|
concept printable_pointer = smart_pointer<T> || non_string_pointer<T>;
|
|
|
|
// Some simple assertions to avoid breaking the code above.
|
|
static_assert(printable_pointer<int*>);
|
|
static_assert(printable_pointer<int*&>);
|
|
static_assert(printable_pointer<int const*&>);
|
|
static_assert(printable_pointer<int* const&>);
|
|
static_assert(printable_pointer<int (&)[4]>);
|
|
static_assert(printable_pointer<int const (&)[4]>);
|
|
|
|
static_assert(!printable_pointer<char*>);
|
|
static_assert(!printable_pointer<char*&>);
|
|
static_assert(!printable_pointer<char const*>);
|
|
static_assert(!printable_pointer<char const*&>);
|
|
static_assert(!printable_pointer<char (&)[4]>);
|
|
static_assert(!printable_pointer<char const (&)[4]>);
|
|
|
|
static_assert(!printable_pointer<void*>);
|
|
static_assert(!printable_pointer<void*&>);
|
|
static_assert(!printable_pointer<void const*>);
|
|
static_assert(!printable_pointer<void const*&>);
|
|
|
|
static_assert(printable_pointer<std::unique_ptr<int>>);
|
|
static_assert(printable_pointer<std::unique_ptr<int>&>);
|
|
static_assert(printable_pointer<std::unique_ptr<int> const&>);
|
|
|
|
static_assert(printable_pointer<std::unique_ptr<int const>>);
|
|
static_assert(printable_pointer<std::unique_ptr<int const>&>);
|
|
static_assert(printable_pointer<std::unique_ptr<int const> const&>);
|
|
|
|
} // namespace detail
|
|
|
|
} // namespace logging
|
|
} // namespace parselink
|
|
|
|
#endif // logging_traits_34e410874c0179c6
|