#pragma once //#include #include "fl/stdint.h" #include "fl/namespace.h" #include "fl/vector.h" #include "fl/map.h" #include "fl/rbtree.h" #include "fl/allocator.h" #include "fl/pair.h" namespace fl { template class set; // VectorSet stores values in order of insertion. template class VectorSetFixed; template class VectorSet; template using FixedSet = VectorSetFixed; // Backwards compatibility // A simple unordered set implementation with a fixed size. // The user is responsible for making sure that the inserts // do not exceed the capacity of the set, otherwise they will // fail. Because of this limitation, this set is not a drop in // replacement for std::set. template class VectorSetFixed { public: typedef FixedVector VectorType; typedef typename VectorType::iterator iterator; typedef typename VectorType::const_iterator const_iterator; // Constructor constexpr VectorSetFixed() = default; iterator begin() { return data.begin(); } iterator end() { return data.end(); } const_iterator begin() const { return data.begin(); } const_iterator end() const { return data.end(); } iterator find(const Key &key) { for (auto it = begin(); it != end(); ++it) { if (*it == key) { return it; } } return end(); } const_iterator find(const Key &key) const { for (auto it = begin(); it != end(); ++it) { if (*it == key) { return it; } } return end(); } bool insert(const Key &key) { if (data.size() < N) { auto it = find(key); if (it == end()) { data.push_back(key); return true; } } return false; } // Move version of insert bool insert(Key &&key) { if (data.size() < N) { auto it = find(key); if (it == end()) { data.push_back(fl::move(key)); return true; } } return false; } // Emplace - construct in place with perfect forwarding template bool emplace(Args&&... args) { if (data.size() < N) { // Create a temporary to check if it already exists Key temp_key(fl::forward(args)...); auto it = find(temp_key); if (it == end()) { data.push_back(fl::move(temp_key)); return true; } } return false; } bool erase(const Key &key) { auto it = find(key); if (it != end()) { data.erase(it); return true; } return false; } bool erase(iterator pos) { if (pos != end()) { data.erase(pos); return true; } return false; } bool next(const Key &key, Key *next_key, bool allow_rollover = false) const { const_iterator it = find(key); if (it != end()) { ++it; if (it != end()) { *next_key = *it; return true; } else if (allow_rollover && !empty()) { *next_key = *begin(); return true; } } return false; } bool prev(const Key &key, Key *prev_key, bool allow_rollover = false) const { const_iterator it = find(key); if (it != end()) { if (it != begin()) { --it; *prev_key = *it; return true; } else if (allow_rollover && !empty()) { *prev_key = data[data.size() - 1]; return true; } } return false; } // Get the current size of the set constexpr fl::size size() const { return data.size(); } constexpr bool empty() const { return data.empty(); } // Get the capacity of the set constexpr fl::size capacity() const { return N; } // Clear the set void clear() { data.clear(); } bool has(const Key &key) const { return find(key) != end(); } // Return the first element of the set const Key &front() const { return data.front(); } // Return the last element of the set const Key &back() const { return data.back(); } private: VectorType data; }; template > class VectorSet { public: typedef fl::HeapVector VectorType; typedef typename VectorType::iterator iterator; typedef typename VectorType::const_iterator const_iterator; // Constructor constexpr VectorSet() = default; iterator begin() { return data.begin(); } iterator end() { return data.end(); } const_iterator begin() const { return data.begin(); } const_iterator end() const { return data.end(); } iterator find(const Key &key) { for (auto it = begin(); it != end(); ++it) { if (*it == key) { return it; } } return end(); } const_iterator find(const Key &key) const { for (auto it = begin(); it != end(); ++it) { if (*it == key) { return it; } } return end(); } bool insert(const Key &key) { auto it = find(key); if (it == end()) { data.push_back(key); return true; } return false; } // Move version of insert bool insert(Key &&key) { auto it = find(key); if (it == end()) { data.push_back(fl::move(key)); return true; } return false; } // Emplace - construct in place with perfect forwarding template bool emplace(Args&&... args) { // Create a temporary to check if it already exists Key temp_key(fl::forward(args)...); auto it = find(temp_key); if (it == end()) { data.push_back(fl::move(temp_key)); return true; } return false; } bool erase(const Key &key) { auto it = find(key); if (it != end()) { data.erase(it); return true; } return false; } bool erase(iterator pos) { if (pos != end()) { data.erase(pos); return true; } return false; } // Get the current size of the set constexpr fl::size size() const { return data.size(); } constexpr bool empty() const { return data.empty(); } // Get the capacity of the set constexpr fl::size capacity() const { return data.capacity(); } // Clear the set void clear() { data.clear(); } bool has(const Key &key) const { return find(key) != end(); } // Return the first element of the set const Key &front() const { return data.front(); } // Return the last element of the set const Key &back() const { return data.back(); } private: VectorType data; }; // fl::set - Ordered set implementation using SetRedBlackTree // This is an ordered set that keeps elements sorted, similar to std::set template > class set { private: using TreeType = fl::SetRedBlackTree, Allocator>; TreeType tree_; public: // Standard set typedefs using key_type = Key; using value_type = Key; using size_type = fl::size; using difference_type = ptrdiff_t; using reference = const Key&; using const_reference = const Key&; using pointer = const Key*; using const_pointer = const Key*; // Iterator types - we only provide const iterators since set elements are immutable using const_iterator = typename TreeType::const_iterator; using iterator = const_iterator; // set only provides const iterators // Constructors set() = default; set(const set& other) = default; set(set&& other) = default; set& operator=(const set& other) = default; set& operator=(set&& other) = default; // Iterators const_iterator begin() const { return tree_.begin(); } const_iterator end() const { return tree_.end(); } const_iterator cbegin() const { return tree_.cbegin(); } const_iterator cend() const { return tree_.cend(); } // Capacity bool empty() const { return tree_.empty(); } size_type size() const { return tree_.size(); } size_type max_size() const { return tree_.max_size(); } // Modifiers void clear() { tree_.clear(); } fl::pair insert(const Key& key) { return tree_.insert(key); } fl::pair insert(Key&& key) { return tree_.insert(fl::move(key)); } template fl::pair emplace(Args&&... args) { return tree_.emplace(fl::forward(args)...); } const_iterator erase(const_iterator pos) { return tree_.erase(pos); } size_type erase(const Key& key) { return tree_.erase(key); } void swap(set& other) { tree_.swap(other.tree_); } // Lookup size_type count(const Key& key) const { return tree_.count(key); } const_iterator find(const Key& key) const { return tree_.find(key); } bool contains(const Key& key) const { return tree_.contains(key); } bool has(const Key& key) const { return contains(key); } fl::pair equal_range(const Key& key) const { return tree_.equal_range(key); } const_iterator lower_bound(const Key& key) const { return tree_.lower_bound(key); } const_iterator upper_bound(const Key& key) const { return tree_.upper_bound(key); } }; // fl::set_inlined - Inlined set implementation using proper allocator // This is a using declaration that sets the proper allocator for fl::set template using set_inlined = fl::set>; } // namespace fl