osb/source/core/StarOrderedSet.hpp
Kae e6f96cb2bd std::allocator::rebind is deprecated
Clang should no longer scream
2024-02-20 19:34:58 +11:00

434 lines
15 KiB
C++

#ifndef STAR_ORDERED_SET_HPP
#define STAR_ORDERED_SET_HPP
#include <map>
#include "StarFlatHashMap.hpp"
#include "StarSet.hpp"
#include "StarList.hpp"
namespace Star {
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
class OrderedSetWrapper {
public:
typedef Value value_type;
typedef LinkedList<value_type, typename std::allocator_traits<Allocator>::template rebind_alloc<value_type>> OrderType;
typedef Map<
std::reference_wrapper<value_type const>, typename OrderType::const_iterator, Args...,
typename std::allocator_traits<Allocator>::template rebind_alloc<pair<std::reference_wrapper<value_type const> const, typename OrderType::const_iterator>>
> MapType;
typedef typename OrderType::const_iterator const_iterator;
typedef const_iterator iterator;
typedef typename OrderType::const_reverse_iterator const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
template <typename Collection>
static OrderedSetWrapper from(Collection const& c);
OrderedSetWrapper();
OrderedSetWrapper(OrderedSetWrapper const& set);
template <typename InputIterator>
OrderedSetWrapper(InputIterator beg, InputIterator end);
OrderedSetWrapper(initializer_list<value_type> list);
OrderedSetWrapper& operator=(OrderedSetWrapper const& set);
// Guaranteed to be in order.
List<value_type> values() const;
bool contains(value_type const& v) const;
// add either adds the value to the back, or does not move it from its
// current order.
pair<iterator, bool> insert(value_type const& v);
// like insert, but only returns whether the value was added or not.
bool add(Value const& v);
// Always replaces an existing value with a new value if it exists, and
// always moves to the back.
bool replace(Value const& v);
// Either adds a value to the end of the order, or moves an existing value to
// the back.
bool addBack(Value const& v);
// Either adds a value to the beginning of the order, or moves an existing
// value to the beginning.
bool addFront(Value const& v);
template <typename Container>
void addAll(Container const& c);
iterator toFront(iterator i);
iterator toBack(iterator i);
bool remove(value_type const& v);
template <typename Container>
void removeAll(Container const& c);
void clear();
value_type const& first() const;
value_type const& last() const;
void removeFirst();
void removeLast();
value_type takeFirst();
value_type takeLast();
template <typename Compare>
void sort(Compare comp);
void sort();
size_t empty() const;
size_t size() const;
const_iterator begin() const;
const_iterator end() const;
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
Maybe<size_t> indexOf(value_type const& v) const;
value_type const& at(size_t i) const;
value_type& at(size_t i);
OrderedSetWrapper intersection(OrderedSetWrapper const& s) const;
OrderedSetWrapper difference(OrderedSetWrapper const& s) const;
private:
MapType m_map;
OrderType m_order;
};
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
std::ostream& operator<<(std::ostream& os, OrderedSetWrapper<Map, Value, Allocator, Args...> const& set);
template <typename Value, typename Compare = std::less<Value>, typename Allocator = std::allocator<Value>>
using OrderedSet = OrderedSetWrapper<std::map, Value, Allocator, Compare>;
template <typename Value, typename Hash = Star::hash<Value>, typename Equals = std::equal_to<Value>, typename Allocator = std::allocator<Value>>
using OrderedHashSet = OrderedSetWrapper<FlatHashMap, Value, Allocator, Hash, Equals>;
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Collection>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::from(Collection const& c) -> OrderedSetWrapper {
return OrderedSetWrapper(c.begin(), c.end());
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper() {}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper(OrderedSetWrapper const& set) {
for (auto const& p : set)
add(p);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename InputIterator>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper(InputIterator beg, InputIterator end) {
while (beg != end) {
add(*beg);
++beg;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper(initializer_list<value_type> list) {
for (value_type const& v : list)
add(v);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::operator=(OrderedSetWrapper const& set) -> OrderedSetWrapper& {
if (this != &set) {
clear();
for (auto const& p : set)
add(p);
}
return *this;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::values() const -> List<value_type> {
List<value_type> values;
for (auto p : *this)
values.append(std::move(p));
return values;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::contains(value_type const& v) const {
return m_map.find(v) != m_map.end();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::insert(value_type const& v) -> pair<iterator, bool> {
auto i = m_map.find(v);
if (i == m_map.end()) {
auto orderIt = m_order.insert(m_order.end(), v);
m_map.insert(typename MapType::value_type(std::cref(*orderIt), orderIt));
return {orderIt, true};
}
return {i->second, false};
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::add(Value const& v) {
return insert(v).second;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::replace(Value const& v) {
bool replaced = remove(v);
add(v);
return replaced;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::addBack(Value const& v) {
auto i = m_map.find(v);
if (i != m_map.end()) {
m_order.splice(m_order.end(), m_order, i->second);
return false;
} else {
iterator orderIt = m_order.insert(m_order.end(), v);
m_map.insert(typename MapType::value_type(std::cref(*orderIt), orderIt));
return true;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::addFront(Value const& v) {
auto i = m_map.find(v);
if (i != m_map.end()) {
m_order.splice(m_order.begin(), m_order, i->second);
return false;
} else {
iterator orderIt = m_order.insert(m_order.end(), v);
m_map.insert(typename MapType::value_type(std::cref(*orderIt), orderIt));
return true;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Container>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::addAll(Container const& c) {
for (auto const& v : c)
add(v);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::toFront(iterator i) -> iterator {
m_order.splice(m_order.begin(), m_order, i);
return m_order.begin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::toBack(iterator i) -> iterator {
m_order.splice(m_order.end(), m_order, i);
return prev(m_order.end());
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::remove(value_type const& v) {
auto i = m_map.find(v);
if (i != m_map.end()) {
auto orderIt = i->second;
m_map.erase(i);
m_order.erase(orderIt);
return true;
}
return false;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Container>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::removeAll(Container const& c) {
for (auto const& v : c)
remove(v);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::clear() {
m_map.clear();
m_order.clear();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::first() const -> value_type const& {
if (empty())
throw SetException("first() called on empty OrderedSet");
return *begin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::last() const -> value_type const& {
if (empty())
throw SetException("last() called on empty OrderedSet");
return *(prev(end()));
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::removeFirst() {
if (empty())
throw SetException("OrderedSet::removeFirst() called on empty OrderedSet");
auto i = m_order.begin();
m_map.erase(*i);
m_order.erase(i);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::removeLast() {
if (empty())
throw SetException("OrderedSet::removeLast() called on empty OrderedSet");
auto i = m_order.end();
--i;
m_map.erase(*i);
m_order.erase(i);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::takeFirst() -> value_type {
if (empty())
throw SetException("OrderedSet::takeFirst() called on empty OrderedSet");
auto i = m_order.begin();
m_map.erase(*i);
value_type v = *i;
m_order.erase(i);
return v;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::takeLast() -> value_type {
if (empty())
throw SetException("OrderedSet::takeLast() called on empty OrderedSet");
auto i = m_order.end();
--i;
m_map.erase(*i);
value_type v = *i;
m_order.erase(i);
return v;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Compare>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::sort(Compare comp) {
m_order.sort(comp);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::sort() {
m_order.sort();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
size_t OrderedSetWrapper<Map, Value, Allocator, Args...>::empty() const {
return m_map.empty();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
size_t OrderedSetWrapper<Map, Value, Allocator, Args...>::size() const {
return m_map.size();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::begin() const -> const_iterator {
return m_order.begin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::end() const -> const_iterator {
return m_order.end();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::rbegin() const -> const_reverse_iterator {
return m_order.rbegin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::rend() const -> const_reverse_iterator {
return m_order.rend();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
Maybe<size_t> OrderedSetWrapper<Map, Value, Allocator, Args...>::indexOf(value_type const& v) const {
auto i = m_map.find(v);
if (i == m_map.end())
return {};
return std::distance(begin(), const_iterator(i->second));
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::at(size_t i) const -> value_type const& {
auto it = begin();
std::advance(it, i);
return *it;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::at(size_t i) -> value_type& {
auto it = begin();
std::advance(it, i);
return *it;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::intersection(OrderedSetWrapper const& s) const -> OrderedSetWrapper {
OrderedSetWrapper ret;
for (auto const& e : s) {
if (contains(e))
ret.add(e);
}
return ret;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::difference(OrderedSetWrapper const& s) const -> OrderedSetWrapper {
OrderedSetWrapper ret;
for (auto const& e : *this) {
if (!s.contains(e))
ret.add(e);
}
return ret;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
std::ostream& operator<<(std::ostream& os, OrderedSetWrapper<Map, Value, Allocator, Args...> const& set) {
os << "(";
for (auto i = set.begin(); i != set.end(); ++i) {
if (i != set.begin())
os << ", ";
os << *i;
}
os << ")";
return os;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
struct fmt::formatter<Star::OrderedSetWrapper<Map, Value, Allocator, Args...>> : ostream_formatter {};
#endif