/src/WasmEdge/include/common/dense_enum_map.h
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: 2019-2024 Second State INC |
3 | | |
4 | | //===-- wasmedge/common/dense_enum_map.h - mapping dense enum to data -----===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// |
10 | | /// \file |
11 | | /// This file contains a class for mapping enum value to data. |
12 | | /// |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #pragma once |
16 | | |
17 | | #include <array> |
18 | | #include <memory> |
19 | | #include <string_view> |
20 | | #include <type_traits> |
21 | | |
22 | | namespace WasmEdge { |
23 | | |
24 | | template <std::size_t Size, class Key, class T = std::string_view> |
25 | | class DenseEnumMap { |
26 | | static_assert(std::is_enum_v<Key>, "Key should be an enum type!"); |
27 | | |
28 | | public: |
29 | | class ConstIterator; |
30 | | using key_type = Key; |
31 | | using mapped_type = T; |
32 | | using value_type = const std::pair<Key, T>; |
33 | | using size_type = std::size_t; |
34 | | using difference_type = std::ptrdiff_t; |
35 | | using reference = value_type &; |
36 | | using const_reference = const value_type &; |
37 | | using pointer = value_type *; |
38 | | using const_pointer = const value_type *; |
39 | | using iterator = ConstIterator; |
40 | | using const_iterator = ConstIterator; |
41 | | |
42 | | constexpr DenseEnumMap() noexcept = delete; |
43 | | constexpr DenseEnumMap(const DenseEnumMap &) noexcept = delete; |
44 | | constexpr DenseEnumMap(DenseEnumMap &&) noexcept = default; |
45 | | constexpr DenseEnumMap &operator=(const DenseEnumMap &) noexcept = delete; |
46 | | constexpr DenseEnumMap &operator=(DenseEnumMap &&) noexcept = default; |
47 | | |
48 | | constexpr DenseEnumMap( |
49 | | const std::pair<Key, std::string_view> (&Array)[Size]) noexcept { |
50 | | for (size_type I = 0; I < Size; ++I) { |
51 | | Data[static_cast<size_type>(Array[I].first)] = Array[I].second; |
52 | | } |
53 | | } |
54 | | |
55 | 0 | constexpr const mapped_type &operator[](key_type K) const noexcept { |
56 | 0 | return Data[static_cast<size_type>(K)]; |
57 | 0 | } Unexecuted instantiation: WasmEdge::DenseEnumMap<6ul, WasmEdge::WasmPhase, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::WasmPhase) const Unexecuted instantiation: WasmEdge::DenseEnumMap<2ul, WasmEdge::ValMut, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::ValMut) const Unexecuted instantiation: WasmEdge::DenseEnumMap<5ul, WasmEdge::ExternalType, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::ExternalType) const Unexecuted instantiation: WasmEdge::DenseEnumMap<88ul, WasmEdge::ASTNodeAttr, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::ASTNodeAttr) const Unexecuted instantiation: WasmEdge::DenseEnumMap<2ul, WasmEdge::ErrInfo::PtrType, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::ErrInfo::PtrType) const Unexecuted instantiation: WasmEdge::DenseEnumMap<11ul, WasmEdge::ErrInfo::MismatchCategory, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::ErrInfo::MismatchCategory) const Unexecuted instantiation: WasmEdge::DenseEnumMap<14ul, WasmEdge::ErrInfo::IndexCategory, std::__1::basic_string_view<char, std::__1::char_traits<char> > >::operator[](WasmEdge::ErrInfo::IndexCategory) const |
58 | | |
59 | | constexpr const_iterator begin() const noexcept { |
60 | | return {Data, static_cast<size_type>(0)}; |
61 | | } |
62 | | |
63 | 0 | constexpr const_iterator end() const noexcept { |
64 | 0 | return {Data, static_cast<size_type>(Size)}; |
65 | 0 | } |
66 | | |
67 | 0 | constexpr const_iterator find(key_type K) const noexcept { |
68 | 0 | return {Data, std::min(static_cast<size_type>(K), Size)}; |
69 | 0 | } |
70 | | |
71 | | private: |
72 | | std::array<T, Size> Data; |
73 | | }; |
74 | | |
75 | | template <class Key, std::size_t Size> |
76 | | DenseEnumMap(const std::pair<Key, std::string_view> (&)[Size]) |
77 | | -> DenseEnumMap<Size, Key>; |
78 | | |
79 | | template <std::size_t Size, class Key, class T> |
80 | | class DenseEnumMap<Size, Key, T>::ConstIterator { |
81 | | public: |
82 | | using difference_type = DenseEnumMap<Size, Key, T>::difference_type; |
83 | | using value_type = DenseEnumMap<Size, Key, T>::value_type; |
84 | | using pointer = DenseEnumMap<Size, Key, T>::pointer; |
85 | | using reference = DenseEnumMap<Size, Key, T>::reference; |
86 | | using iterator_category = std::random_access_iterator_tag; |
87 | | |
88 | | constexpr ConstIterator() noexcept = default; |
89 | | constexpr ConstIterator(const ConstIterator &) noexcept = default; |
90 | | constexpr ConstIterator(ConstIterator &&) noexcept = default; |
91 | | constexpr ConstIterator &operator=(const ConstIterator &) noexcept = default; |
92 | | constexpr ConstIterator &operator=(ConstIterator &&) noexcept = default; |
93 | | |
94 | | constexpr ConstIterator(const std::array<T, Size> &D, size_type I) noexcept |
95 | 0 | : Data(std::addressof(D)), |
96 | 0 | Value(static_cast<Key>(I), I < Size ? D[I] : T{}) {} |
97 | | |
98 | | constexpr reference operator*() noexcept { return Value; } |
99 | | constexpr const_reference operator*() const noexcept { return Value; } |
100 | | |
101 | 0 | constexpr pointer operator->() noexcept { return std::addressof(Value); } |
102 | | constexpr const_pointer operator->() const noexcept { |
103 | | return std::addressof(Value); |
104 | | } |
105 | | |
106 | | constexpr ConstIterator &operator++() noexcept { |
107 | | size_type I = static_cast<size_type>(Value.first); |
108 | | ++I; |
109 | | Value = {static_cast<Key>(I), I < Size ? (*Data)[I] : T{}}; |
110 | | return *this; |
111 | | } |
112 | | |
113 | | constexpr ConstIterator &operator--() noexcept { |
114 | | size_type I = static_cast<size_type>(Value.first); |
115 | | --I; |
116 | | Value = {static_cast<Key>(I), I < Size ? (*Data)[I] : T{}}; |
117 | | return *this; |
118 | | } |
119 | | |
120 | | constexpr ConstIterator operator++(int) noexcept { |
121 | | ConstIterator Iter(*this); |
122 | | ++*this; |
123 | | return Iter; |
124 | | } |
125 | | |
126 | | constexpr ConstIterator operator--(int) noexcept { |
127 | | ConstIterator Iter(*this); |
128 | | --*this; |
129 | | return Iter; |
130 | | } |
131 | | |
132 | | constexpr ConstIterator &operator+=(difference_type N) noexcept { |
133 | | size_type I = static_cast<size_type>(Value.first); |
134 | | I = static_cast<size_type>(static_cast<difference_type>(I) + N); |
135 | | Value = {static_cast<Key>(I), I < Size ? (*Data)[I] : T{}}; |
136 | | return *this; |
137 | | } |
138 | | |
139 | | constexpr ConstIterator &operator-=(difference_type N) noexcept { |
140 | | size_type I = static_cast<size_type>(Value.first); |
141 | | I = static_cast<size_type>(static_cast<difference_type>(I) - N); |
142 | | Value = {static_cast<Key>(I), I < Size ? (*Data)[I] : T{}}; |
143 | | return *this; |
144 | | } |
145 | | |
146 | | friend constexpr ConstIterator operator+(const ConstIterator &LHS, |
147 | | difference_type RHS) noexcept { |
148 | | ConstIterator Iter = LHS; |
149 | | return Iter += RHS; |
150 | | } |
151 | | |
152 | | friend constexpr difference_type |
153 | 0 | operator-(const ConstIterator &LHS, const ConstIterator &RHS) noexcept { |
154 | 0 | const T *const L = |
155 | 0 | std::addressof((*LHS.Data)[static_cast<size_type>(LHS.Value.first)]); |
156 | 0 | const T *const R = |
157 | 0 | std::addressof((*RHS.Data)[static_cast<size_type>(RHS.Value.first)]); |
158 | 0 | return L - R; |
159 | 0 | } |
160 | | |
161 | | constexpr reference operator[](difference_type N) noexcept { |
162 | | return *((*this) + N); |
163 | | } |
164 | | |
165 | | friend constexpr bool operator==(const ConstIterator &LHS, |
166 | 0 | const ConstIterator &RHS) noexcept { |
167 | 0 | return (LHS - RHS) == 0; |
168 | 0 | } |
169 | | |
170 | | friend constexpr bool operator!=(const ConstIterator &LHS, |
171 | 0 | const ConstIterator &RHS) noexcept { |
172 | 0 | return !(LHS == RHS); |
173 | 0 | } |
174 | | |
175 | | friend constexpr bool operator<(const ConstIterator &LHS, |
176 | | const ConstIterator &RHS) noexcept { |
177 | | return (RHS - LHS) > 0; |
178 | | } |
179 | | |
180 | | friend constexpr bool operator>(const ConstIterator &LHS, |
181 | | const ConstIterator &RHS) noexcept { |
182 | | return (LHS - RHS) > 0; |
183 | | } |
184 | | |
185 | | friend constexpr bool operator<=(const ConstIterator &LHS, |
186 | | const ConstIterator &RHS) noexcept { |
187 | | return !(LHS > RHS); |
188 | | } |
189 | | |
190 | | friend constexpr bool operator>=(const ConstIterator &LHS, |
191 | | const ConstIterator &RHS) noexcept { |
192 | | return !(LHS < RHS); |
193 | | } |
194 | | |
195 | | private: |
196 | | const std::array<T, Size> *Data = nullptr; |
197 | | std::pair<Key, T> Value; |
198 | | }; |
199 | | |
200 | | } // namespace WasmEdge |