mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
241 lines
7.2 KiB
C++
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>>);
|