repr 0.1
Reconstructable string representations and more
Loading...
Searching...
No Matches
accessor.h
Go to the documentation of this file.
1#pragma once
2#include <array>
3#include <bit>
4#include <cstddef>
5#include <iterator>
6#include <string_view>
7#include <type_traits>
8
9
11
12#include "util.h"
13
14namespace librepr::ctei {
15
16template <typename T, EnumKind Kind, typename Structure = TypeList<>>
17 requires std::is_enum_v<T>
18struct Accessor {
21 constexpr static auto kind = Kind;
22
23private:
24 static constexpr auto get_enum_names() {
25 if constexpr (structure::size == 0) {
27 } else {
28 auto constexpr full_size = structure::invoke([]<typename... Range>() { return ((Range::size) + ...); });
30
31 structure::for_each(
32 [offset = 0U]<typename Range>(auto& output) mutable {
33 constexpr auto range_names = Range::template enum_names<T, Kind>;
34
35 // populate array in reverse
38 },
39 buffer);
40
41 return buffer;
42 }
43 }
44
45public:
46 constexpr static auto names = get_enum_names();
47 //TODO enum_values?
48
49 template <std::size_t Idx = 0>
50 constexpr static std::string_view search_name(underlying value)
51 requires(Kind == EnumKind::Linear)
52 {
53 using range = typename structure::template get<Idx>;
54
55 if (range::contains(value)) {
56 auto offset = value - range::min;
57 // TODO assert offset is >= 0
58 return range::template enum_names<T, Kind>[std::size_t(offset)];
59 }
60
61 if constexpr (Idx + 1 < structure::size) {
62 // we haven't yet found, advance to next range
63 // TODO could do binary search instead
64 return search_name<Idx + 1>(value);
65 } else {
66 return {};
67 }
68 }
69
71 requires(Kind == EnumKind::Flags)
72 {
73 static_assert(structure::size == 1, "Flag-like enum structure should only consist of one contiguous subrange");
74 using range = typename structure::template get<0>;
75
76 if (value == 0) {
77 // special case 0
78 return names[0];
79 }
80
81 if (!std::has_single_bit(value)) {
82 // more than one flag
83 return {};
84 }
85
86 auto width = std::bit_width(value);
87 if (width > range::max) {
88 // value too large
89 return {};
90 }
91 auto offset = std::countr_zero(value) + 1;
92 // TODO assert offset is >= 0
93 return names[std::size_t(offset)];
94 }
95
97 requires(Kind == EnumKind::Empty)
98 {
99 return {};
100 }
101
102 constexpr static std::string_view get_name(T value) {
103 auto underlying = static_cast<std::underlying_type_t<T>>(value);
104 return search_name(underlying);
105 }
106
107 constexpr static auto get_names() { return names; }
108
109 constexpr static auto get_names()
110 requires(Kind == EnumKind::Flags)
111 {
112 constexpr auto valid_count =
114
116 auto idx = 0U;
117 for (auto&& element : names) {
118 if (element.empty()) {
119 continue;
120 }
121
122 buffer[idx++] = element;
123 }
124 return buffer;
125 }
126};
127} // namespace librepr::ctei
T begin(T... args)
T bit_width(T... args)
T copy(T... args)
T count_if(T... args)
T countr_zero(T... args)
T end(T... args)
T has_single_bit(T... args)
Definition accessor.h:14
std::string code_for()
Definition repr:39
T next(T... args)
Definition accessor.h:18
Structure structure
Definition accessor.h:19
static constexpr std::string_view search_name(underlying value)
Definition accessor.h:50
static std::string_view search_name(underlying value)
Definition accessor.h:70
static constexpr std::string_view get_name(T value)
Definition accessor.h:102
static constexpr auto get_names()
Definition accessor.h:109
static std::string_view search_name(underlying)
Definition accessor.h:96
static constexpr auto names
Definition accessor.h:46
static constexpr auto kind
Definition accessor.h:21
static constexpr auto get_names()
Definition accessor.h:107
Definition range.h:12
static constexpr auto size
Definition range.h:15