jrtplib  3.6.0
rtphashtable.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2006 Jori Liesenborgs
5 
6  Contact: jori.liesenborgs@gmail.com
7 
8  This library was developed at the "Expertisecentrum Digitale Media"
9  (http://www.edm.uhasselt.be), a research center of the Hasselt University
10  (http://www.uhasselt.be). The library is based upon work done for
11  my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
12 
13  Permission is hereby granted, free of charge, to any person obtaining a
14  copy of this software and associated documentation files (the "Software"),
15  to deal in the Software without restriction, including without limitation
16  the rights to use, copy, modify, merge, publish, distribute, sublicense,
17  and/or sell copies of the Software, and to permit persons to whom the
18  Software is furnished to do so, subject to the following conditions:
19 
20  The above copyright notice and this permission notice shall be included
21  in all copies or substantial portions of the Software.
22 
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29  IN THE SOFTWARE.
30 
31 */
32 
33 #ifndef RTPHASHTABLE_H
34 
35 #define RTPHASHTABLE_H
36 
41 #include "rtperrors.h"
42 #include "rtpmemoryobject.h"
43 
44 #ifdef RTPDEBUG
45 #include <iostream>
46 #endif // RTPDEBUG
47 
48 //template<class Element,int GetIndex(const Element &k),int hashsize>
49 template<class Element,class GetIndex,int hashsize>
50 class RTPHashTable : public RTPMemoryObject
51 {
52 public:
53  RTPHashTable(RTPMemoryManager *mgr = 0, int memtype = RTPMEM_TYPE_OTHER);
54  ~RTPHashTable() { Clear(); }
55 
56  void GotoFirstElement() { curhashelem = firsthashelem; }
57  void GotoLastElement() { curhashelem = lasthashelem; }
58  bool HasCurrentElement() { return (curhashelem == 0)?false:true; }
59  int DeleteCurrentElement();
60  Element &GetCurrentElement() { return curhashelem->GetElement(); }
61  int GotoElement(const Element &e);
62  bool HasElement(const Element &e);
63  void GotoNextElement();
64  void GotoPreviousElement();
65  void Clear();
66 
67  int AddElement(const Element &elem);
68  int DeleteElement(const Element &elem);
69 
70 #ifdef RTPDEBUG
71  void Dump();
72 #endif // RTPDEBUG
73 private:
74  class HashElement
75  {
76  public:
77  HashElement(const Element &e,int index):element(e) { hashprev = 0; hashnext = 0; listnext = 0; listprev = 0; hashindex = index; }
78  int GetHashIndex() { return hashindex; }
79  Element &GetElement() { return element; }
80 #ifdef RTPDEBUG
81  void Dump() { std::cout << "\tHash index " << hashindex << " | Element " << element << std::endl; }
82 #endif // RTPDEBUG
83  private:
84  int hashindex;
85  Element element;
86  public:
87  HashElement *hashprev,*hashnext;
88  HashElement *listprev,*listnext;
89  };
90 
91  HashElement *table[hashsize];
92  HashElement *firsthashelem,*lasthashelem;
93  HashElement *curhashelem;
94 #ifdef RTP_SUPPORT_MEMORYMANAGEMENT
95  int memorytype;
96 #endif // RTP_SUPPORT_MEMORYMANAGEMENT
97 };
98 
99 template<class Element,class GetIndex,int hashsize>
100 inline RTPHashTable<Element,GetIndex,hashsize>::RTPHashTable(RTPMemoryManager *mgr,int memtype) : RTPMemoryObject(mgr)
101 {
102  for (int i = 0 ; i < hashsize ; i++)
103  table[i] = 0;
104  firsthashelem = 0;
105  lasthashelem = 0;
106 #ifdef RTP_SUPPORT_MEMORYMANAGEMENT
107  memorytype = memtype;
108 #endif // RTP_SUPPORT_MEMORYMANAGEMENT
109 }
110 
111 template<class Element,class GetIndex,int hashsize>
112 inline int RTPHashTable<Element,GetIndex,hashsize>::DeleteCurrentElement()
113 {
114  if (curhashelem)
115  {
116  HashElement *tmp1,*tmp2;
117  int index;
118 
119  // First, relink elements in current hash bucket
120 
121  index = curhashelem->GetHashIndex();
122  tmp1 = curhashelem->hashprev;
123  tmp2 = curhashelem->hashnext;
124  if (tmp1 == 0) // no previous element in hash bucket
125  {
126  table[index] = tmp2;
127  if (tmp2 != 0)
128  tmp2->hashprev = 0;
129  }
130  else // there is a previous element in the hash bucket
131  {
132  tmp1->hashnext = tmp2;
133  if (tmp2 != 0)
134  tmp2->hashprev = tmp1;
135  }
136 
137  // Relink elements in list
138 
139  tmp1 = curhashelem->listprev;
140  tmp2 = curhashelem->listnext;
141  if (tmp1 == 0) // curhashelem is first in list
142  {
143  firsthashelem = tmp2;
144  if (tmp2 != 0)
145  tmp2->listprev = 0;
146  else // curhashelem is also last in list
147  lasthashelem = 0;
148  }
149  else
150  {
151  tmp1->listnext = tmp2;
152  if (tmp2 != 0)
153  tmp2->listprev = tmp1;
154  else // curhashelem is last in list
155  lasthashelem = tmp1;
156  }
157 
158  // finally, with everything being relinked, we can delete curhashelem
159  RTPDelete(curhashelem,GetMemoryManager());
160  curhashelem = tmp2; // Set to next element in the list
161  }
162  else
163  return ERR_RTP_HASHTABLE_NOCURRENTELEMENT;
164  return 0;
165 }
166 
167 template<class Element,class GetIndex,int hashsize>
168 inline int RTPHashTable<Element,GetIndex,hashsize>::GotoElement(const Element &e)
169 {
170  int index;
171  bool found;
172 
173  index = GetIndex::GetIndex(e);
174  if (index >= hashsize)
175  return ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
176 
177  curhashelem = table[index];
178  found = false;
179  while(!found && curhashelem != 0)
180  {
181  if (curhashelem->GetElement() == e)
182  found = true;
183  else
184  curhashelem = curhashelem->hashnext;
185  }
186  if (!found)
187  return ERR_RTP_HASHTABLE_ELEMENTNOTFOUND;
188  return 0;
189 }
190 
191 template<class Element,class GetIndex,int hashsize>
192 inline bool RTPHashTable<Element,GetIndex,hashsize>::HasElement(const Element &e)
193 {
194  int index;
195  bool found;
196  HashElement *tmp;
197 
198  index = GetIndex::GetIndex(e);
199  if (index >= hashsize)
200  return false;
201 
202  tmp = table[index];
203  found = false;
204  while(!found && tmp != 0)
205  {
206  if (tmp->GetElement() == e)
207  found = true;
208  else
209  tmp = tmp->hashnext;
210  }
211  return found;
212 }
213 
214 template<class Element,class GetIndex,int hashsize>
215 inline void RTPHashTable<Element,GetIndex,hashsize>::GotoNextElement()
216 {
217  if (curhashelem)
218  curhashelem = curhashelem->listnext;
219 }
220 
221 template<class Element,class GetIndex,int hashsize>
222 inline void RTPHashTable<Element,GetIndex,hashsize>::GotoPreviousElement()
223 {
224  if (curhashelem)
225  curhashelem = curhashelem->listprev;
226 }
227 
228 template<class Element,class GetIndex,int hashsize>
229 inline void RTPHashTable<Element,GetIndex,hashsize>::Clear()
230 {
231  HashElement *tmp1,*tmp2;
232 
233  for (int i = 0 ; i < hashsize ; i++)
234  table[i] = 0;
235 
236  tmp1 = firsthashelem;
237  while (tmp1 != 0)
238  {
239  tmp2 = tmp1->listnext;
240  RTPDelete(tmp1,GetMemoryManager());
241  tmp1 = tmp2;
242  }
243  firsthashelem = 0;
244  lasthashelem = 0;
245 }
246 
247 template<class Element,class GetIndex,int hashsize>
248 inline int RTPHashTable<Element,GetIndex,hashsize>::AddElement(const Element &elem)
249 {
250  int index;
251  bool found;
252  HashElement *e,*newelem;
253 
254  index = GetIndex::GetIndex(elem);
255  if (index >= hashsize)
256  return ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
257 
258  e = table[index];
259  found = false;
260  while(!found && e != 0)
261  {
262  if (e->GetElement() == elem)
263  found = true;
264  else
265  e = e->hashnext;
266  }
267  if (found)
268  return ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS;
269 
270  // Okay, the key doesn't exist, so we can add the new element in the hash table
271 
272  newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(elem,index);
273  if (newelem == 0)
274  return ERR_RTP_OUTOFMEM;
275 
276  e = table[index];
277  table[index] = newelem;
278  newelem->hashnext = e;
279  if (e != 0)
280  e->hashprev = newelem;
281 
282  // Now, we still got to add it to the linked list
283 
284  if (firsthashelem == 0)
285  {
286  firsthashelem = newelem;
287  lasthashelem = newelem;
288  }
289  else // there already are some elements in the list
290  {
291  lasthashelem->listnext = newelem;
292  newelem->listprev = lasthashelem;
293  lasthashelem = newelem;
294  }
295  return 0;
296 }
297 
298 template<class Element,class GetIndex,int hashsize>
299 inline int RTPHashTable<Element,GetIndex,hashsize>::DeleteElement(const Element &elem)
300 {
301  int status;
302 
303  status = GotoElement(elem);
304  if (status < 0)
305  return status;
306  return DeleteCurrentElement();
307 }
308 
309 #ifdef RTPDEBUG
310 template<class Element,class GetIndex,int hashsize>
311 inline void RTPHashTable<Element,GetIndex,hashsize>::Dump()
312 {
313  HashElement *e;
314 
315  std::cout << "DUMPING TABLE CONTENTS:" << std::endl;
316  for (int i = 0 ; i < hashsize ; i++)
317  {
318  e = table[i];
319  while (e != 0)
320  {
321  e->Dump();
322  e = e->hashnext;
323  }
324  }
325 
326  std::cout << "DUMPING LIST CONTENTS:" << std::endl;
327  e = firsthashelem;
328  while (e != 0)
329  {
330  e->Dump();
331  e = e->listnext;
332  }
333 }
334 #endif // RTPDEBUG
335 
336 #endif // RTPHASHTABLE_H
337 
A memory manager.
Definition: rtpmemorymanager.h:144
#define RTPMEM_TYPE_OTHER
Used to indicate a general kind of memory block.
Definition: rtpmemorymanager.h:45