Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
RegisteredMultiArray.h
Go to the documentation of this file.
1
31#pragma once
32
33
34#include <ogdf/basic/basic.h>
36
37#include <cstddef>
38#include <cstdint>
39#include <stdexcept>
40#include <tuple>
41#include <unordered_map>
42#include <utility>
43
44namespace ogdf {
45
47
51template<typename Key2, typename Value, int array_max>
53 using ValuePairType = std::pair<Key2, Value>;
54 using ValueArrayType = std::array<ValuePairType, array_max>;
55 using ValueMapType = std::unordered_map<Key2, Value>;
56
57 uint8_t m_size = 0;
58 void* m_value = nullptr;
59
60
61 UsuallySmallMap() = default;
62
64 if (m_value != nullptr) {
65 if (m_size <= 0) {
66 delete (ValueMapType*)m_value;
67 } else if (m_size == 1) {
68 delete (ValuePairType*)m_value;
69 } else {
70 delete (ValueArrayType*)m_value;
71 }
72 }
73 }
74
76 if (copy.m_value == nullptr) {
77 m_value = nullptr;
78 } else if (m_size <= 0) {
79 m_value = new ValueMapType(copy.getValueMap());
80 } else if (m_size == 1) {
82 } else {
84 }
85 }
86
88
90 using std::swap;
91 swap(first.m_size, second.m_size);
92 swap(first.m_value, second.m_value);
93 }
94
95 void unset(const Key2& key) {
96 if (!contains(key)) {
97 return;
98 }
99 if (m_size <= 0) {
100 ValueMapType& map = getValueMap();
101 int cnt = map.erase(key);
102 OGDF_ASSERT(cnt == 1);
103 } else if (m_size == 1) {
104 delete (ValuePairType*)m_value;
105 m_value = nullptr;
106 m_size = 0;
107 } else {
108 ValueArrayType& array = getValueArray();
109 for (int i = 0; i < m_size; ++i) {
110 if (array[i].first == key) {
111 if (i != m_size - 1) {
112 using std::swap;
113 swap(array[i], array[m_size - 1]);
114 }
115 m_size--;
116 break;
117 }
118 }
119 }
120 }
121
122 Value& get_or_create(const Key2& key, const Value& def = Value()) {
123 if (m_value == nullptr) {
124 // create scalar value
125 m_size = 1;
126 ValuePairType* pair = new ValuePairType(key, def);
127 m_value = pair;
128 return pair->second;
129 } else if (m_size <= 0) {
130 ValueMapType& map = getValueMap();
131 auto it = map.find(key);
132 if (it != map.end()) {
133 return it->second;
134 }
135
136 // insert into map
137 auto ins = map.insert({key, def});
138 OGDF_ASSERT(ins.second);
139 return ins.first->second;
140 } else if (m_size == 1) {
142 if (pair.first == key) {
143 return pair.second;
144 }
145
146 // convert to array
147 m_size = 2;
148 ValueArrayType* array = new ValueArrayType {std::move(pair), ValuePairType(key, def)};
149 delete (ValuePairType*)m_value;
150 m_value = array;
151 return (*array)[1].second;
152 } else {
153 ValueArrayType& array = getValueArray();
154 for (int i = 0; i < m_size; ++i) {
155 if (array[i].first == key) {
156 return array[i].second;
157 }
158 }
159
160 if (m_size < array_max) {
161 // insert into array
162 int i = m_size;
163 m_size++;
164 array[i] = ValuePairType(key, def);
165 return array[i].second;
166 } else {
167 // convert to map
168 ValueMapType* map = new ValueMapType();
169 for (int i = 0; i < array_max; ++i) {
170 map->insert(std::move(array[i]));
171 }
172 delete (ValueArrayType*)m_value;
173 m_value = map;
174 m_size = 0;
175 return get_or_create(key);
176 }
177 }
178 }
179
180 Value& get_or_raise(const Key2& key) const {
181 if (m_value == nullptr) {
182 throw std::out_of_range("no keys stored");
183 } else if (m_size <= 0) {
184 ValueMapType& map = getValueMap();
185 auto it = map.find(key);
186 if (it == map.end()) {
187 throw std::out_of_range("key not in map");
188 }
189 return it->second;
190 } else if (m_size == 1) {
192 if (pair.first == key) {
193 return pair.second;
194 } else {
195 throw std::out_of_range("key not in scalar");
196 }
197 } else {
198 ValueArrayType& array = getValueArray();
199 for (int i = 0; i < m_size; ++i) {
200 if (array[i].first == key) {
201 return array[i].second;
202 }
203 }
204 throw std::out_of_range("key not in array");
205 }
206 }
207
208 bool contains(const Key2& key) const {
209 if (m_value == nullptr) {
210 return false;
211 } else if (m_size <= 0) {
212 return getValueMap().count(key);
213 } else if (m_size == 1) {
214 return getValueScalar().first == key;
215 } else {
216 ValueArrayType& array = getValueArray();
217 for (int i = 0; i < m_size; ++i) {
218 if (array[i].first == key) {
219 return true;
220 }
221 }
222 return false;
223 }
224 }
225
226 bool empty() const { return m_value == nullptr; }
227
228 size_t size() const {
229 if (m_value == nullptr) {
230 return 0;
231 } else if (m_size > 0) {
232 return m_size;
233 } else {
234 return getValueMap().size();
235 }
236 }
237
238 bool usesMap() const { return m_size == 0 && m_value != nullptr; }
239
241 OGDF_ASSERT(m_size == 1);
242 OGDF_ASSERT(m_value != nullptr);
243 return *((ValuePairType*)m_value);
244 }
245
247 OGDF_ASSERT(m_size > 1);
248 OGDF_ASSERT(m_value != nullptr);
249 return *((ValueArrayType*)m_value);
250 }
251
253 OGDF_ASSERT(m_size == 0);
254 OGDF_ASSERT(m_value != nullptr);
255 return *((ValueMapType*)m_value);
256 }
257};
258
259template<typename Key1, typename Key2, typename Value, template<typename...> class BaseArray,
260 int array_max = 64>
262
270public:
272
274
277
278 template<class... T>
279 explicit RegisteredMultiArray(T&&... t) : m_array(std::forward<T>(t)...) {};
280
281 Value& operator()(const Key1& k1, const Key2& k2) { return m_array[k1].get_or_create(k2); }
282
283 Value& get_or_create(const Key1& k1, const Key2& k2) { return m_array[k1].get_or_create(k2); }
284
285 Value& get_or_raise(const Key1& k1, const Key2& k2) { return m_array[k1].get_or_raise(k2); }
286
287 const Value& get_or_raise(const Key1& k1, const Key2& k2) const {
288 return m_array[k1].get_or_raise(k2);
289 }
290
291 EntryType& get_all(const Key1& k1) { return m_array[k1]; }
292
293 const EntryType& get_all(const Key1& k1) const { return m_array[k1]; }
294
295 void remove(const Key1& k1, const Key2& k2) { return m_array[k1].unset(k2); }
296
297 bool contains(const Key1& k1, const Key2& k2) const { return m_array[k1].contains(k2); }
298
299 size_t count(const Key1& k1) const { return m_array[k1].size(k1); }
300
301 bool has(const Key1& k1) const { return !m_array[k1].empty(k1); }
302
303private:
304 BaseArray<EntryType> m_array;
305};
306
307}
Basic declarations, included by all source files.
Data structure for two-dimensional mappings that are sparse in the second dimension.
const Value & get_or_raise(const Key1 &k1, const Key2 &k2) const
Value & get_or_create(const Key1 &k1, const Key2 &k2)
Value & get_or_raise(const Key1 &k1, const Key2 &k2)
Value & operator()(const Key1 &k1, const Key2 &k2)
size_t count(const Key1 &k1) const
bool contains(const Key1 &k1, const Key2 &k2) const
const EntryType & get_all(const Key1 &k1) const
bool has(const Key1 &k1) const
EntryType & get_all(const Key1 &k1)
BaseArray< EntryType > m_array
void remove(const Key1 &k1, const Key2 &k2)
Utility macros for declaring copy and move constructors and assignment operations.
#define OGDF_DEFAULT_MOVE(cls)
Explicitly provides default move construction and assignment for class cls.
Definition copy_move.h:52
#define OGDF_DEFAULT_COPY(cls)
Explicitly provides default copy construction and assignment for class cls.
Definition copy_move.h:47
#define OGDF_SWAP_OP(cls)
Declares the swap function for class cls.
Definition copy_move.h:65
#define OGDF_COPY_MOVE_BY_SWAP(cls)
Provide move construct/assign and copy assign given there is a copy constructor and swap.
Definition copy_move.h:76
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.
Definition GML.h:111
A wrapper around std::map that uses a constant-size array (or only a single value) plus linear search...
ValueMapType & getValueMap() const
bool contains(const Key2 &key) const
ValuePairType & getValueScalar() const
UsuallySmallMap(const UsuallySmallMap &copy)
std::unordered_map< Key2, Value > ValueMapType
Value & get_or_create(const Key2 &key, const Value &def=Value())
Value & get_or_raise(const Key2 &key) const
std::pair< Key2, Value > ValuePairType
void unset(const Key2 &key)
std::array< ValuePairType, array_max > ValueArrayType
friend void swap(UsuallySmallMap &first, UsuallySmallMap &second) noexcept
ValueArrayType & getValueArray() const