Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_Hash.h
Go to the documentation of this file.
1 /************************************************************************************
2 
3 PublicHeader: None
4 Filename : OVR_Hash.h
5 Content : Template hash-table/set implementation
6 Created : September 19, 2012
7 Notes :
8 
9 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
10 
11 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
15 
16 You may obtain a copy of the License at
17 
18 http://www.oculusvr.com/licenses/LICENSE-3.1
19 
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
25 
26 ************************************************************************************/
27 
28 #ifndef OVR_Hash_h
29 #define OVR_Hash_h
30 
31 #include "OVR_ContainerAllocator.h"
32 #include "OVR_Alg.h"
33 
34 // 'new' operator is redefined/used in this file.
35 #undef new
36 
37 namespace OVR {
38 
39 //-----------------------------------------------------------------------------------
40 // ***** Hash Table Implementation
41 
42 // HastSet and Hash.
43 //
44 // Hash table, linear probing, internal chaining. One interesting/nice thing
45 // about this implementation is that the table itself is a flat chunk of memory
46 // containing no pointers, only relative indices. If the key and value types
47 // of the Hash contain no pointers, then the Hash can be serialized using raw IO.
48 //
49 // Never shrinks, unless you explicitly Clear() it. Expands on
50 // demand, though. For best results, if you know roughly how big your
51 // table will be, default it to that size when you create it.
52 //
53 // Key usability feature:
54 //
55 // 1. Allows node hash values to either be cached or not.
56 //
57 // 2. Allows for alternative keys with methods such as GetAlt(). Handy
58 // if you need to search nodes by their components; no need to create
59 // temporary nodes.
60 //
61 
62 
63 // *** Hash functors:
64 //
65 // IdentityHash - use when the key is already a good hash
66 // HFixedSizeHash - general hash based on object's in-memory representation.
67 
68 
69 // Hash is just the input value; can use this for integer-indexed hash tables.
70 template<class C>
72 {
73 public:
74  UPInt operator()(const C& data) const
75  { return (UPInt) data; }
76 };
77 
78 // Computes a hash of an object's representation.
79 template<class C>
81 {
82 public:
83  // Alternative: "sdbm" hash function, suggested at same web page
84  // above, http::/www.cs.yorku.ca/~oz/hash.html
85  // This is somewhat slower then Bernstein, but it works way better than the above
86  // hash function for hashing large numbers of 32-bit ints.
87  static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381)
88  {
89  const UByte* data = (const UByte*) data_in;
90  UPInt h = seed;
91  while (size > 0)
92  {
93  size--;
94  h = (h << 16) + (h << 6) - h + (UPInt)data[size];
95  }
96  return h;
97  }
98 
99  UPInt operator()(const C& data) const
100  {
101  unsigned char* p = (unsigned char*) &data;
102  int size = sizeof(C);
103 
104  return SDBM_Hash(p, size);
105  }
106 };
107 
108 
109 
110 // *** HashsetEntry Entry types.
111 
112 // Compact hash table Entry type that re-computes hash keys during hash traversal.
113 // Good to use if the hash function is cheap or the hash value is already cached in C.
114 template<class C, class HashF>
116 {
117 public:
118  // Internal chaining for collisions.
120  C Value;
121 
123  : NextInChain(-2) { }
125  : NextInChain(e.NextInChain), Value(e.Value) { }
126  HashsetEntry(const C& key, SPInt next)
127  : NextInChain(next), Value(key) { }
128 
129  bool IsEmpty() const { return NextInChain == -2; }
130  bool IsEndOfChain() const { return NextInChain == -1; }
131 
132  // Cached hash value access - can be optimized bu storing hash locally.
133  // Mask value only needs to be used if SetCachedHash is not implemented.
134  UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; }
136 
137  void Clear()
138  {
139  Value.~C(); // placement delete
140  NextInChain = -2;
141  }
142  // Free is only used from dtor of hash; Clear is used during regular operations:
143  // assignment, hash reallocations, value reassignments, so on.
144  void Free() { Clear(); }
145 };
146 
147 // Hash table Entry type that caches the Entry hash value for nodes, so that it
148 // does not need to be re-computed during access.
149 template<class C, class HashF>
151 {
152 public:
153  // Internal chaining for collisions.
156  C Value;
157 
159  : NextInChain(-2) { }
162  HashsetCachedEntry(const C& key, SPInt next)
163  : NextInChain(next), Value(key) { }
164 
165  bool IsEmpty() const { return NextInChain == -2; }
166  bool IsEndOfChain() const { return NextInChain == -1; }
167 
168  // Cached hash value access - can be optimized bu storing hash locally.
169  // Mask value only needs to be used if SetCachedHash is not implemented.
170  UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; }
171  void SetCachedHash(UPInt hashValue) { HashValue = hashValue; }
172 
173  void Clear()
174  {
175  Value.~C();
176  NextInChain = -2;
177  }
178  // Free is only used from dtor of hash; Clear is used during regular operations:
179  // assignment, hash reallocations, value reassignments, so on.
180  void Free() { Clear(); }
181 };
182 
183 
184 //-----------------------------------------------------------------------------------
185 // *** HashSet implementation - relies on either cached or regular entries.
186 //
187 // Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to
188 // compute and thus need caching in entries.
189 // Entry = HashsetEntry<C, HashF> if hashes are already externally cached.
190 //
191 template<class C, class HashF = FixedSizeHash<C>,
192  class AltHashF = HashF,
193  class Allocator = ContainerAllocator<C>,
194  class Entry = HashsetCachedEntry<C, HashF> >
196 {
197  enum { HashMinSize = 8 };
198 
199 public:
201 
202  typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> SelfType;
203 
205  HashSetBase(int sizeHint) : pTable(NULL) { SetCapacity(this, sizeHint); }
206  HashSetBase(const SelfType& src) : pTable(NULL) { Assign(this, src); }
207 
209  {
210  if (pTable)
211  {
212  // Delete the entries.
213  for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
214  {
215  Entry* e = &E(i);
216  if (!e->IsEmpty())
217  e->Free();
218  }
219 
221  pTable = NULL;
222  }
223  }
224 
225 
226  void Assign(const SelfType& src)
227  {
228  Clear();
229  if (src.IsEmpty() == false)
230  {
231  SetCapacity(src.GetSize());
232 
233  for (ConstIterator it = src.Begin(); it != src.End(); ++it)
234  {
235  Add(*it);
236  }
237  }
238  }
239 
240 
241  // Remove all entries from the HashSet table.
242  void Clear()
243  {
244  if (pTable)
245  {
246  // Delete the entries.
247  for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
248  {
249  Entry* e = &E(i);
250  if (!e->IsEmpty())
251  e->Clear();
252  }
253 
255  pTable = NULL;
256  }
257  }
258 
259  // Returns true if the HashSet is empty.
260  bool IsEmpty() const
261  {
262  return pTable == NULL || pTable->EntryCount == 0;
263  }
264 
265 
266  // Set a new or existing value under the key, to the value.
267  // Pass a different class of 'key' so that assignment reference object
268  // can be passed instead of the actual object.
269  template<class CRef>
270  void Set(const CRef& key)
271  {
272  UPInt hashValue = HashF()(key);
273  SPInt index = (SPInt)-1;
274 
275  if (pTable != NULL)
276  index = findIndexCore(key, hashValue & pTable->SizeMask);
277 
278  if (index >= 0)
279  {
280  E(index).Value = key;
281  }
282  else
283  {
284  // Entry under key doesn't exist.
285  add(key, hashValue);
286  }
287  }
288 
289  template<class CRef>
290  inline void Add(const CRef& key)
291  {
292  UPInt hashValue = HashF()(key);
293  add(key, hashValue);
294  }
295 
296  // Remove by alternative key.
297  template<class K>
298  void RemoveAlt(const K& key)
299  {
300  if (pTable == NULL)
301  return;
302 
303  UPInt hashValue = AltHashF()(key);
304  SPInt index = hashValue & pTable->SizeMask;
305 
306  Entry* e = &E(index);
307 
308  // If empty node or occupied by collider, we have nothing to remove.
309  if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index))
310  return;
311 
312  // Save index
313  SPInt naturalIndex = index;
314  SPInt prevIndex = -1;
315 
316  while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
317  {
318  // Keep looking through the chain.
319  prevIndex = index;
320  index = e->NextInChain;
321  if (index == -1)
322  return; // End of chain, item not found
323  e = &E(index);
324  }
325 
326  // Found it - our item is at index
327  if (naturalIndex == index)
328  {
329  // If we have a follower, move it to us
330  if (!e->IsEndOfChain())
331  {
332  Entry* enext = &E(e->NextInChain);
333  e->Clear();
334  new (e) Entry(*enext);
335  // Point us to the follower's cell that will be cleared
336  e = enext;
337  }
338  }
339  else
340  {
341  // We are not at natural index, so deal with the prev items next index
342  E(prevIndex).NextInChain = e->NextInChain;
343  }
344 
345  // Clear us, of the follower cell that was moved.
346  e->Clear();
347  pTable->EntryCount --;
348  // Should we check the size to condense hash? ...
349  }
350 
351  // Remove by main key.
352  template<class CRef>
353  void Remove(const CRef& key)
354  {
355  RemoveAlt(key);
356  }
357 
358  // Retrieve the pointer to a value under the given key.
359  // - If there's no value under the key, then return NULL.
360  // - If there is a value, return the pointer.
361  template<class K>
362  C* Get(const K& key)
363  {
364  SPInt index = findIndex(key);
365  if (index >= 0)
366  return &E(index).Value;
367  return 0;
368  }
369 
370  template<class K>
371  const C* Get(const K& key) const
372  {
373  SPInt index = findIndex(key);
374  if (index >= 0)
375  return &E(index).Value;
376  return 0;
377  }
378 
379  // Alternative key versions of Get. Used by Hash.
380  template<class K>
381  const C* GetAlt(const K& key) const
382  {
383  SPInt index = findIndexAlt(key);
384  if (index >= 0)
385  return &E(index).Value;
386  return 0;
387  }
388 
389  template<class K>
390  C* GetAlt(const K& key)
391  {
392  SPInt index = findIndexAlt(key);
393  if (index >= 0)
394  return &E(index).Value;
395  return 0;
396  }
397 
398  template<class K>
399  bool GetAlt(const K& key, C* pval) const
400  {
401  SPInt index = findIndexAlt(key);
402  if (index >= 0)
403  {
404  if (pval)
405  *pval = E(index).Value;
406  return true;
407  }
408  return false;
409  }
410 
411 
412  UPInt GetSize() const
413  {
414  return pTable == NULL ? 0 : (UPInt)pTable->EntryCount;
415  }
416 
417 
418  // Resize the HashSet table to fit one more Entry. Often this
419  // doesn't involve any action.
420  void CheckExpand()
421  {
422  if (pTable == NULL)
423  {
424  // Initial creation of table. Make a minimum-sized table.
426  }
427  else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4)
428  {
429  // pTable is more than 5/4 ths full. Expand.
430  setRawCapacity((pTable->SizeMask + 1) * 2);
431  }
432  }
433 
434  // Hint the bucket count to >= n.
435  void Resize(UPInt n)
436  {
437  // Not really sure what this means in relation to
438  // STLport's hash_map... they say they "increase the
439  // bucket count to at least n" -- but does that mean
440  // their real capacity after Resize(n) is more like
441  // n*2 (since they do linked-list chaining within
442  // buckets?).
443  SetCapacity(n);
444  }
445 
446  // Size the HashSet so that it can comfortably contain the given
447  // number of elements. If the HashSet already contains more
448  // elements than newSize, then this may be a no-op.
449  void SetCapacity(UPInt newSize)
450  {
451  UPInt newRawSize = (newSize * 5) / 4;
452  if (newRawSize <= GetSize())
453  return;
454  setRawCapacity(newRawSize);
455  }
456 
457  // Disable inappropriate 'operator ->' warning on MSVC6.
458 #ifdef OVR_CC_MSVC
459 #if (OVR_CC_MSVC < 1300)
460 # pragma warning(disable : 4284)
461 #endif
462 #endif
463 
464  // Iterator API, like STL.
466  {
467  const C& operator * () const
468  {
470  return pHash->E(Index).Value;
471  }
472 
473  const C* operator -> () const
474  {
476  return &pHash->E(Index).Value;
477  }
478 
480  {
481  // Find next non-empty Entry.
482  if (Index <= (SPInt)pHash->pTable->SizeMask)
483  {
484  Index++;
485  while ((UPInt)Index <= pHash->pTable->SizeMask &&
486  pHash->E(Index).IsEmpty())
487  {
488  Index++;
489  }
490  }
491  }
492 
493  bool operator == (const ConstIterator& it) const
494  {
495  if (IsEnd() && it.IsEnd())
496  {
497  return true;
498  }
499  else
500  {
501  return (pHash == it.pHash) && (Index == it.Index);
502  }
503  }
504 
505  bool operator != (const ConstIterator& it) const
506  {
507  return ! (*this == it);
508  }
509 
510 
511  bool IsEnd() const
512  {
513  return (pHash == NULL) ||
514  (pHash->pTable == NULL) ||
516  }
517 
519  : pHash(NULL), Index(0)
520  { }
521 
522  public:
523  // Constructor was intentionally made public to allow create
524  // iterator with arbitrary index.
526  : pHash(h), Index(index)
527  { }
528 
529  const SelfType* GetContainer() const
530  {
531  return pHash;
532  }
533  SPInt GetIndex() const
534  {
535  return Index;
536  }
537 
538  protected:
539  friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
540 
541  const SelfType* pHash;
543  };
544 
545  friend struct ConstIterator;
546 
547 
548  // Non-const Iterator; Get most of it from ConstIterator.
549  struct Iterator : public ConstIterator
550  {
551  // Allow non-const access to entries.
552  C& operator*() const
553  {
555  return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value;
556  }
557 
558  C* operator->() const
559  {
560  return &(operator*());
561  }
562 
564  : ConstIterator(NULL, 0)
565  { }
566 
567  // Removes current element from Hash
568  void Remove()
569  {
570  RemoveAlt(operator*());
571  }
572 
573  template <class K>
574  void RemoveAlt(const K& key)
575  {
576  SelfType* phash = const_cast<SelfType*>(ConstIterator::pHash);
577  //Entry* ee = &phash->E(ConstIterator::Index);
578  //const C& key = ee->Value;
579 
580  UPInt hashValue = AltHashF()(key);
581  SPInt index = hashValue & phash->pTable->SizeMask;
582 
583  Entry* e = &phash->E(index);
584 
585  // If empty node or occupied by collider, we have nothing to remove.
586  if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index))
587  return;
588 
589  // Save index
590  SPInt naturalIndex = index;
591  SPInt prevIndex = -1;
592 
593  while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
594  {
595  // Keep looking through the chain.
596  prevIndex = index;
597  index = e->NextInChain;
598  if (index == -1)
599  return; // End of chain, item not found
600  e = &phash->E(index);
601  }
602 
603  if (index == (SPInt)ConstIterator::Index)
604  {
605  // Found it - our item is at index
606  if (naturalIndex == index)
607  {
608  // If we have a follower, move it to us
609  if (!e->IsEndOfChain())
610  {
611  Entry* enext = &phash->E(e->NextInChain);
612  e->Clear();
613  new (e) Entry(*enext);
614  // Point us to the follower's cell that will be cleared
615  e = enext;
617  }
618  }
619  else
620  {
621  // We are not at natural index, so deal with the prev items next index
622  phash->E(prevIndex).NextInChain = e->NextInChain;
623  }
624 
625  // Clear us, of the follower cell that was moved.
626  e->Clear();
627  phash->pTable->EntryCount --;
628  }
629  else
630  OVR_ASSERT(0); //?
631  }
632 
633  private:
634  friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
635 
637  : ConstIterator(h, i0)
638  { }
639  };
640 
641  friend struct Iterator;
642 
644  {
645  if (pTable == 0)
646  return Iterator(NULL, 0);
647 
648  // Scan till we hit the First valid Entry.
649  UPInt i0 = 0;
650  while (i0 <= pTable->SizeMask && E(i0).IsEmpty())
651  {
652  i0++;
653  }
654  return Iterator(this, i0);
655  }
656  Iterator End() { return Iterator(NULL, 0); }
657 
658  ConstIterator Begin() const { return const_cast<SelfType*>(this)->Begin(); }
659  ConstIterator End() const { return const_cast<SelfType*>(this)->End(); }
660 
661  template<class K>
662  Iterator Find(const K& key)
663  {
664  SPInt index = findIndex(key);
665  if (index >= 0)
666  return Iterator(this, index);
667  return Iterator(NULL, 0);
668  }
669 
670  template<class K>
671  Iterator FindAlt(const K& key)
672  {
673  SPInt index = findIndexAlt(key);
674  if (index >= 0)
675  return Iterator(this, index);
676  return Iterator(NULL, 0);
677  }
678 
679  template<class K>
680  ConstIterator Find(const K& key) const { return const_cast<SelfType*>(this)->Find(key); }
681 
682  template<class K>
683  ConstIterator FindAlt(const K& key) const { return const_cast<SelfType*>(this)->FindAlt(key); }
684 
685 private:
686  // Find the index of the matching Entry. If no match, then return -1.
687  template<class K>
688  SPInt findIndex(const K& key) const
689  {
690  if (pTable == NULL)
691  return -1;
692  UPInt hashValue = HashF()(key) & pTable->SizeMask;
693  return findIndexCore(key, hashValue);
694  }
695 
696  template<class K>
697  SPInt findIndexAlt(const K& key) const
698  {
699  if (pTable == NULL)
700  return -1;
701  UPInt hashValue = AltHashF()(key) & pTable->SizeMask;
702  return findIndexCore(key, hashValue);
703  }
704 
705  // Find the index of the matching Entry. If no match, then return -1.
706  template<class K>
707  SPInt findIndexCore(const K& key, UPInt hashValue) const
708  {
709  // Table must exist.
710  OVR_ASSERT(pTable != 0);
711  // Hash key must be 'and-ed' by the caller.
712  OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0);
713 
714  UPInt index = hashValue;
715  const Entry* e = &E(index);
716 
717  // If empty or occupied by a collider, not found.
718  if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index))
719  return -1;
720 
721  while(1)
722  {
723  OVR_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue);
724 
725  if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key)
726  {
727  // Found it.
728  return index;
729  }
730  // Values can not be equal at this point.
731  // That would mean that the hash key for the same value differs.
732  OVR_ASSERT(!(e->Value == key));
733 
734  // Keep looking through the chain.
735  index = e->NextInChain;
736  if (index == (UPInt)-1)
737  break; // end of chain
738 
739  e = &E(index);
740  OVR_ASSERT(!e->IsEmpty());
741  }
742  return -1;
743  }
744 
745 
746  // Add a new value to the HashSet table, under the specified key.
747  template<class CRef>
748  void add(const CRef& key, UPInt hashValue)
749  {
750  CheckExpand();
751  hashValue &= pTable->SizeMask;
752 
753  pTable->EntryCount++;
754 
755  SPInt index = hashValue;
756  Entry* naturalEntry = &(E(index));
757 
758  if (naturalEntry->IsEmpty())
759  {
760  // Put the new Entry in.
761  new (naturalEntry) Entry(key, -1);
762  }
763  else
764  {
765  // Find a blank spot.
766  SPInt blankIndex = index;
767  do {
768  blankIndex = (blankIndex + 1) & pTable->SizeMask;
769  } while(!E(blankIndex).IsEmpty());
770 
771  Entry* blankEntry = &E(blankIndex);
772 
773  if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index)
774  {
775  // Collision. Link into this chain.
776 
777  // Move existing list head.
778  new (blankEntry) Entry(*naturalEntry); // placement new, copy ctor
779 
780  // Put the new info in the natural Entry.
781  naturalEntry->Value = key;
782  naturalEntry->NextInChain = blankIndex;
783  }
784  else
785  {
786  // Existing Entry does not naturally
787  // belong in this slot. Existing
788  // Entry must be moved.
789 
790  // Find natural location of collided element (i.e. root of chain)
791  SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask);
792  OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
793  for (;;)
794  {
795  Entry* e = &E(collidedIndex);
796  if (e->NextInChain == index)
797  {
798  // Here's where we need to splice.
799  new (blankEntry) Entry(*naturalEntry);
800  e->NextInChain = blankIndex;
801  break;
802  }
803  collidedIndex = e->NextInChain;
804  OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
805  }
806 
807  // Put the new data in the natural Entry.
808  naturalEntry->Value = key;
809  naturalEntry->NextInChain = -1;
810  }
811  }
812 
813  // Record hash value: has effect only if cached node is used.
814  naturalEntry->SetCachedHash(hashValue);
815  }
816 
817  // Index access helpers.
818  Entry& E(UPInt index)
819  {
820  // Must have pTable and access needs to be within bounds.
821  OVR_ASSERT(index <= pTable->SizeMask);
822  return *(((Entry*) (pTable + 1)) + index);
823  }
824  const Entry& E(UPInt index) const
825  {
826  OVR_ASSERT(index <= pTable->SizeMask);
827  return *(((Entry*) (pTable + 1)) + index);
828  }
829 
830 
831  // Resize the HashSet table to the given size (Rehash the
832  // contents of the current table). The arg is the number of
833  // HashSet table entries, not the number of elements we should
834  // actually contain (which will be less than this).
835  void setRawCapacity(UPInt newSize)
836  {
837  if (newSize == 0)
838  {
839  // Special case.
840  Clear();
841  return;
842  }
843 
844  // Minimum size; don't incur rehashing cost when expanding
845  // very small tables. Not that we perform this check before
846  // 'log2f' call to avoid fp exception with newSize == 1.
847  if (newSize < HashMinSize)
848  newSize = HashMinSize;
849  else
850  {
851  // Force newSize to be a power of two.
852  int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1);
853  OVR_ASSERT((UPInt(1) << bits) >= newSize);
854  newSize = UPInt(1) << bits;
855  }
856 
857  SelfType newHash;
858  newHash.pTable = (TableType*)
860  sizeof(TableType) + sizeof(Entry) * newSize);
861  // Need to do something on alloc failure!
862  OVR_ASSERT(newHash.pTable);
863 
864  newHash.pTable->EntryCount = 0;
865  newHash.pTable->SizeMask = newSize - 1;
866  UPInt i, n;
867 
868  // Mark all entries as empty.
869  for (i = 0; i < newSize; i++)
870  newHash.E(i).NextInChain = -2;
871 
872  // Copy stuff to newHash
873  if (pTable)
874  {
875  for (i = 0, n = pTable->SizeMask; i <= n; i++)
876  {
877  Entry* e = &E(i);
878  if (e->IsEmpty() == false)
879  {
880  // Insert old Entry into new HashSet.
881  newHash.Add(e->Value);
882  // placement delete of old element
883  e->Clear();
884  }
885  }
886 
887  // Delete our old data buffer.
889  }
890 
891  // Steal newHash's data.
892  pTable = newHash.pTable;
893  newHash.pTable = NULL;
894  }
895 
896  struct TableType
897  {
900  // Entry array follows this structure
901  // in memory.
902  };
903  TableType* pTable;
904 };
905 
906 
907 
908 //-----------------------------------------------------------------------------------
909 template<class C, class HashF = FixedSizeHash<C>,
910  class AltHashF = HashF,
911  class Allocator = ContainerAllocator<C>,
912  class Entry = HashsetCachedEntry<C, HashF> >
913 class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry>
914 {
915 public:
918 
919  HashSet() { }
920  HashSet(int sizeHint) : BaseType(sizeHint) { }
921  HashSet(const SelfType& src) : BaseType(src) { }
922  ~HashSet() { }
923 
924  void operator = (const SelfType& src) { BaseType::Assign(src); }
925 
926  // Set a new or existing value under the key, to the value.
927  // Pass a different class of 'key' so that assignment reference object
928  // can be passed instead of the actual object.
929  template<class CRef>
930  void Set(const CRef& key)
931  {
932  BaseType::Set(key);
933  }
934 
935  template<class CRef>
936  inline void Add(const CRef& key)
937  {
938  BaseType::Add(key);
939  }
940 
941  // Hint the bucket count to >= n.
942  void Resize(UPInt n)
943  {
945  }
946 
947  // Size the HashSet so that it can comfortably contain the given
948  // number of elements. If the HashSet already contains more
949  // elements than newSize, then this may be a no-op.
950  void SetCapacity(UPInt newSize)
951  {
952  BaseType::SetCapacity(newSize);
953  }
954 
955 };
956 
957 // HashSet with uncached hash code; declared for convenience.
958 template<class C, class HashF = FixedSizeHash<C>,
959  class AltHashF = HashF,
960  class Allocator = ContainerAllocator<C> >
961 class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> >
962 {
963 public:
964 
967 
968  // Delegated constructors.
970  HashSetUncached(int sizeHint) : BaseType(sizeHint) { }
971  HashSetUncached(const SelfType& src) : BaseType(src) { }
973 
974  void operator = (const SelfType& src)
975  {
977  }
978 };
979 
980 
981 //-----------------------------------------------------------------------------------
982 // ***** Hash hash table implementation
983 
984 // Node for Hash - necessary so that Hash can delegate its implementation
985 // to HashSet.
986 template<class C, class U, class HashF>
987 struct HashNode
988 {
990  typedef C FirstType;
991  typedef U SecondType;
992 
993  C First;
995 
996  // NodeRef is used to allow passing of elements into HashSet
997  // without using a temporary object.
998  struct NodeRef
999  {
1000  const C* pFirst;
1001  const U* pSecond;
1002 
1003  NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { }
1004  NodeRef(const NodeRef& src) : pFirst(src.pFirst), pSecond(src.pSecond) { }
1005 
1006  // Enable computation of ghash_node_hashf.
1007  inline UPInt GetHash() const { return HashF()(*pFirst); }
1008  // Necessary conversion to allow HashNode::operator == to work.
1009  operator const C& () const { return *pFirst; }
1010  };
1011 
1012  // Note: No default constructor is necessary.
1013  HashNode(const HashNode& src) : First(src.First), Second(src.Second) { }
1014  HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond) { }
1015  void operator = (const NodeRef& src) { First = *src.pFirst; Second = *src.pSecond; }
1016 
1017  template<class K>
1018  bool operator == (const K& src) const { return (First == src); }
1019 
1020  template<class K>
1021  static UPInt CalcHash(const K& data) { return HashF()(data); }
1022  inline UPInt GetHash() const { return HashF()(First); }
1023 
1024  // Hash functors used with this node. A separate functor is used for alternative
1025  // key lookup so that it does not need to access the '.First' element.
1026  struct NodeHashF
1027  {
1028  template<class K>
1029  UPInt operator()(const K& data) const { return data.GetHash(); }
1030  };
1032  {
1033  template<class K>
1034  UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); }
1035  };
1036 };
1037 
1038 
1039 
1040 // **** Extra hashset_entry types to allow NodeRef construction.
1041 
1042 // The big difference between the below types and the ones used in hash_set is that
1043 // these allow initializing the node with 'typename C::NodeRef& keyRef', which
1044 // is critical to avoid temporary node allocation on stack when using placement new.
1045 
1046 // Compact hash table Entry type that re-computes hash keys during hash traversal.
1047 // Good to use if the hash function is cheap or the hash value is already cached in C.
1048 template<class C, class HashF>
1050 {
1051 public:
1052  // Internal chaining for collisions.
1055 
1057  : NextInChain(-2) { }
1059  : NextInChain(e.NextInChain), Value(e.Value) { }
1060  HashsetNodeEntry(const C& key, SPInt next)
1061  : NextInChain(next), Value(key) { }
1062  HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
1063  : NextInChain(next), Value(keyRef) { }
1064 
1065  bool IsEmpty() const { return NextInChain == -2; }
1066  bool IsEndOfChain() const { return NextInChain == -1; }
1067  UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; }
1068  void SetCachedHash(UPInt hashValue) { OVR_UNUSED(hashValue); }
1069 
1070  void Clear()
1071  {
1072  Value.~C(); // placement delete
1073  NextInChain = -2;
1074  }
1075  // Free is only used from dtor of hash; Clear is used during regular operations:
1076  // assignment, hash reallocations, value reassignments, so on.
1077  void Free() { Clear(); }
1078 };
1079 
1080 // Hash table Entry type that caches the Entry hash value for nodes, so that it
1081 // does not need to be re-computed during access.
1082 template<class C, class HashF>
1084 {
1085 public:
1086  // Internal chaining for collisions.
1090 
1092  : NextInChain(-2) { }
1095  HashsetCachedNodeEntry(const C& key, SPInt next)
1096  : NextInChain(next), Value(key) { }
1097  HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
1098  : NextInChain(next), Value(keyRef) { }
1099 
1100  bool IsEmpty() const { return NextInChain == -2; }
1101  bool IsEndOfChain() const { return NextInChain == -1; }
1102  UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; }
1103  void SetCachedHash(UPInt hashValue) { HashValue = hashValue; }
1104 
1105  void Clear()
1106  {
1107  Value.~C();
1108  NextInChain = -2;
1109  }
1110  // Free is only used from dtor of hash; Clear is used during regular operations:
1111  // assignment, hash reallocations, value reassignments, so on.
1112  void Free() { Clear(); }
1113 };
1114 
1115 
1116 //-----------------------------------------------------------------------------------
1117 template<class C, class U,
1118  class HashF = FixedSizeHash<C>,
1119  class Allocator = ContainerAllocator<C>,
1120  class HashNode = OVR::HashNode<C,U,HashF>,
1121  class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>,
1122  class Container = HashSet<HashNode, typename HashNode::NodeHashF,
1123  typename HashNode::NodeAltHashF, Allocator,
1124  Entry> >
1125 class Hash
1126 {
1127 public:
1129 
1130  // Types used for hash_set.
1131  typedef U ValueType;
1132  typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container> SelfType;
1133 
1134  // Actual hash table itself, implemented as hash_set.
1135  Container mHash;
1136 
1137 public:
1138  Hash() { }
1139  Hash(int sizeHint) : mHash(sizeHint) { }
1140  Hash(const SelfType& src) : mHash(src.mHash) { }
1141  ~Hash() { }
1142 
1143  void operator = (const SelfType& src) { mHash = src.mHash; }
1144 
1145  // Remove all entries from the Hash table.
1146  inline void Clear() { mHash.Clear(); }
1147  // Returns true if the Hash is empty.
1148  inline bool IsEmpty() const { return mHash.IsEmpty(); }
1149 
1150  // Access (set).
1151  inline void Set(const C& key, const U& value)
1152  {
1153  typename HashNode::NodeRef e(key, value);
1154  mHash.Set(e);
1155  }
1156  inline void Add(const C& key, const U& value)
1157  {
1158  typename HashNode::NodeRef e(key, value);
1159  mHash.Add(e);
1160  }
1161 
1162  // Removes an element by clearing its Entry.
1163  inline void Remove(const C& key)
1164  {
1165  mHash.RemoveAlt(key);
1166  }
1167  template<class K>
1168  inline void RemoveAlt(const K& key)
1169  {
1170  mHash.RemoveAlt(key);
1171  }
1172 
1173  // Retrieve the value under the given key.
1174  // - If there's no value under the key, then return false and leave *pvalue alone.
1175  // - If there is a value, return true, and Set *Pvalue to the Entry's value.
1176  // - If value == NULL, return true or false according to the presence of the key.
1177  bool Get(const C& key, U* pvalue) const
1178  {
1179  const HashNode* p = mHash.GetAlt(key);
1180  if (p)
1181  {
1182  if (pvalue)
1183  *pvalue = p->Second;
1184  return true;
1185  }
1186  return false;
1187  }
1188 
1189  template<class K>
1190  bool GetAlt(const K& key, U* pvalue) const
1191  {
1192  const HashNode* p = mHash.GetAlt(key);
1193  if (p)
1194  {
1195  if (pvalue)
1196  *pvalue = p->Second;
1197  return true;
1198  }
1199  return false;
1200  }
1201 
1202  // Retrieve the pointer to a value under the given key.
1203  // - If there's no value under the key, then return NULL.
1204  // - If there is a value, return the pointer.
1205  inline U* Get(const C& key)
1206  {
1207  HashNode* p = mHash.GetAlt(key);
1208  return p ? &p->Second : 0;
1209  }
1210  inline const U* Get(const C& key) const
1211  {
1212  const HashNode* p = mHash.GetAlt(key);
1213  return p ? &p->Second : 0;
1214  }
1215 
1216  template<class K>
1217  inline U* GetAlt(const K& key)
1218  {
1219  HashNode* p = mHash.GetAlt(key);
1220  return p ? &p->Second : 0;
1221  }
1222  template<class K>
1223  inline const U* GetAlt(const K& key) const
1224  {
1225  const HashNode* p = mHash.GetAlt(key);
1226  return p ? &p->Second : 0;
1227  }
1228 
1229  // Sizing methods - delegate to Hash.
1230  inline UPInt GetSize() const { return mHash.GetSize(); }
1231  inline void Resize(UPInt n) { mHash.Resize(n); }
1232  inline void SetCapacity(UPInt newSize) { mHash.SetCapacity(newSize); }
1233 
1234  // Iterator API, like STL.
1235  typedef typename Container::ConstIterator ConstIterator;
1236  typedef typename Container::Iterator Iterator;
1237 
1238  inline Iterator Begin() { return mHash.Begin(); }
1239  inline Iterator End() { return mHash.End(); }
1240  inline ConstIterator Begin() const { return mHash.Begin(); }
1241  inline ConstIterator End() const { return mHash.End(); }
1242 
1243  Iterator Find(const C& key) { return mHash.FindAlt(key); }
1244  ConstIterator Find(const C& key) const { return mHash.FindAlt(key); }
1245 
1246  template<class K>
1247  Iterator FindAlt(const K& key) { return mHash.FindAlt(key); }
1248  template<class K>
1249  ConstIterator FindAlt(const K& key) const { return mHash.FindAlt(key); }
1250 };
1251 
1252 
1253 
1254 // Hash with uncached hash code; declared for convenience.
1255 template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = ContainerAllocator<C> >
1257  : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
1258  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
1259 {
1260 public:
1265 
1266  // Delegated constructors.
1268  HashUncached(int sizeHint) : BaseType(sizeHint) { }
1269  HashUncached(const SelfType& src) : BaseType(src) { }
1271  void operator = (const SelfType& src) { BaseType::operator = (src); }
1272 };
1273 
1274 
1275 
1276 // And identity hash in which keys serve as hash value. Can be uncached,
1277 // since hash computation is assumed cheap.
1278 template<class C, class U, class Allocator = ContainerAllocator<C>, class HashF = IdentityHash<C> >
1280  : public HashUncached<C, U, HashF, Allocator>
1281 {
1282 public:
1285 
1286  // Delegated constructors.
1288  HashIdentity(int sizeHint) : BaseType(sizeHint) { }
1289  HashIdentity(const SelfType& src) : BaseType(src) { }
1291  void operator = (const SelfType& src) { BaseType::operator = (src); }
1292 };
1293 
1294 
1295 } // OVR
1296 
1297 
1298 #ifdef OVR_DEFINE_NEW
1299 #define new OVR_DEFINE_NEW
1300 #endif
1301 
1302 #endif
#define OVR_FORCE_INLINE
void Remove(const CRef &key)
Definition: OVR_Hash.h:353
const C * Get(const K &key) const
Definition: OVR_Hash.h:371
static OVR_FORCE_INLINE UPInt SDBM_Hash(const void *data_in, UPInt size, UPInt seed=5381)
Definition: OVR_Hash.h:87
ConstIterator FindAlt(const K &key) const
Definition: OVR_Hash.h:1249
void Add(const C &key, const U &value)
Definition: OVR_Hash.h:1156
Iterator Begin()
Definition: OVR_Hash.h:1238
UPInt GetCachedHash(UPInt maskValue) const
Definition: OVR_Hash.h:170
HashsetNodeEntry(const HashsetNodeEntry &e)
Definition: OVR_Hash.h:1058
Iterator End()
Definition: OVR_Hash.h:1239
HashSetBase< C, HashF, AltHashF, Allocator, Entry > BaseType
Definition: OVR_Hash.h:916
HashsetCachedNodeEntry(const C &key, SPInt next)
Definition: OVR_Hash.h:1095
HashSetBase(int sizeHint)
Definition: OVR_Hash.h:205
HashSetUncached(const SelfType &src)
Definition: OVR_Hash.h:971
U * GetAlt(const K &key)
Definition: OVR_Hash.h:1217
void Add(const CRef &key)
Definition: OVR_Hash.h:936
SPInt findIndex(const K &key) const
Definition: OVR_Hash.h:688
const C * GetAlt(const K &key) const
Definition: OVR_Hash.h:381
HashsetCachedNodeEntry(const HashsetCachedNodeEntry &e)
Definition: OVR_Hash.h:1093
HashSetUncached< C, HashF, AltHashF, Allocator > SelfType
Definition: OVR_Hash.h:965
#define NULL
void operator=(const NodeRef &src)
Definition: OVR_Hash.h:1015
void Clear()
Definition: OVR_Hash.h:1146
bool IsEndOfChain() const
Definition: OVR_Hash.h:1101
Entry & E(UPInt index)
Definition: OVR_Hash.h:818
Hash(const SelfType &src)
Definition: OVR_Hash.h:1140
HashsetCachedEntry(const C &key, SPInt next)
Definition: OVR_Hash.h:162
Hash< C, U, HashF, Allocator, HashNode< C, U, HashF >, HashsetNodeEntry< HashNode< C, U, HashF >, typename HashNode< C, U, HashF >::NodeHashF > > BaseType
Definition: OVR_Hash.h:1264
Iterator Find(const K &key)
Definition: OVR_Hash.h:662
void Resize(UPInt n)
Definition: OVR_Hash.h:942
UPInt operator()(const K &data) const
Definition: OVR_Hash.h:1029
HashUncached(int sizeHint)
Definition: OVR_Hash.h:1268
friend struct ConstIterator
Definition: OVR_Hash.h:545
void SetCapacity(UPInt newSize)
Definition: OVR_Hash.h:449
void operator=(const SelfType &src)
Definition: OVR_Hash.h:924
Iterator End()
Definition: OVR_Hash.h:656
bool IsEmpty() const
Definition: OVR_Hash.h:1148
void operator=(const SelfType &src)
Definition: OVR_Hash.h:1291
UPInt operator()(const C &data) const
Definition: OVR_Hash.h:74
NodeRef(const C &f, const U &s)
Definition: OVR_Hash.h:1003
#define OVR_UNUSED(a)
const C & operator*() const
Definition: OVR_Hash.h:467
void setRawCapacity(UPInt newSize)
Definition: OVR_Hash.h:835
const U * GetAlt(const K &key) const
Definition: OVR_Hash.h:1223
void Set(const C &key, const U &value)
Definition: OVR_Hash.h:1151
U * Get(const C &key)
Definition: OVR_Hash.h:1205
HashIdentity(const SelfType &src)
Definition: OVR_Hash.h:1289
size_t UPInt
Definition: OVR_Types.h:218
Iterator FindAlt(const K &key)
Definition: OVR_Hash.h:1247
bool GetAlt(const K &key, U *pvalue) const
Definition: OVR_Hash.h:1190
uint8_t UByte
Definition: OVR_Types.h:249
HashsetEntry(const C &key, SPInt next)
Definition: OVR_Hash.h:126
void operator=(const SelfType &src)
Definition: OVR_Hash.h:974
UPInt GetCachedHash(UPInt maskValue) const
Definition: OVR_Hash.h:1067
bool IsEmpty() const
Definition: OVR_Hash.h:260
C * Get(const K &key)
Definition: OVR_Hash.h:362
UPInt GetSize() const
Definition: OVR_Hash.h:1230
void Remove(const C &key)
Definition: OVR_Hash.h:1163
ConstIterator Find(const K &key) const
Definition: OVR_Hash.h:680
Container mHash
Definition: OVR_Hash.h:1135
bool GetAlt(const K &key, C *pval) const
Definition: OVR_Hash.h:399
ConstIterator(const SelfType *h, SPInt index)
Definition: OVR_Hash.h:525
ConstIterator Find(const C &key) const
Definition: OVR_Hash.h:1244
HashSet< C, HashF, AltHashF, Allocator, Entry > SelfType
Definition: OVR_Hash.h:917
UByte UpperBit(UPInt val)
Definition: OVR_Alg.h:670
Iterator Begin()
Definition: OVR_Hash.h:643
UPInt GetSize() const
Definition: OVR_Hash.h:412
UPInt GetHash() const
Definition: OVR_Hash.h:1022
void operator=(const SelfType &src)
Definition: OVR_Hash.h:1271
void RemoveAlt(const K &key)
Definition: OVR_Hash.h:1168
HashSet< C, HashF, AltHashF, Allocator, HashsetEntry< C, HashF > > BaseType
Definition: OVR_Hash.h:966
bool operator!=(const ConstIterator &it) const
Definition: OVR_Hash.h:505
void SetCachedHash(UPInt hashValue)
Definition: OVR_Hash.h:1103
HashsetNodeEntry(const typename C::NodeRef &keyRef, SPInt next)
Definition: OVR_Hash.h:1062
HashUncached(const SelfType &src)
Definition: OVR_Hash.h:1269
#define OVR_ASSERT(p)
const Entry & E(UPInt index) const
Definition: OVR_Hash.h:824
void RemoveAlt(const K &key)
Definition: OVR_Hash.h:574
#define OVR_MEMORY_REDEFINE_NEW(class_name)
Definition: OVR_Allocator.h:91
HashUncached< C, U, HashF, Allocator > BaseType
Definition: OVR_Hash.h:1284
HashsetEntry(const HashsetEntry &e)
Definition: OVR_Hash.h:124
UPInt GetHash() const
Definition: OVR_Hash.h:1007
const U * Get(const C &key) const
Definition: OVR_Hash.h:1210
C * GetAlt(const K &key)
Definition: OVR_Hash.h:390
void operator=(const SelfType &src)
Definition: OVR_Hash.h:1143
void CheckExpand()
Definition: OVR_Hash.h:420
HashIdentity< C, U, Allocator, HashF > SelfType
Definition: OVR_Hash.h:1283
HashNode(const NodeRef &src)
Definition: OVR_Hash.h:1014
Iterator FindAlt(const K &key)
Definition: OVR_Hash.h:671
Container::ConstIterator ConstIterator
Definition: OVR_Hash.h:1235
UPInt operator()(const C &data) const
Definition: OVR_Hash.h:99
bool IsEmpty() const
Definition: OVR_Hash.h:165
HashNode< C, U, HashF > SelfType
Definition: OVR_Hash.h:989
void Add(const CRef &key)
Definition: OVR_Hash.h:290
HashNode(const HashNode &src)
Definition: OVR_Hash.h:1013
HashSet(int sizeHint)
Definition: OVR_Hash.h:920
HashsetCachedNodeEntry(const typename C::NodeRef &keyRef, SPInt next)
Definition: OVR_Hash.h:1097
void SetCachedHash(UPInt)
Definition: OVR_Hash.h:135
void RemoveAlt(const K &key)
Definition: OVR_Hash.h:298
HashSet(const SelfType &src)
Definition: OVR_Hash.h:921
void Set(const CRef &key)
Definition: OVR_Hash.h:270
SPInt findIndexAlt(const K &key) const
Definition: OVR_Hash.h:697
NodeRef(const NodeRef &src)
Definition: OVR_Hash.h:1004
void SetCapacity(UPInt newSize)
Definition: OVR_Hash.h:950
void SetCapacity(UPInt newSize)
Definition: OVR_Hash.h:1232
SPInt findIndexCore(const K &key, UPInt hashValue) const
Definition: OVR_Hash.h:707
void SetCachedHash(UPInt hashValue)
Definition: OVR_Hash.h:1068
ConstIterator Begin() const
Definition: OVR_Hash.h:658
C & operator*() const
Definition: OVR_Hash.h:552
void Resize(UPInt n)
Definition: OVR_Hash.h:1231
Container::Iterator Iterator
Definition: OVR_Hash.h:1236
ptrdiff_t SPInt
Definition: OVR_Types.h:219
virtual void * Alloc(UPInt size)=0
bool IsEmpty() const
Definition: OVR_Hash.h:1065
ConstIterator Begin() const
Definition: OVR_Hash.h:1240
ConstIterator FindAlt(const K &key) const
Definition: OVR_Hash.h:683
UPInt operator()(const K &data) const
Definition: OVR_Hash.h:1034
bool IsEndOfChain() const
Definition: OVR_Hash.h:130
Iterator Find(const C &key)
Definition: OVR_Hash.h:1243
void add(const CRef &key, UPInt hashValue)
Definition: OVR_Hash.h:748
Iterator(SelfType *h, SPInt i0)
Definition: OVR_Hash.h:636
static UPInt CalcHash(const K &data)
Definition: OVR_Hash.h:1021
int char * index(const char *__s, int __c) __THROW __attribute_pure__ __nonnull((1))
HashsetCachedEntry(const HashsetCachedEntry &e)
Definition: OVR_Hash.h:160
void SetCachedHash(UPInt hashValue)
Definition: OVR_Hash.h:171
bool operator==(const K &src) const
Definition: OVR_Hash.h:1018
void Assign(const SelfType &src)
Definition: OVR_Hash.h:226
bool IsEndOfChain() const
Definition: OVR_Hash.h:166
Hash(int sizeHint)
Definition: OVR_Hash.h:1139
UPInt GetCachedHash(UPInt maskValue) const
Definition: OVR_Hash.h:1102
friend struct Iterator
Definition: OVR_Hash.h:641
HashUncached< C, U, HashF, Allocator > SelfType
Definition: OVR_Hash.h:1261
ConstIterator End() const
Definition: OVR_Hash.h:659
virtual void Free(void *p)=0
void Set(const CRef &key)
Definition: OVR_Hash.h:930
HashSetBase(const SelfType &src)
Definition: OVR_Hash.h:206
const C * operator->() const
Definition: OVR_Hash.h:473
C * operator->() const
Definition: OVR_Hash.h:558
HashIdentity(int sizeHint)
Definition: OVR_Hash.h:1288
ConstIterator End() const
Definition: OVR_Hash.h:1241
UPInt GetCachedHash(UPInt maskValue) const
Definition: OVR_Hash.h:134
void Resize(UPInt n)
Definition: OVR_Hash.h:435
bool IsEmpty() const
Definition: OVR_Hash.h:129
const SelfType * GetContainer() const
Definition: OVR_Hash.h:529
TableType * pTable
Definition: OVR_Hash.h:903
HashsetNodeEntry(const C &key, SPInt next)
Definition: OVR_Hash.h:1060
bool operator==(const ConstIterator &it) const
Definition: OVR_Hash.h:493
HashSetUncached(int sizeHint)
Definition: OVR_Hash.h:970
bool Get(const C &key, U *pvalue) const
Definition: OVR_Hash.h:1177
bool IsEndOfChain() const
Definition: OVR_Hash.h:1066