dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
ScopedUnorderedMap.hpp
1
11#pragma once
12
13#include <functional>
14#include <iostream>
15#include <memory>
16#include <tuple>
17#include <unordered_map>
18#include <utility>
19#include <vector>
20
21namespace dlinear {
22
23template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
24 class Allocator = std::allocator<std::pair<const Key, T>>>
25
27 public:
28 // Aliases.
29 using UnorderedMapType = std::unordered_map<Key, T, Hash, KeyEqual, Allocator>;
30 using value_type = typename UnorderedMapType::value_type;
31 using size_type = typename UnorderedMapType::size_type;
32 using const_iterator = typename UnorderedMapType::const_iterator;
33
37 enum class ActionKind {
38 INSERT,
39 UPDATE,
40 };
41 using Action = std::tuple<ActionKind, Key, T>;
42
43 ScopedUnorderedMap() = default;
44 ScopedUnorderedMap(const ScopedUnorderedMap &) = default;
45 ScopedUnorderedMap(ScopedUnorderedMap &&) noexcept = default;
46 ScopedUnorderedMap &operator=(const ScopedUnorderedMap &) = default;
47 ScopedUnorderedMap &operator=(ScopedUnorderedMap &&) noexcept = default;
48 ~ScopedUnorderedMap() = default;
49
50 // Iterators.
51 //
52 // @note We only provide 'const' iterators because any modification
53 // should be done explicitly via its APIs so that we can keep track
54 // of changes and undo when pop() is called.
55 const_iterator begin() const { return map_.begin(); }
56 const_iterator cbegin() const { return map_.cbegin(); }
57 const_iterator end() const { return map_.end(); }
58 const_iterator cend() const { return map_.cend(); }
59
60 [[nodiscard]] bool empty() const { return map_.empty(); }
61 size_type size() const { return map_.size(); }
62
64 void clear() {
65 map_.clear();
66 actions_.clear();
67 stack_.clear();
68 }
69
75 void insert(const Key &k, const T &v) {
76 auto it = map_.find(k);
77 if (it == map_.end()) {
78 // Case 1) k does not exist.
79 actions_.emplace_back(ActionKind::INSERT, k, v);
80 map_.emplace(k, v);
81 } else {
82 // Case 2) k exists. Save the old value so that we can roll
83 // back later.
84 actions_.emplace_back(ActionKind::UPDATE, k, it->second);
85 it->second = v; // Perform Update.
86 }
87 }
88
95 const T &operator[](const Key &key) const {
96 const auto it = map_.find(key);
97 if (it == map_.end()) {
98 throw std::runtime_error("ScopedUnorderedMap has no entry for the key {}" + std::to_string(key));
99 }
100 return it->second;
101 }
102
109 const T &at(const Key &key) const { return map_.at(key); }
110
111 size_type count(const Key &key) const { return map_.count(key); }
112 // @note It returns 'const' iterator.
113 const_iterator find(const Key &key) const { return map_.find(key); }
114
115 // Push/Pop
116 void push() { stack_.push_back(actions_.size()); }
117 void pop() {
118 if (stack_.empty()) {
119 throw std::runtime_error("ScopedUnorderedMap cannot be popped because it's scope is empty.");
120 }
121 size_type idx = stack_.back();
122 while (idx < actions_.size()) {
123 const Action &item{actions_.back()};
124 const ActionKind kind{std::get<0>(item)};
125 const Key &k{std::get<1>(item)};
126 const T &v{std::get<2>(item)};
127 auto it = map_.find(k);
128 switch (kind) {
130 // Remove (k, v).
131 map_.erase(it);
132 break;
134 // Roll back to map_[k] = v.
135 it->second = v;
136 break;
137 }
138 actions_.pop_back();
139 }
140 stack_.pop_back();
141 }
142
143 private:
144 std::vector<Action> actions_;
145 std::vector<size_type> stack_;
146 UnorderedMapType map_;
147};
148
149} // namespace dlinear
ActionKind
Action to perform on the scoped unordered map.
@ UPDATE
Update(k, v) means that (k, v) was replaced by a new value.
@ INSERT
Insert(k, v) means that (k, v) is inserted.
std::vector< Action > actions_
Vector of actions that have been applied.
const T & operator[](const Key &key) const
Lookup the value for the given key.
UnorderedMapType map_
Actual map.
const T & at(const Key &key) const
Lookup the value for the given key.
void insert(const Key &k, const T &v)
Insert a new key-value pair.
Global namespace for the dlinear library.