Elm  2
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
HashTable.h
1 /*
2  * HashTable class interface
3  *
4  * This file is part of OTAWA
5  * Copyright (c) 2016, IRIT UPS.
6  *
7  * OTAWA is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * OTAWA is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with OTAWA; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 #ifndef ELM_DATA_HASHTABLE_H_
22 #define ELM_DATA_HASHTABLE_H_
23 
24 #include "custom.h"
25 #include <elm/adapter.h>
26 #include <elm/array.h>
27 #include <elm/hash.h>
28 
29 namespace elm {
30 
31 template <class T, class H = HashKey<T>, class A = DefaultAlloc >
32 class HashTable: public H, public A {
33 public:
35 
36 private:
37  class node_t {
38  public:
39  inline node_t(const T& d): next(0), data(d) { }
40  node_t *next;
41  T data;
42  };
43 
44 protected:
45  node_t *find(const T& key) const {
46  int i = H::computeHash(key) % _size;
47  for(node_t *node = _tab[i], *prev = 0; node; prev = node, node = node->next)
48  if(H::isEqual(node->data, key)) {
49  if(prev) { prev->next = node->next; node->next = _tab[i]; _tab[i] = node; }
50  return node;
51  }
52  return 0;
53  }
54 
55  node_t *find_const(const T& key) const {
56  int i = H::computeHash(key) % _size;
57  for(node_t *node = _tab[i], *prev = 0; node; prev = node, node = node->next)
58  if(H::isEqual(node->data, key)) {
59  return node;
60  }
61  return 0;
62  }
63 
64 private:
65 
66  node_t *make(const T& data) {
67  int i = H::computeHash(data) % _size;
68  node_t *node = new(A::allocate(sizeof(node_t))) node_t(data);
69  node->next = _tab[i];
70  _tab[i] = node;
71  return node;
72  }
73 
74  struct InternIterator {
75  friend class HashTable;
76  inline InternIterator(const self_t& _htab): node(nullptr), htab(&_htab) { i = 0; step(); }
77  inline InternIterator(const self_t& _htab, bool end): node(nullptr), htab(&_htab)
78  { if(end) { i = htab->_size; node = nullptr; } else { i = 0; step(); } }
79  inline bool ended(void) const { return i >= htab->_size; }
80  inline void next(void) { node = node->next; if(!node) { i++; step(); } }
81  inline bool equals(const InternIterator& it) const { return node == it.node && i == it.i && htab == it.htab; }
82  protected:
83  node_t *node;
84  private:
85  inline void step(void) { for(; i < htab->_size; i++) if(htab->_tab[i]) { node = htab->_tab[i]; break; } }
86  const self_t *htab;
87  int i;
88  };
89 
90 public:
91 
92  HashTable(int _size = 211): _size(_size), _tab(new(A::allocate(_size * sizeof(node_t *))) node_t *[_size])
93  { array::fast<node_t*>::clear(_tab, _size); }
94  HashTable(const self_t& h): _size(h._size), _tab(new(A::allocate(_size * sizeof(node_t *))) node_t *[h._size])
95  { array::fast<node_t*>::clear(_tab, _size); putAll(h); }
96  ~HashTable(void)
97  { clear(); delete [] _tab; }
98  inline const H& hash() const { return *this; }
99  inline H& hash() { return *this; }
100  inline const A& allocator() const { return *this; }
101  inline A& allocator() { return *this; }
102 
103  inline const T *get(const T& key) const
104  { node_t *node = find(key); return node ? &node->data : 0; }
105  inline const T *get_const(const T& key) const
106  { node_t *node = find_const(key); return node ? &node->data : 0; }
107  inline bool hasKey(const T& key) const
108  { node_t *node = find(key); return node != 0; }
109  inline bool hasKey_const(const T& key) const
110  { node_t *node = find_const(key); return node != 0; }
111  inline bool exists(const T& key) const { return hasKey(key); }
112  inline bool exists_const(const T& key) const { return hasKey_const(key); }
113 
114  void put(const T& data)
115  { node_t *node = find(data); if(node) node->data = data; else add(data); }
116  template <class CC> void putAll(const CC& c)
117  { for(const auto x: c) put(x); }
118 
119 
120  // Collection concept
121  bool isEmpty(void) const
122  { for(int i = 0; i < _size; i++) if(_tab[i]) return false; return true; }
123  operator bool() const { return !isEmpty(); }
124  int count(void) const
125  { int cnt = 0; for(int i = 0; i < _size; i++) for(node_t *cur = _tab[i]; cur; cur = cur->next) cnt++; return cnt; }
126  inline bool contains(const T& x) const
127  { return find(x) != nullptr; }
128  inline bool contains_const(const T& x) const
129  { return find_const(x) != nullptr; }
130  template <class CC> bool containsAll(const CC& c) const
131  { for(const auto x: c) if(!contains(x)) return false; return true; }
132  template <class CC> bool containsAll_const(const CC& c) const
133  { for(const auto x: c) if(!contains_const(x)) return false; return true; }
134 
135  class Iter: public InternIterator, public InplacePreIterator<Iter, T> {
136  public:
137  inline Iter(const self_t& htab): InternIterator(htab) { };
138  inline Iter(const self_t& htab, bool end): InternIterator(htab, end) { };
139  inline const T& item(void) const { return this->node->data; }
140  };
141  inline Iter begin() const { return Iter(*this); }
142  inline Iter end() const { return Iter(*this, true); }
143 
144  inline bool equals(const HashTable<T>& h) const
145  { return containsAll(h) && h.containsAll(*this); }
146  inline bool equals_const(const HashTable<T>& h) const
147  { return containsAll_const(h) && h.containsAll_const(*this); }
148  inline bool operator==(const HashTable<T>& t) const { return equals(t); }
149  inline bool operator!=(const HashTable<T>& t) const { return !equals(t); }
150 
151  // MutableCollection concept
152  void clear(void) {
153  for(int i = 0; i < _size; i++) {
154  for(node_t *cur = _tab[i], *next; cur; cur = next) { next = cur->next; A::free(cur); }
155  _tab[i] = 0;
156  }
157  }
158 
159  T *add(const T& data) { return &make(data)->data; }
160 
161  inline self_t& operator+=(const T& x) { add(x); return *this; }
162 
163  template <class C> void addAll(const C& c)
164  { for(const auto x: c) add(x); }
165 
166  void remove(const T& key) {
167  int i = H::computeHash(key) % _size;
168  for(node_t *node = _tab[i], *prev = 0; node; prev = node, node = node->next)
169  if(H::isEqual(node->data, key)) {
170  if(prev)
171  prev->next = node->next;
172  else
173  _tab[i] = node->next;
174  A::free(node);
175  break;
176  }
177  }
178 
179  template <class C> void removeAll(const C& c)
180  { for(const auto x: c) remove(x); }
181 
182  inline self_t& operator-=(const T& x) { remove(x); return *this; }
183 
184  void remove(const Iter& i) {
185  node_t *p = nullptr;
186  for(node_t *n = _tab[i.i]; n != i.node; p = n, n = n->next);
187  if(p == nullptr)
188  _tab[i.i] = i.node->next;
189  else
190  p->next = i.node->next;
191  A::free(i.node);
192  }
193 
194  void copy(const HashTable<T, H>& t) {
195  clear();
196  if(_size != t._size)
197  putAll(t);
198  else {
199  for(int i = 0; i < _size; i++) {
200  if(t._tab[i] != nullptr) {
201  node_t *q = t._tab[i];
202  node_t *p = new(A::allocate(sizeof(node_t))) node_t(q->data);
203  _tab[i] = p;
204  while(q->next != nullptr) {
205  q = q->next;
206  p->next = new(A::allocate(sizeof(node_t))) node_t(q->data);
207  p = p->next;
208  }
209  }
210  }
211  }
212  }
213  inline self_t& operator=(const HashTable<T, H>& c) { copy(c); return *this; }
214 
215  inline T *get(const T& key)
216  { node_t *node = find(key); return node ? &node->data : 0; }
217 
218 # ifdef ELM_STAT
219  int minEntry(void) const { int m = count(0); for(int i = 1; i < _size; i++) m = min(m, count(i)); return m; }
220  int maxEntry(void) const { int m = count(0); for(int i = 1; i < _size; i++) m = max(m, count(i)); return m; }
221  int zeroEntry(void) const { int c = 0; for(int i = 0; i < _size; i++) if(count(i) == 0) c++; return c; }
222  int size(void) const { return _size; }
223 # endif
224 
225 private:
226 # ifdef ELM_STAT
227  int count(int i) const { int c = 0; for(node_t *n = _tab[i]; n; n = n->next) c++; return c; }
228 # endif
229 
230  int _size;
231  node_t **_tab;
232 };
233 
234 } // otawa
235 
236 #endif /* ELM_DATA_HASHTABLE_H_ */
elm::HashTable::operator!=
bool operator!=(const HashTable< T > &t) const
Definition: HashTable.h:149
elm::io::p
Printable< T, M > p(const T &data, const M &man)
Definition: Output.h:302
elm::HashTable::removeAll
void removeAll(const C &c)
Definition: HashTable.h:179
elm::HashTable::hasKey_const
bool hasKey_const(const T &key) const
Definition: HashTable.h:109
elm::HashTable::end
Iter end() const
Definition: HashTable.h:142
elm::HashTable::operator-=
self_t & operator-=(const T &x)
Definition: HashTable.h:182
elm::HashTable::operator+=
self_t & operator+=(const T &x)
Definition: HashTable.h:161
elm::HashTable::remove
void remove(const Iter &i)
Definition: HashTable.h:184
elm::HashTable::containsAll
bool containsAll(const CC &c) const
Definition: HashTable.h:130
elm::max
const T & max(const T &x, const T &y)
Definition: compare.h:108
elm::HashTable::~HashTable
~HashTable(void)
Definition: HashTable.h:96
elm::HashTable::contains_const
bool contains_const(const T &x) const
Definition: HashTable.h:128
elm::HashTable::addAll
void addAll(const C &c)
Definition: HashTable.h:163
elm::HashTable::hash
const H & hash() const
Definition: HashTable.h:98
elm::HashTable::HashTable
HashTable(const self_t &h)
Definition: HashTable.h:94
elm::Pair
Definition: Pair.h:33
elm::HashTable::Iter
Definition: HashTable.h:135
elm::HashTable::allocator
const A & allocator() const
Definition: HashTable.h:100
bool
elm::HashTable::allocator
A & allocator()
Definition: HashTable.h:101
elm::DefaultAllocatorDelegate::allocate
t::ptr allocate(t::size size) const
Definition: custom.h:31
elm::HashTable::put
void put(const T &data)
Definition: HashTable.h:114
elm::min
const T & min(const T &x, const T &y)
Definition: compare.h:104
elm::HashTable::Iter::item
const T & item(void) const
Definition: HashTable.h:139
elm::HashTable::equals
bool equals(const HashTable< T > &h) const
Definition: HashTable.h:144
elm::HashTable::get
const T * get(const T &key) const
Definition: HashTable.h:103
elm::HashTable::equals_const
bool equals_const(const HashTable< T > &h) const
Definition: HashTable.h:146
elm
Definition: adapter.h:26
elm::HashTable::Iter::Iter
Iter(const self_t &htab, bool end)
Definition: HashTable.h:138
elm::HashTable::copy
void copy(const HashTable< T, H > &t)
Definition: HashTable.h:194
elm::HashTable::hasKey
bool hasKey(const T &key) const
Definition: HashTable.h:107
elm::HashTable::putAll
void putAll(const CC &c)
Definition: HashTable.h:116
elm::HashTable::operator==
bool operator==(const HashTable< T > &t) const
Definition: HashTable.h:148
elm::t::size
uint64 size
Definition: arch.h:35
elm::HashTable::Iter::Iter
Iter(const self_t &htab)
Definition: HashTable.h:137
elm::HashTable::get_const
const T * get_const(const T &key) const
Definition: HashTable.h:105
elm::HashTable::count
int count(void) const
Definition: HashTable.h:124
elm::HashTable::hash
H & hash()
Definition: HashTable.h:99
elm::HashTable::clear
void clear(void)
Definition: HashTable.h:152
elm::HashTable::remove
void remove(const T &key)
Definition: HashTable.h:166
elm::HashTable
Definition: HashTable.h:32
elm::HashTable::contains
bool contains(const T &x) const
Definition: HashTable.h:126
elm::HashTable::add
T * add(const T &data)
Definition: HashTable.h:159
elm::InplacePreIterator
Definition: iter.h:49
elm::HashTable::exists
bool exists(const T &key) const
Definition: HashTable.h:111
elm::HashTable::begin
Iter begin() const
Definition: HashTable.h:141
elm::array::fast::clear
static void clear(T *target, int size)
Definition: array.h:42
elm::HashTable::self_t
HashTable< T, H, A > self_t
Definition: HashTable.h:34
elm::HashTable::HashTable
HashTable(int _size=211)
Definition: HashTable.h:92
elm::HashTable::operator=
self_t & operator=(const HashTable< T, H > &c)
Definition: HashTable.h:213
elm::HashTable::find
node_t * find(const T &key) const
Definition: HashTable.h:45
elm::HashTable::containsAll_const
bool containsAll_const(const CC &c) const
Definition: HashTable.h:132
elm::HashTable::get
T * get(const T &key)
Definition: HashTable.h:215
elm::HashTable::exists_const
bool exists_const(const T &key) const
Definition: HashTable.h:112
elm::HashTable::find_const
node_t * find_const(const T &key) const
Definition: HashTable.h:55
elm::HashTable::isEmpty
bool isEmpty(void) const
Definition: HashTable.h:121