HPCToolkit
HashTable.cpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 /******************************************************************************
48  * *
49  * File: C++ Hash Table Utility *
50  * Author: Kevin Cureton *
51  * Date: March 1993 *
52  * *
53  * See the include file HashTable.h for an explanation of the *
54  * data and functions in the HashTable class. *
55  * *
56  * Programming Environment Project *
57  * *
58  *****************************************************************************/
59 
60 //************************** System Include Files ***************************
61 
62 #include <iostream>
63 
64 #ifdef NO_STD_CHEADERS
65 # include <stdlib.h>
66 # include <string.h>
67 #else
68 # include <cstdlib>
69 # include <cstring>
70 using namespace std; // For compatibility with non-std C headers
71 #endif
72 
73 //*************************** User Include Files ****************************
74 
75 #include <include/gcc-attr.h>
76 
77 #include "HashTable.hpp"
78 
80 
81 /******************************* local defines *******************************/
82 
83 using std::cout;
84 using std::endl;
85 
86 static const int FIRST_SLOT = 0;
87 static const int EMPTY = -1;
88 static const int DELETED = -2;
89 static const int INVALID_INDEX = -99;
90 
91 static const int ENTRY_DEPTH_FOR_HASHING = 32;
92 static const int LOOKING_FOR_AN_INDEX = 1;
93 
94 static ulong NEXT_ID = 0;
95 
96 /******************* HashTable static function prototypes ********************/
97 
98 static uint DefaultHashFunct (const void* entry, const uint size);
99 static uint DefaultRehashFunct (const uint oldHashValue, const uint size);
100 static int DefaultEntryCompare (const void* entry1, const void* entry2);
101 static void DefaultEntryCleanup (void* entry);
102 
103 /********************* HashTable public member functions *********************/
104 
105 //
106 //
108  : id(NEXT_ID++)
109 {
110  numSlots = 0;
112  entrySize = 0;
113  entries = (void*)NULL;
114  indexSetSize = 0;
115  indexSet = (int*)NULL ;
116 
117  hashTableCreated = false;
118 
123 
124  return;
125 }
126 
127 //
128 //
130 {
131  if (hashTableCreated)
132  {
134  }
135 }
136 
137 //
138 //
139 void HashTable::Create (const uint theEntrySize, uint initialSlots,
140  HashFunctFunctPtr const _HashFunctCallback,
141  RehashFunctFunctPtr const _RehashFunctCallback,
142  EntryCompareFunctPtr const _EntryCompareCallback,
143  EntryCleanupFunctPtr const _EntryCleanupCallback)
144 {
145 
146  if (!hashTableCreated)
147  {
148  register unsigned int power = 0, i = 31;
149 
150  if (initialSlots < 8) initialSlots = 8;
151 
152  while (i > 1) // compute size for the sparse index set
153  {
154  if (initialSlots & (1 << i))
155  {
156  if (i < 20) power = (1 << (i + 2)) - 1;
157  else power = (1 << i) - 1;
158  break;
159  }
160  i--;
161  }
162 
163  numSlots = initialSlots;
165  entrySize = theEntrySize;
166  entries = (void*) new char[entrySize * numSlots];
167  indexSetSize = power;
168  indexSet = new int[indexSetSize];
169 
170  memset (entries, 0, entrySize * numSlots);
171 
172  for (i = 0; i < indexSetSize; i++) indexSet[i] = EMPTY;
173 
174  // Set the function pointer and the HashTable will use those
175  // instead of the virtual functions. If any are left out (or
176  // set NULL by the user) just use the virtual function as a
177  // default.
178  if (_HashFunctCallback) HashFunctCallback = _HashFunctCallback;
179 
180  if (_RehashFunctCallback) RehashFunctCallback = _RehashFunctCallback;
181 
182  if (_EntryCompareCallback) EntryCompareCallback = _EntryCompareCallback;
183 
184  if (_EntryCleanupCallback) EntryCleanupCallback = _EntryCleanupCallback;
185 
186 # ifdef DEBUG
187  cerr << "\tHashTable::HashTable" << "\n"
188  << "\t\tnumSlots: " << numSlots << "\n"
189  << "\t\tnextSlot: " << nextSlot << "\n"
190  << "\t\tentrySize: " << entrySize << "\n"
191  << "\t\tentries: " << entries << "\n"
192  << "\t\tindexSetSize: " << indexSetSize << "\n"
193  << "\t\tindexSet: " << indexSet << "\n"
194  << endl;
195 # endif
196 
197  hashTableCreated = true;
198  }
199 
200  return;
201 }
202 
203 //
204 //
206 {
207  if (hashTableCreated)
208  {
209  char* cEntries = (char*)entries;
210  for (unsigned int entryIndex = 0; entryIndex < nextSlot; entryIndex++)
211  {
212  EntryCleanup(cEntries);
213  cEntries += entrySize;
214  }
215  delete [] (char*)entries;
216  delete [] (char*)indexSet;
217 
218  numSlots = 0;
219  nextSlot = FIRST_SLOT;
220  entrySize = 0;
221  entries = NULL;
222  indexSetSize = 0;
223  indexSet = NULL;
224  hashTableCreated = false;
225 
230  }
231 }
232 
233 //
234 // Explicitly defined to prevent usage.
236 {
237  DIAG_Die("Should not call HashTable::operator=()!");
238  return *this;
239 }
240 
241 //
242 //
244 {
245  return (id == rhsTab.id);
246 }
247 
248 //
249 //
250 void HashTable::AddEntry (void* entry, AddEntryFunctPtr const AddEntryCallback, ...)
251 {
252  if (hashTableCreated)
253  {
254  va_list argList;
255  int index = QueryIndexSet (entry, true);
256  char* cEntries = (char*)entries;
257 
258  DIAG_Assert(index != INVALID_INDEX, "");
259 
260 # ifdef DEBUG
261  cerr << "HashTable::AddEntry: using index " << index
262  << endl;
263 # endif
264 
265  if (indexSet[index] < 0)
266  { // add entry
267  indexSet[index] = nextSlot++;
268  memcpy (&cEntries[entrySize * indexSet[index]], entry, entrySize);
269  if (nextSlot == numSlots) OverflowEntries ();
270  }
271  else
272  { // entry already present
273  if (AddEntryCallback != NULL)
274  {
275  va_start (argList, AddEntryCallback);
276  AddEntryCallback ((void*)&cEntries[entrySize * indexSet[index]],
277  entry, argList);
278  va_end (argList);
279  }
280  else
281  {
282  EntryCleanup ((void*)&cEntries[entrySize * indexSet[index]]);
283  memcpy (&cEntries[entrySize * indexSet[index]], entry, entrySize);
284  }
285  }
286  }
287  else
288  {
290  return;
291  }
292 }
293 
294 //
295 //
296 void HashTable::DeleteEntry (void* entry, DeleteEntryFunctPtr const DeleteEntryCallback, ...)
297 {
298  if (hashTableCreated)
299  {
300  va_list argList;
301  int index = QueryIndexSet (entry, false);
302  char* cEntries = (char*) entries;
303 
304  if (index == INVALID_INDEX || indexSet[index] == EMPTY || indexSet[index] == DELETED)
305  { // entry doesn't exist
306 # ifdef DEBUG
307  cerr << "\tHashTable::DeleteEntry: entry not found."
308  << endl;
309 # endif
310  }
311  else
312  { // move the last entry into the vacant slot and fix the index set
313 # ifdef DEBUG
314  cerr << "\tHashTable::DeleteEntry: deleting entry for index " << index
315  << endl;
316 # endif
317 
318  int last = nextSlot - 1;
319 
320 # ifdef DEBUG
321  cerr << "\tHashTable::DeleteEntry: moving last entry to empty slot."
322  << endl;
323 # endif
324 
325  if (last >= 0)
326  {
327  if (indexSet[index] != last)
328  {
329  char* tempEntry = new char[entrySize];
330  int tempIndexSetValue = 0;
331  int toIndex = index;
332  int fromIndex = QueryIndexSet (&cEntries[last * entrySize], false);
333 
334  memcpy (tempEntry,
335  &cEntries[entrySize * indexSet[toIndex]],
336  entrySize);
337  memcpy (&cEntries[entrySize * indexSet[toIndex]],
338  &cEntries[entrySize * indexSet[fromIndex]],
339  entrySize);
340  memcpy (&cEntries[entrySize * indexSet[fromIndex]],
341  tempEntry,
342  entrySize);
343 
344  tempIndexSetValue = indexSet[toIndex];
345  indexSet[toIndex] = indexSet[fromIndex];
346  indexSet[fromIndex] = tempIndexSetValue;
347 
348  delete [] tempEntry;
349  }
350 
351  nextSlot = last;
352  indexSet[index] = DELETED;
353 
354  if (DeleteEntryCallback != NULL)
355  {
356  va_start (argList, DeleteEntryCallback);
357  DeleteEntryCallback ((void*)&cEntries[last * entrySize], argList);
358  va_end (argList);
359  }
360  else
361  {
362  EntryCleanup ((void*)&cEntries[last * entrySize]);
363  }
364 
365  memset (&cEntries[entrySize * last], 0, entrySize); // finish deletion
366  }
367  else
368  { // there is only one entry left in the table
369  nextSlot = 0;
370  indexSet[index] = DELETED;
371 
372  if (DeleteEntryCallback != NULL)
373  {
374  va_start (argList, DeleteEntryCallback);
375  DeleteEntryCallback ((void*)&cEntries[0], argList);
376  va_end (argList);
377  }
378  else
379  {
380  EntryCleanup ((void*)&cEntries[0]);
381  }
382 
383  memset (&cEntries[0], 0, entrySize); // finish deletion
384  }
385  }
386  }
387  else
388  {
390  return;
391  }
392 }
393 
394 //
395 //
396 void* HashTable::QueryEntry (const void* entry) const
397 {
398  if (hashTableCreated)
399  {
400  int index = QueryIndexSet (entry, false);
401  char* cEntries = (char*) entries;
402 
403 # ifdef DEBUG
404  cerr << "\tHashTable::QueryEntry (" << entry << ")."
405  << endl;
406 # endif
407 
408  if (index == INVALID_INDEX || indexSet[index] == EMPTY || indexSet[index] == DELETED)
409  {
410  return (void*)NULL;
411  }
412  else
413  {
414  return (void*)(&cEntries[entrySize * indexSet[index]]);
415  }
416  }
417  else
418  {
420  return (void*)NULL;
421  }
422 }
423 
424 //
425 //
426 int HashTable::GetEntryIndex (const void* entry) const
427 {
428  if (hashTableCreated)
429  {
430  int index = QueryIndexSet (entry, false);
431 
432  if (index == INVALID_INDEX || indexSet[index] < 0) return EMPTY;
433  else return indexSet[index];
434  }
435  else
436  {
438  return EMPTY;
439  }
440 }
441 
442 //
443 //
444 void* HashTable::GetEntryByIndex (const uint index) const
445 {
446  if (hashTableCreated)
447  {
448  if (index >= nextSlot) return (void*)NULL;
449  else return (void*)&((char*)entries)[entrySize * index];
450  }
451  else
452  {
454  return (void*)NULL;
455  }
456 }
457 
458 //
459 //
461 {
462  if (hashTableCreated)
463  {
464  return nextSlot;
465  }
466  else
467  {
469  return 0;
470  }
471 }
472 
473 //
474 //
476 {
477  cout << "HashTable: " << this << " (id: " << id << ")" << endl;
478  if (hashTableCreated) {
479  HashTableIterator stp(this);
480  int i;
481 
482  for (i =0; stp.Current(); stp++, i++) {
483  cout << i << " : indx " << GetEntryIndex(stp.Current())
484  << " : ptr " << stp.Current() << endl;
485  }
486  } else {
487  cout << " NOT CREATED" << endl;
488  }
489 }
490 
491 /******************* HashTable protected member functions ********************/
492 
493 //
494 //
495 void HashTable::Create (const uint theEntrySize, uint initialSlots)
496 {
497  if (!hashTableCreated)
498  {
499  register unsigned int power = 0, i = 31;
500 
501  if (initialSlots < 8) initialSlots = 8;
502 
503  while (i > 1) // compute size for the sparse index set
504  {
505  if (initialSlots & (1 << i))
506  {
507  if (i < 20) power = (1 << (i + 2)) - 1;
508  else power = (1 << i) - 1;
509  break;
510  }
511  i--;
512  }
513 
514  numSlots = initialSlots;
516  entrySize = theEntrySize;
517  entries = (void*) new char[entrySize * numSlots];
518  indexSetSize = power;
519  indexSet = new int[indexSetSize];
520 
521  memset (entries, 0, entrySize * numSlots);
522 
523  for (i = 0; i < indexSetSize; i++) indexSet[i] = EMPTY;
524 
525 # ifdef DEBUG
526  cerr << "\tHashTable::HashTable\n"
527  << "\t\tnumSlots: " << numSlots << "\n"
528  << "\t\tnextSlot: " << nextSlot << "\n"
529  << "\t\tentrySize: " << entrySize << "\n"
530  << "\t\tentries: " << entries << "\n"
531  << "\t\tindexSetSize: " << indexSetSize << "\n"
532  << "\t\tindexSet: " << indexSet << "\n"
533  << endl;
534 # endif
535 
536  hashTableCreated = true;
537  }
538 
539  return;
540 }
541 
542 //
543 //
544 uint HashTable::HashFunct (const void* entry, const uint size)
545 {
546  return HashFunctCallback (entry, size);
547 }
548 
549 //
550 //
551 uint HashTable::RehashFunct (const uint oldHashValue, const uint size)
552 {
553  return RehashFunctCallback (oldHashValue, size);
554 }
555 
556 //
557 //
558 int HashTable::EntryCompare (const void* entry1, const void* entry2)
559 {
560  return EntryCompareCallback (entry1, entry2);
561 }
562 
563 //
564 //
565 void HashTable::EntryCleanup (void* entry)
566 {
567  EntryCleanupCallback (entry);
568 }
569 
570 /********************* HashTable private member functions ********************/
571 
572 //
573 //
574 int HashTable::QueryIndexSet (const void* entry, const bool addingEntry) const
575 {
576  int initialIndex, currentIndex;
577  int firstDeletedIndex = INVALID_INDEX;
578  int rehashCount = 0;
579  char* cEntries = (char*)entries;
580  HashTable* This = (HashTable*)this; // for circumventing const'ness
581 
582  currentIndex = initialIndex = This->HashFunct(entry, indexSetSize);
583 
584 # ifdef DEBUG
585  cerr << "\tHashTable::QueryIndexSet(" << entry << ", " << addingEntry << ")."
586  << endl;
587 # endif
588 
589  while (LOOKING_FOR_AN_INDEX)
590  {
591  switch (indexSet[currentIndex])
592  {
593  case EMPTY:
594  if (firstDeletedIndex != INVALID_INDEX)
595  { // if there was a "DELETED" slot before the "EMPTY" slot, use it.
596  return firstDeletedIndex;
597  }
598  else
599  { // otherwise, use the "EMPTY" slot.
600  return currentIndex;
601  }
602 
603  case DELETED:
604  if (firstDeletedIndex != INVALID_INDEX)
605  {
606  if (firstDeletedIndex == currentIndex)
607  { // wrapped the table, use this first "DELETED" slot.
608  return currentIndex;
609  }
610  }
611  else
612  { // tag the first encountered "DELETED" slot for the future.
613  firstDeletedIndex = currentIndex;
614  }
615  break;
616 
617  default:
618  if (This->EntryCompare(entry,
619  &cEntries[entrySize * indexSet[currentIndex]]) == 0)
620  {
621  return currentIndex;
622  }
623  break;
624  }
625 
626 # ifdef DEBUG
627  cerr << "\tRehashing the Index"
628  << endl;
629 # endif
630 
631  currentIndex = This->RehashFunct(currentIndex, indexSetSize);
632  rehashCount ++;
633 
634  if (addingEntry)
635  { // if we've rehashed to much and the table is more than half full or
636  // we've wrapped the table looking for an empty slot, then
637  // increase the size of the table and rehash the entries fix problem.
638  if (((rehashCount > 10) && ((2 * nextSlot) > indexSetSize)) ||
639  (currentIndex == initialIndex))
640  {
641  This->OverflowIndexSet ();
642  return QueryIndexSet (entry, false);
643  }
644  }
645  else if (currentIndex == initialIndex)
646  { // not adding an entry and we've wrapped table looking for the entry.
647  // conclusion is it's not here, so let's leave.
648  return INVALID_INDEX;
649  }
650  }
651 }
652 
654 //
655 // The indexSet table can overflow for two very different reasons:
656 //
657 // (1) It is full. This only happens with a reasonably good distribution
658 // from the Hash function. (Check the collision limit code in
659 // HashTableIndexSet(). If we get here with a full table, we should add
660 // a reasonable increment -- after all, the indexSet table is designed
661 // to be a sparse table. (See the code in HashTable() that picks the
662 // indexSet set size as a function of the number of requested slots.)
663 //
664 // (2) We're getting bad behavior from the hash function and the table
665 // is moderately full. (The combination of a table that is over
666 // 50% full and an insertion that has more than ten probes triggers
667 // an overflow.) In this case, we'd like to change the distribution.
668 // Typically, two factors make a difference here: the density of
669 // entries in the indexSet table and numerical properties involving
670 // the MOD oepration in the hash function.
671 //
672 // So, after much discussion and some limited experimentation, we chose
673 // the following scheme. The indexSet set size is enlarged by roughly the
674 // number of symbols already entered (nextSlot).
675 //
676 // I say "roughly", because we first mask off the low order bit to ensure
677 // that the increment is even. This keeps the rehash quotient relatively
678 // prime to the size of the indexSet table. It also ensures that the MOD
679 // operation in the hash function is taken relative to an odd number.
680 // This keeps it from being a simple masking off of some high order bits.
681 // (We hope that this changes the distribution radically in pathological
682 // cases. Our thinking is that too many collisions should trigger a
683 // resize on the indexSet set. In turn, that should change the distribution
684 // enough to get us out of the collisions.
685 //
686 // Linda Torczon suggested the rehash limit. The decisions about
687 // incremental size increases for both indexSet and Entries sets were the
688 // result of a lengthy discussion. We hope that this scheme avoids
689 // most pathology and provides reasonable behavior.
690 //
692 
693 //
694 //
696 {
697  register unsigned int i, initialIndex, finalIndex, size;
698  char* cEntries = (char*)entries;
699 
700  if (indexSetSize < 4096)
701  { // big table => more careful choice
702  size = indexSetSize + 1024; // small table => big increment
703  } // big table => more careful choice
704  else
705  { // big table => more careful choice
706  size = nextSlot & 0xFFFFFFFE; // make it even
707  size += indexSetSize; // add number of entries to index set
708  }
709 
710 # ifdef DEBUG
711  cerr << "\tHashTable::OverflowIndexSet: old size: " << indexSetSize
712  << ", new size: " << size
713  << endl;
714 # endif
715 
716  indexSetSize = size;
717 
718  if (indexSet != 0) delete [] indexSet;
719 
720  indexSet = new int[indexSetSize];
721 
722  for (i = 0; i < indexSetSize; i++) indexSet[i] = EMPTY;
723 
724  for (i = 0; i < nextSlot; i++)
725  {
726  finalIndex = initialIndex = HashFunct (&cEntries[entrySize * i], indexSetSize);
727 
728  while(indexSet[finalIndex] != EMPTY)
729  {
730 # ifdef DEBUG
731  cerr << "\tRehashing for OverflowIndexSet()"
732  << endl;
733 # endif
734 
735  finalIndex = RehashFunct (finalIndex, indexSetSize);
736  DIAG_Assert(finalIndex != initialIndex, "shouldn't wrap table w/o allocating an index");
737  }
738 
739  indexSet[finalIndex] = i;
740  }
741 
742  return;
743 }
744 
745 //
746 //
748 {
749  int newSlots, newSize, oldSize;
750  char* ptr;
751 
752  if (numSlots < 4096) newSlots = numSlots + 512;
753  else if (numSlots < 16384) newSlots = numSlots + 2048;
754  else newSlots = (int) (1.33 * numSlots);
755 
756  oldSize = numSlots * entrySize;
757  newSize = newSlots * entrySize;
758 
759  ptr = new char [newSize];
760  memset (ptr, 0, newSize);
761  memcpy (ptr, entries, oldSize); // copy the old values
762 
763  delete [] (char*)entries; // and replace it
764  entries = ptr;
765 
766 # ifdef DEBUG
767  cerr << "\tHashTable::OverflowEntries: old slots: " << numSlots
768  << ", new slots: " << newSlots
769  << endl;
770 # endif
771 
772  numSlots = newSlots;
773 
774  return;
775 }
776 
777 //
778 //
780 {
781  DIAG_Die("Failure to call Create() before using the HashTable");
782 }
783 
784 //
785 //
787 {
788  DIAG_Die("Failure to call Destroy() before deleting the HashTable");
789 }
790 
791 /************************ HashTable extern functions *************************/
792 
793 //
794 //
795 uint IntegerHashFunct (const int value, const uint size)
796 {
797  return (uint)((int)value % size);
798 }
799 
800 //
801 //
802 uint IntegerRehashHashFunct (const uint oldHashValue, const uint size)
803 {
804  // 16 is relatively prime to a Mersenne prime!
805  return (uint)((oldHashValue + 16) % size);
806 }
807 
808 //
809 //
810 int IntegerEntryCompare (const int value1, const int value2)
811 {
812  return (int)((int)value1 != (int)value2);
813 }
814 
815 //
816 //
817 uint StringHashFunct (const void* entry, const uint size)
818 {
819  uint result = 0;
820  char* cEntry = (char*) entry;
821  unsigned char c;
822 
823  for (int i = 0; (i < ENTRY_DEPTH_FOR_HASHING) && (*cEntry != '\000'); i++)
824  {
825  c = (unsigned char) *cEntry++;
826  result += (c & 0x3f);
827  result = (result << 5) + (result >> 27);
828  }
829 
830  return (result % size);
831 }
832 
833 //
834 //
835 uint StringRehashFunct (const uint oldHashValue, const uint size)
836 {
837  // 16 is relatively prime to a Mersenne prime!
838  return (uint)((oldHashValue + 16) % size);
839 }
840 
841 //
842 //
843 int StringEntryCompare (const void* entry1, const void* entry2)
844 {
845  char* cEntry1 = (char*)entry1;
846  char* cEntry2 = (char*)entry2;
847 
848  return strcmp (cEntry1, cEntry2);
849 }
850 
851 /************************ HashTable static functions *************************/
852 
853 //
854 //
855 static uint DefaultHashFunct (const void* GCC_ATTR_UNUSED entry,
856  const uint GCC_ATTR_UNUSED size)
857 {
858  DIAG_Die("Failure to specify HashFunct function.");
859  return 0;
860 }
861 
862 //
863 //
864 static uint DefaultRehashFunct (const uint oldHashValue, const uint size)
865 {
866  uint newHashValue;
867 
868  // 16 is relatively prime to a Mersenne prime!
869  newHashValue = (oldHashValue + 16) % size;
870 
871 # ifdef DEBUG
872  cerr << "\tHashTable::DefaultRehashFunct\t" << oldHashValue
873  << " ---> " << newHashValue
874  << endl;
875 # endif
876 
877  return newHashValue;
878 }
879 
880 //
881 //
882 static int DefaultEntryCompare (const void* GCC_ATTR_UNUSED entry1,
883  const void* GCC_ATTR_UNUSED entry2)
884 {
885  DIAG_Die("Failure to specify EntryCompare function.");
886  return 0;
887 }
888 
889 //
890 //
891 static void DefaultEntryCleanup (void* GCC_ATTR_UNUSED entry)
892 {
893 # ifdef DEBUG
894  cerr << "\tHashTable::DefaultEntryCleanup\t" << (int)entry
895  << endl;
896 # endif
897 
898  return;
899 }
900 
901 /****************** HashTableIterator public member functions ****************/
902 
903 //
904 //
906 {
907  hashTable = (HashTable*)theHashTable;
908 
910 
911  return;
912 }
913 
914 //
915 //
917 {
918  return;
919 }
920 
921 //
922 //
924 {
925  currentEntryNumber--;
926 
927  return;
928 }
929 
930 //
931 //
933 {
934  // Second condition could still arise if someone tries to access the
935  // current entry after calling DeleteEntry on it.
936 
937  if (currentEntryNumber >= 0 &&
938  (unsigned int)currentEntryNumber < ((HashTable*)hashTable)->nextSlot)
939  {
940  char* cEntries = (char*)((HashTable*)hashTable)->entries;
941 
942  return (void*)&cEntries[currentEntryNumber * ((HashTable*)hashTable)->entrySize];
943  }
944  else
945  {
946  return (void*)NULL;
947  }
948 }
949 
950 //
951 //
953 {
954  currentEntryNumber = ((HashTable*)hashTable)->nextSlot - 1;
955 
956  return;
957 }
void FailureToDestroyError() const
Definition: HashTable.cpp:786
EntryCleanupFunctPtr EntryCleanupCallback
Definition: HashTable.hpp:365
int IntegerEntryCompare(const int value1, const int value2)
Definition: HashTable.cpp:810
int(* EntryCompareFunctPtr)(const void *, const void *)
Definition: HashTable.hpp:300
virtual uint RehashFunct(const uint oldHashValue, const uint size)
Definition: HashTable.cpp:551
bool hashTableCreated
Definition: HashTable.hpp:360
static const int EMPTY
Definition: HashTable.cpp:87
HashTable & operator=(const HashTable &rhs)
Definition: HashTable.cpp:235
static void DefaultEntryCleanup(void *entry)
static const int INVALID_INDEX
Definition: HashTable.cpp:89
void Create(const uint entrySize, uint initialSize, HashFunctFunctPtr const HashFunctCallback, RehashFunctFunctPtr const RehashFunctCallback, EntryCompareFunctPtr const EntryCompareCallback, EntryCleanupFunctPtr const EntryCleanupCallback)
Definition: HashTable.cpp:139
EntryCompareFunctPtr EntryCompareCallback
Definition: HashTable.hpp:364
static uint DefaultRehashFunct(const uint oldHashValue, const uint size)
Definition: HashTable.cpp:864
void * entries
Definition: HashTable.hpp:356
void OverflowEntries()
Definition: HashTable.cpp:747
uint entrySize
Definition: HashTable.hpp:355
void(* DeleteEntryFunctPtr)(void *, va_list)
Definition: HashTable.hpp:291
uint StringHashFunct(const void *entry, const uint size)
Definition: HashTable.cpp:817
uint(* HashFunctFunctPtr)(const void *, const uint)
Definition: HashTable.hpp:294
virtual void EntryCleanup(void *entry)
Definition: HashTable.cpp:565
uint IntegerHashFunct(const int value, const uint size)
Definition: HashTable.cpp:795
virtual ~HashTable()
Definition: HashTable.cpp:129
uint(* RehashFunctFunctPtr)(const uint, const uint)
Definition: HashTable.hpp:297
uint numSlots
Definition: HashTable.hpp:353
static const int DELETED
Definition: HashTable.cpp:88
void operator++(int)
Definition: HashTable.cpp:923
static int DefaultEntryCompare(const void *entry1, const void *entry2)
const ulong id
Definition: HashTable.hpp:352
RehashFunctFunctPtr RehashFunctCallback
Definition: HashTable.hpp:363
void OverflowIndexSet()
Definition: HashTable.cpp:695
bool operator==(HashTable &rhsTab)
Definition: HashTable.cpp:243
unsigned long int ulong
Definition: uint.h:128
static ulong NEXT_ID
Definition: HashTable.cpp:94
static uint DefaultHashFunct(const void *entry, const uint size)
uint IntegerRehashHashFunct(const uint oldHashValue, const uint size)
Definition: HashTable.cpp:802
static const int ENTRY_DEPTH_FOR_HASHING
Definition: HashTable.cpp:91
int QueryIndexSet(const void *entry, const bool expand) const
Definition: HashTable.cpp:574
unsigned int uint
Definition: uint.h:124
virtual uint HashFunct(const void *entry, const uint size)
Definition: HashTable.cpp:544
int * indexSet
Definition: HashTable.hpp:358
void Destroy()
Definition: HashTable.cpp:205
void(* AddEntryFunctPtr)(void *, void *, va_list)
Definition: HashTable.hpp:288
virtual ~HashTableIterator()
Definition: HashTable.cpp:916
void DeleteEntry(void *entry, DeleteEntryFunctPtr const DeleteEntryCallback=0,...)
Definition: HashTable.cpp:296
int GetEntryIndex(const void *entry) const
Definition: HashTable.cpp:426
void Dump()
Definition: HashTable.cpp:475
void AddEntry(void *entry, AddEntryFunctPtr const AddEntryCallback=0,...)
Definition: HashTable.cpp:250
uint nextSlot
Definition: HashTable.hpp:354
void * Current() const
Definition: HashTable.cpp:932
int StringEntryCompare(const void *entry1, const void *entry2)
Definition: HashTable.cpp:843
static const int LOOKING_FOR_AN_INDEX
Definition: HashTable.cpp:92
void FailureToCreateError() const
Definition: HashTable.cpp:779
uint NumberOfEntries() const
Definition: HashTable.cpp:460
HashFunctFunctPtr HashFunctCallback
Definition: HashTable.hpp:362
#define NULL
Definition: ElfHelper.cpp:85
void(* EntryCleanupFunctPtr)(void *)
Definition: HashTable.hpp:303
#define DIAG_Die(...)
Definition: diagnostics.h:267
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
static char * last
Definition: tokenize.c:65
static const int FIRST_SLOT
Definition: HashTable.cpp:86
uint StringRehashFunct(const uint oldHashValue, const uint size)
Definition: HashTable.cpp:835
void * QueryEntry(const void *entry) const
Definition: HashTable.cpp:396
virtual int EntryCompare(const void *entry1, const void *entry2)
Definition: HashTable.cpp:558
void * GetEntryByIndex(const uint index) const
Definition: HashTable.cpp:444
HashTableIterator(const HashTable *theHashTable)
Definition: HashTable.cpp:905
uint indexSetSize
Definition: HashTable.hpp:357