Gorgon Game Engine
Hashmap.h
Go to the documentation of this file.
1 
3 #pragma once
4 
5 #pragma warning(error: 4239)
6 
7 #include <map>
8 #include <stdexcept>
9 #include <algorithm>
10 #include <assert.h>
11 #include <tuple>
12 #include <sstream>
13 
14 #include "../Utils/Assert.h"
15 
16 #include "Iterator.h"
17 #include <Gorgon/TMP.h>
18 
19 namespace Gorgon {
20  namespace Containers {
21 
34  template<class K_, class T_, K_ (*KeyFn)(const T_&) = (K_(*)(const T_&))nullptr, template <class ...> class M_=std::map, class C_=std::less<K_>>
35  class Hashmap {
36  using MapType=M_<K_, T_*, C_, std::allocator<std::pair<const K_, T_*>>>;
37 
41  template <class I_, class H_>
42  class Iterator_ :
44  Iterator_<I_, H_>,
45  std::pair<const typename H_::KeyType, typename H_::ValueType &>
46  > {
47  typedef std::pair<const typename H_::KeyType, typename H_::ValueType &> Type;
49  friend class Hashmap;
50 
51  public:
53  Iterator_() {
54  }
56  Iterator_(const Iterator_ &it) : currentit(it.currentit), container(it.container) {
57  }
58 
63  void Remove() {
64  if(container==nullptr) {
65  throw std::runtime_error("Iterator is not valid.");
66  }
67 
68  currentit=container->mapping.erase(current());
69  }
70 
75  void Delete() {
76  if(container==nullptr) {
77  throw std::runtime_error("Iterator is not valid.");
78  }
79 
80  auto item=currentit->second;
81 
82  currentit=container->mapping.erase(currentit);
83  delete item;
84  }
85 
87  void SetItem(typename H_::ValueType &newitem, bool deleteprev=false) {
88  if(deleteprev) {
89  delete currentit->second;
90  }
91  currentit->second=&newitem;
92  }
93 
94  protected:
95  Iterator_(H_ &container, const I_ iterator) : currentit(iterator), container(&container) {
96  }
97 
98  protected:
101  Type current() const {
102  if(!isvalid())
103  throw std::out_of_range("Iterator is not valid.");
104 
105  return {currentit->first, *(currentit->second)};
106  }
107 
108  bool isvalid() const {
109  if(container==nullptr) return false;
110 
111  return currentit!=container->mapping.end();
112  }
113 
114  bool moveby(long amount) {
115  if(container==nullptr) return false;
116 
117  //sanity check
118  if(amount==0) return isvalid();
119 
120  if(amount>0) {
121  for(int i=0;i<amount;i++)
122  ++currentit;
123  }
124  else {
125  for(int i=amount;i<0;i++)
126  --currentit;
127  }
128 
129  return isvalid();
130  }
131 
132  bool compare(const Iterator_ &it) const {
133  return it.currentit==currentit;
134  }
135 
136  void set(const Iterator_ &it) {
137  currentit=it.currentit;
138  container=it.container;
139  }
140 
141  long distance(const Iterator_ &it) const {
142  return it.currentit-currentit;
143  }
144 
145  bool isbefore(const Iterator_ &it) const {
146  return currentit<it.currentit;
147  }
149 
150  public:
151 
153  Iterator_ &operator =(const Iterator_ &iterator) {
154  set(iterator);
155 
156  return *this;
157  }
158 
159  protected:
160  I_ currentit;
161  H_ *container = nullptr;
162  };
163 
164  template<class I_, class H_>
165  friend class Iterator_;
166 
167  public:
168  typedef T_ ValueType;
169  typedef K_ KeyType;
170 
172  typedef Iterator_<typename std::map<K_, T_*>::iterator, Hashmap> Iterator;
173 
175  class ConstIterator : public Iterator_<typename MapType::const_iterator, const Hashmap> {
176  friend class Hashmap;
177  public:
179  ConstIterator(const Iterator &it) {
180  this->currentit=it.currentit;
181  this->container=it.container;
182  }
183 
184  private:
185  ConstIterator(const Hashmap &h, const typename MapType::const_iterator it) :
186  Iterator_<typename MapType::const_iterator, const Hashmap>(h, it) {
187  }
188 
189  void Remove() {}
190  void Delete() {}
191  void SetKey(const K_ &newkey) {}
192  };
193 
194 
196  Hashmap() { }
197 
202  Hashmap(std::initializer_list<std::pair<const K_, T_*>> list) : mapping(list) {
203 #ifndef NDEBUG
204  for(auto &p : list) {
205  assert(p.second && "Element is nullptr");
206  }
207 #endif
208  }
209 
211  Hashmap(std::initializer_list<std::pair<const K_, T_&>> list) {
212  for(auto &p : list) {
213  mapping.insert(std::make_pair(p.first, &p.second));
214  }
215  }
216 
219  Hashmap(std::initializer_list<T_*> list) {
220  assert(KeyFn && "Key retrieval function should be set.");
221 
222  for(auto &p : list) {
223  if(p) {
224  mapping.insert(std::make_pair(KeyFn(*p), p));
225  }
226  }
227  }
228 
230  Hashmap(const Hashmap &) = delete;
231 
233  Hashmap(Hashmap &&other) {
234  Swap(other);
235  }
236 
237  Hashmap Duplicate() const {
238  Hashmap ret;
239  ret.mapping=mapping;
240 
241  return ret;
242  }
243 
245  void Swap(Hashmap &other) {
246  using std::swap;
247 
248  swap(mapping, other.mapping);
249  }
250 
252  Hashmap &operator= (const Hashmap &other) = delete;
253 
256  RemoveAll();
257  Swap(other);
258 
259  return *this;
260  }
261 
264  void Add(const K_ &key, T_ &obj, bool deleteprev = false) {
265  auto it = mapping.find(key);
266  if( it != mapping.end() ) {
267  if(deleteprev) {
268  delete it->second;
269  }
270  it->second = &obj;
271  }
272  else {
273  mapping.insert(std::make_pair(key, &obj));
274  }
275  }
276 
280  void Add(const K_ &key, T_ *obj, bool deleteprev = false) {
281  if(obj) {
282  auto it = mapping.find(key);
283  if( it != mapping.end() ) {
284  if(deleteprev) {
285  delete it->second;
286  }
287  it->second = obj;
288  }
289  else {
290  mapping.insert(std::make_pair(key, obj));
291  }
292  }
293  else {
294  auto it = mapping.find(key);
295  if( it != mapping.end() ) {
296  if(deleteprev) {
297  delete it->second;
298  }
299  mapping.erase(it);
300  }
301  }
302  }
303 
306  void Add(T_ &obj, bool deleteprev=false) {
307  assert(KeyFn!=nullptr && "Key retrieval function should be set.");
308 
309  Add(KeyFn(obj), obj, deleteprev);
310  }
311 
315  void Add(T_ *obj, bool deleteprev=false) {
316  assert(KeyFn!=nullptr && "Key retrieval function should be set.");
317 
318  if(obj)
319  Add(KeyFn(*obj), obj, deleteprev);
320  else
321  Add({}, obj, deleteprev);
322  }
323 
326  void Remove(const K_ &key) {
327  mapping.erase(key);
328  }
329 
332  void Delete(const K_ &key) {
333  auto it = mapping.find(key);
334  if(it!=mapping.end()) {
335  delete it->second;
336  mapping.erase(it);
337  }
338  }
339 
342  void RemoveAll() {
343  mapping.clear();
344  }
345 
348  void Collapse() {
349  decltype(mapping) newmap;
350 
351  using std::swap;
352  swap(mapping, newmap);
353  }
354 
355 
357  void DeleteAll() {
358  for(auto &p : mapping) {
359  delete p.second;
360  }
361 
362  mapping.clear();
363  }
364 
366  void Destroy() {
367  for(auto &p : mapping) {
368  delete p.second;
369  }
370 
371  Collapse();
372  }
373 
375  long GetCount() const {
376  return (long)mapping.size();
377  }
378 
380  long GetSize() const {
381  return (long)mapping.size();
382  }
383 
385  T_ &operator [](const K_ &key) const {
386  auto it = mapping.find(key);
387 
388  if(it == mapping.end()) {
389  properthrow(key);
390  }
391 
392  return *(it->second);
393  }
394 
396  bool Exists(const K_ &key) const {
397  return mapping.count(key)!=0;
398  }
399 
402  Iterator Find(const K_ &key) {
403  return Iterator(*this, mapping.find(key));
404  }
405 
408  ConstIterator Find(const K_ &key) const {
409  return ConstIterator(*this, mapping.find(key));
410  }
411 
416  return Iterator(*this, mapping.begin());
417  }
418 
421  return Iterator(*this, mapping.end());
422  }
423 
426  return Iterator(*this, mapping.begin());
427  }
428 
431  auto it = mapping.end();
432  if(mapping.size()>0)
433  --it;
434 
435  return Iterator(*this, it);
436  }
437 
439  ConstIterator begin() const {
440  return ConstIterator(*this, mapping.begin());
441  }
442 
444  ConstIterator end() const {
445  return ConstIterator(*this, mapping.end());
446  }
447 
449  ConstIterator First() const {
450  return ConstIterator(*this, mapping.begin());
451  }
452 
454  ConstIterator Last() const {
455  auto it = mapping.end();
456  if(mapping.size()>0)
457  --it;
458 
459  return ConstIterator(*this, it);
460  }
462 
463 
464 
465  private:
466 
467  template<class K__>
468  typename std::enable_if<TMP::IsStreamable<K__>::Value, void>::type properthrow(const K__ &key) const {
469  std::stringstream ss;
470  ss<<"Item not found: ";
471  ss<<key;
472 #ifdef TEST
473  ASSERT(false, ss.str(), 0, 8);
474 #endif
475  throw std::runtime_error(ss.str());
476  }
477 
478  template<class K__>
479  typename std::enable_if<!TMP::IsStreamable<K__>::Value, void>::type properthrow(const K__ &key) const {
480 #ifdef TEST
481  ASSERT(false, "Item not found", 0, 8);
482 #endif
483  throw std::runtime_error("Item not found");
484  }
485 
486  MapType mapping;
487  };
488 
489  template<class K_, class T_, K_ (KeyFn)(const T_&)=nullptr, template <class ...> class M_=std::map, class C_=std::less<K_>>
491  left.Swap(right);
492  }
493 
494  }
495 }
Gorgon::Containers::Hashmap::DeleteAll
void DeleteAll()
Deletes and removes all the elements of this map.
Definition: Hashmap.h:357
Gorgon::Containers::Remove
void Remove(const I_ &first, const I_ &end)
This function works with collection iterators.
Definition: Iterator.h:386
Gorgon::Containers::Hashmap::Hashmap
Hashmap(Hashmap &&other)
Move constructor.
Definition: Hashmap.h:233
Gorgon::Containers::Hashmap::RemoveAll
void RemoveAll()
Removes all elements from this mapping without deleting them.
Definition: Hashmap.h:342
Gorgon::Containers::Hashmap::ConstIterator::ConstIterator
ConstIterator(const Iterator &it)
Regular iterators can be converted to const iterators.
Definition: Hashmap.h:179
Gorgon::Containers::swap
void swap(Collection< T_ > &l, Collection< T_ > &r)
Swaps two collections.
Definition: Collection.h:707
Gorgon::Containers::Hashmap
This class is a reference based hashmap.
Definition: Hashmap.h:35
Gorgon::Containers::Hashmap::GetCount
long GetCount() const
Returns the number of elements in the map.
Definition: Hashmap.h:375
Gorgon::Containers::Hashmap::Add
void Add(T_ *obj, bool deleteprev=false)
Adds the given item by retrieving the related key.
Definition: Hashmap.h:315
Gorgon::Containers::Hashmap::Last
Iterator Last()
returns the iterator to the last item
Definition: Hashmap.h:430
Gorgon::Containers::Hashmap::KeyType
K_ KeyType
Definition: Hashmap.h:169
Gorgon::Containers::Hashmap::begin
ConstIterator begin() const
begin iterator
Definition: Hashmap.h:439
Gorgon::Containers::Hashmap::Add
void Add(const K_ &key, T_ &obj, bool deleteprev=false)
Adds the given item with the related key.
Definition: Hashmap.h:264
TMP.h
This file contains template metaprogramming methods and classes used throughout Gorgon Library.
Gorgon::Containers::ValueIterator
Generic iterator interface.
Definition: Iterator.h:219
Gorgon::Containers::Hashmap::Delete
void Delete(const K_ &key)
Removes the item with the given key from the mapping and deletes it.
Definition: Hashmap.h:332
Gorgon::Containers::Hashmap::Destroy
void Destroy()
Deletes and removes all the elements of this map, in addition to destroying data used.
Definition: Hashmap.h:366
Gorgon::Containers::Hashmap::Swap
void Swap(Hashmap &other)
Swaps two hashmaps.
Definition: Hashmap.h:245
Gorgon::Containers::Hashmap::First
ConstIterator First() const
returns the iterator to the first item
Definition: Hashmap.h:449
Gorgon::Containers::Hashmap::Iterator
Iterator_< typename std::map< K_, T_ * >::iterator, Hashmap > Iterator
Regular iterator.
Definition: Hashmap.h:172
Gorgon
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
Gorgon::Containers::Hashmap::Add
void Add(T_ &obj, bool deleteprev=false)
Adds the given item by retrieving the related key.
Definition: Hashmap.h:306
Gorgon::Containers::Hashmap::end
Iterator end()
end iterator
Definition: Hashmap.h:420
ASSERT
#define ASSERT(expression, message,...)
Replaces regular assert to allow messages and backtrace.
Definition: Assert.h:161
Gorgon::Containers::Hashmap::Add
void Add(const K_ &key, T_ *obj, bool deleteprev=false)
Adds the given item with the related key.
Definition: Hashmap.h:280
Iterator.h
contains filesystem Iterator. Lists file and directories.
Gorgon::Containers::Hashmap::GetSize
long GetSize() const
Returns the number of elements in the map.
Definition: Hashmap.h:380
Gorgon::Input::Keyboard::Keycodes::Delete
constexpr Key Delete
Definition: Keyboard.h:43
Gorgon::Containers::Hashmap::Remove
void Remove(const K_ &key)
Removes the item with the given key from the mapping.
Definition: Hashmap.h:326
Gorgon::Containers::Hashmap::begin
Iterator begin()
Definition: Hashmap.h:415
Gorgon::Containers::Hashmap::Duplicate
Hashmap Duplicate() const
Definition: Hashmap.h:237
Gorgon::GL::UBOBindingPoint::Type
Type
Definition: Shader.h:14
Gorgon::Containers::Hashmap::Hashmap
Hashmap(const Hashmap &)=delete
Copy constructor is disabled.
Gorgon::Containers::Hashmap::Last
ConstIterator Last() const
returns the iterator to the last item
Definition: Hashmap.h:454
Gorgon::Containers::Hashmap::Hashmap
Hashmap(std::initializer_list< T_ * > list)
Filling constructor that takes the keys using KeyFn function.
Definition: Hashmap.h:219
Gorgon::Containers::Hashmap::Hashmap
Hashmap(std::initializer_list< std::pair< const K_, T_ & >> list)
Filling constructor. This constructor uses initializer list of std::pair<K_, T_&>
Definition: Hashmap.h:211
Gorgon::Containers::Hashmap::ConstIterator
Const iterator allows iteration of const collections.
Definition: Hashmap.h:175
Gorgon::Containers::Hashmap::end
ConstIterator end() const
end iterator
Definition: Hashmap.h:444
Gorgon::Containers::Hashmap::Find
ConstIterator Find(const K_ &key) const
Finds the given key in the hashmap and returns iterator for it.
Definition: Hashmap.h:408
Gorgon::Containers::Hashmap::First
Iterator First()
returns the iterator to the first item
Definition: Hashmap.h:425
Gorgon::Containers::Hashmap::ValueType
T_ ValueType
Definition: Hashmap.h:168
Gorgon::Containers::Hashmap::operator[]
T_ & operator[](const K_ &key) const
If not found throws.
Definition: Hashmap.h:385
Gorgon::Scripting::ValueType
ValueType
Possible value types.
Definition: Instruction.h:61
Gorgon::Containers::Hashmap::operator=
Hashmap & operator=(const Hashmap &other)=delete
Copy constructor is disabled.
Gorgon::Containers::Hashmap::Collapse
void Collapse()
Clears the contents of the map and releases the memory used for the list.
Definition: Hashmap.h:348
Gorgon::Containers::Hashmap::Find
Iterator Find(const K_ &key)
Finds the given key in the hashmap and returns iterator for it.
Definition: Hashmap.h:402
Gorgon::Containers::Hashmap::Hashmap
Hashmap()
Default constructor.
Definition: Hashmap.h:196
Gorgon::Containers::Hashmap::Hashmap
Hashmap(std::initializer_list< std::pair< const K_, T_ * >> list)
Filling constructor.
Definition: Hashmap.h:202
Gorgon::Containers::Hashmap::Exists
bool Exists(const K_ &key) const
Checks if an element with the given key exists.
Definition: Hashmap.h:396
Gorgon::Containers::Hashmap::Iterator_
friend class Iterator_
Definition: Hashmap.h:165
Gorgon::Containers::swap
void swap(Hashmap< K_, T_, KeyFn, M_, C_ > &left, Hashmap< K_, T_, KeyFn, M_, C_ > &right)
Definition: Hashmap.h:490