Files
revng-revng/include/revng/ADT/MutableSet.h
2024-06-27 11:05:50 +02:00

241 lines
7.2 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <map>
#include "llvm/ADT/STLExtras.h"
#include "revng/ADT/KeyedObjectContainer.h"
template<KeyedObjectContainerCompatible T,
class Compare = DefaultKeyObjectComparator<T>>
class MutableSet {
private:
using KOT = KeyedObjectTraits<T>;
using non_const_key_type = decltype(KOT::key(std::declval<T>()));
public:
using key_type = const non_const_key_type;
private:
using map_type = std::map<non_const_key_type, T, Compare>;
public:
using size_type = typename map_type::size_type;
using value_type = T;
using difference_type = typename map_type::difference_type;
using allocator_type = typename map_type::allocator_type;
using reference = T &;
using const_reference = const T &;
using pointer = T *;
using const_pointer = const T *;
private:
using inner_mapped_type = typename map_type::mapped_type;
using inner_iterator = typename map_type::iterator;
using const_inner_iterator = typename map_type::const_iterator;
using inner_reverse_iterator = typename map_type::reverse_iterator;
using ciri = typename map_type::const_reverse_iterator;
using const_inner_reverse_iterator = ciri;
private:
template<typename A, typename B>
using mapped_iterator = llvm::mapped_iterator<A, B>;
private:
using pair = std::pair<key_type, inner_mapped_type>;
static inner_mapped_type &getSecond(pair &Pair) { return Pair.second; }
static const inner_mapped_type &getConstSecond(const pair &Pair) {
return Pair.second;
}
public:
using iterator = mapped_iterator<inner_iterator, decltype(getSecond) *>;
using const_iterator = mapped_iterator<const_inner_iterator,
decltype(getConstSecond) *>;
using reverse_iterator = mapped_iterator<inner_reverse_iterator,
decltype(getSecond) *>;
using const_reverse_iterator = mapped_iterator<const_inner_reverse_iterator,
decltype(getConstSecond) *>;
public:
static constexpr bool KeyedObjectContainerTag = true;
private:
map_type TheMap;
public:
MutableSet() {}
MutableSet(std::initializer_list<T> List) {
auto Inserter = batch_insert_or_assign();
for (const T &Element : List) {
Inserter.insert_or_assign(Element);
}
}
public:
void swap(MutableSet &Other) { TheMap.swap(Other.TheMap); }
bool operator==(const MutableSet &Other) const = default;
public:
T &at(const key_type &Key) { return TheMap.at(Key); }
const T &at(const key_type &Key) const { return TheMap.at(Key); }
T &operator[](const key_type &Key) {
return TheMap.insert({ Key, KOT::fromKey(Key) }).first->second;
}
T &operator[](key_type &&Key) {
return TheMap.insert({ Key, KOT::fromKey(Key) }).first->second;
}
iterator begin() { return wrapIterator(TheMap.begin()); }
iterator end() { return wrapIterator(TheMap.end()); }
const_iterator begin() const { return wrapIterator(TheMap.begin()); }
const_iterator end() const { return wrapIterator(TheMap.end()); }
const_iterator cbegin() const { return wrapIterator(TheMap.cbegin()); }
const_iterator cend() const { return wrapIterator(TheMap.cend()); }
reverse_iterator rbegin() { return wrapIterator(TheMap.rbegin()); }
reverse_iterator rend() { return wrapIterator(TheMap.rend()); }
const_reverse_iterator rbegin() const {
return wrapIterator(TheMap.rbegin());
}
const_reverse_iterator rend() const { return wrapIterator(TheMap.rend()); }
const_reverse_iterator crbegin() const {
return wrapIterator(TheMap.crbegin());
}
const_reverse_iterator crend() const { return wrapIterator(TheMap.crend()); }
bool empty() const { return TheMap.empty(); }
size_type size() const { return TheMap.size(); }
size_type max_size() const { return TheMap.max_size(); }
void clear() { TheMap.clear(); }
std::pair<iterator, bool> insert(const T &Value) {
auto Result = TheMap.insert({ KOT::key(Value), Value });
return { wrapIterator(Result.first), Result.second };
}
template<typename... Types>
std::pair<iterator, bool> emplace(Types &&...Values) {
T NewElement{ Values... };
auto Result = TheMap.emplace(KOT::key(NewElement), std::move(NewElement));
return { wrapIterator(Result.first), Result.second };
}
template<typename... Types>
std::pair<iterator, bool> try_emplace(Types &&...Values) {
T NewElement{ Values... };
auto Result = TheMap.try_emplace(KOT::key(NewElement),
std::move(NewElement));
return { wrapIterator(Result.first), Result.second };
}
std::pair<iterator, bool> insert_or_assign(const T &Value) {
auto Result = TheMap.insert_or_assign(KOT::key(Value), Value);
return { wrapIterator(Result.first), Result.second };
}
iterator erase(iterator Pos) {
return wrapIterator(TheMap.erase(unwrapIterator(Pos)));
}
iterator erase(iterator First, iterator Last) {
auto It = TheMap.erase(unwrapIterator(First), unwrapIterator(Last));
return wrapIterator(It);
}
size_type erase(const key_type &Key) { return TheMap.erase(Key); }
template<typename CallableType>
size_type erase_if(CallableType &&Callable) {
return std::erase_if(TheMap, std::forward<CallableType>(Callable));
}
size_type count(const key_type &Key) const { return TheMap.count(Key); }
iterator find(const key_type &Key) { return wrapIterator(TheMap.find(Key)); }
const_iterator find(const key_type &Key) const {
return wrapIterator(TheMap.find(Key));
}
bool contains(const key_type &Key) const { return find(Key) != end(); }
iterator lower_bound(const key_type &Key) {
return wrapIterator(TheMap.lower_bound(Key));
}
const_iterator lower_bound(const key_type &Key) const {
return wrapIterator(TheMap.lower_bound(Key));
}
iterator upper_bound(const key_type &Key) {
return wrapIterator(TheMap.upper_bound(Key));
}
const_iterator upper_bound(const key_type &Key) const {
return wrapIterator(TheMap.upper_bound(Key));
}
public:
class BatchInserter {
private:
MutableSet &MS;
public:
BatchInserter(MutableSet &MS) : MS(MS) {}
T &insert(const T &Value) { return *MS.insert(Value).first; }
};
BatchInserter batch_insert() { return BatchInserter(*this); }
class BatchInsertOrAssigner {
private:
MutableSet &MS;
public:
BatchInsertOrAssigner(MutableSet &MS) : MS(MS) {}
T &insert_or_assign(const T &Value) {
return *MS.insert_or_assign(Value).first;
}
};
BatchInsertOrAssigner batch_insert_or_assign() {
return BatchInsertOrAssigner(*this);
}
private:
static inner_iterator unwrapIterator(iterator It) { return It.getCurrent(); }
static const_inner_iterator unwrapIterator(const_iterator It) {
return It.getCurrent();
}
static iterator wrapIterator(inner_iterator It) {
return iterator(It, getSecond);
}
static const_iterator wrapIterator(const_inner_iterator It) {
return const_iterator(It, getConstSecond);
}
static reverse_iterator wrapIterator(inner_reverse_iterator It) {
return reverse_iterator(It, getSecond);
}
static const_reverse_iterator wrapIterator(const_inner_reverse_iterator It) {
return const_reverse_iterator(It, getConstSecond);
}
};
static_assert(KeyedObjectContainer<MutableSet<int>>);