Skip to content

Commit

Permalink
Various fix from EVE/KIWAKU
Browse files Browse the repository at this point in the history
- shorter symbol names
- better ID support
- more constexpr
  • Loading branch information
jfalcou authored May 18, 2023
1 parent d580cbf commit a6db42a
Showing 1 changed file with 146 additions and 67 deletions.
213 changes: 146 additions & 67 deletions include/raberu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <array>
#include <compare>
#include <cstring>
#include <cstdint>
#include <ostream>
#include <string_view>
#include <type_traits>
Expand Down Expand Up @@ -108,13 +109,45 @@ namespace rbr::concepts
//! instantiation of a precise [Keyword](@ref rbr::concepts::keyword)
//================================================================================================
template<typename Option, auto Keyword>
concept exactly = stdfix::same_as< typename Option::keyword_type
, std::remove_cvref_t<decltype(Keyword)>
>;
concept exactly = stdfix::same_as < typename Option::keyword_type
, std::remove_cvref_t<decltype(Keyword)>
>;
}

namespace rbr::detail
{
// Check for check()
template<typename K, typename T>
concept checks_for = requires(K)
{
{ K::template check<T>() };
};

// Checks for identifier
template<typename T>
concept identifiable = requires(T t)
{
{ t.identifier };
};

// Checks for identifier
template<typename T>
concept self_identifiable = requires(T t, std::ostream& os)
{
{ os << t };
};

// Checks for display
template<typename T, typename V>
concept displayable = requires(T t, std::ostream& os, V v)
{
{ t.display(os,v) };
};

// Concept to constraint size
template<std::size_t N, std::size_t M>
concept fits = (N <= M);

// Lightweight container of value in alternatives
template<concepts::keyword T, typename V> struct type_or_
{
Expand All @@ -125,27 +158,45 @@ namespace rbr::detail
};

// Type -> String converter
template <typename T> constexpr auto type_name() noexcept
template <typename T> constexpr auto typer() noexcept
{
std::string_view name, prefix, suffix;
#ifdef __clang__
name = __PRETTY_FUNCTION__;
prefix = "auto rbr::detail::type_name() [T = ";
suffix = "]";
#elif defined(__GNUC__)
name = __PRETTY_FUNCTION__;
prefix = "constexpr auto rbr::detail::type_name() [with T = ";
suffix = "]";
#elif defined(_MSC_VER)
name = __FUNCSIG__;
prefix = "auto __cdecl rbr::detail::type_name<";
suffix = ">(void)";
#endif
name.remove_prefix(prefix.size());
name.remove_suffix(suffix.size());
return name;
#if defined(__clang__)
constexpr auto pfx = std::string_view("auto rbr::detail::typer() [T = ").size();
constexpr auto sfx = std::string_view("]").size();
constexpr auto raw = std::string_view(__PRETTY_FUNCTION__);
#elif defined(__GNUC__)
constexpr auto pfx = std::string_view("constexpr auto rbr::detail::typer() [with " "T = ").size();
constexpr auto sfx = std::string_view("]").size();
constexpr auto raw = std::string_view(__PRETTY_FUNCTION__);
#elif defined(_MSC_VER)
constexpr auto pfx = std::string_view("auto __cdecl rbr::detail::typer<").size();
constexpr auto sfx = std::string_view(">(void)").size();
constexpr auto raw = std::string_view(__FUNCSIG__);
#endif
auto value = raw;
value.remove_prefix(pfx);
value.remove_suffix(sfx);

constexpr auto size = raw.size() - (pfx + sfx);
auto fn = [&]<std::size_t... Is>(std::index_sequence<Is...>)
{
return std::array<char const, sizeof...(Is) + 1>{value[Is]...};
};

return fn(std::make_index_sequence<size>{});
}

template<typename T> inline constexpr auto type_array = typer<T>();

template<typename T, auto ID = type_array<T>>
struct type_t
{
static constexpr auto name() { return std::string_view(ID.data(), ID.size());}
};

template<typename T>
inline constexpr auto type = type_t<T>{};

// Helpers for working on list of keys as unique lists - needed by merge and some contains_*
template<typename... Ks> struct keys {};

Expand Down Expand Up @@ -197,6 +248,10 @@ namespace rbr::detail
{};
}

#if !defined(RBR_MAX_LITERAL_SIZE)
#define RBR_MAX_LITERAL_SIZE 32
#endif

namespace rbr
{
//================================================================================================
Expand All @@ -208,34 +263,45 @@ namespace rbr
//==============================================================================================
//! @ingroup utility
//! @brief Compile-time static string
//! @tparam N Size of the embedded string
//==============================================================================================
template<std::size_t N> struct str_
struct str
{
std::array<char,N> data;
static constexpr std::size_t max_size = RBR_MAX_LITERAL_SIZE;

template <std::size_t... Is>
constexpr str_(const char (&str)[N], std::index_sequence<Is...>) :data{str[Is]...} {}
constexpr str_(const char (&str)[N]) : str_{str, std::make_index_sequence<N>{}} {}
char data_[max_size+1];
std::uint8_t size_;

static constexpr auto size() { return N; }
auto value() const { return std::string_view(&data[0],strlen(&data[0])); }
};
template<std::size_t N, std::size_t... Is>
requires detail::fits<N,max_size>
constexpr str(const char (&s)[N], std::index_sequence<Is...>) : data_{s[Is]...}, size_(N)
{}

template <std::size_t N>
requires detail::fits<N,max_size>
constexpr str(const char (&s)[N]) : str{s, std::make_index_sequence<N>{}}
{}

template<std::size_t N> str_(const char (&str)[N]) -> str_<N>;
constexpr std::size_t size() const { return size_; }
constexpr std::string_view value() const { return std::string_view(&data_[0],size_); }

friend std::ostream& operator<<(std::ostream& os, str const& s)
{
return os << '\'' << s.value() << '\'';
}
};
}

//================================================================================================
//! @ingroup utility
//! @brief Compile-time text based ID
//! @tparam ID Compile-time string for the ID
//================================================================================================
template<literals::str_ ID> struct id_
template<literals::str ID> struct id_
{
/// Inserts an rbr::id_ in an output stream
friend std::ostream& operator<<(std::ostream& os, id_ const&)
{
return os << '\'' << ID.value() << '\'';
return os << ID;
}
};

Expand All @@ -246,7 +312,7 @@ namespace rbr
//! @brief Forms an ID constant literal
//! @return An instance of rbr::id_ for the specified string
//==============================================================================================
template<str_ ID> constexpr auto operator""_id() noexcept { return id_<ID>{}; }
template<str ID> constexpr auto operator""_id() noexcept { return id_<ID>{}; }
}

//================================================================================================
Expand Down Expand Up @@ -310,19 +376,13 @@ namespace rbr
//! ## Example:
//! @snippet doc/accept.cpp Custom Accept
//==============================================================================================
template<typename T>
static constexpr bool accept() requires (!stdfix::same_as<std::remove_cvref_t<T>,as_keyword>)
{
if constexpr( requires(Keyword) { Keyword::template check<T>(); } )
return Keyword::template check<T>();
else
return true;
}

template<typename T>
static constexpr bool accept() requires (stdfix::same_as<std::remove_cvref_t<T>,as_keyword>)
static constexpr bool accept()
{
return true;
if constexpr(stdfix::same_as<std::remove_cvref_t<T>,as_keyword>) return true;
else if constexpr(detail::checks_for<Keyword,T>) return Keyword::template check<T>();
else return true;
}

//==============================================================================================
Expand All @@ -346,7 +406,8 @@ namespace rbr
//! Display a textual description of current keyword and bound value over an output stream.
//!
//! If `Keyword` defines a `display` member variable, it will be used to perform this display.
//! Otherwise, the typename name of the keyword and its value will be displayed.
//! Otherwise, its value will be displayed along with either a user-defined identifier or its
//! stringified typename.
//!
//! @param os Output stream
//! @param v Value bound to current keyword
Expand All @@ -357,11 +418,13 @@ namespace rbr
//==============================================================================================
template<typename V> std::ostream& show(std::ostream& os, V const& v) const
{
if constexpr( requires(Keyword t) { t.display(os,v); } ) return Keyword{}.display(os,v);
if constexpr(detail::displayable<Keyword,V>) return Keyword{}.display(os,v);
else
{
os << '[' << detail::type_name<Keyword>() << ']';
return os << " : " << v << " (" << detail::type_name<V>() << ')';
if constexpr(detail::identifiable<Keyword>) os << Keyword::identifier;
else os << '[' << detail::type<Keyword>.name() << ']';

return os << " : " << v << " (" << detail::type<V>.name() << ')';
}
}

Expand Down Expand Up @@ -411,11 +474,15 @@ namespace rbr
template<typename V>
std::ostream& display(std::ostream& os, V const& v) const
{
if constexpr( requires(ID t) { os << ID{}; } ) os << ID{};
else os << '[' << detail::type_name<ID>() << ']';
if constexpr(detail::self_identifiable<ID>) os << ID{};
else
{
if constexpr(detail::identifiable<ID>) os << ID::identifier;
else os << '[' << detail::type<ID>.name() << ']';
}

os << " ::: " << v << " (" << detail::type_name<V>() << ") checked by '";
return os << detail::type_name<Checker<V>>() << '\'';
os << " ::: " << v << " (" << detail::type<V>.name() << ") checked by '";
return os << detail::type<Checker<V>>.name() << '\'';
}
};

Expand All @@ -438,10 +505,14 @@ namespace rbr
template<typename V>
std::ostream& display(std::ostream& os, V const& v) const
{
if constexpr( requires(ID t) { os << ID{}; } ) os << ID{};
else os << '[' << detail::type_name<ID>() << ']';
if constexpr(detail::self_identifiable<ID>) os << ID{};
else
{
if constexpr(detail::identifiable<ID>) os << ID::identifier;
else os << '[' << detail::type<ID>.name() << ']';
}

return os << " : " << v << " [[" << detail::type_name<V>() << "]]";
return os << " : " << v << " of type '" << detail::type<V>.name() << '\'';
}
};

Expand All @@ -464,10 +535,14 @@ namespace rbr
template<typename V>
std::ostream& display(std::ostream& os, V const& v) const
{
if constexpr(requires(ID t) { os << ID{}; }) os << ID{};
else os << '[' << detail::type_name<ID>() << ']';
if constexpr(detail::self_identifiable<ID>) os << ID{};
else
{
if constexpr(detail::identifiable<ID>) os << ID::identifier;
else os << '[' << detail::type<ID>.name() << ']';
}

return os << " : " << v << " (" << detail::type_name<V>() << ')';
return os << " : " << v << " (" << detail::type<V>.name() << ')';
}
};

Expand Down Expand Up @@ -495,7 +570,14 @@ namespace rbr
return std::is_same_v<std::true_type, T>;
}

std::ostream& show(std::ostream& os, bool) const { return os << ID{} << " : set"; }
std::ostream& show(std::ostream& os, bool) const
{
if constexpr(detail::identifiable<ID>) os << ID::identifier;
else if constexpr(detail::self_identifiable<ID>) os << ID{};
else os << '[' << detail::type<ID>.name() << ']';

return os << " : set";
}

using tag_type = ID;
using keyword_type = flag_keyword;
Expand Down Expand Up @@ -584,7 +666,7 @@ namespace rbr
//! @brief Forms an instance of rbr::any_keyword from a literal string
//! @return An instance of rbr::any_keyword using the specified string as ID
//==============================================================================================
template<str_ ID>
template<str ID>
constexpr auto operator""_kw() noexcept { return any_keyword<id_<ID>>{}; }

//==============================================================================================
Expand All @@ -593,15 +675,12 @@ namespace rbr
//! @brief Forms an instance of rbr::flag_keyword from a literal string
//! @return An instance of rbr::flag_keyword using the specified string as ID
//==============================================================================================
template<str_ ID>
template<str ID>
constexpr auto operator""_fl() noexcept { return flag_keyword<id_<ID>>{}; }
}

/// Type indicating that a [Keyword](@ref rbr::concepts::keyword) is not available
struct unknown_key
{
using type = unknown_key;
};
struct unknown_key { using type = unknown_key; };

// Option calls aggregator
template<concepts::option... Ts> struct aggregator : Ts...
Expand Down Expand Up @@ -959,7 +1038,7 @@ namespace rbr
//! @include doc/keywords.cpp
//================================================================================================
template<template<typename...> class List, typename... Opts>
auto keywords([[maybe_unused]]rbr::settings<Opts...> const& s)
constexpr auto keywords([[maybe_unused]]rbr::settings<Opts...> const& s)
{
return result::keywords_t<rbr::settings<Opts...>,List>{typename Opts::keyword_type{}...};
}
Expand Down Expand Up @@ -989,7 +1068,7 @@ namespace rbr
//! @include doc/values.cpp
//================================================================================================
template<template<typename...> class List, typename... Opts>
auto values(rbr::settings<Opts...> const& s)
constexpr auto values(rbr::settings<Opts...> const& s)
{
return result::values_t<rbr::settings<Opts...>,List>{ s[typename Opts::keyword_type{}]... };
}
Expand Down

0 comments on commit a6db42a

Please sign in to comment.