P4C
The P4 Compiler
Loading...
Searching...
No Matches
hvec_set.h
1/*
2Copyright 2023-present Intel
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef LIB_HVEC_SET_H_
18#define LIB_HVEC_SET_H_
19
20#include <initializer_list>
21#include <tuple>
22#include <vector>
23
24#include "exceptions.h"
25#include "hashvec.h"
26
27namespace P4 {
28
29template <class KEY, class HASH = std::hash<KEY>, class PRED = std::equal_to<KEY>,
30 class ALLOC = std::allocator<KEY>>
32 HASH hf; // FIXME -- use empty base optimization for these?
33 PRED eql;
34
35 public:
36 typedef const KEY value_type;
37 typedef HASH hasher;
38 typedef PRED key_equal;
39 typedef ALLOC allocator_type;
40 typedef value_type *pointer, *const_pointer, &reference, &const_reference;
42
43 explicit hvec_set(size_t icap = 0, const hasher &hf = hasher(),
44 const key_equal &eql = key_equal(),
45 const allocator_type &a = allocator_type())
46 : hash_vector_base(false, false, icap), hf(hf), eql(eql), data(a) {
47 data.reserve(icap);
48 }
49 hvec_set(const hvec_set &) = default;
50 hvec_set(hvec_set &&) = default;
51 hvec_set &operator=(const hvec_set &that) {
52 if (this != std::addressof(that)) {
53 clear();
54 hf = that.hf;
55 eql = that.eql;
56
57 data.reserve(that.size());
58 insert(that.begin(), that.end());
59 }
60
61 return *this;
62 }
63 hvec_set &operator=(hvec_set &&) = default;
64 ~hvec_set() = default;
65 template <class ITER>
66 hvec_set(ITER begin, ITER end, const hasher &hf = hasher(), const key_equal &eql = key_equal(),
67 const allocator_type &a = allocator_type())
68 : hash_vector_base(false, false, end - begin), hf(hf), eql(eql), data(a) {
69 data.reserve(end - begin);
70 for (auto it = begin; it != end; ++it) insert(*it);
71 }
72 hvec_set(std::initializer_list<value_type> il, const hasher &hf = hasher(),
73 const key_equal &eql = key_equal(), const allocator_type &a = allocator_type())
74 : hash_vector_base(false, false, il.size()), hf(hf), eql(eql), data(a) {
75 data.reserve(il.size());
76 for (auto &i : il) insert(i);
77 }
78
79 private:
80 template <class HVM, class VT>
81 class _iter {
82 HVM *self;
83 size_t idx;
84
85 friend class hvec_set;
86 _iter(HVM &s, size_t i) : self(&s), idx(i) {}
87
88 public:
89 using value_type = VT;
90 using difference_type = ssize_t;
91 using pointer = typename HVM::pointer;
92 using reference = typename HVM::reference;
93 using iterator_category = std::bidirectional_iterator_tag;
94 _iter(const _iter &) = default;
95 _iter &operator=(const _iter &a) {
96 self = a.self;
97 idx = a.idx;
98 return *this;
99 }
100 value_type &operator*() const { return self->data[idx]; }
101 value_type *operator->() const { return &self->data[idx]; }
102 _iter &operator++() {
103 do {
104 ++idx;
105 } while (self->erased[idx]);
106 return *this;
107 }
108 _iter &operator--() {
109 do {
110 --idx;
111 } while (self->erased[idx]);
112 return *this;
113 }
114 _iter operator++(int) {
115 auto copy = *this;
116 ++*this;
117 return copy;
118 }
119 _iter operator--(int) {
120 auto copy = *this;
121 --*this;
122 return copy;
123 }
124 bool operator==(const _iter &a) const { return self == a.self && idx == a.idx; }
125 bool operator!=(const _iter &a) const { return self != a.self || idx != a.idx; }
126 operator _iter<const HVM, const VT>() const {
127 return _iter<const HVM, const VT>(*self, idx);
128 }
129 };
130
131 public:
132 typedef _iter<hvec_set, value_type> iterator;
133 typedef _iter<const hvec_set, const value_type> const_iterator;
134 iterator begin() { return iterator(*this, erased.ffz()); }
135 iterator end() { return iterator(*this, data.size()); }
136 const_iterator begin() const { return const_iterator(*this, erased.ffz()); }
137 const_iterator end() const { return const_iterator(*this, data.size()); }
138 const_iterator cbegin() const { return const_iterator(*this, erased.ffz()); }
139 const_iterator cend() const { return const_iterator(*this, data.size()); }
140 value_type &front() const { return *begin(); }
141 value_type &back() const {
142 auto it = end();
143 return *--it;
144 }
145
146 bool empty() const { return inuse == 0; }
147 size_t size() const { return inuse; }
148 size_t max_size() const { return UINT32_MAX; }
149 bool operator==(const hvec_set &a) const {
150 if (inuse != a.inuse) return false;
151 auto it = begin();
152 for (auto &el : a)
153 if (el != *it++) return false;
154 return true;
155 }
156 bool operator!=(const hvec_set &a) const { return !(*this == a); }
157 void clear() {
158 hash_vector_base::clear();
159 data.clear();
160 }
161
162 iterator find(const KEY &k) {
164 size_t idx = hash_vector_base::find(&k, &cache);
165 return idx ? iterator(*this, idx - 1) : end();
166 }
167 const_iterator find(const KEY &k) const {
169 size_t idx = hash_vector_base::find(&k, &cache);
170 return idx ? const_iterator(*this, idx - 1) : end();
171 }
172 size_t count(const KEY &k) const {
174 size_t idx = hash_vector_base::find(&k, &cache);
175 return idx > 0;
176 }
177
178 template <typename... KK>
179 std::pair<iterator, bool> emplace(KK &&...k) {
180 return insert(value_type(std::forward<KK>(k)...));
181 }
182 std::pair<iterator, bool> insert(const value_type &v) {
183 bool new_key = false;
184 size_t idx = hv_insert(&v);
185 if (idx >= data.size()) {
186 idx = data.size();
187 data.push_back(v);
188 new_key = true;
189 } else if ((new_key = erased[idx])) {
190 erased[idx] = 0;
191 data[idx] = v;
192 }
193 return std::make_pair(iterator(*this, idx), new_key);
194 }
195 std::pair<iterator, bool> insert(value_type &&v) {
196 bool new_key = false;
197 size_t idx = hv_insert(&v);
198 if (idx >= data.size()) {
199 idx = data.size();
200 data.push_back(std::move(v));
201 new_key = true;
202 } else if ((new_key = erased[idx])) {
203 erased[idx] = 0;
204 data[idx] = std::move(v);
205 }
206 return std::make_pair(iterator(*this, idx), new_key);
207 }
208
209 template <typename InputIterator>
210 void insert(InputIterator first, InputIterator last) {
211 for (; first != last; ++first) insert(*first);
212 }
213 void insert(std::initializer_list<value_type> vl) { return insert(vl.begin(), vl.end()); }
214 template <class HVM, class VT>
215 _iter<HVM, VT> erase(_iter<HVM, VT> it) {
216 BUG_CHECK(this == it.self, "incorrect iterator for hvec_set::erase");
217 erased[it.idx] = 1;
218 // FIXME -- would be better to call dtor here, but that will cause
219 // problems with the vector when it is resized or destroyed. Could
220 // use raw memory and manual construct instead.
221 data[it.idx] = KEY();
222 ++it;
223 --inuse;
224 return it;
225 }
226 size_t erase(const KEY &k) {
227 size_t idx = remove(&k);
228 if (idx + 1 == 0) return 0;
229 if (idx < data.size()) {
230 data[idx] = KEY();
231 }
232 return 1;
233 }
234#ifdef DEBUG
235 using hash_vector_base::dump;
236#endif
237
238 private:
239 std::vector<KEY, ALLOC> data;
240 size_t hashfn(const void *a) const override { return hf(*static_cast<const KEY *>(a)); }
241 bool cmpfn(const void *a, const void *b) const override {
242 return eql(*static_cast<const KEY *>(a), *static_cast<const KEY *>(b));
243 }
244 bool cmpfn(const void *a, size_t b) const override {
245 return eql(*static_cast<const KEY *>(a), data[b]);
246 }
247 const void *getkey(uint32_t i) const override { return &data[i]; }
248 void *getval(uint32_t) override {
249 BUG("getval in set");
250 return nullptr;
251 }
252 uint32_t limit() override { return data.size(); }
253 void resizedata(size_t sz) override { data.resize(sz); }
254 void moveentry(size_t to, size_t from) override { data[to] = data[from]; }
255};
256
257} // namespace P4
258
259#endif /* LIB_HVEC_SET_H_ */
Definition hashvec.h:29
Definition hvec_set.h:31
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition hashvec.h:51