JRTPLIB  3.11.1
rtpkeyhashtable.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2017 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  JRTPLIB_UNUSED(memtype); // possibly unused
109 
110  for (int i = 0 ; i < hashsize ; i++)
111  table[i] = 0;
112  firsthashelem = 0;
113  lasthashelem = 0;
114 #ifdef RTP_SUPPORT_MEMORYMANAGEMENT
115  memorytype = memtype;
116 #endif // RTP_SUPPORT_MEMORYMANAGEMENT
117 }
118 
119 template<class Key,class Element,class GetIndex,int hashsize>
120 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteCurrentElement()
121 {
122  if (curhashelem)
123  {
124  HashElement *tmp1,*tmp2;
125  int index;
126 
127  // First, relink elements in current hash bucket
128 
129  index = curhashelem->GetHashIndex();
130  tmp1 = curhashelem->hashprev;
131  tmp2 = curhashelem->hashnext;
132  if (tmp1 == 0) // no previous element in hash bucket
133  {
134  table[index] = tmp2;
135  if (tmp2 != 0)
136  tmp2->hashprev = 0;
137  }
138  else // there is a previous element in the hash bucket
139  {
140  tmp1->hashnext = tmp2;
141  if (tmp2 != 0)
142  tmp2->hashprev = tmp1;
143  }
144 
145  // Relink elements in list
146 
147  tmp1 = curhashelem->listprev;
148  tmp2 = curhashelem->listnext;
149  if (tmp1 == 0) // curhashelem is first in list
150  {
151  firsthashelem = tmp2;
152  if (tmp2 != 0)
153  tmp2->listprev = 0;
154  else // curhashelem is also last in list
155  lasthashelem = 0;
156  }
157  else
158  {
159  tmp1->listnext = tmp2;
160  if (tmp2 != 0)
161  tmp2->listprev = tmp1;
162  else // curhashelem is last in list
163  lasthashelem = tmp1;
164  }
165 
166  // finally, with everything being relinked, we can delete curhashelem
167  RTPDelete(curhashelem,GetMemoryManager());
168  curhashelem = tmp2; // Set to next element in list
169  }
170  else
171  return ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT;
172  return 0;
173 }
174 
175 template<class Key,class Element,class GetIndex,int hashsize>
176 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoElement(const Key &k)
177 {
178  int index;
179  bool found;
180 
181  index = GetIndex::GetIndex(k);
182  if (index >= hashsize)
183  return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
184 
185  curhashelem = table[index];
186  found = false;
187  while(!found && curhashelem != 0)
188  {
189  if (curhashelem->GetKey() == k)
190  found = true;
191  else
192  curhashelem = curhashelem->hashnext;
193  }
194  if (!found)
195  return ERR_RTP_KEYHASHTABLE_KEYNOTFOUND;
196  return 0;
197 }
198 
199 template<class Key,class Element,class GetIndex,int hashsize>
200 inline bool RTPKeyHashTable<Key,Element,GetIndex,hashsize>::HasElement(const Key &k)
201 {
202  int index;
203  bool found;
204  HashElement *tmp;
205 
206  index = GetIndex::GetIndex(k);
207  if (index >= hashsize)
208  return false;
209 
210  tmp = table[index];
211  found = false;
212  while(!found && tmp != 0)
213  {
214  if (tmp->GetKey() == k)
215  found = true;
216  else
217  tmp = tmp->hashnext;
218  }
219  return found;
220 }
221 
222 template<class Key,class Element,class GetIndex,int hashsize>
223 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoNextElement()
224 {
225  if (curhashelem)
226  curhashelem = curhashelem->listnext;
227 }
228 
229 template<class Key,class Element,class GetIndex,int hashsize>
230 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoPreviousElement()
231 {
232  if (curhashelem)
233  curhashelem = curhashelem->listprev;
234 }
235 
236 template<class Key,class Element,class GetIndex,int hashsize>
237 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Clear()
238 {
239  HashElement *tmp1,*tmp2;
240 
241  for (int i = 0 ; i < hashsize ; i++)
242  table[i] = 0;
243 
244  tmp1 = firsthashelem;
245  while (tmp1 != 0)
246  {
247  tmp2 = tmp1->listnext;
248  RTPDelete(tmp1,GetMemoryManager());
249  tmp1 = tmp2;
250  }
251  firsthashelem = 0;
252  lasthashelem = 0;
253 }
254 
255 template<class Key,class Element,class GetIndex,int hashsize>
256 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::AddElement(const Key &k,const Element &elem)
257 {
258  int index;
259  bool found;
260  HashElement *e,*newelem;
261 
262  index = GetIndex::GetIndex(k);
263  if (index >= hashsize)
264  return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
265 
266  e = table[index];
267  found = false;
268  while(!found && e != 0)
269  {
270  if (e->GetKey() == k)
271  found = true;
272  else
273  e = e->hashnext;
274  }
275  if (found)
276  return ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS;
277 
278  // Okay, the key doesn't exist, so we can add the new element in the hash table
279 
280  newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(k,elem,index);
281  if (newelem == 0)
282  return ERR_RTP_OUTOFMEM;
283 
284  e = table[index];
285  table[index] = newelem;
286  newelem->hashnext = e;
287  if (e != 0)
288  e->hashprev = newelem;
289 
290  // Now, we still got to add it to the linked list
291 
292  if (firsthashelem == 0)
293  {
294  firsthashelem = newelem;
295  lasthashelem = newelem;
296  }
297  else // there already are some elements in the list
298  {
299  lasthashelem->listnext = newelem;
300  newelem->listprev = lasthashelem;
301  lasthashelem = newelem;
302  }
303  return 0;
304 }
305 
306 template<class Key,class Element,class GetIndex,int hashsize>
307 inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteElement(const Key &k)
308 {
309  int status;
310 
311  status = GotoElement(k);
312  if (status < 0)
313  return status;
314  return DeleteCurrentElement();
315 }
316 
317 #ifdef RTPDEBUG
318 template<class Key,class Element,class GetIndex,int hashsize>
319 inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Dump()
320 {
321  HashElement *e;
322 
323  std::cout << "DUMPING TABLE CONTENTS:" << std::endl;
324  for (int i = 0 ; i < hashsize ; i++)
325  {
326  e = table[i];
327  while (e != 0)
328  {
329  e->Dump();
330  e = e->hashnext;
331  }
332  }
333 
334  std::cout << "DUMPING LIST CONTENTS:" << std::endl;
335  e = firsthashelem;
336  while (e != 0)
337  {
338  e->Dump();
339  e = e->listnext;
340  }
341 }
342 #endif // RTPDEBUG
343 
344 } // end namespace
345 
346 #endif // RTPKEYHASHTABLE_H
Definition: rtpfaketransmitter.h:64
#define RTPMEM_TYPE_OTHER
Used to indicate a general kind of memory block.
Definition: rtpmemorymanager.h:45