Blender V5.0
BLI_set_slots.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
21
22#include "BLI_hash_tables.hh"
23#include "BLI_memory_utils.hh"
24#include "BLI_string_ref.hh"
25
26namespace blender {
27
33template<typename Key> class SimpleSetSlot {
34 private:
35 enum State : uint8_t {
36 Empty = 0,
37 Occupied = 1,
38 Removed = 2,
39 };
40
41 State state_;
42 TypedBuffer<Key> key_buffer_;
43
44 public:
49 {
50 state_ = Empty;
51 }
52
57 {
58 if (state_ == Occupied) {
59 key_buffer_.ref().~Key();
60 }
61 }
62
68 {
69 state_ = other.state_;
70 if (other.state_ == Occupied) {
71 new (&key_buffer_) Key(*other.key_buffer_);
72 }
73 }
74
80 SimpleSetSlot(SimpleSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v<Key>)
81 {
82 state_ = other.state_;
83 if (other.state_ == Occupied) {
84 new (&key_buffer_) Key(std::move(*other.key_buffer_));
85 }
86 }
87
92 {
93 return key_buffer_;
94 }
95
99 const Key *key() const
100 {
101 return key_buffer_;
102 }
103
107 bool is_occupied() const
108 {
109 return state_ == Occupied;
110 }
111
115 bool is_empty() const
116 {
117 return state_ == Empty;
118 }
119
124 template<typename Hash> uint64_t get_hash(const Hash &hash) const
125 {
126 BLI_assert(this->is_occupied());
127 return hash(*key_buffer_);
128 }
129
134 template<typename ForwardKey, typename IsEqual>
135 bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t /*hash*/) const
136 {
137 if (state_ == Occupied) {
138 return is_equal(key, *key_buffer_);
139 }
140 return false;
141 }
142
147 template<typename ForwardKey> void occupy(ForwardKey &&key, uint64_t /*hash*/)
148 {
149 BLI_assert(!this->is_occupied());
150 new (&key_buffer_) Key(std::forward<ForwardKey>(key));
151 state_ = Occupied;
152 }
153
157 void remove()
158 {
159 BLI_assert(this->is_occupied());
160 key_buffer_.ref().~Key();
161 state_ = Removed;
162 }
163};
164
169template<typename Key> class HashedSetSlot {
170 private:
171 enum State : uint8_t {
172 Empty = 0,
173 Occupied = 1,
174 Removed = 2,
175 };
176
177 uint64_t hash_;
178 State state_;
179 TypedBuffer<Key> key_buffer_;
180
181 public:
183 {
184 state_ = Empty;
185 }
186
188 {
189 if (state_ == Occupied) {
190 key_buffer_.ref().~Key();
191 }
192 }
193
195 {
196 state_ = other.state_;
197 if (other.state_ == Occupied) {
198 hash_ = other.hash_;
199 new (&key_buffer_) Key(*other.key_buffer_);
200 }
201 }
202
203 HashedSetSlot(HashedSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v<Key>)
204 {
205 state_ = other.state_;
206 if (other.state_ == Occupied) {
207 hash_ = other.hash_;
208 new (&key_buffer_) Key(std::move(*other.key_buffer_));
209 }
210 }
211
213 {
214 return key_buffer_;
215 }
216
217 const Key *key() const
218 {
219 return key_buffer_;
220 }
221
222 bool is_occupied() const
223 {
224 return state_ == Occupied;
225 }
226
227 bool is_empty() const
228 {
229 return state_ == Empty;
230 }
231
232 template<typename Hash> uint64_t get_hash(const Hash & /*hash*/) const
233 {
234 BLI_assert(this->is_occupied());
235 return hash_;
236 }
237
238 template<typename ForwardKey, typename IsEqual>
239 bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t hash) const
240 {
241 /* `hash_` might be uninitialized here, but that is ok. */
242 if (hash_ == hash) {
243 if (state_ == Occupied) {
244 return is_equal(key, *key_buffer_);
245 }
246 }
247 return false;
248 }
249
250 template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t hash)
251 {
252 BLI_assert(!this->is_occupied());
253 new (&key_buffer_) Key(std::forward<ForwardKey>(key));
254 state_ = Occupied;
255 hash_ = hash;
256 }
257
258 void remove()
259 {
260 BLI_assert(this->is_occupied());
261 key_buffer_.ref().~Key();
262 state_ = Removed;
263 }
264};
265
274template<typename Key, typename KeyInfo> class IntrusiveSetSlot {
275 private:
276 Key key_ = KeyInfo::get_empty();
277
278 public:
279 IntrusiveSetSlot() = default;
280 ~IntrusiveSetSlot() = default;
281 IntrusiveSetSlot(const IntrusiveSetSlot &other) = default;
282 IntrusiveSetSlot(IntrusiveSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v<Key>) =
283 default;
284
286 {
287 return &key_;
288 }
289
290 const Key *key() const
291 {
292 return &key_;
293 }
294
295 bool is_occupied() const
296 {
297 return KeyInfo::is_not_empty_or_removed(key_);
298 }
299
300 bool is_empty() const
301 {
302 return KeyInfo::is_empty(key_);
303 }
304
305 template<typename Hash> uint64_t get_hash(const Hash &hash) const
306 {
307 BLI_assert(this->is_occupied());
308 return hash(key_);
309 }
310
311 template<typename ForwardKey, typename IsEqual>
312 bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t /*hash*/) const
313 {
314 BLI_assert(KeyInfo::is_not_empty_or_removed(key));
315 return is_equal(key_, key);
316 }
317
318 template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t /*hash*/)
319 {
320 BLI_assert(!this->is_occupied());
321 BLI_assert(KeyInfo::is_not_empty_or_removed(key));
322 key_ = std::forward<ForwardKey>(key);
323 }
324
325 void remove()
326 {
327 BLI_assert(this->is_occupied());
328 KeyInfo::remove(key_);
329 }
330};
331
336template<typename Int, Int EmptyValue, Int RemovedValue>
338
339template<typename Key> struct DefaultSetSlot;
340
344template<typename Key> struct DefaultSetSlot {
346};
347
352template<> struct DefaultSetSlot<std::string> {
354};
355template<> struct DefaultSetSlot<StringRef> {
357};
361
366template<typename Key> struct DefaultSetSlot<Key *> {
368};
369
370} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
struct Key Key
unsigned long long int uint64_t
HashedSetSlot(HashedSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v< Key >)
const Key * key() const
uint64_t get_hash(const Hash &) const
bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t hash) const
void occupy(ForwardKey &&key, const uint64_t hash)
HashedSetSlot(const HashedSetSlot &other)
const Key * key() const
uint64_t get_hash(const Hash &hash) const
IntrusiveSetSlot(IntrusiveSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v< Key >)=default
IntrusiveSetSlot(const IntrusiveSetSlot &other)=default
void occupy(ForwardKey &&key, const uint64_t)
bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t) const
bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t) const
SimpleSetSlot(SimpleSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v< Key >)
const Key * key() const
uint64_t get_hash(const Hash &hash) const
SimpleSetSlot(const SimpleSetSlot &other)
void occupy(ForwardKey &&key, uint64_t)
IntrusiveSetSlot< Int, TemplatedKeyInfo< Int, EmptyValue, RemovedValue > > IntegerSetSlot
#define hash
Definition noise_c.cc:154
IntrusiveSetSlot< Key *, PointerKeyInfo< Key * > > type
HashedSetSlot< StringRefNull > type
HashedSetSlot< StringRef > type
HashedSetSlot< std::string > type
SimpleSetSlot< Key > type