#ifndef wasm_support_insert_ordered_h
#define wasm_support_insert_ordered_h
#include <list>
#include <stddef.h>
#include <unordered_map>
#include "support/utilities.h"
namespace wasm {
template<typename T> struct InsertOrderedSet {
std::unordered_map<T, typename std::list<T>::iterator> Map;
std::list<T> List;
using iterator = typename std::list<T>::iterator;
iterator begin() { return List.begin(); }
iterator end() { return List.end(); }
void erase(const T& val) {
auto it = Map.find(val);
if (it != Map.end()) {
List.erase(it->second);
Map.erase(it);
}
}
void erase(iterator position) {
Map.erase(*position);
List.erase(position);
}
bool insert(const T& val) {
auto [it, inserted] = Map.insert({val, List.begin()});
if (inserted) {
List.push_back(val);
it->second = --List.end();
}
return inserted;
}
size_t size() const { return Map.size(); }
bool empty() const { return Map.empty(); }
void clear() {
Map.clear();
List.clear();
}
size_t count(const T& val) const { return Map.count(val); }
InsertOrderedSet() = default;
InsertOrderedSet(const InsertOrderedSet& other) { *this = other; }
InsertOrderedSet& operator=(const InsertOrderedSet& other) {
clear();
for (auto i : other.List) {
insert(i); }
return *this;
}
};
template<typename Key, typename T> struct InsertOrderedMap {
std::unordered_map<Key, typename std::list<std::pair<const Key, T>>::iterator>
Map;
std::list<std::pair<const Key, T>> List;
using iterator = typename std::list<std::pair<const Key, T>>::iterator;
iterator begin() { return List.begin(); }
iterator end() { return List.end(); }
typedef
typename std::list<std::pair<const Key, T>>::const_iterator const_iterator;
const_iterator begin() const { return List.begin(); }
const_iterator end() const { return List.end(); }
std::pair<iterator, bool> insert(const std::pair<const Key, T>& kv) {
auto inserted = Map.insert({kv.first, List.end()});
if (inserted.second) {
List.push_back(kv);
inserted.first->second = std::prev(List.end());
}
return {inserted.first->second, inserted.second};
}
T& operator[](const Key& k) {
std::pair<const Key, T> kv = {k, {}};
return insert(kv).first->second;
}
T& at(const Key& k) { return Map.at(k)->second; }
iterator find(const Key& k) {
auto it = Map.find(k);
if (it == Map.end()) {
return end();
}
return it->second;
}
void erase(const Key& k) {
auto it = Map.find(k);
if (it != Map.end()) {
List.erase(it->second);
Map.erase(it);
}
}
void erase(iterator position) { erase(position->first); }
void clear() {
Map.clear();
List.clear();
}
void swap(InsertOrderedMap<Key, T>& Other) {
Map.swap(Other.Map);
List.swap(Other.List);
}
size_t size() const { return Map.size(); }
bool empty() const { return Map.empty(); }
size_t count(const Key& k) const { return Map.count(k); }
InsertOrderedMap() = default;
InsertOrderedMap(const InsertOrderedMap& other) {
for (auto kv : other) {
insert(kv);
}
}
InsertOrderedMap& operator=(const InsertOrderedMap& other) {
if (this != &other) {
this->~InsertOrderedMap();
new (this) InsertOrderedMap<Key, T>(other);
}
return *this;
}
bool operator==(const InsertOrderedMap& other) {
return Map == other.Map && List == other.List;
}
bool operator!=(const InsertOrderedMap& other) { return !(*this == other); }
};
}
#endif