repr 0.1
Reconstructable string representations and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
accessor.h
Go to the documentation of this file.
#pragma once
#include <array>
#include <bit>
#include <cstddef>
#include <iterator>
#include <string_view>
#include <type_traits>
#include "util.h"
namespace librepr::ctei {
template <typename T, EnumKind Kind, typename Structure = TypeList<>>
requires std::is_enum_v<T>
struct Accessor {
constexpr static auto kind = Kind;
private:
static constexpr auto get_enum_names() {
if constexpr (structure::size == 0) {
} else {
auto constexpr full_size = structure::invoke([]<typename... Range>() { return ((Range::size) + ...); });
structure::for_each(
[offset = 0U]<typename Range>(auto& output) mutable {
constexpr auto range_names = Range::template enum_names<T, Kind>;
// populate array in reverse
},
buffer);
return buffer;
}
}
public:
constexpr static auto names = get_enum_names();
//TODO enum_values?
template <std::size_t Idx = 0>
constexpr static std::string_view search_name(underlying value)
requires(Kind == EnumKind::Linear)
{
using range = typename structure::template get<Idx>;
if (range::contains(value)) {
auto offset = value - range::min;
// TODO assert offset is >= 0
return range::template enum_names<T, Kind>[std::size_t(offset)];
}
if constexpr (Idx + 1 < structure::size) {
// we haven't yet found, advance to next range
// TODO could do binary search instead
return search_name<Idx + 1>(value);
} else {
return {};
}
}
requires(Kind == EnumKind::Flags)
{
static_assert(structure::size == 1, "Flag-like enum structure should only consist of one contiguous subrange");
using range = typename structure::template get<0>;
if (value == 0) {
// special case 0
return names[0];
}
if (!std::has_single_bit(value)) {
// more than one flag
return {};
}
auto width = std::bit_width(value);
if (width > range::max) {
// value too large
return {};
}
auto offset = std::countr_zero(value) + 1;
// TODO assert offset is >= 0
}
requires(Kind == EnumKind::Empty)
{
return {};
}
constexpr static std::string_view get_name(T value) {
auto underlying = static_cast<std::underlying_type_t<T>>(value);
}
constexpr static auto get_names() { return names; }
constexpr static auto get_names()
requires(Kind == EnumKind::Flags)
{
constexpr auto valid_count =
auto idx = 0U;
for (auto&& element : names) {
if (element.empty()) {
continue;
}
buffer[idx++] = element;
}
return buffer;
}
};
} // namespace librepr::ctei