Elm  1.0
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HashTable.h
1 /*
2  * $Id$
3  * genstruct::HashTable class interface
4  *
5  * This file is part of OTAWA
6  * Copyright (c) 2004-08, IRIT UPS.
7  *
8  * OTAWA is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * OTAWA is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with OTAWA; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #ifndef ELM_GENSTRUCT_HASHTABLE_H
23 #define ELM_GENSTRUCT_HASHTABLE_H
24 
25 #include <elm/util/Pair.h>
26 #include <elm/PreIterator.h>
27 #include <elm/util/HashKey.h>
28 #include <elm/type_info.h>
29 
30 namespace elm { namespace genstruct {
31 
32 // InHashTable class
33 template <class K, class T, class H = HashKey<K> >
34 class HashTable {
35 
36  typedef struct node_t {
37  node_t *next;
38  K key;
39  T value;
40  } node_t;
41 
42  int size;
43  node_t **tab;
44 
45  node_t *find(const K& key) {
46  int i = H::hash(key) % size;
47  for(node_t *node = tab[i], *prev = 0; node; prev = node, node = node->next)
48  if(H::equals(node->key, 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 *make(const K& key, const T& value)
56  { int i = H::hash(key) % size; node_t *node = new node_t; node->next = tab[i];
57  tab[i] = node; node->key = key; node->value = value; return node; }
58 
59  // InternIterator
60  class InternIterator {
61  public:
62  inline InternIterator(const HashTable<K, T, H>& _htab): htab(&_htab) { i = 0; step(); }
63  inline InternIterator(const InternIterator& it): node(it.node), htab(it.htab), i(it.i) { }
64  inline InternIterator& operator=(const InternIterator& it) { htab = it.htab; i = it.i; node = it.node; }
65  inline bool ended(void) const { return i >= htab->size; }
66  inline void next(void) { node = node->next; if(!node) { i++; step(); } }
67  protected:
68  node_t *node;
69  private:
70  inline void step(void) { for(; i < htab->size; i++) if(htab->tab[i]) { node = htab->tab[i]; break; } }
71  const HashTable<K, T, H> *htab;
72  int i;
73  };
74 
75  class Ref {
76  public:
77  inline Ref(HashTable<K, T, H>& tab, const K& key): t(tab), k(key) { }
78  inline operator const K&(void) const { return get(); }
79  inline const T& operator*(void) const { return get(); };
80  inline T& operator=(const T& v) const {
81  node_t *node = t.find(k);
82  if(!node)
83  node = t.make(k, v);
84  return node->value;
85  }
86  private:
87  inline const T& get(void) const { node_t *node = t.find(k); ASSERTP(node, "key " << k << " not in hashtab"); return node->value; }
89  const K& k;
90  };
91 
92 public:
93  HashTable(int _size = 211): size(_size), tab(new node_t *[_size])
94  { for(int i = 0; i < size; i++) tab[i] = 0; }
95  ~HashTable(void)
96  { clear(); delete [] tab; }
97 
98  bool isEmpty(void) const
99  { for(int i = 0; i <size; i++) if(tab[i]) return false; return true; }
100  int count(void) const
101  { int cnt = 0; for(int i = 0; i < size; i++) for(node_t *cur = tab[i]; cur; cur = cur->next) cnt++; return cnt; }
102 
103  inline Option<T> get(const K& key)
104  { node_t *node = find(key); return node ? Option<T>(type_info<T>::get(node->value)) : Option<T>(); }
105  inline const T get(const K& key, const T& def_value)
106  { node_t *node = find(key); return node ? type_info<T>::get(node->value) : def_value; }
107  inline bool hasKey(const K& key)
108  { node_t *node = find(key); return node != 0; }
109  inline bool exists(const K& key) { return hasKey(key); };
110 
111  inline Ref operator[](const K& key) { return Ref(*this, key); }
112 
113  void put(const K& key, const T& value)
114  { node_t *node = find(key); if(node) node->value = value; else add(key, value); }
115  void add(const K& key, const T& value) { make(key, value); }
116  void putAll(const HashTable<K, T, H>& htab)
117  { for(int i = 0; i < htab.size; i++) for(node_t *node = htab.tab[i]; node; node = node->next) put(type_info<K>::get(node->key), type_info<T>::get(node->value)); }
118 
119  void remove(const K& key) {
120  int i = H::hash(key) % size;
121  for(node_t *node = tab[i], *prev = 0; node; prev = node, node = node->next)
122  if(H::equals(type_info<K>::get(node->key), key)) {
123  if(prev)
124  prev->next = node->next;
125  else
126  tab[i] = node->next;
127  delete node;
128  break;
129  }
130  }
131 
132  void clear(void) {
133  for(int i = 0; i < size; i++) {
134  for(node_t *cur = tab[i], *next; cur; cur = next) { next = cur->next; delete cur; }
135  tab[i] = 0;
136  }
137  }
138 
139  // KeyIterator class
140  class KeyIterator: public InternIterator, public PreIterator<KeyIterator, K> {
141  public:
142  inline KeyIterator(const HashTable<K, T, H>& htab): InternIterator(htab) { };
143  inline KeyIterator(const KeyIterator& it): InternIterator(it) { }
144  inline KeyIterator& operator=(const KeyIterator& it) { InternIterator::operator==(it); return *this; }
145  inline const K& item(void) const { return type_info<K>::get(this->node->key); }
146  };
147 
148  // Iterator class
149  class Iterator: public InternIterator, public PreIterator<Iterator, T> {
150  public:
151  inline Iterator(const HashTable<K, T, H>& htab): InternIterator(htab) { };
152  inline Iterator(const Iterator& it): InternIterator(it) { }
153  inline Iterator& operator=(const Iterator& it) { InternIterator::operator=(it); return *this; }
154  inline const T& item(void) const { return type_info<T>::get(this->node->value); }
155  inline const T& useItem(void) const { return type_info<T>::get(this->node->value); }
156  inline const K& key(void) const { return type_info<K>::get(this->node->key); };
157  };
158 
159  // PairIterator class
160  class PairIterator: public InternIterator, public PreIterator<PairIterator, Pair<K, T> > {
161  public:
162  inline PairIterator(const HashTable<K, T, H>& htab): InternIterator(htab) { };
163  inline PairIterator(const PairIterator& it): InternIterator(it) { }
164  inline PairIterator& operator=(const PairIterator& it) { InternIterator::operator=(it); return *this; }
165  inline Pair<K, T> item(void) const { return pair(type_info<K>::get(this->node->key), this->node->value); }
166  };
167 
168  // SameKeyIterator
169  class SameKeyIterator: public PreIterator<SameKeyIterator, T> {
170  const HashTable<K, T, H>& htab;
171  K key;
172  node_t *node;
173  int i;
174  public:
175  inline SameKeyIterator(const HashTable<K, T, H>& _htab, const K& _key)
176  : htab(_htab)
177  { type_info<K>::put(key, _key); i = H::hash(key) % size;
178  for (node = htab.tab[i]; node && (node->key != key); node = node->next)
179  ;
180  ASSERT(node != NULL); }
181  inline bool ended(void) const { return node == 0; }
182  inline void next(void)
183  { node = node->next; for (node = htab.tab[i]; node && (type_info<K>::get(node->key) != type_info<K>::get(key)); node = node->next); }
184  inline const T& item(void) const { return this->node->value; }
185  };
186 
187 };
188 
189 } } // elm::genstruct
190 
191 #endif // ELM_GENSTRUCT_HASHTABLE_H
const K & item(void) const
Definition: HashTable.h:145
const K & key(void) const
Definition: HashTable.h:156
Pair< K, T > item(void) const
Definition: HashTable.h:165
Definition: PreIterator.h:29
KeyIterator & operator=(const KeyIterator &it)
Definition: HashTable.h:144
Definition: Ref.h:18
PairIterator(const HashTable< K, T, H > &htab)
Definition: HashTable.h:162
int count(void) const
Definition: HashTable.h:100
Pair< T1, T2 > pair(const T1 &v1, const T2 &v2)
Definition: Pair.h:41
static const T & get(const T &v)
Definition: type_info.h:49
bool hasKey(const K &key)
Definition: HashTable.h:107
const T & useItem(void) const
Definition: HashTable.h:155
void putAll(const HashTable< K, T, H > &htab)
Definition: HashTable.h:116
Ref operator[](const K &key)
Definition: HashTable.h:111
HashTable(int _size=211)
Definition: HashTable.h:93
static void put(T &l, const T &v)
Definition: type_info.h:48
KeyIterator(const KeyIterator &it)
Definition: HashTable.h:143
bool exists(const K &key)
Definition: HashTable.h:109
bool isEmpty(void) const
Definition: HashTable.h:98
Definition: type_info.h:70
const T & item(void) const
Definition: HashTable.h:154
value_t value(CString name, int value)
Definition: rtti.h:40
Iterator(const HashTable< K, T, H > &htab)
Definition: HashTable.h:151
Definition: Option.h:22
Iterator & operator=(const Iterator &it)
Definition: HashTable.h:153
const T & item(void) const
Definition: HashTable.h:184
void put(const K &key, const T &value)
Definition: HashTable.h:113
KeyIterator(const HashTable< K, T, H > &htab)
Definition: HashTable.h:142
~HashTable(void)
Definition: HashTable.h:95
SameKeyIterator(const HashTable< K, T, H > &_htab, const K &_key)
Definition: HashTable.h:175
void clear(void)
Definition: HashTable.h:132
Iterator(const Iterator &it)
Definition: HashTable.h:152
Definition: Pair.h:16
void next(void)
Definition: HashTable.h:182
void add(const K &key, const T &value)
Definition: HashTable.h:115
bool ended(void) const
Definition: HashTable.h:181
Definition: HashTable.h:149
PairIterator(const PairIterator &it)
Definition: HashTable.h:163
PairIterator & operator=(const PairIterator &it)
Definition: HashTable.h:164
Definition: HashTable.h:160
Definition: HashTable.h:140
Definition: HashTable.h:34