JRTPLIB  3.9.0
rtpkeyhashtable.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2011 Jori Liesenborgs
5 
6  Contact: jori.liesenborgs@gmail.com
7 
8  This library was developed at the Expertise Centre for Digital 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 
37 #ifndef RTPKEYHASHTABLE_H
38 
39 #define RTPKEYHASHTABLE_H
40 
41 #include "rtpconfig.h"
42 #include "rtperrors.h"
43 #include "rtpmemoryobject.h"
44 
45 #ifdef RTPDEBUG
46 #include <iostream>
47 #endif // RTPDEBUG
48 
49 namespace jrtplib
50 {
51 
52 template<class Key,class Element,class GetIndex,int hashsize>
53 class RTPKeyHashTable : public RTPMemoryObject
54 {
55 public:
56  RTPKeyHashTable(RTPMemoryManager *mgr = 0,int memtype = RTPMEM_TYPE_OTHER);
57  ~RTPKeyHashTable() { Clear(); }
58 
59  void GotoFirstElement() { curhashelem = firsthashelem; }
60  void GotoLastElement() { curhashelem = lasthashelem; }
61  bool HasCurrentElement() { return (curhashelem == 0)?false:true; }
62  int DeleteCurrentElement();
63  Element &GetCurrentElement() { return curhashelem->GetElement(); }
64  Key &GetCurrentKey() { return curhashelem->GetKey(); }
65  int GotoElement(const Key &k);
66  bool HasElement(const Key &k);
67  void GotoNextElement();
68  void GotoPreviousElement();
69  void Clear();
70 
71  int AddElement(const Key &k,const Element &elem);
72  int DeleteElement(const Key &k);
73 
74 #ifdef RTPDEBUG
75  void Dump();
76 #endif // RTPDEBUG
77 private:
78  class HashElement
79  {
80  public:
81  HashElement(const Key &k,const Element &e,int index):key(k),element(e) { hashprev = 0; hashnext = 0; listnext = 0; listprev = 0; hashindex = index; }
82  int GetHashIndex() { return hashindex; }
83  Key &GetKey() { return key; }
84  Element &GetElement() { return element; }
85 #ifdef RTPDEBUG
86  void Dump() { std::cout << "\tHash index " << hashindex << " | Key " << key << " | Element " << element << std::endl; }
87 #endif // RTPDEBUG
88  private:
89  int hashindex;
90  Key key;
91  Element element;
92  public:
93  HashElement *hashprev,*hashnext;
94  HashElement *listprev,*listnext;
95  };
96 
97  HashElement *table[hashsize];
98  HashElement *firsthashelem,*lasthashelem;
99  HashElement *curhashelem;
100 #ifdef RTP_SUPPORT_MEMORYMANAGEMENT
101  int memorytype;
102 #endif // RTP_SUPPORT_MEMORYMANAGEMENT
103 };
104 
105 template<class Key,class Element,class GetIndex,int hashsize>
106 inline RTPKeyHashTable<Key,Element,GetIndex,hashsize>::RTPKeyHashTable(RTPMemoryManager *mgr,int memtype) : RTPMemoryObject(mgr)
107 {
108  for (int i = 0 ; i < hashsize ; i++)
109  table[i] = 0;
110  firsthashelem = 0;
111  lasthashelem = 0;
112 #ifdef RTP_SUPPORT_MEMORYMANAGEMENT
113  memorytype = memtype;
114 #endif // RTP_SUPPORT_MEMORYMANAGEMENT
115 }
116 
117 template<class Key,class Element,class GetIndex,int hashsize>
118 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteCurrentElement()
119 {
120  if (curhashelem)
121  {
122  HashElement *tmp1,*tmp2;
123  int index;
124 
125  // First, relink elements in current hash bucket
126 
127  index = curhashelem->GetHashIndex();
128  tmp1 = curhashelem->hashprev;
129  tmp2 = curhashelem->hashnext;
130  if (tmp1 == 0) // no previous element in hash bucket
131  {
132  table[index] = tmp2;
133  if (tmp2 != 0)
134  tmp2->hashprev = 0;
135  }
136  else // there is a previous element in the hash bucket
137  {
138  tmp1->hashnext = tmp2;
139  if (tmp2 != 0)
140  tmp2->hashprev = tmp1;
141  }
142 
143  // Relink elements in list
144 
145  tmp1 = curhashelem->listprev;
146  tmp2 = curhashelem->listnext;
147  if (tmp1 == 0) // curhashelem is first in list
148  {
149  firsthashelem = tmp2;
150  if (tmp2 != 0)
151  tmp2->listprev = 0;
152  else // curhashelem is also last in list
153  lasthashelem = 0;
154  }
155  else
156  {
157  tmp1->listnext = tmp2;
158  if (tmp2 != 0)
159  tmp2->listprev = tmp1;
160  else // curhashelem is last in list
161  lasthashelem = tmp1;
162  }
163 
164  // finally, with everything being relinked, we can delete curhashelem
165  RTPDelete(curhashelem,GetMemoryManager());
166  curhashelem = tmp2; // Set to next element in list
167  }
168  else
169  return ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT;
170  return 0;
171 }
172 
173 template<class Key,class Element,class GetIndex,int hashsize>
174 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoElement(const Key &k)
175 {
176  int index;
177  bool found;
178 
179  index = GetIndex::GetIndex(k);
180  if (index >= hashsize)
181  return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
182 
183  curhashelem = table[index];
184  found = false;
185  while(!found && curhashelem != 0)
186  {
187  if (curhashelem->GetKey() == k)
188  found = true;
189  else
190  curhashelem = curhashelem->hashnext;
191  }
192  if (!found)
193  return ERR_RTP_KEYHASHTABLE_KEYNOTFOUND;
194  return 0;
195 }
196 
197 template<class Key,class Element,class GetIndex,int hashsize>
198 inline bool RTPKeyHashTable<Key,Element,GetIndex,hashsize>::HasElement(const Key &k)
199 {
200  int index;
201  bool found;
202  HashElement *tmp;
203 
204  index = GetIndex::GetIndex(k);
205  if (index >= hashsize)
206  return false;
207 
208  tmp = table[index];
209  found = false;
210  while(!found && tmp != 0)
211  {
212  if (tmp->GetKey() == k)
213  found = true;
214  else
215  tmp = tmp->hashnext;
216  }
217  return found;
218 }
219 
220 template<class Key,class Element,class GetIndex,int hashsize>
221 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoNextElement()
222 {
223  if (curhashelem)
224  curhashelem = curhashelem->listnext;
225 }
226 
227 template<class Key,class Element,class GetIndex,int hashsize>
228 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoPreviousElement()
229 {
230  if (curhashelem)
231  curhashelem = curhashelem->listprev;
232 }
233 
234 template<class Key,class Element,class GetIndex,int hashsize>
235 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Clear()
236 {
237  HashElement *tmp1,*tmp2;
238 
239  for (int i = 0 ; i < hashsize ; i++)
240  table[i] = 0;
241 
242  tmp1 = firsthashelem;
243  while (tmp1 != 0)
244  {
245  tmp2 = tmp1->listnext;
246  RTPDelete(tmp1,GetMemoryManager());
247  tmp1 = tmp2;
248  }
249  firsthashelem = 0;
250  lasthashelem = 0;
251 }
252 
253 template<class Key,class Element,class GetIndex,int hashsize>
254 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::AddElement(const Key &k,const Element &elem)
255 {
256  int index;
257  bool found;
258  HashElement *e,*newelem;
259 
260  index = GetIndex::GetIndex(k);
261  if (index >= hashsize)
262  return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
263 
264  e = table[index];
265  found = false;
266  while(!found && e != 0)
267  {
268  if (e->GetKey() == k)
269  found = true;
270  else
271  e = e->hashnext;
272  }
273  if (found)
274  return ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS;
275 
276  // Okay, the key doesn't exist, so we can add the new element in the hash table
277 
278  newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(k,elem,index);
279  if (newelem == 0)
280  return ERR_RTP_OUTOFMEM;
281 
282  e = table[index];
283  table[index] = newelem;
284  newelem->hashnext = e;
285  if (e != 0)
286  e->hashprev = newelem;
287 
288  // Now, we still got to add it to the linked list
289 
290  if (firsthashelem == 0)
291  {
292  firsthashelem = newelem;
293  lasthashelem = newelem;
294  }
295  else // there already are some elements in the list
296  {
297  lasthashelem->listnext = newelem;
298  newelem->listprev = lasthashelem;
299  lasthashelem = newelem;
300  }
301  return 0;
302 }
303 
304 template<class Key,class Element,class GetIndex,int hashsize>
305 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteElement(const Key &k)
306 {
307  int status;
308 
309  status = GotoElement(k);
310  if (status < 0)
311  return status;
312  return DeleteCurrentElement();
313 }
314 
315 #ifdef RTPDEBUG
316 template<class Key,class Element,class GetIndex,int hashsize>
317 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Dump()
318 {
319  HashElement *e;
320 
321  std::cout << "DUMPING TABLE CONTENTS:" << std::endl;
322  for (int i = 0 ; i < hashsize ; i++)
323  {
324  e = table[i];
325  while (e != 0)
326  {
327  e->Dump();
328  e = e->hashnext;
329  }
330  }
331 
332  std::cout << "DUMPING LIST CONTENTS:" << std::endl;
333  e = firsthashelem;
334  while (e != 0)
335  {
336  e->Dump();
337  e = e->listnext;
338  }
339 }
340 #endif // RTPDEBUG
341 
342 } // end namespace
343 
344 #endif // RTPKEYHASHTABLE_H
#define RTPMEM_TYPE_OTHER
Used to indicate a general kind of memory block.
Definition: rtpmemorymanager.h:45