From cf6488c74947c42590b9abda9036119f73377cc3 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Tue, 21 Jan 2025 10:00:05 -0600 Subject: [PATCH] Add srb2::HashSet --- src/core/CMakeLists.txt | 2 + src/core/hash_map.hpp | 12 +++ src/core/hash_set.cpp | 32 ++++++ src/core/hash_set.hpp | 214 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 src/core/hash_set.cpp create mode 100644 src/core/hash_set.hpp diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9a1ae3357..dca1a6d39 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,5 +1,7 @@ target_sources(SRB2SDL2 PRIVATE hash_map.hpp + hash_set.cpp + hash_set.hpp memory.cpp memory.h spmc_queue.hpp diff --git a/src/core/hash_map.hpp b/src/core/hash_map.hpp index 35b29d941..8f430aee3 100644 --- a/src/core/hash_map.hpp +++ b/src/core/hash_map.hpp @@ -24,6 +24,9 @@ namespace srb2 { +template +class HashSet; + template class HashMap { @@ -35,6 +38,8 @@ class HashMap public: using Entry = std::pair; + class ConstIter; + class Iter { const HashMap* self_; @@ -47,7 +52,14 @@ public: , cur_(cur) {} + Iter(const ConstIter& r) + : self_(r.iter_.self_) + , bucket_(r.iter_.bucket_) + , cur_(r.iter_.cur_) + {} + friend class HashMap; + friend class HashSet; friend class ConstIter; public: diff --git a/src/core/hash_set.cpp b/src/core/hash_set.cpp new file mode 100644 index 000000000..72c0dd5da --- /dev/null +++ b/src/core/hash_set.cpp @@ -0,0 +1,32 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Ronald "Eidolon" Kinard +// Copyright (C) 2025 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include "hash_set.hpp" + +#include + +#include "string.h" + +namespace srb2 +{ + +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; +template class HashSet; + +} // namespace srb2 diff --git a/src/core/hash_set.hpp b/src/core/hash_set.hpp new file mode 100644 index 000000000..ed2a714a0 --- /dev/null +++ b/src/core/hash_set.hpp @@ -0,0 +1,214 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Ronald "Eidolon" Kinard +// Copyright (C) 2025 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef SRB2_CORE_HASH_SET_HPP +#define SRB2_CORE_HASH_SET_HPP + +#include +#include + +#include "hash_map.hpp" +#include "string.h" + +namespace srb2 +{ + +template +class HashSet +{ + using Inner = HashMap; + +public: + class Iter + { + typename Inner::Iter iter_; + + Iter(typename Inner::Iter iter) : iter_(iter) {} + + friend class HashSet; + friend class ConstIter; + + public: + Iter() = default; + Iter(const Iter&) = default; + Iter(Iter&&) noexcept = default; + ~Iter() = default; + + Iter& operator=(const Iter&) = default; + Iter& operator=(Iter&&) noexcept = default; + + bool operator==(const Iter& r) const noexcept { return iter_ == r.iter_; } + bool operator!=(const Iter& r) const noexcept { return !(*this == r); } + + V& operator*() const noexcept { return iter_->first; } + V* operator->() const noexcept { return &iter_->first; } + Iter& operator++() noexcept + { + ++iter_; + return *this; + } + Iter operator++(int) noexcept + { + Iter self = *this; + ++*this; + return self; + } + }; + + class ConstIter + { + typename Inner::ConstIter iter_; + + friend class HashSet; + friend class Iter; + + public: + ConstIter() = default; + ConstIter(const ConstIter&) = default; + ConstIter(ConstIter&&) noexcept = default; + ~ConstIter() = default; + + ConstIter(const Iter& iter) : iter_(iter.iter_) {} + ConstIter(const typename Inner::ConstIter& iter) : iter_(iter) {} + + ConstIter& operator=(const ConstIter&) = default; + ConstIter& operator=(ConstIter&&) noexcept = default; + + bool operator==(const ConstIter& r) const noexcept { return iter_ == r.iter_; } + bool operator!=(const ConstIter& r) const noexcept { return !(*this == r); } + + const V& operator*() const noexcept { return iter_->first; } + const V* operator->() const noexcept { return &iter_->first; } + ConstIter& operator++() noexcept + { + ++iter_; + return *this; + } + ConstIter operator++(int) noexcept + { + ConstIter self = *this; + ++*this; + return self; + } + }; + +private: + Inner map_; + +public: + using key_type = V; + using value_type = V; + using size_type = typename Inner::size_type; + using difference_type = typename Inner::difference_type; + using hasher = typename Inner::hasher; + using key_equal = typename Inner::key_equal; + using reference = V&; + using const_reference = const V&; + using pointer = V*; + using const_pointer = const V*; + using iterator = Iter; + using const_iterator = ConstIter; + + HashSet() = default; + HashSet(const HashSet&) = default; + HashSet(HashSet&&) noexcept = default; + ~HashSet() = default; + + HashSet& operator=(const HashSet&) = default; + HashSet& operator=(HashSet&&) noexcept = default; + + Iter begin() { return map_.begin(); } + Iter end() { return map_.end(); } + ConstIter cbegin() const { return map_.cbegin(); } + ConstIter cend() const { return map_.cend(); } + ConstIter begin() const { return cbegin(); } + ConstIter end() const { return cend(); } + + bool empty() const noexcept { return map_.empty(); } + size_t size() const noexcept { return map_.size(); } + + void clear() { map_.clear(); } + + std::pair insert(const V& value) + { + V copy { value }; + return insert(std::move(copy)); + } + + std::pair insert(V&& value) + { + return emplace(std::move(value)); + } + + template + std::pair emplace(Args&&... args) + { + std::pair res; + auto [map_iter, map_inserted] = map_.emplace(std::forward(args)..., 0); + res.first = map_iter; + res.second = map_inserted; + return res; + } + + Iter erase(Iter pos) + { + auto map_ret = map_.erase(pos.iter_); + return map_ret; + } + + Iter erase(ConstIter pos) + { + auto map_ret = map_.erase(pos.iter_); + return map_ret; + } + + Iter erase(ConstIter first, ConstIter last) + { + ConstIter iter; + for (iter = first; iter != last;) + { + iter = erase(iter); + } + return typename Inner::Iter(iter.iter_); + } + + Iter find(const V& value) + { + auto map_ret = map_.find(value); + return map_ret; + } + + ConstIter find(const V& value) const + { + auto map_ret = map_.find(value); + return map_ret; + } + + void rehash(size_t count) + { + map_.rehash(count); + } +}; + +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; +extern template class HashSet; + +} // namespace srb2 + +#endif // SRB2_CORE_HASH_SET_HPP