Dynalib Utils
DynaHashMapImpl.h
Go to the documentation of this file.
1 //
2 // Created by Ken Kopelson on 20/10/17.
3 //
4 
5 #ifndef DYNAHASHMAPIMPL_H
6 #define DYNAHASHMAPIMPL_H
7 #include <iostream>
8 #include <type_traits>
9 using namespace std;
10 #include "BitManip.h"
11 #include "DynaAllocImpl.h"
12 #include "DynaHashMap.h"
13 #include "CheckForError.h"
14 //#include "SharedGlobals.h"
15 
16 #define MAKE_MAPTYPE_INSTANCE(K, V, T) \
17  template class DynaHashMap<K,V>; \
18  typedef DynaHashMap<K,V> T##Map
19 
20 //===========================================================================
21 // Static Methods
22 //===========================================================================
23 
24 //===========================================================================
25 // Private/Protected Methods
26 //===========================================================================
27 template <typename K, typename V> void DynaHashMap<K,V>::_init(int size) {
28  _table = new MapEntry<K,V>*[size];
29  memset((void*)_table, 0, size * sizeof(MapEntry<K,V>*));
30 }
31 
32 template <typename K, typename V> int DynaHashMap<K,V>::_getHashCode(const K* key) const {
33  int hash = 0;
34  try {
35  hash = key->hashCode();
36  }
37  catch (Exception& e) {
38  hash = 0;
39  }
40  return hash;
41 }
42 
43 template <typename K, typename V> void DynaHashMap<K,V>::_reHash(int newCapacity) {
44  int oldCapacity = _capacity;
45  auto** newTable = new MapEntry<K,V>*[newCapacity];
46  memset((void*)newTable, 0, newCapacity * sizeof(MapEntry<K,V>*));
47  for (int idx = 0; idx < oldCapacity; ++idx) {
48  MapEntry<K,V>* obj = _table[idx];
49  if (obj == nullptr || obj == deletedObject)
50  continue;
51  int hash = _getHashCode(obj->getKey());
52  int index = ( hash & 0x7FFFFFF ) % newCapacity;
53  int offset = 1;
54  while (newTable[index] != nullptr) {
55  index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
56  offset = offset * 2 + 1;
57  if (offset == -1)
58  offset = 2;
59  }
60  newTable[index] = obj;
61  _table[idx] = nullptr;
62  }
63  delete[] _table;
64  _table = newTable;
65  _capacity = newCapacity;
66  _freeCells = newCapacity - _count;
67 }
68 
69 //===========================================================================
70 // Constructors/Destructor
71 //===========================================================================
79 template <typename K, typename V> MapEntry<K,V>::MapEntry(K* key, V* value, bool ownsValue) :
80  _key(key), _value(value), _ownsValue(ownsValue) {
81 }
82 
83 template <typename K, typename V> MapEntry<K,V>::MapEntry(const MapEntry<K,V>& entry) {
84  _key = (entry._key)->copy();
85  _ownsValue = entry._ownsValue;
86  if (entry._value != nullptr) {
87  try {
88  _value = _ownsValue ? (V*)(entry._value)->copy() : entry._value;
89  }
90  catch (Exception& e) {
91  _value = entry._value;
92  _ownsValue = false;
93  }
94  }
95 }
96 
97 template <typename K, typename V> MapEntry<K,V>::~MapEntry() {
98  if (_key != DynaHashMap<K,V>::nullObject) {
99  delete _key;
100  _key = nullptr;
101  }
102  if (_ownsValue) {
103  delete _value;
104  _value = nullptr;
105  }
106 }
107 
108 template <typename K, typename V> MapEntry<K,V>* MapEntry<K,V>::copy() {
109  return new MapEntry<K,V>(*this);
110 };
111 
112 
118 template <typename K, typename V> DynaHashMap<K,V>::DynaHashMap() :
119  _count(0), _capacity(INITIAL_SIZE), _freeCells(INITIAL_SIZE), _modCount(0), _ownsMembers(true) {
121 }
122 
123 template <typename K, typename V> DynaHashMap<K,V>::DynaHashMap(int size) :
124  _count(0), _capacity(size), _freeCells(size), _modCount(0), _ownsMembers(true) {
125  _init(size);
126 }
127 
128 template <typename K, typename V> DynaHashMap<K,V>::~DynaHashMap() {
129  clear();
130  delete[] _table;
131 }
132 
133 template <typename K, typename V> DynaHashMap<K,V>::DynaHashMap(const DynaHashMap<K,V>& other) {
134  MapEntry<K,V>* entry;
135  _count = other._count;
136  _capacity = other._capacity;
137  _modCount = other._modCount;
138  _freeCells = other._freeCells;
139  _ownsMembers = other._ownsMembers;
140  _table = new MapEntry<K,V>*[other._capacity];
141  for (int i = 0, len = other._capacity; i < len; ++i) {
142  entry = other._table[i];
143  if (entry != nullptr) {
144  try {
145  _table[i] = entry->copy();
146  }
147  catch (Exception& e) {
148  }
149  }
150  }
151 }
152 
153 template <typename K, typename V> DynaHashMap<K,V>* DynaHashMap<K,V>::copy() {
154  return new DynaHashMap<K,V>(*this);
155 };
156 
157 template <typename K, typename V> MapKeyIter<K,V>::MapKeyIter(const DynaHashMap<K,V>* map, int start) : _curIndex(start), _map(map) {
158  MapEntry<K,V>** table = _map->_table;
159  for (; hasNext() && (table[_curIndex] == nullptr || table[_curIndex] == _map->deletedObject); ++_curIndex);
160 }
161 
162 template <typename K, typename V> MapValueIter<K,V>::MapValueIter(const DynaHashMap<K,V>* map, int start) : _curIndex(start), _map(map) {
163  MapEntry<K,V>** table = _map->_table;
164  for (; hasNext() && (table[_curIndex] == nullptr || table[_curIndex] == _map->deletedObject); ++_curIndex);
165 }
166 
167 template <typename K, typename V> int DynaHashMap<K,V>::_getTableIndex(K* key) {
168  if (key == nullptr)
169  key = nullObject;
170  int hash = _getHashCode(key);
171  int index = ( hash & 0x7FFFFFF ) % _capacity;
172  int offset = 1;
173 
174  MapEntry<K,V>* entry = _table[index];
175  while (entry != nullptr &&
176  (entry == deletedObject || !((_getHashCode(entry->getKey()) == hash) && (*(entry->getKey()) == *key)))) {
177  index = ((index + offset) & 0x7FFFFFFF) % _capacity;
178  entry = _table[index];
179  offset = offset * 2 + 1;
180  if (offset == -1)
181  offset = 2;
182  }
183  return index;
184 }
185 
186 //===========================================================================
187 // Public Methods
188 //===========================================================================
196 template <typename K, typename V> const V* MapEntry<K,V>::setValue(V* newValue) {
197  V* oldValue = _value;
198  _value = newValue;
199  return oldValue;
200 }
201 template <typename K, typename V> bool MapEntry<K,V>::operator== (const MapEntry<K,V>& other) const {
202  K* k1 = getKey();
203  K* k2 = other.getKey();
204  if (k1 == k2 || (k1 != nullptr && k1 != DynaHashMap<K,V>::nullObject && *k1 == *k2)) {
205  V* v1 = getValue();
206  V* v2 = other.getValue();
207  if (v1 == v2 || (v1 != nullptr && *v1 == *v2))
208  return true;
209  }
210  return false;
211 }
212 
220 template <typename K, typename V> MapEntry<K,V>* DynaHashMap<K,V>::getEntry(K* key) {
221  int index = _getTableIndex(key);
222  return _table[index];
223 };
224 
225 template <typename K, typename V> MapEntry<K, V>* DynaHashMap<K,V>::getEntry(K key) {
226  return getEntry(&key);
227 }
228 
229 template <typename K, typename V> V* DynaHashMap<K,V>::get(K* key) {
230  MapEntry<K,V>* entry = getEntry(key);
231  return entry != nullptr ? entry->getValue() : nullptr;
232 }
233 
234 template <typename K, typename V> V* DynaHashMap<K,V>::get(K key) {
235  return get(&key);
236 }
237 
238 template <typename K, typename V> V* DynaHashMap<K,V>::put(K* key, V* value) {
239  if (key == nullptr)
240  key = nullObject;
241  int hash = _getHashCode(key);
242  int index = ( hash & 0x7FFFFFF ) % _capacity;
243  int offset = 1;
244  int deletedIdx = -1;
245 
246  MapEntry<K,V>* entry = _table[index];
247  while ( entry != nullptr &&
248  (entry == deletedObject || !((_getHashCode(entry->getKey()) == hash) && (*(entry->getKey()) == *key)))) {
249  if (entry == deletedObject)
250  deletedIdx = index;
251 
252  index = ((index + offset) & 0x7FFFFFFF) % _capacity;
253  entry = _table[index];
254  offset = offset * 2 + 1;
255  if (offset == -1)
256  offset = 2;
257  }
258 
259  V* oldValue = nullptr;
260  if (entry == nullptr) {
261  if (deletedIdx != -1)
262  index = deletedIdx;
263  else
264  --_freeCells;
265  ++_modCount;
266  ++_count;
267  _table[index] = new MapEntry<K,V>(key, value, _ownsMembers);
268 
269  if (1 - (_freeCells / (double)_capacity) > LOAD_FACTOR) {
270  _reHash(_capacity);
271  if (1 - (_freeCells / (double)_capacity) > LOAD_FACTOR) {
272  _reHash(_capacity * 2 + 1);
273  }
274  }
275  }
276  else {
277  oldValue = _table[index]->getValue();
278  _table[index]->setValue(value);
279  delete key; // Delete the key that was passed in, since it was not added to the map
280  }
281  return oldValue;
282 }
283 
284 template <typename K, typename V> V* DynaHashMap<K,V>::put(K key, V* value) {
285  return put(new K(key), value);
286 }
287 
288 template <typename K, typename V> V* DynaHashMap<K,V>::remove(K* key) {
289  int index = _getTableIndex(key);
290 
291  if (_table[index] != nullptr && _table[index] != deletedObject) {
292  V* saveValue = _table[index]->getValue();
293  _table[index]->setValue(nullptr); // Prevent the value object from being deleted
294  delete _table[index]; // delete the entry from the table
295  _table[index] = deletedObject; // Mark the table entry as deleted
296  ++_modCount;
297  --_count;
298  return saveValue;
299  }
300  else
301  return nullptr;
302 }
303 
304 template <typename K, typename V> V* DynaHashMap<K,V>::remove(K key) {
305  return remove(&key);
306 }
307 
308 template <typename K, typename V> void DynaHashMap<K,V>::deleteEntry(K* key) {
309  int index = _getTableIndex(key);
310 
311  if (_table[index] != nullptr && _table[index] != deletedObject) {
312  delete _table[index]; // delete the entry from the table
313  _table[index] = deletedObject; // Mark the table entry as deleted
314  ++_modCount;
315  --_count;
316  }
317 }
318 
319 template <typename K, typename V> void DynaHashMap<K,V>::deleteEntry(K key) {
320  return deleteEntry(&key);
321 };
322 
323 template <typename K, typename V> MapEntry<K, V>* DynaHashMap<K,V>::removeEntry(MapEntry<K,V>* ent) {
324  if (ent == nullptr)
325  return nullptr;
326  int index = _getTableIndex(ent->getKey());
327 
328  if (_table[index] != nullptr && _table[index] != deletedObject) {
329  MapEntry<K,V>* saveEntry = _table[index];
330  _table[index] = deletedObject;
331  ++_modCount;
332  --_count;
333  return saveEntry;
334  }
335  else
336  return nullptr;
337 }
338 
339 template <typename K, typename V> void DynaHashMap<K,V>::clear() {
340  for (int idx = 0; idx < _capacity; ++idx) {
341  MapEntry<K,V>* entry = _table[idx];
342  if (entry != nullptr) {
343  if (entry != DynaHashMap<K,V>::deletedObject) {
344  delete entry;
345  --_count;
346  }
347  _table[idx] = nullptr;
348  }
349  }
350  _count = 0;
351  _freeCells = _capacity;
352  ++_modCount;
353 }
354 
355 template <typename K, typename V> DynaMapIter<K,V> DynaHashMap<K,V>::begin() {
356  return DynaMapIter<K,V>( this, 0 );
357 }
358 
359 template <typename K, typename V> DynaMapIter<K,V> DynaHashMap<K,V>::end() {
360  return DynaMapIter<K,V>( this, _capacity );
361 }
362 
363 template <typename K, typename V> MapKeyIter<K,V> DynaHashMap<K,V>::keys() {
364  return MapKeyIter<K,V>(this);
365 };
366 
367 template <typename K, typename V> MapValueIter<K,V> DynaHashMap<K,V>::values() {
368  return MapValueIter<K,V>(this);
369 };
370 
371 template <typename K, typename V> const MapKeyIter<K,V>& MapKeyIter<K,V>::operator++ () {
372  MapEntry<K,V>** table = _map->_table;
373  for (++_curIndex; hasNext() &&
374  (table[_curIndex] == nullptr || table[_curIndex] == _map->deletedObject); ++_curIndex);
375  return *this;
376 }
377 
378 template <typename K, typename V> const MapKeyIter<K,V>& MapKeyIter<K,V>::operator-- () {
379  MapEntry<K,V>** table = _map->_table;
380  for (--_curIndex; hasPrev() &&
381  (table[_curIndex] == nullptr || table[_curIndex] == _map->deletedObject); --_curIndex);
382  return *this;
383 }
384 
385 template <typename K, typename V> const MapValueIter<K,V>& MapValueIter<K,V>::operator++ () {
386  MapEntry<K,V>** table = _map->_table;
387  for (++_curIndex; hasNext() &&
388  (table[_curIndex] == nullptr || table[_curIndex] == _map->deletedObject); ++_curIndex);
389  return *this;
390 }
391 
392 template <typename K, typename V> const MapValueIter<K,V>& MapValueIter<K,V>::operator-- () {
393  MapEntry<K,V>** table = _map->_table;
394  for (--_curIndex; hasPrev() &&
395  (table[_curIndex] == nullptr || table[_curIndex] == _map->deletedObject); --_curIndex);
396  return *this;
397 }
398 
399 //===========================================================================
400 // Static Initialization
401 //===========================================================================
402 // template <typename K, typename V> MapObject<K> DynaHashMap<K,V>::nullObjectInstance = MapObject<K>();
403 // template <typename K, typename V> K* DynaHashMap<K,V>::nullObject = (K*)(void*)(&DynaHashMap<K,V>::nullObjectInstance);
404 
405 template <typename K, typename V> K DynaHashMap<K,V>::nullObjectInstance;
406 template <typename K, typename V> K* DynaHashMap<K,V>::nullObject = &nullObjectInstance;
407 
408 
409 template <typename K, typename V> MapEntry<K,V> DynaHashMap<K,V>::deletedObjectInstance = MapEntry<K,V>(DynaHashMap<K,V>::nullObject, nullptr, false);
410 template <typename K, typename V> MapEntry<K,V>* DynaHashMap<K,V>::deletedObject = &deletedObjectInstance;
411 
412 #endif //DYNAHASHMAPIMPL_H
int _getTableIndex(K *key)
Definition: DynaHashMapImpl.h:167
Definition: DynaHashMap.h:26
bool _ownsMembers
Definition: DynaHashMap.h:92
MapKeyIter< K, V > keys()
Definition: DynaHashMapImpl.h:363
bool hasNext()
Definition: DynaHashMap.h:196
GeneratorWrapper< std::tuple< Ts... > > table(std::initializer_list< std::tuple< typename std::decay< Ts >::type... >> tuples)
Definition: catch.hpp:4058
const MapKeyIter< K, V > & operator++()
Definition: DynaHashMapImpl.h:371
bool hasPrev()
Definition: DynaHashMap.h:238
K * getKey() const
Definition: DynaHashMap.h:37
bool hasNext()
Definition: DynaHashMap.h:237
DynaHashMap< K, V > * copy() override
Definition: DynaHashMapImpl.h:153
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4005
MapValueIter(const DynaHashMap< K, V > *map, int start)
Definition: DynaHashMapImpl.h:162
const MapKeyIter< K, V > & operator--()
Definition: DynaHashMapImpl.h:378
MapEntry< K, V > * getEntry(K *key)
Definition: DynaHashMapImpl.h:220
Definition: DynaHashMap.h:73
const MapValueIter< K, V > & operator++()
Definition: DynaHashMapImpl.h:385
MapValueIter< K, V > values()
Definition: DynaHashMapImpl.h:367
MapKeyIter(const DynaHashMap< K, V > *map, int start)
Definition: DynaHashMapImpl.h:157
const V * setValue(V *newValue)
Definition: DynaHashMapImpl.h:196
void clear()
Definition: DynaHashMapImpl.h:339
void deleteEntry(K *key)
Definition: DynaHashMapImpl.h:308
V * getValue() const
Definition: DynaHashMap.h:38
Definition: DynaHashMap.h:64
MapEntry< K, V > ** _table
Definition: DynaHashMap.h:87
static constexpr int INITIAL_SIZE
Definition: DynaHashMap.h:84
DynaMapIter< K, V > end()
Definition: DynaHashMapImpl.h:359
virtual ~DynaHashMap()
Definition: DynaHashMapImpl.h:128
bool operator==(const MapEntry< K, V > &other) const override
Definition: DynaHashMapImpl.h:201
V * get(K *key)
Definition: DynaHashMapImpl.h:229
void _init(int size)
Definition: DynaHashMapImpl.h:27
const MapValueIter< K, V > & operator--()
Definition: DynaHashMapImpl.h:392
V * put(K *key, V *value)
Definition: DynaHashMapImpl.h:238
virtual ~MapEntry()
Definition: DynaHashMapImpl.h:97
Definition: Exception.h:13
Definition: DynaHashMap.h:63
int _freeCells
Definition: DynaHashMap.h:90
MapEntry< K, V > * removeEntry(MapEntry< K, V > *entry)
Definition: DynaHashMapImpl.h:323
DynaHashMap()
Definition: DynaHashMapImpl.h:118
int _capacity
Definition: DynaHashMap.h:89
MapEntry< K, V > * copy() override
Definition: DynaHashMapImpl.h:108
void _reHash(int newCapacity)
Definition: DynaHashMapImpl.h:43
V * remove(K *key)
Definition: DynaHashMapImpl.h:288
int _getHashCode(const K *key) const
Definition: DynaHashMapImpl.h:32
MapEntry(K *key, V *value, bool ownsValue)
Definition: DynaHashMapImpl.h:79
int _count
Definition: DynaHashMap.h:88
Definition: DynaHashMap.h:65
int _modCount
Definition: DynaHashMap.h:91
GeneratorWrapper< T > map(Func &&function, GeneratorWrapper< U > &&generator)
Definition: catch.hpp:4282
DynaMapIter< K, V > begin()
Definition: DynaHashMapImpl.h:355