36 template<
typename value_type>
class unordered_set;
38 template<
typename set_iterator,
typename value_type>
39 concept set_container_iterator_t = std::same_as<typename unordered_set<value_type>::iterator, jsonifier_internal::unwrap_t<set_iterator>>;
41 template<
typename value_type_new>
42 class unordered_set :
protected hash_policy<unordered_set<value_type_new>>,
protected jsonifier_internal::alloc_wrapper<value_type_new>,
protected object_compare {
44 template<
typename value_type_newer>
using key_accessor = key_accessor<value_type_newer>;
45 using key_type = value_type_new;
46 using value_type = value_type_new;
47 using mapped_type = value_type;
48 using allocator_type = jsonifier_internal::alloc_wrapper<value_type>;
49 using allocator_traits = std::allocator_traits<allocator_type>;
50 using size_type = uint64_t;
51 using difference_type = int64_t;
52 using pointer =
typename allocator_traits::pointer;
53 using const_pointer =
typename allocator_traits::const_pointer;
54 using reference = value_type&;
55 using const_reference =
const value_type&;
56 using iterator = hash_iterator<unordered_set<value_type>>;
57 using const_iterator = hash_iterator<const unordered_set<value_type>>;
58 using object_compare = object_compare;
59 using hash_policy_new = hash_policy<unordered_set<value_type>>;
61 friend hash_policy_new;
63 friend const_iterator;
65 DCA_INLINE unordered_set(){};
67 DCA_INLINE unordered_set& operator=(unordered_set&& other)
noexcept {
75 DCA_INLINE unordered_set(unordered_set&& other)
noexcept {
76 *
this = std::move(other);
79 DCA_INLINE unordered_set& operator=(
const unordered_set& other) {
83 reserve(other.capacity());
84 for (
const auto& value: other) {
91 DCA_INLINE unordered_set(
const unordered_set& other) {
95 DCA_INLINE unordered_set(std::initializer_list<value_type> list) {
97 for (
auto& value: list) {
98 emplace(std::move(value));
102 template<
typename args> iterator emplace(args&& value) {
103 return emplaceInternal(std::forward<args>(value));
106 template<
typename key_type_new> DCA_INLINE const_iterator find(key_type_new&& key)
const {
108 auto currentIndex = getKey(key) & (capacityVal - 1);
109 for (size_type x{}; x < static_cast<size_type>(maxLookAheadDistance); ++x, ++currentIndex) {
110 if (sentinelVector[currentIndex] > 0 && object_compare()(getKey(data[currentIndex]), getKey(key))) {
111 return {
this, currentIndex };
118 template<
typename key_type_new> DCA_INLINE iterator find(key_type_new&& key) {
120 auto currentIndex = getKey(key) & (capacityVal - 1);
121 for (size_type x{}; x < static_cast<size_type>(maxLookAheadDistance); ++x, ++currentIndex) {
122 if (sentinelVector[currentIndex] > 0 && object_compare()(getKey(data[currentIndex]), getKey(key))) {
123 return {
this, currentIndex };
130 template<
typename key_type_new> DCA_INLINE const_reference operator[](key_type_new&& key)
const {
131 auto iter = find(std::forward<key_type_new>(key));
133 iter = emplace(mapped_type{});
138 template<
typename key_type_new> DCA_INLINE reference operator[](key_type_new&& key) {
139 auto iter = find(std::forward<key_type_new>(key));
141 iter = emplace(mapped_type{});
146 template<
typename key_type_new> DCA_INLINE const_reference at(key_type_new&& key)
const {
147 auto iter = find(std::forward<key_type_new>(key));
149 throw std::runtime_error{
"Sorry, but an object by that key doesn't exist in this map." };
154 template<
typename key_type_new> DCA_INLINE reference at(key_type_new&& key) {
155 auto iter = find(std::forward<key_type_new>(key));
157 throw std::runtime_error{
"Sorry, but an object by that key doesn't exist in this map." };
162 template<
typename key_type_new> DCA_INLINE
bool contains(key_type_new&& key)
const {
164 auto currentIndex = getKey(key) & (capacityVal - 1);
165 for (size_type x{}; x < static_cast<size_type>(maxLookAheadDistance); ++x, ++currentIndex) {
166 if (sentinelVector[currentIndex] > 0 && object_compare()(getKey(data[currentIndex]), getKey(key))) {
174 template<set_container_iterator_t<mapped_type> set_iterator> DCA_INLINE iterator erase(set_iterator&& iter) {
176 auto currentIndex =
static_cast<size_type
>(iter.getRawPtr() - data);
177 for (size_type x{}; x < static_cast<size_type>(maxLookAheadDistance); ++x, ++currentIndex) {
178 if (sentinelVector[currentIndex] > 0 && object_compare()(getKey(data[currentIndex]), getKey(iter.operator*()))) {
179 sentinelVector[currentIndex] = 0;
181 return {
this, ++currentIndex };
188 template<
typename key_type_new> DCA_INLINE iterator erase(key_type_new&& key) {
190 auto currentIndex = getKey(key) & (capacityVal - 1);
191 for (size_type x{}; x < static_cast<size_type>(maxLookAheadDistance); ++x, ++currentIndex) {
192 if (sentinelVector[currentIndex] > 0 && object_compare()(getKey(data[currentIndex]), getKey(key))) {
193 sentinelVector[currentIndex] = 0;
195 return {
this, ++currentIndex };
202 DCA_INLINE const_iterator begin()
const {
203 for (size_type x{ 0 }; x < capacityVal; ++x) {
204 if (sentinelVector.at(x) > 0) {
211 DCA_INLINE const_iterator end()
const {
215 DCA_INLINE iterator begin() {
216 for (size_type x{ 0 }; x < capacityVal; ++x) {
217 if (sentinelVector.at(x) > 0) {
224 DCA_INLINE iterator end() {
228 DCA_INLINE
bool full()
const {
229 return static_cast<float>(sizeVal) >=
static_cast<float>(capacityVal) * 0.90f;
232 DCA_INLINE size_type size()
const {
236 DCA_INLINE
bool empty()
const {
240 DCA_INLINE
void reserve(size_type sizeNew) {
244 DCA_INLINE
void swap(unordered_set& other) {
245 std::swap(maxLookAheadDistance, other.maxLookAheadDistance);
246 std::swap(sentinelVector, other.sentinelVector);
247 std::swap(capacityVal, other.capacityVal);
248 std::swap(sizeVal, other.sizeVal);
249 std::swap(data, other.data);
252 DCA_INLINE size_type capacity()
const {
256 DCA_INLINE
bool operator==(
const unordered_set& other)
const {
257 if (capacityVal != other.capacityVal || sizeVal != other.sizeVal || data != other.data) {
260 for (
auto iter01{ begin() }, iter02{ other.begin() }; iter01 != end(); ++iter01, ++iter02) {
261 if (!object_compare()(iter01.operator*(), iter02.operator*())) {
268 DCA_INLINE
void clear() {
269 for (size_type x = 0; x < sentinelVector.size(); ++x) {
270 if (sentinelVector.at(x) > 0) {
271 allocator_traits::destroy(*
this, data + x);
272 sentinelVector.at(x) = 0;
278 DCA_INLINE ~unordered_set() {
283 jsonifier::vector<int8_t> sentinelVector{};
284 int8_t maxLookAheadDistance{ 0 };
285 size_type capacityVal{};
289 template<
typename mapped_type_new> DCA_INLINE iterator emplaceInternal(mapped_type_new&& value) {
290 if (full() || capacityVal == 0) {
291 resize(capacityVal + 1);
293 auto currentIndex = getKey(value) & (capacityVal - 1);
294 for (size_type x{}; x < static_cast<size_type>(maxLookAheadDistance); ++x, ++currentIndex) {
295 if (sentinelVector[currentIndex] == 0) {
296 new (std::addressof(data[currentIndex])) value_type{ std::forward<mapped_type_new>(value) };
297 sentinelVector[currentIndex] = 1;
299 return {
this, currentIndex };
300 }
else if (sentinelVector[currentIndex] > 0 && object_compare()(getKey(data[currentIndex]), getKey(value))) {
301 if constexpr (!std::is_void_v<mapped_type_new>) {
302 data[currentIndex] = std::forward<mapped_type_new>(value);
304 return {
this, currentIndex };
307 resize(capacityVal + 1);
308 return emplaceInternal(std::forward<mapped_type_new>(value));
311 template<
typename value_type_newer> DCA_INLINE uint64_t getKey(value_type_newer&& keyValue)
const {
312 return key_accessor<jsonifier_internal::unwrap_t<value_type_newer>>::getHashKey(std::forward<value_type_newer>(keyValue));
315 DCA_INLINE
void resize(size_type capacityNew) {
316 auto newSize = hash_policy_new::nextPowerOfTwo(capacityNew);
317 if (newSize > capacityVal) {
318 jsonifier::vector<int8_t> oldSentinelVector = std::move(sentinelVector);
319 auto oldMaxLookAheadDistance = maxLookAheadDistance;
320 auto oldCapacity = capacityVal;
321 auto oldSize = sizeVal;
323 maxLookAheadDistance = hash_policy_new::computeMaxLookAheadDistance(newSize);
325 data = allocator_traits::allocate(*
this, newSize + 1 + maxLookAheadDistance);
326 sentinelVector.resize(newSize + 1 + maxLookAheadDistance);
327 sentinelVector[newSize + maxLookAheadDistance] = -1;
328 capacityVal = newSize;
329 for (size_type x = 0, y = 0; y < oldSize; ++x) {
330 if (oldSentinelVector.at(x) > 0) {
332 emplaceInternal(std::move(oldPtr[x]));
335 if (oldPtr && oldCapacity) {
336 allocator_traits::deallocate(*
this, oldPtr, oldCapacity + 1 + oldMaxLookAheadDistance);
341 DCA_INLINE
void reset() {
342 if (data && sizeVal > 0) {
343 for (uint64_t x = 0; x < sentinelVector.size(); ++x) {
344 if (sentinelVector.at(x) > 0) {
345 allocator_traits::destroy(*
this, data + x);
346 sentinelVector.at(x) = 0;
349 allocator_traits::deallocate(*
this, data, capacityVal + 1 + maxLookAheadDistance);
350 sentinelVector.clear();
The main namespace for the forward-facing interfaces.