FreeNOS
HashTable.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef __LIB_LIBSTD_HASHTABLE_H
19 #define __LIB_LIBSTD_HASHTABLE_H
20 
21 #include "Types.h"
22 #include "Macros.h"
23 #include "Vector.h"
24 #include "List.h"
25 #include "ListIterator.h"
26 #include "HashFunction.h"
27 #include "Associative.h"
28 #include "Assert.h"
29 
31 #define HASHTABLE_DEFAULT_SIZE 64
32 
44 template <class K, class V> class HashTable : public Associative<K,V>
45 {
46  public:
47 
51  class Bucket
52  {
53  public:
54 
59  {
60  }
61 
68  Bucket(K k, V v)
69  : key(k), value(v)
70  {
71  }
72 
76  Bucket(const Bucket & b)
77  : key(b.key), value(b.value)
78  {
79  }
80 
86  bool operator == (const Bucket & b) const
87  {
88  return key == b.key && value == b.value;
89  }
90 
94  bool operator != (const Bucket & b) const
95  {
96  return !(key == b.key && value == b.value);
97  }
98 
100  K key;
101 
103  V value;
104  };
105 
112  : m_table(size)
113  {
114  assert(size > 0);
115 
116  m_count = ZERO;
117 
118  // Fill the Vector with empty Bucket Lists.
119  for (Size i = 0; i < m_table.size(); i++)
120  m_table.insert(List<Bucket>());
121  }
122 
133  virtual bool insert(const K & key, const V & value)
134  {
135 
136  Size idx = hash(key, m_table.size());
137 
138  // See if the given key exists. Overwrite if so.
139  for (ListIterator<Bucket> i(m_table[idx]); i.hasCurrent(); i++)
140  {
141  if (i.current().key == key)
142  {
143  i.current().value = value;
144  return true;
145  }
146  }
147 
148  // Key does not exist. Append it.
149  m_table[idx].append(Bucket(key, value));
150  m_count++;
151  return true;
152  }
153 
162  virtual bool append(const K & key, const V & value)
163  {
164 
165  // Always append
166  m_table[hash(key, m_table.size())].append(Bucket(key, value));
167  m_count++;
168  return true;
169  }
170 
178  virtual int remove(const K & key)
179  {
180  int removed = 0;
181 
182  for (ListIterator<Bucket> i(m_table[hash(key, m_table.size())]); i.hasCurrent(); )
183  {
184  if (i.current().key == key)
185  {
186  i.remove();
187  m_count--;
188  removed++;
189  }
190  else
191  i++;
192  }
193  return removed;
194  }
195 
201  virtual Size size() const
202  {
203  return m_table.size();
204  }
205 
211  virtual Size count() const
212  {
213  return m_count;
214  }
215 
221  virtual List<K> keys() const
222  {
223  List<K> lst;
224 
225  for (Size i = 0; i < m_table.count(); i++)
226  for (ListIterator<Bucket> j(m_table[i]); j.hasCurrent(); j++)
227  if (!lst.contains(j.current().key))
228  lst << j.current().key;
229 
230  return lst;
231  }
232 
236  virtual List<K> keys(const V & value) const
237  {
238  List<K> lst;
239 
240  for (Size i = 0; i < m_table.count(); i++)
241  for (ListIterator<Bucket> j(m_table[i]); j.hasCurrent(); j++)
242  if (j.current().value == value && !lst.contains(j.current().key))
243  lst << j.current().key;
244 
245  return lst;
246  }
247 
253  virtual List<V> values() const
254  {
255  List<V> lst;
256 
257  for (Size i = 0; i < m_table.count(); i++)
258  for (ListIterator<Bucket> j(m_table[i]); j.hasCurrent(); j++)
259  lst << j.current().value;
260 
261  return lst;
262  }
263 
269  virtual List<V> values(const K & key) const
270  {
271  List<V> lst;
272 
273  for (ListIterator<Bucket> i(m_table[hash(key, m_table.size())]); i.hasCurrent(); i++)
274  if (i.current().key == key)
275  lst << i.current().value;
276 
277  return lst;
278  }
279 
287  virtual const V * get(const K & key) const
288  {
289  const List<Bucket> & lst = m_table[hash(key, m_table.size())];
290 
291  for (ListIterator<Bucket> i(lst); i.hasCurrent(); i++)
292  if (i.current().key == key)
293  return &i.current().value;
294 
295  return ZERO;
296  }
297 
307  virtual const V & at(const K & key) const
308  {
309  const List<Bucket> & lst = m_table[hash(key, m_table.size())];
310 
311  for (ListIterator<Bucket> i(lst); i.hasCurrent(); i++)
312  if (i.current().key == key)
313  return i.current().value;
314 
315  return m_table[0].head()->data.value;
316  }
317 
325  virtual const V value(const K & key, const V defaultValue = V()) const
326  {
327  const List<Bucket> & lst = m_table[hash(key, m_table.size())];
328 
329  for (ListIterator<Bucket> i(lst); i.hasCurrent(); i++)
330  if (i.current().key == key)
331  return i.current().value;
332 
333  return defaultValue;
334  }
335 
342  {
343  return m_table;
344  }
345 
349  V & operator[](const K & key)
350  {
351  return (V &) at(key);
352  }
353 
357  const V & operator[](const K & key) const
358  {
359  return (const V &) at(key);
360  }
361 
362  private:
363 
366 
369 };
370 
376 #endif /* __LIB_LIBSTD_HASHTABLE_H */
HashTable::Bucket::operator==
bool operator==(const Bucket &b) const
Comparision operator.
Definition: HashTable.h:86
HashTable::values
virtual List< V > values(const K &key) const
Retrieve values for the given key inside the Association.
Definition: HashTable.h:269
HashTable
Efficient key -> value lookups.
Definition: HashTable.h:44
HashTable::Bucket::value
V value
Value of the item.
Definition: HashTable.h:103
HashTable::operator[]
const V & operator[](const K &key) const
Constant index operator.
Definition: HashTable.h:357
Macros.h
Vector.h
HashFunction.h
Types.h
HashTable::keys
virtual List< K > keys(const V &value) const
Retrieve list of Keys for the given value.
Definition: HashTable.h:236
hash
Size hash(const String &key, Size mod)
Compute a hash using the FNV algorithm.
Definition: HashFunction.cpp:21
HashTable::Bucket::Bucket
Bucket(K k, V v)
Constructor.
Definition: HashTable.h:68
HashTable::append
virtual bool append(const K &key, const V &value)
Append a new item.
Definition: HashTable.h:162
HashTable::keys
virtual List< K > keys() const
Retrieve all keys inside the Association.
Definition: HashTable.h:221
HashTable::at
virtual const V & at(const K &key) const
Returns a reference to the first value for the given key.
Definition: HashTable.h:307
Assert.h
HASHTABLE_DEFAULT_SIZE
#define HASHTABLE_DEFAULT_SIZE
Default size of the HashTable internal table.
Definition: HashTable.h:31
HashTable::Bucket
Describes a bucket in the HashTable, for collision avoidance.
Definition: HashTable.h:51
HashTable::operator[]
V & operator[](const K &key)
Modifiable index operator.
Definition: HashTable.h:349
HashTable::remove
virtual int remove(const K &key)
Remove value(s) for the given key.
Definition: HashTable.h:178
ListIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item on the List.
Definition: ListIterator.h:104
HashTable::get
virtual const V * get(const K &key) const
Returns the first value for the given key.
Definition: HashTable.h:287
HashTable::count
virtual Size count() const
Get the number of values stored in the HashTable.
Definition: HashTable.h:211
HashTable::Bucket::Bucket
Bucket(const Bucket &b)
Copy constructor.
Definition: HashTable.h:76
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
HashTable::Bucket::key
K key
Key for this item.
Definition: HashTable.h:100
HashTable::values
virtual List< V > values() const
Retrieve all values inside the Association.
Definition: HashTable.h:253
HashTable::Bucket::operator!=
bool operator!=(const Bucket &b) const
Inequality operator.
Definition: HashTable.h:94
HashTable::Bucket::Bucket
Bucket()
Default constructor.
Definition: HashTable.h:58
HashTable::HashTable
HashTable(Size size=HASHTABLE_DEFAULT_SIZE)
Class constructor.
Definition: HashTable.h:111
ListIterator.h
HashTable::m_table
Vector< List< Bucket > > m_table
Internal table.
Definition: HashTable.h:365
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
HashTable::table
Vector< List< Bucket > > & table()
Get the internal Vector with Buckets.
Definition: HashTable.h:341
Associative
Associatives are containers that provide a mapping of keys to values.
Definition: Associative.h:39
HashTable::m_count
Size m_count
Number of values in the buckets.
Definition: HashTable.h:368
List::contains
virtual bool contains(const T t) const
Check whether an element is on the List.
Definition: List.h:219
List
Simple linked list template class.
Definition: List.h:36
HashTable::size
virtual Size size() const
Get the size of the HashTable.
Definition: HashTable.h:201
Associative.h
Vector
Vectors are dynamically resizeable Arrays.
Definition: Vector.h:41
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
HashTable::insert
virtual bool insert(const K &key, const V &value)
Inserts the given item to the HashTable.
Definition: HashTable.h:133
HashTable::value
virtual const V value(const K &key, const V defaultValue=V()) const
Return the first value for the given key.
Definition: HashTable.h:325
List.h
ListIterator
Iterate through a List.
Definition: ListIterator.h:37