TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Table.h
Go to the documentation of this file.
1 
13 #ifndef G3D_Table_h
14 #define G3D_Table_h
15 
16 #include <cstddef>
17 #include <string>
18 
19 #include "G3D/platform.h"
20 #include "G3D/Array.h"
21 #include "G3D/debug.h"
22 #include "G3D/System.h"
23 #include "G3D/g3dmath.h"
24 #include "G3D/EqualsTrait.h"
25 #include "G3D/HashTrait.h"
26 #include "G3D/MemoryManager.h"
27 
28 #ifdef _MSC_VER
29 # pragma warning (push)
30  // Debug name too long warning
31 # pragma warning (disable : 4786)
32 #endif
33 
34 namespace G3D {
35 
100 template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key> >
101 class Table {
102 public:
103 
107  class Entry {
108  public:
109  Key key;
111  Entry() {}
112  Entry(const Key& k) : key(k) {}
113  Entry(const Key& k, const Value& v) : key(k), value(v) {}
114  bool operator==(const Entry &peer) const { return (key == peer.key && value == peer.value); }
115  bool operator!=(const Entry &peer) const { return !operator==(peer); }
116  };
117 
118 private:
119 
121 
125  class Node {
126  public:
128  size_t hashCode;
130 
131  private:
132 
133  // Private to require use of the allocator
134  Node(const Key& k, const Value& v, size_t h, Node* n)
135  : entry(k, v), hashCode(h), next(n) {
136  debugAssert((next == NULL) || isValidHeapPointer(next));
137  }
138 
139  Node(const Key& k, size_t h, Node* n)
140  : entry(k), hashCode(h), next(n) {
141  debugAssert((next == NULL) || isValidHeapPointer(next));
142  }
143 
144  public:
145 
146  static Node* create(const Key& k, const Value& v, size_t h, Node* n, MemoryManager::Ref& mm) {
147  Node* node = (Node*)mm->alloc(sizeof(Node));
148  return new (node) Node(k, v, h, n);
149  }
150 
151  static Node* create(const Key& k, size_t hashCode, Node* n, MemoryManager::Ref& mm) {
152  Node* node = (Node*)mm->alloc(sizeof(Node));
153  return new (node) Node(k, hashCode, n);
154  }
155 
156  static void destroy(Node* n, MemoryManager::Ref& mm) {
157  n->~Node();
158  mm->free(n);
159  }
160 
165  return create(this->entry.key, this->entry.value, hashCode, (next == NULL) ? NULL : next->clone(mm), mm);
166  }
167  };
168 
169  void checkIntegrity() const {
170 # ifdef G3D_DEBUG
172  for (size_t b = 0; b < m_numBuckets; ++b) {
173  Node* node = m_bucket[b];
174  debugAssert(node == NULL || isValidHeapPointer(node));
175  while (node != NULL) {
176  debugAssert(node == NULL || isValidHeapPointer(node));
177  node = node->next;
178  }
179  }
180 # endif
181  }
182 
184  size_t m_size;
185 
192  Node** m_bucket;
193 
197  size_t m_numBuckets;
198 
200 
201  void* alloc(size_t s) const {
202  return m_memoryManager->alloc(s);
203  }
204 
205  void free(void* p) const {
206  return m_memoryManager->free(p);
207  }
208 
212  void resize(size_t newSize) {
213 
214  // Hang onto the old m_bucket array
215  Node** oldBucket = m_bucket;
216 
217  // Allocate a new m_bucket array with the new size
218  m_bucket = (Node**)alloc(sizeof(Node*) * newSize);
219  alwaysAssertM(m_bucket != NULL, "MemoryManager::alloc returned NULL. Out of memory.");
220  // Set all pointers to NULL
221  System::memset(m_bucket, 0, newSize * sizeof(Node*));
222  // Move each node to its new hash location
223  for (size_t b = 0; b < m_numBuckets; ++b) {
224  Node* node = oldBucket[b];
225 
226  // There is a linked list of nodes at this m_bucket
227  while (node != NULL) {
228  // Hang onto the old next pointer
229  Node* nextNode = node->next;
230 
231  // Insert at the head of the list for m_bucket[i]
232  size_t i = node->hashCode % newSize;
233  node->next = m_bucket[i];
234  m_bucket[i] = node;
235 
236  // Move on to the next node
237  node = nextNode;
238  }
239 
240  // Drop the old pointer for cleanliness when debugging
241  oldBucket[b] = NULL;
242  }
243 
244  // Delete the old storage
245  free(oldBucket);
246  this->m_numBuckets = newSize;
247 
248  checkIntegrity();
249  }
250 
251 
252  void copyFrom(const ThisType& h) {
253  if (&h == this) {
254  return;
255  }
256 
257  debugAssert(m_bucket == NULL);
258  m_size = h.m_size;
259  m_numBuckets = h.m_numBuckets;
260  m_bucket = (Node**)alloc(sizeof(Node*) * m_numBuckets);
261  // No need to NULL elements since we're about to overwrite them
262 
263  for (size_t b = 0; b < m_numBuckets; ++b) {
264  if (h.m_bucket[b] != NULL) {
265  m_bucket[b] = h.m_bucket[b]->clone(m_memoryManager);
266  } else {
267  m_bucket[b] = NULL;
268  }
269  }
270 
271  checkIntegrity();
272  }
273 
277  void freeMemory() {
278  checkIntegrity();
279 
280  for (size_t b = 0; b < m_numBuckets; ++b) {
281  Node* node = m_bucket[b];
282  while (node != NULL) {
283  Node* next = node->next;
284  Node::destroy(node, m_memoryManager);
285  node = next;
286  }
287  m_bucket[b] = NULL;
288  }
289  free(m_bucket);
290  m_bucket = NULL;
291  m_numBuckets = 0;
292  m_size = 0;
293  }
294 
295 public:
296 
300  Table() : m_bucket(NULL) {
301  m_memoryManager = MemoryManager::create();
302  m_numBuckets = 0;
303  m_size = 0;
304  m_bucket = NULL;
305  checkIntegrity();
306  }
307 
310  clear();
311  debugAssert(m_bucket == NULL);
312  m_memoryManager = m;
313  }
314 
318  void setSizeHint(size_t n) {
319  size_t s = n * 3;
320  if (s > m_numBuckets) {
321  resize(s);
322  }
323  }
324 
331  virtual ~Table() {
332  freeMemory();
333  }
334 
336  Table(const ThisType& h) {
337  m_memoryManager = MemoryManager::create();
338  m_numBuckets = 0;
339  m_size = 0;
340  m_bucket = NULL;
341  this->copyFrom(h);
342  checkIntegrity();
343  }
344 
345 
346  Table& operator=(const ThisType& h) {
347  // No need to copy if the argument is this
348  if (this != &h) {
349  // Free the existing nodes
350  freeMemory();
351  this->copyFrom(h);
352  checkIntegrity();
353  }
354  return *this;
355  }
356 
360  size_t debugGetDeepestBucketSize() const {
361  size_t deepest = 0;
362 
363  for (size_t b = 0; b < m_numBuckets; ++b) {
364  size_t count = 0;
365  Node* node = m_bucket[b];
366  while (node != NULL) {
367  node = node->next;
368  ++count;
369  }
370 
371  if (count > deepest) {
372  deepest = count;
373  }
374  }
375 
376  return deepest;
377  }
378 
383  uint64 num = 0;
384 
385  for (size_t b = 0; b < m_numBuckets; ++b) {
386  Node* node = m_bucket[b];
387  if (node != NULL) {
388  ++num;
389  }
390  }
391 
392  return (float)((double)size() / num);
393  }
394 
402  double debugGetLoad() const {
403  return (double)size() / m_numBuckets;
404  }
405 
409  size_t debugGetNumBuckets() const {
410  return m_numBuckets;
411  }
412 
416  class Iterator {
417  private:
418  friend class Table<Key, Value, HashFunc, EqualsFunc>;
419 
423  size_t index;
424 
429 
430  size_t m_numBuckets;
432  bool isDone;
433 
437  Iterator() : index(0), node(NULL), m_bucket(NULL) {
438  isDone = true;
439  }
440 
441  Iterator(size_t numBuckets, Node** m_bucket) :
442  index(0),
443  node(NULL),
444  m_numBuckets(numBuckets),
445  m_bucket(m_bucket) {
446 
447  if (m_numBuckets == 0) {
448  // Empty table
449  isDone = true;
450  return;
451  }
452 
453 # ifdef G3D_DEBUG
454  for (unsigned int i = 0; i < m_numBuckets; ++i) {
455  debugAssert((m_bucket[i] == NULL) || isValidHeapPointer(m_bucket[i]));
456  }
457 # endif
458 
459  index = 0;
460  node = m_bucket[index];
461  debugAssert((node == NULL) || isValidHeapPointer(node));
462  isDone = false;
463  findNext();
464  debugAssert((node == NULL) || isValidHeapPointer(node));
465  }
466 
471  void findNext() {
472  while (node == NULL) {
473  ++index;
474  if (index >= m_numBuckets) {
475  m_bucket = NULL;
476  index = 0;
477  isDone = true;
478  return;
479  } else {
480  node = m_bucket[index];
481  debugAssert((node == NULL) || isValidHeapPointer(node));
482  }
483  }
485  }
486 
487  public:
488  inline bool operator!=(const Iterator& other) const {
489  return !(*this == other);
490  }
491 
492  bool operator==(const Iterator& other) const {
493  if (other.isDone || isDone) {
494  // Common case; check against isDone.
495  return (isDone == other.isDone);
496  } else {
497  return (node == other.node) && (index == other.index);
498  }
499  }
500 
505  debugAssert(! isDone);
506  debugAssert(node != NULL);
508  debugAssert((node->next == NULL) || isValidHeapPointer(node->next));
509  node = node->next;
510  findNext();
511  debugAssert(isDone || isValidHeapPointer(node));
512  return *this;
513  }
514 
519  Iterator old = *this;
520  ++(*this);
521  return old;
522  }
523 
524  const Entry& operator*() const {
525  return node->entry;
526  }
527 
528  const Value& value() const {
529  return node->entry.value;
530  }
531 
532  const Key& key() const {
533  return node->entry.key;
534  }
535 
536  Entry* operator->() const {
538  return &(node->entry);
539  }
540 
541  operator Entry*() const {
543  return &(node->entry);
544  }
545 
546  bool isValid() const {
547  return ! isDone;
548  }
549 
551  bool hasMore() const {
552  return ! isDone;
553  }
554  };
555 
556 
562  Iterator begin() const {
563  return Iterator(m_numBuckets, m_bucket);
564  }
565 
570  const Iterator end() const {
571  return Iterator();
572  }
573 
578  void clear() {
579  freeMemory();
580  m_numBuckets = 0;
581  m_size = 0;
582  m_bucket = NULL;
583  }
584 
585 
589  size_t size() const {
590  return m_size;
591  }
592 
593 
599  void set(const Key& key, const Value& value) {
600  getCreateEntry(key).value = value;
601  }
602 
603 private:
604 
606  bool remove(const Key& key, Key& removedKey, Value& removedValue, bool updateRemoved) {
607  if (m_numBuckets == 0) {
608  return false;
609  }
610 
611  const size_t code = HashFunc::hashCode(key);
612  const size_t b = code % m_numBuckets;
613 
614  // Go to the m_bucket
615  Node* n = m_bucket[b];
616 
617  if (n == NULL) {
618  return false;
619  }
620 
621  Node* previous = NULL;
622 
623  // Try to find the node
624  do {
625  if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
626  // This is the node; remove it
627 
628  // Replace the previous's next pointer
629  if (previous == NULL) {
630  m_bucket[b] = n->next;
631  } else {
632  previous->next = n->next;
633  }
634 
635  if (updateRemoved) {
636  removedKey = n->entry.key;
637  removedValue = n->entry.value;
638  }
639  // Delete the node
640  Node::destroy(n, m_memoryManager);
641  --m_size;
642 
643  //checkIntegrity();
644  return true;
645  }
646 
647  previous = n;
648  n = n->next;
649  } while (n != NULL);
650 
651  //checkIntegrity();
652  return false;
653  }
654 
655 public:
656 
660  bool getRemove(const Key& key, Key& removedKey, Value& removedValue) {
661  return remove(key, removedKey, removedValue, true);
662  }
663 
668  bool remove(const Key& key) {
669  Key x;
670  Value v;
671  return remove(key, x, v, false);
672  }
673 
674 private:
675 
676  Entry* getEntryPointer(const Key& key) const {
677  if (m_numBuckets == 0) {
678  return NULL;
679  }
680 
681  size_t code = HashFunc::hashCode(key);
682  size_t b = code % m_numBuckets;
683 
684  Node* node = m_bucket[b];
685 
686  while (node != NULL) {
687  if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
688  return &(node->entry);
689  }
690  node = node->next;
691  }
692 
693  return NULL;
694  }
695 
696 public:
697 
701  const Key* getKeyPointer(const Key& key) const {
702  const Entry* e = getEntryPointer(key);
703  if (e == NULL) {
704  return NULL;
705  } else {
706  return &(e->key);
707  }
708  }
709 
714  Value& get(const Key& key) const {
715  Entry* e = getEntryPointer(key);
716  debugAssertM(e != NULL, "Key not found");
717  return e->value;
718  }
719 
720 
731  Value* getPointer(const Key& key) const {
732  if (m_numBuckets == 0) {
733  return NULL;
734  }
735 
736  size_t code = HashFunc::hashCode(key);
737  size_t b = code % m_numBuckets;
738 
739  Node* node = m_bucket[b];
740 
741  while (node != NULL) {
742  if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
743  // found key
744  return &(node->entry.value);
745  }
746  node = node->next;
747  }
748 
749  // Failed to find key
750  return NULL;
751  }
752 
757  bool get(const Key& key, Value& val) const {
758  Value* v = getPointer(key);
759  if (v != NULL) {
760  val = *v;
761  return true;
762  } else {
763  return false;
764  }
765  }
766 
767 
772  Entry& getCreateEntry(const Key& key, bool& created) {
773  created = false;
774 
775  if (m_numBuckets == 0) {
776  resize(10);
777  }
778 
779  size_t code = HashFunc::hashCode(key);
780  size_t b = code % m_numBuckets;
781 
782  // Go to the m_bucket
783  Node* n = m_bucket[b];
784 
785  // No m_bucket, so this must be the first
786  if (n == NULL) {
787  m_bucket[b] = Node::create(key, code, NULL, m_memoryManager);
788  ++m_size;
789  created = true;
790  //checkIntegrity();
791  return m_bucket[b]->entry;
792  }
793 
794  size_t bucketLength = 1;
795 
796  // Sometimes a bad hash code will cause all elements
797  // to collide. Detect this case and don't rehash when
798  // it occurs; nothing good will come from the rehashing.
799  bool allSameCode = true;
800 
801  // Try to find the node
802  do {
803  allSameCode = allSameCode && (code == n->hashCode);
804 
805  if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
806  // This is the a pre-existing node
807  //checkIntegrity();
808  return n->entry;
809  }
810 
811  n = n->next;
812  ++bucketLength;
813  } while (n != NULL);
814 
815  // Allow the load factor to rise as the table gets huge
816  const int bucketsPerElement =
817  (m_size > 50000) ? 3 :
818  ((m_size > 10000) ? 5 :
819  ((m_size > 5000) ? 10 : 15));
820 
821  const size_t maxBucketLength = 3;
822  // (Don't bother changing the size of the table if all entries
823  // have the same hashcode--they'll still collide)
824  if ((bucketLength > maxBucketLength) &&
825  ! allSameCode &&
826  (m_numBuckets < m_size * bucketsPerElement)) {
827 
828  // This m_bucket was really large; rehash if all elements
829  // don't have the same hashcode the number of buckets is
830  // reasonable.
831 
832  // Back off the scale factor as the number of buckets gets
833  // large
834  float f = 3.0f;
835  if (m_numBuckets > 1000000) {
836  f = 1.5f;
837  } else if (m_numBuckets > 100000) {
838  f = 2.0f;
839  }
840  int newSize = iMax((int)(m_numBuckets * f) + 1, (int)(m_size * f));
841  resize(newSize);
842  }
843 
844  // Not found; insert at the head.
845  b = code % m_numBuckets;
846  m_bucket[b] = Node::create(key, code, m_bucket[b], m_memoryManager);
847  ++m_size;
848  created = true;
849 
850  //checkIntegrity();
851  return m_bucket[b]->entry;
852  }
853 
854  Entry& getCreateEntry(const Key& key) {
855  bool ignore;
856  return getCreateEntry(key, ignore);
857  }
858 
859 
861  Value& getCreate(const Key& key) {
862  return getCreateEntry(key).value;
863  }
864 
866  Value& getCreate(const Key& key, bool& created) {
867  return getCreateEntry(key, created).value;
868  }
869 
870 
874  bool containsKey(const Key& key) const {
875  if (m_numBuckets == 0) {
876  return false;
877  }
878 
879  size_t code = HashFunc::hashCode(key);
880  size_t b = code % m_numBuckets;
881 
882  Node* node = m_bucket[b];
883 
884  while (node != NULL) {
885  if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
886  return true;
887  }
888  node = node->next;
889  }
890 
891  return false;
892  }
893 
894 
898  inline Value& operator[](const Key &key) const {
899  return get(key);
900  }
901 
907  Array<Key> getKeys() const {
908  Array<Key> keyArray;
909  getKeys(keyArray);
910  return keyArray;
911  }
912 
913  void getKeys(Array<Key>& keyArray) const {
915  for (size_t i = 0; i < m_numBuckets; ++i) {
916  Node* node = m_bucket[i];
917  while (node != NULL) {
918  keyArray.append(node->entry.key);
919  node = node->next;
920  }
921  }
922  }
923 
925  void getValues(Array<Value>& valueArray) const {
926  valueArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
927  for (size_t i = 0; i < m_numBuckets; ++i) {
928  Node* node = m_bucket[i];
929  while (node != NULL) {
930  valueArray.append(node->entry.value);
931  node = node->next;
932  }
933  }
934  }
935 
939  void deleteKeys() {
940  for (size_t i = 0; i < m_numBuckets; ++i) {
941  Node* node = m_bucket[i];
942  while (node != NULL) {
943  delete node->entry.key;
944  node->entry.key = NULL;
945  node = node->next;
946  }
947  }
948  clear();
949  }
950 
959  void deleteValues() {
960  for (size_t i = 0; i < m_numBuckets; ++i) {
961  Node* node = m_bucket[i];
962  while (node != NULL) {
963  delete node->entry.value;
964  node->entry.value = NULL;
965  node = node->next;
966  }
967  }
968  }
969 
970  template<class H, class E>
971  bool operator==(const Table<Key, Value, H, E>& other) const {
972  if (size() != other.size()) {
973  return false;
974  }
975 
976  for (Iterator it = begin(); it.hasMore(); ++it) {
977  const Value* v = other.getPointer(it->key);
978  if ((v == NULL) || (*v != it->value)) {
979  // Either the key did not exist or the value was not the same
980  return false;
981  }
982  }
983 
984  // this and other have the same number of keys, so we don't
985  // have to check for extra keys in other.
986 
987  return true;
988  }
989 
990  template<class H, class E>
991  bool operator!=(const Table<Key, Value, H, E>& other) const {
992  return ! (*this == other);
993  }
994 
996  debugPrintf("Deepest bucket size = %d\n", (int)debugGetDeepestBucketSize());
997  debugPrintf("Average bucket size = %g\n", debugGetAverageBucketSize());
998  debugPrintf("Load factor = %g\n", debugGetLoad());
999  }
1000 };
1001 
1002 } // namespace
1003 
1004 #ifdef _MSC_VER
1005 # pragma warning (pop)
1006 #endif
1007 
1008 #endif
static void destroy(Node *n, MemoryManager::Ref &mm)
Definition: Table.h:156
std::string __cdecl debugPrintf(const char *fmt...) G3D_CHECK_PRINTF_ARGS
Definition: debugAssert.cpp:355
const Value & value() const
Definition: Table.h:528
Value * getPointer(const Key &key) const
Definition: Table.h:731
Value & getCreate(const Key &key, bool &created)
Definition: Table.h:866
static void memset(void *dst, uint8 value, size_t numBytes)
Definition: System.cpp:695
size_t m_numBuckets
Definition: Table.h:430
bool operator==(const Entry &peer) const
Definition: Table.h:114
float debugGetAverageBucketSize() const
Definition: Table.h:382
static MemoryManager::Ref create()
Definition: MemoryManager.cpp:35
Entry()
Definition: Table.h:111
void setSizeHint(size_t n)
Definition: Table.h:318
void resize(size_t n, bool shrinkIfNecessary=true)
Definition: Array.h:490
bool getRemove(const Key &key, Key &removedKey, Value &removedValue)
Definition: Table.h:660
size_t hashCode() const
Definition: Vector2unorm16.h:76
static Node * create(const Key &k, const Value &v, size_t h, Node *n, MemoryManager::Ref &mm)
Definition: Table.h:146
void free(void *p) const
Definition: Table.h:205
Definition: Table.h:107
Entry * operator->() const
Definition: Table.h:536
size_t index
Definition: Table.h:423
Definition: Table.h:416
int next(int i, int n)
Definition: RecastContour.cpp:469
void clear()
Definition: Table.h:578
size_t size() const
Definition: Table.h:589
Iterator(size_t numBuckets, Node **m_bucket)
Definition: Table.h:441
Definition: AABox.h:25
Dynamic 1D array tuned for performance.
Definition: Array.h:95
double debugGetLoad() const
Definition: Table.h:402
Iterator begin() const
Definition: Table.h:562
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
size_t hashCode
Definition: Table.h:128
bool operator==(const Iterator &other) const
Definition: Table.h:492
Node ** m_bucket
Definition: Table.h:192
uint64_t uint64
Definition: g3dmath.h:170
bool operator==(const Table< Key, Value, H, E > &other) const
Definition: Table.h:971
shared_ptr< class MemoryManager > Ref
Definition: MemoryManager.h:31
void set(const Key &key, const Value &value)
Definition: Table.h:599
bool hasMore() const
Definition: Table.h:551
void checkIntegrity() const
Definition: Table.h:169
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
const Entry & operator*() const
Definition: Table.h:524
void deleteKeys()
Definition: Table.h:939
bool operator!=(const Iterator &other) const
Definition: Table.h:488
bool operator!=(const Entry &peer) const
Definition: Table.h:115
Node * node
Definition: Table.h:428
Entry
Definition: boss_headless_horseman.cpp:50
virtual ~Table()
Definition: Table.h:331
const bool DONT_SHRINK_UNDERLYING_ARRAY
Definition: Array.h:43
Definition: Table.h:125
size_t debugGetDeepestBucketSize() const
Definition: Table.h:360
void getKeys(Array< Key > &keyArray) const
Definition: Table.h:913
#define debugAssert(exp)
Definition: debugAssert.h:160
Table()
Definition: Table.h:300
Key key
Definition: Table.h:109
void getValues(Array< Value > &valueArray) const
Definition: Table.h:925
Node(const Key &k, const Value &v, size_t h, Node *n)
Definition: Table.h:134
Definition: Table.h:101
uint32_t previous(octet_iterator &it, octet_iterator pass_start)
Deprecated in versions that include "prior".
Definition: checked.h:179
Table< Key, Value, HashFunc, EqualsFunc > ThisType
Definition: Table.h:120
Entry(const Key &k)
Definition: Table.h:112
Entry & getCreateEntry(const Key &key, bool &created)
Definition: Table.h:772
void resize(size_t newSize)
Definition: Table.h:212
static Node * create(const Key &k, size_t hashCode, Node *n, MemoryManager::Ref &mm)
Definition: Table.h:151
const Key & key() const
Definition: Table.h:532
Value & getCreate(const Key &key)
Definition: Table.h:861
void freeMemory()
Definition: Table.h:277
Node ** m_bucket
Definition: Table.h:431
Definition: inftrees.h:24
void deleteValues()
Definition: Table.h:959
const Iterator end() const
Definition: Table.h:570
Iterator operator++(int)
Definition: Table.h:518
void * alloc(size_t s) const
Definition: Table.h:201
Value value
Definition: Table.h:110
Node * next
Definition: Table.h:129
Array< Key > getKeys() const
Definition: Table.h:907
const Key * getKeyPointer(const Key &key) const
Definition: Table.h:701
Entry entry
Definition: Table.h:127
bool isDone
Definition: Table.h:432
Node(const Key &k, size_t h, Node *n)
Definition: Table.h:139
void copyFrom(const ThisType &h)
Definition: Table.h:252
void debugPrintStatus()
Definition: Table.h:995
const FieldDescriptor value
Definition: descriptor.h:1522
Table & operator=(const ThisType &h)
Definition: Table.h:346
void clearAndSetMemoryManager(const MemoryManager::Ref &m)
Definition: Table.h:309
Entry & getCreateEntry(const Key &key)
Definition: Table.h:854
G3D::int16 x
Definition: Vector2int16.h:37
int iMax(int x, int y)
Definition: g3dmath.h:759
Iterator & operator++()
Definition: Table.h:504
void findNext()
Definition: Table.h:471
void append(const T &value)
Definition: Array.h:583
size_t debugGetNumBuckets() const
Definition: Table.h:409
#define alwaysAssertM(exp, message)
Definition: debugAssert.h:165
Entry * getEntryPointer(const Key &key) const
Definition: Table.h:676
Entry(const Key &k, const Value &v)
Definition: Table.h:113
bool operator!=(const Table< Key, Value, H, E > &other) const
Definition: Table.h:991
bool isValidHeapPointer(const void *x)
Definition: debug.h:38
bool containsKey(const Key &key) const
Definition: Table.h:874
Iterator()
Definition: Table.h:437
bool isValid() const
Definition: Table.h:546
Table(const ThisType &h)
Definition: Table.h:336
Value & operator[](const Key &key) const
Definition: Table.h:898
Node * clone(MemoryManager::Ref &mm)
Definition: Table.h:164
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197