WHashMap.h
Go to the documentation of this file.
1 /* $Id: HashMap.h 1198 2011-06-14 21:08:27Z bhagman $
2 ||
3 || @author Alexander Brevig <abrevig@wiring.org.co>
4 || @url http://wiring.org.co/
5 || @url http://alexanderbrevig.com/
6 || @contribution Brett Hagman <bhagman@wiring.org.co>
7 ||
8 || @description
9 || | Implementation of a HashMap data structure.
10 || |
11 || | Wiring Cross-platform Library
12 || #
13 ||
14 || @license Please see cores/Common/License.txt.
15 ||
16 */
17 
18 /*
19  * @author: 3 Oct 2018 - mikee47 <mike@sillyhouse.net>
20  *
21  * Modified to use references (const or otherwise) to avoid object copies when used with classes, e.g. String.
22  *
23  * Note that if the value is a primitive then setNullValue should be called to provide a default value to be
24  * used when adding a new unspecified entry, or if a key value is not present. This should not be necessary
25  * for object values as the default constructor will be used.
26  *
27  */
28 
29 #pragma once
30 
31 #include <cstdint>
32 
37 template <typename K, typename V> class HashMap
38 {
39 public:
40  typedef bool (*comparator)(const K&, const K&);
41 
42  /*
43  || @constructor
44  || | Default constructor
45  || #
46  */
48  {
49  }
50 
51  /*
52  || @constructor
53  || | Initialize this HashMap
54  || #
55  ||
56  || @parameter compare optional function for comparing a key against another (for complex types)
57  */
58  HashMap(comparator compare) : cb_comparator(compare)
59  {
60  }
61 
63  {
64  clear();
65  }
66 
67  /*
68  || @description
69  || | Get the size of this HashMap
70  || #
71  ||
72  || @return The size of this HashMap
73  */
74  unsigned int count() const
75  {
76  return currentIndex;
77  }
78 
79  /*
80  || @description
81  || | Get a key at a specified index
82  || #
83  ||
84  || @parameter idx the index to get the key at
85  ||
86  || @return The key at index idx
87  */
88  const K& keyAt(unsigned int idx) const
89  {
90  if(idx >= count()) {
91  abort();
92  }
93  return *keys[idx];
94  }
95 
96  K& keyAt(unsigned int idx)
97  {
98  if(idx >= count()) {
99  abort();
100  }
101  return *keys[idx];
102  }
103 
104  /*
105  || @description
106  || | Get a value at a specified index
107  || #
108  ||
109  || @parameter idx the index to get the value at
110  ||
111  || @return The value at index idx
112  */
113  const V& valueAt(unsigned int idx) const
114  {
115  if(idx >= count()) {
116  abort();
117  }
118  return *values[idx];
119  }
120 
121  V& valueAt(unsigned int idx)
122  {
123  if(idx >= count()) {
124  abort();
125  }
126  return *values[idx];
127  }
128 
129  /*
130  || @description
131  || | An indexer for accessing and assigning a value to a key
132  || | If a key is used that exists, it returns the value for that key
133  || | If there exists no value for that key, a nil value is returned
134  || |
135  || | Note that if the HashMap object is not const, the non-const version
136  || | of this operator will be called which will create a default value
137  || | for this key. If that behaviour is not desired, then check for the
138  || | existence of the key first, using either contains() or indexOf().
139  || #
140  ||
141  || @parameter key the key to get the value for
142  ||
143  || @return The const value for key
144  */
145  const V& operator[](const K& key) const
146  {
147  // Don't create non-existent values
148  auto i = indexOf(key);
149  return (i >= 0) ? *values[i] : nil;
150  }
151 
152  /*
153  || @description
154  || | An indexer for accessing and assigning a value to a key
155  || | If a key is used that exists, it returns the value for that key
156  || | If there exists no value for that key, the key is added
157  || #
158  ||
159  || @parameter key the key to get the value for
160  ||
161  || @return The value for key
162  */
163  V& operator[](const K& key);
164 
165  void allocate(unsigned int newSize);
166 
167  /*
168  || @description
169  || | Get the index of a key
170  || #
171  ||
172  || @parameter key the key to get the index for
173  ||
174  || @return The index of the key, or -1 if key does not exist
175  */
176  int indexOf(const K& key) const;
177 
178  /*
179  || @description
180  || | Check if a key is contained within this HashMap
181  || #
182  ||
183  || @parameter key the key to check if is contained within this HashMap
184  ||
185  || @return true if it is contained in this HashMap
186  */
187  bool contains(const K& key) const
188  {
189  return indexOf(key) >= 0;
190  }
191 
192  /*
193  || @description
194  || | Remove entry at given index
195  || #
196  ||
197  || @parameter index location to remove from this HashMap
198  */
199  void removeAt(unsigned index);
200 
201  /*
202  || @description
203  || | Remove a key from this HashMap
204  || #
205  ||
206  || @parameter key the key to remove from this HashMap
207  */
208  void remove(const K& key)
209  {
210  int index = indexOf(key);
211  if(index >= 0) {
212  removeAt(index);
213  }
214  }
215 
216  void clear();
217 
218  void setMultiple(const HashMap<K, V>& map);
219 
220  void setNullValue(const V& nullv)
221  {
222  nil = nullv;
223  }
224 
225 protected:
226  K** keys = nullptr;
227  V** values = nullptr;
228  V nil;
232 
233 private:
234  HashMap(const HashMap<K, V>& that);
235 };
236 
237 template <typename K, typename V> V& HashMap<K, V>::operator[](const K& key)
238 {
239  int i = indexOf(key);
240  if(i >= 0) {
241  return *values[i];
242  }
243  if(currentIndex >= size) {
244  allocate(currentIndex + 1);
245  }
246  *keys[currentIndex] = key;
247  *values[currentIndex] = nil;
248  currentIndex++;
249  return *values[currentIndex - 1];
250 }
251 
252 template <typename K, typename V> void HashMap<K, V>::allocate(unsigned int newSize)
253 {
254  if(newSize <= size)
255  return;
256 
257  K** nkeys = new K*[newSize];
258  V** nvalues = new V*[newSize];
259 
260  if(keys != nullptr) {
261  for(unsigned i = 0; i < size; i++) {
262  nkeys[i] = keys[i];
263  nvalues[i] = values[i];
264  }
265 
266  delete[] keys;
267  delete[] values;
268  }
269  for(unsigned i = size; i < newSize; i++) {
270  nkeys[i] = new K();
271  nvalues[i] = new V();
272  }
273 
274  keys = nkeys;
275  values = nvalues;
276  size = newSize;
277 }
278 
279 template <typename K, typename V> int HashMap<K, V>::indexOf(const K& key) const
280 {
281  for(unsigned i = 0; i < currentIndex; i++) {
282  if(cb_comparator) {
283  if(cb_comparator(key, *keys[i])) {
284  return i;
285  }
286  } else {
287  if(key == *keys[i]) {
288  return i;
289  }
290  }
291  }
292  return -1;
293 }
294 
295 template <typename K, typename V> void HashMap<K, V>::removeAt(unsigned index)
296 {
297  if(index >= currentIndex)
298  return;
299 
300  for(unsigned i = index + 1; i < size; i++) {
301  *keys[i - 1] = *keys[i];
302  *values[i - 1] = *values[i];
303  }
304 
305  currentIndex--;
306 }
307 
308 template <typename K, typename V> void HashMap<K, V>::clear()
309 {
310  if(keys != nullptr) {
311  for(unsigned i = 0; i < size; i++) {
312  delete keys[i];
313  delete values[i];
314  }
315  delete[] keys;
316  delete[] values;
317  keys = nullptr;
318  values = nullptr;
319  }
320  currentIndex = 0;
321  size = 0;
322 }
323 
324 template <typename K, typename V> void HashMap<K, V>::setMultiple(const HashMap<K, V>& map)
325 {
326  for(unsigned i = 0; i < map.count(); i++) {
327  (*this)[map.keyAt(i)] = *(map.values)[i];
328  }
329 }
bool(* comparator)(const K &, const K &)
Definition: WHashMap.h:40
void allocate(unsigned int newSize)
Definition: WHashMap.h:252
const V & operator[](const K &key) const
Definition: WHashMap.h:145
HashMap(comparator compare)
Definition: WHashMap.h:58
HashMap class template.
Definition: WHashMap.h:37
comparator cb_comparator
Definition: WHashMap.h:231
void clear()
Definition: WHashMap.h:308
const K & keyAt(unsigned int idx) const
Definition: WHashMap.h:88
long map(long, long, long, long, long)
const V & valueAt(unsigned int idx) const
Definition: WHashMap.h:113
~HashMap()
Definition: WHashMap.h:62
void setNullValue(const V &nullv)
Definition: WHashMap.h:220
uint16_t size
Definition: WHashMap.h:230
V nil
Definition: WHashMap.h:228
uint16_t currentIndex
Definition: WHashMap.h:229
K & keyAt(unsigned int idx)
Definition: WHashMap.h:96
void setMultiple(const HashMap< K, V > &map)
Definition: WHashMap.h:324
K ** keys
Definition: WHashMap.h:226
V & valueAt(unsigned int idx)
Definition: WHashMap.h:121
HashMap()
Definition: WHashMap.h:47
int indexOf(const K &key) const
Definition: WHashMap.h:279
V ** values
Definition: WHashMap.h:227
bool contains(const K &key) const
Definition: WHashMap.h:187
void removeAt(unsigned index)
Definition: WHashMap.h:295
unsigned int count() const
Definition: WHashMap.h:74