Blender V4.3
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
22#include "BLI_memory_utils.hh"
23#include "BLI_string_ref.hh"
24
25namespace blender {
26
32template<typename Key> class SimpleSetSlot {
33 private:
34 enum State : uint8_t {
35 Empty = 0,
36 Occupied = 1,
37 Removed = 2,
38 };
39
40 State state_;
41 TypedBuffer<Key> key_buffer_;
42
43 public:
48 {
49 state_ = Empty;
50 }
51
56 {
57 if (state_ == Occupied) {
58 key_buffer_.ref().~Key();
59 }
60 }
61
67 {
68 state_ = other.state_;
69 if (other.state_ == Occupied) {
70 new (&key_buffer_) Key(*other.key_buffer_);
71 }
72 }
73
79 SimpleSetSlot(SimpleSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v<Key>)
80 {
81 state_ = other.state_;
82 if (other.state_ == Occupied) {
83 new (&key_buffer_) Key(std::move(*other.key_buffer_));
84 }
85 }
86
91 {
92 return key_buffer_;
93 }
94
98 const Key *key() const
99 {
100 return key_buffer_;
101 }
102
106 bool is_occupied() const
107 {
108 return state_ == Occupied;
109 }
110
114 bool is_empty() const
115 {
116 return state_ == Empty;
117 }
118
123 template<typename Hash> uint64_t get_hash(const Hash &hash) const
124 {
125 BLI_assert(this->is_occupied());
126 return hash(*key_buffer_);
127 }
128
133 template<typename ForwardKey, typename IsEqual>
134 bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t /*hash*/) const
135 {
136 if (state_ == Occupied) {
137 return is_equal(key, *key_buffer_);
138 }
139 return false;
140 }
141
146 template<typename ForwardKey> void occupy(ForwardKey &&key, uint64_t /*hash*/)
147 {
148 BLI_assert(!this->is_occupied());
149 new (&key_buffer_) Key(std::forward<ForwardKey>(key));
150 state_ = Occupied;
151 }
152
156 void remove()
157 {
158 BLI_assert(this->is_occupied());
159 key_buffer_.ref().~Key();
160 state_ = Removed;
161 }
162};
163
168template<typename Key> class HashedSetSlot {
169 private:
170 enum State : uint8_t {
171 Empty = 0,
172 Occupied = 1,
173 Removed = 2,
174 };
175
176 uint64_t hash_;
177 State state_;
178 TypedBuffer<Key> key_buffer_;
179
180 public:
182 {
183 state_ = Empty;
184 }
185
187 {
188 if (state_ == Occupied) {
189 key_buffer_.ref().~Key();
190 }
191 }
192
194 {
195 state_ = other.state_;
196 if (other.state_ == Occupied) {
197 hash_ = other.hash_;
198 new (&key_buffer_) Key(*other.key_buffer_);
199 }
200 }
201
202 HashedSetSlot(HashedSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v<Key>)
203 {
204 state_ = other.state_;
205 if (other.state_ == Occupied) {
206 hash_ = other.hash_;
207 new (&key_buffer_) Key(std::move(*other.key_buffer_));
208 }
209 }
210
212 {
213 return key_buffer_;
214 }
215
216 const Key *key() const
217 {
218 return key_buffer_;
219 }
220
221 bool is_occupied() const
222 {
223 return state_ == Occupied;
224 }
225
226 bool is_empty() const
227 {
228 return state_ == Empty;
229 }
230
231 template<typename Hash> uint64_t get_hash(const Hash & /*hash*/) const
232 {
233 BLI_assert(this->is_occupied());
234 return hash_;
235 }
236
237 template<typename ForwardKey, typename IsEqual>
238 bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t hash) const
239 {
240 /* `hash_` might be uninitialized here, but that is ok. */
241 if (hash_ == hash) {
242 if (state_ == Occupied) {
243 return is_equal(key, *key_buffer_);
244 }
245 }
246 return false;
247 }
248
249 template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t hash)
250 {
251 BLI_assert(!this->is_occupied());
252 new (&key_buffer_) Key(std::forward<ForwardKey>(key));
253 state_ = Occupied;
254 hash_ = hash;
255 }
256
257 void remove()
258 {
259 BLI_assert(this->is_occupied());
260 key_buffer_.ref().~Key();
261 state_ = Removed;
262 }
263};
264
273template<typename Key, typename KeyInfo> class IntrusiveSetSlot {
274 private:
275 Key key_ = KeyInfo::get_empty();
276
277 public:
278 IntrusiveSetSlot() = default;
279 ~IntrusiveSetSlot() = default;
280 IntrusiveSetSlot(const IntrusiveSetSlot &other) = default;
281 IntrusiveSetSlot(IntrusiveSetSlot &&other) noexcept(std::is_nothrow_move_constructible_v<Key>) =
282 default;
283
285 {
286 return &key_;
287 }
288
289 const Key *key() const
290 {
291 return &key_;
292 }
293
294 bool is_occupied() const
295 {
296 return KeyInfo::is_not_empty_or_removed(key_);
297 }
298
299 bool is_empty() const
300 {
301 return KeyInfo::is_empty(key_);
302 }
303
304 template<typename Hash> uint64_t get_hash(const Hash &hash) const
305 {
306 BLI_assert(this->is_occupied());
307 return hash(key_);
308 }
309
310 template<typename ForwardKey, typename IsEqual>
311 bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t /*hash*/) const
312 {
313 BLI_assert(KeyInfo::is_not_empty_or_removed(key));
314 return is_equal(key_, key);
315 }
316
317 template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t /*hash*/)
318 {
319 BLI_assert(!this->is_occupied());
320 BLI_assert(KeyInfo::is_not_empty_or_removed(key));
321 key_ = std::forward<ForwardKey>(key);
322 }
323
324 void remove()
325 {
326 BLI_assert(this->is_occupied());
327 KeyInfo::remove(key_);
328 }
329};
330
335template<typename Int, Int EmptyValue, Int RemovedValue>
337
338template<typename Key> struct DefaultSetSlot;
339
343template<typename Key> struct DefaultSetSlot {
345};
346
351template<> struct DefaultSetSlot<std::string> {
353};
354template<> struct DefaultSetSlot<StringRef> {
356};
360
365template<typename Key> struct DefaultSetSlot<Key *> {
367};
368
369} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:50
struct Key Key
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)
#define hash
Definition noise.c:154
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90