kodi
NptMap.h
1 /*****************************************************************
2 |
3 | Neptune - Maps
4 |
5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 | * Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | * Neither the name of Axiomatic Systems nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 ****************************************************************/
31 
32 #ifndef _NPT_MAP_H_
33 #define _NPT_MAP_H_
34 
35 /*----------------------------------------------------------------------
36 | includes
37 +---------------------------------------------------------------------*/
38 #include "NptTypes.h"
39 #include "NptResults.h"
40 #include "NptList.h"
41 #include "NptHash.h"
42 
43 /*----------------------------------------------------------------------
44 | NPT_Map
45 +---------------------------------------------------------------------*/
46 template <typename K, typename V>
47 class NPT_Map
48 {
49 public:
50  // types
51  class Entry {
52  public:
53  // constructor
54  Entry(const K& key, const V& value) : m_Key(key), m_Value(value) {}
55  Entry(const K& key) : m_Key(key), m_Value() {}
56 
57  // accessors
58  const K& GetKey() const { return m_Key; }
59  const V& GetValue() const { return m_Value; }
60 
61  // operators
62  bool operator==(const Entry& other) const {
63  return m_Key == other.m_Key && m_Value == other.m_Value;
64  }
65 
66  protected:
67  // methods
68  void SetValue(const V& value) { m_Value = value; }
69 
70  // members
71  K m_Key;
72  V m_Value;
73 
74  // friends
75  friend class NPT_Map<K,V>;
76  };
77 
78  // constructors
79  NPT_Map<K,V>() {}
80  NPT_Map<K,V>(const NPT_Map<K,V>& copy);
81 
82  // destructor
83  ~NPT_Map<K,V>();
84 
85  // methods
86  NPT_Result Put(const K& key, const V& value);
87  NPT_Result Get(const K& key, V*& value) const; // WARNING: the second parameter is a POINTER on the value type!!!
88  bool HasKey(const K& key) const { return GetEntry(key) != NULL; }
89  bool HasValue(const V& value) const;
90  NPT_Result Erase(const K& key);
91  NPT_Cardinal GetEntryCount() const { return m_Entries.GetItemCount(); }
92  const NPT_List<Entry*>& GetEntries() const { return m_Entries; }
93  NPT_Result Clear();
94 
95  // operators
96  V& operator[](const K& key);
97  const NPT_Map<K,V>& operator=(const NPT_Map<K,V>& copy);
98  bool operator==(const NPT_Map<K,V>& other) const;
99  bool operator!=(const NPT_Map<K,V>& other) const;
100 
101 private:
102  // types
103  typedef typename NPT_List<Entry*>::Iterator ListIterator;
104 
105  // methods
106  Entry* GetEntry(const K& key) const;
107 
108  // members
109  NPT_List<Entry*> m_Entries;
110 };
111 
112 /*----------------------------------------------------------------------
113 | NPT_Map<K,V>::NPT_Map<K,V>
114 +---------------------------------------------------------------------*/
115 template <typename K, typename V>
117 {
118  *this = copy;
119 }
120 
121 /*----------------------------------------------------------------------
122 | NPT_Map<K,V>::~NPT_Map<K,V>
123 +---------------------------------------------------------------------*/
124 template <typename K, typename V>
126 {
127  // call Clear to ensure we delete all entry objects
128  Clear();
129 }
130 
131 /*----------------------------------------------------------------------
132 | NPT_Map<K,V>::Clear
133 +---------------------------------------------------------------------*/
134 template <typename K, typename V>
135 NPT_Result
137 {
138  m_Entries.Apply(NPT_ObjectDeleter<Entry>());
139  m_Entries.Clear();
140 
141  return NPT_SUCCESS;
142 }
143 
144 /*----------------------------------------------------------------------
145 | NPT_Map<K,V>::GetEntry
146 +---------------------------------------------------------------------*/
147 template <typename K, typename V>
148 typename NPT_Map<K,V>::Entry*
149 NPT_Map<K,V>::GetEntry(const K& key) const
150 {
151  typename NPT_List<Entry*>::Iterator entry = m_Entries.GetFirstItem();
152  while (entry) {
153  if ((*entry)->GetKey() == key) {
154  return *entry;
155  }
156  ++entry;
157  }
158 
159  return NULL;
160 }
161 
162 /*----------------------------------------------------------------------
163 | NPT_Map<K,V>::Put
164 +---------------------------------------------------------------------*/
165 template <typename K, typename V>
166 NPT_Result
167 NPT_Map<K,V>::Put(const K& key, const V& value)
168 {
169  Entry* entry = GetEntry(key);
170  if (entry == NULL) {
171  // no existing entry for that key, create one
172  m_Entries.Add(new Entry(key, value));
173  } else {
174  // replace the existing entry for that key
175  entry->SetValue(value);
176  }
177 
178  return NPT_SUCCESS;
179 }
180 
181 /*----------------------------------------------------------------------
182 | NPT_Map<K,V>::Get
183 +---------------------------------------------------------------------*/
184 template <typename K, typename V>
185 NPT_Result
186 NPT_Map<K,V>::Get(const K& key, V*& value) const
187 {
188  Entry* entry = GetEntry(key);
189  if (entry == NULL) {
190  // no existing entry for that key
191  value = NULL;
192  return NPT_ERROR_NO_SUCH_ITEM;
193  } else {
194  // found an entry with that key
195  value = &entry->m_Value;
196  return NPT_SUCCESS;
197  }
198 }
199 
200 /*----------------------------------------------------------------------
201 | NPT_Map<K,V>::HasValue
202 +---------------------------------------------------------------------*/
203 template <typename K, typename V>
204 bool
205 NPT_Map<K,V>::HasValue(const V& value) const
206 {
207  ListIterator entry = m_Entries.GetFirstItem();
208  while (entry) {
209  if (value == (*entry)->m_Value) {
210  return true;
211  }
212  ++entry;
213  }
214 
215  return false;
216 }
217 
218 /*----------------------------------------------------------------------
219 | NPT_Map<K,V>::operator=
220 +---------------------------------------------------------------------*/
221 template <typename K, typename V>
222 const NPT_Map<K,V>&
224 {
225  // do nothing if we're assigning to ourselves
226  if (this == &copy) return copy;
227 
228  // destroy all entries
229  Clear();
230 
231  // copy all entries one by one
232  ListIterator entry = copy.m_Entries.GetFirstItem();
233  while (entry) {
234  m_Entries.Add(new Entry((*entry)->GetKey(), (*entry)->GetValue()));
235  ++entry;
236  }
237 
238  return *this;
239 }
240 
241 /*----------------------------------------------------------------------
242 | NPT_Map<K,V>::Erase
243 +---------------------------------------------------------------------*/
244 template <typename K, typename V>
245 NPT_Result
246 NPT_Map<K,V>::Erase(const K& key)
247 {
248  ListIterator entry = m_Entries.GetFirstItem();
249  while (entry) {
250  if ((*entry)->GetKey() == key) {
251  delete *entry; // do this before removing the entry from the
252  // list, because Erase() will invalidate the
253  // iterator item
254  m_Entries.Erase(entry);
255  return NPT_SUCCESS;
256  }
257  ++entry;
258  }
259 
260  return NPT_ERROR_NO_SUCH_ITEM;
261 }
262 
263 /*----------------------------------------------------------------------
264 | NPT_Map<K,V>::operator==
265 +---------------------------------------------------------------------*/
266 template <typename K, typename V>
267 bool
268 NPT_Map<K,V>::operator==(const NPT_Map<K,V>& other) const
269 {
270  // quick test
271  if (m_Entries.GetItemCount() != other.m_Entries.GetItemCount()) return false;
272 
273  // compare all entries to all other entries
274  ListIterator entry = m_Entries.GetFirstItem();
275  while (entry) {
276  V* value;
277  if (NPT_SUCCEEDED(other.Get((*entry)->m_Key, value))) {
278  // the other map has an entry for this key, check the value
279  if (!(*value == (*entry)->m_Value)) return false;
280  } else {
281  // the other map does not have an entry for this key
282  return false;
283  }
284  ++entry;
285  }
286 
287  return true;
288 }
289 
290 /*----------------------------------------------------------------------
291 | NPT_Map<K,V>::operator!=
292 +---------------------------------------------------------------------*/
293 template <typename K, typename V>
294 bool
295 NPT_Map<K,V>::operator!=(const NPT_Map<K,V>& other) const
296 {
297  return !(*this == other);
298 }
299 
300 /*----------------------------------------------------------------------
301 | NPT_Map<K,V>::operator[]
302 +---------------------------------------------------------------------*/
303 template <typename K, typename V>
304 V&
305 NPT_Map<K,V>::operator[](const K& key)
306 {
307  Entry* entry = GetEntry(key);
308  if (entry == NULL) {
309  // create a new "default" entry for this key
310  entry = new Entry(key);
311  m_Entries.Add(entry);
312  }
313 
314  return entry->m_Value;
315 }
316 
317 /*----------------------------------------------------------------------
318 | NPT_HashMap
319 +---------------------------------------------------------------------*/
320 template <typename K, typename V, typename HF = NPT_Hash<K> >
322 {
323 public:
324  // types
325  class Entry {
326  public:
327  // constructor
328  Entry(NPT_UInt32 hash_value, const K& key, const V& value) : m_HashValue(hash_value), m_Key(key), m_Value(value) {}
329  Entry(NPT_UInt32 hash_value, const K& key) : m_HashValue(hash_value), m_Key(key), m_Value() {}
330 
331  // accessors
332  const K& GetKey() const { return m_Key; }
333  const V& GetValue() const { return m_Value; }
334  NPT_UInt32 GetHashValue() const { return m_HashValue; }
335 
336  // operators
337  bool operator==(const Entry& other) const {
338  return m_HashValue == other.m_HashValue && m_Key == other.m_Key && m_Value == other.m_Value;
339  }
340 
341  protected:
342  // methods
343  void SetValue(const V& value) { m_Value = value; }
344 
345  // members
346  NPT_UInt32 m_HashValue;
347  K m_Key;
348  V m_Value;
349 
350  // friends
351  friend class NPT_HashMap<K,V,HF>;
352  };
353 
354  class Iterator {
355  public:
356  Iterator() : m_Entry(NULL), m_Map(NULL) {}
357  Iterator(Entry** entry, const NPT_HashMap<K,V,HF>* map) : m_Entry(entry), m_Map(map) {}
358  Iterator(const Iterator& copy) : m_Entry(copy.m_Entry), m_Map(copy.m_Map) {}
359  const Entry& operator*() const { return **m_Entry; }
360  Iterator& operator++() { // prefix
361  if (m_Map && m_Entry) {
362  do {
363  ++m_Entry;
364  if (m_Entry >= &m_Map->m_Buckets[1<<m_Map->m_BucketCountLog]) {
365  m_Entry = NULL;
366  } else {
367  if (*m_Entry) break;
368  }
369  } while (m_Entry);
370  }
371  return (*this);
372  }
373  Iterator operator++(int) { // postfix
374  Iterator saved_this = *this;
375  ++(*this);
376  return saved_this;
377  }
378  operator bool() const {
379  return m_Entry != NULL;
380  }
381  bool operator==(const Iterator& other) const {
382  return m_Map == other.m_Map && m_Entry == other.m_Entry;
383  }
384  bool operator!=(const Iterator& other) const {
385  return !(*this == other);
386  }
387  void operator=(const Iterator& other) {
388  m_Entry = other.m_Entry;
389  m_Map = other.m_Map;
390  }
391 
392  private:
393  // friends
394  friend class NPT_HashMap<K,V,HF>;
395 
396  // members
397  Entry** m_Entry;
398  const NPT_HashMap<K,V,HF>* m_Map;
399  };
400 
401  // constructors
403  NPT_HashMap<K,V,HF>(const HF& hasher);
405 
406  // destructor
408 
409  // methods
410  NPT_Result Put(const K& key, const V& value);
411  NPT_Result Get(const K& key, V*& value) const; // WARNING: the second parameter is a POINTER on the value type!!!
412  bool HasKey(const K& key) const { return GetEntry(key) != NULL; }
413  bool HasValue(const V& value) const;
414  NPT_Result Erase(const K& key);
415  NPT_Cardinal GetEntryCount() const { return m_EntryCount; }
416  Iterator GetEntries() const;
417  NPT_Result Clear();
418 
419  // list operations
420  // keep these template members defined here because MSV6 does not let
421  // us define them later
422  template <typename X>
423  NPT_Result Apply(const X& function) const
424  {
425  for (int i=0; i<(1<<m_BucketCountLog); i++) {
426  if (m_Buckets[i]) {
427  function(m_Buckets[i]);
428  }
429  }
430  return NPT_SUCCESS;
431  }
432 
433  // operators
434  V& operator[](const K& key);
435  const NPT_HashMap<K,V,HF>& operator=(const NPT_HashMap<K,V,HF>& copy);
436  bool operator==(const NPT_HashMap<K,V,HF>& other) const;
437  bool operator!=(const NPT_HashMap<K,V,HF>& other) const;
438 
439 private:
440  // methods
441  Entry* GetEntry(const K& key, NPT_UInt32* position=NULL) const;
442  NPT_Result AddEntry(Entry* entry);
443  void AllocateBuckets(unsigned int count_log);
444  void AdjustBuckets(NPT_Cardinal entry_count, bool allow_shrink=false);
445 
446  // members
447  HF m_Hasher;
448  Entry** m_Buckets;
449  NPT_Cardinal m_BucketCountLog;
450  NPT_Cardinal m_EntryCount;
451 };
452 
453 /*----------------------------------------------------------------------
454 | NPT_HashMap<K,V>::NPT_HashMap
455 +---------------------------------------------------------------------*/
456 template <typename K, typename V, typename HF>
458  m_Buckets(NULL),
459  m_EntryCount(0)
460 {
461  AllocateBuckets(4);
462 }
463 
464 /*----------------------------------------------------------------------
465 | NPT_HashMap<K,V>::NPT_HashMap
466 +---------------------------------------------------------------------*/
467 template <typename K, typename V, typename HF>
468 NPT_HashMap<K,V,HF>::NPT_HashMap(const HF& hasher) :
469  m_Hasher(hasher),
470  m_Buckets(NULL),
471  m_EntryCount(0)
472 {
473  AllocateBuckets(4);
474 }
475 
476 /*----------------------------------------------------------------------
477 | NPT_HashMap<K,V>::NPT_HashMap
478 +---------------------------------------------------------------------*/
479 template <typename K, typename V, typename HF>
481  m_Buckets(NULL),
482  m_BucketCountLog(0),
483  m_EntryCount(0)
484 {
485  *this = copy;
486 }
487 
488 /*----------------------------------------------------------------------
489 | NPT_MapMap<K,V,HF>::NPT_HashMap
490 +---------------------------------------------------------------------*/
491 template <typename K, typename V, typename HF>
493 {
494  for (int i=0; i<(1<<m_BucketCountLog); i++) {
495  delete m_Buckets[i];
496  }
497  delete[] m_Buckets;
498 }
499 
500 /*----------------------------------------------------------------------
501 | NPT_HashMap<K,V,HF>::AllocateBuckets
502 +---------------------------------------------------------------------*/
503 template <typename K, typename V, typename HF>
504 void
505 NPT_HashMap<K,V,HF>::AllocateBuckets(unsigned int count_log)
506 {
507  m_Buckets = new Entry*[1<<count_log];
508  m_BucketCountLog = count_log;
509  for (int i=0; i<(1<<count_log); i++) {
510  m_Buckets[i] = NULL;
511  }
512 }
513 
514 /*----------------------------------------------------------------------
515 | NPT_HashMap<K,V,HF>::AdjustBuckets
516 +---------------------------------------------------------------------*/
517 template <typename K, typename V, typename HF>
518 void
519 NPT_HashMap<K,V,HF>::AdjustBuckets(NPT_Cardinal entry_count, bool allow_shrink)
520 {
521  Entry** buckets = NULL;
522  unsigned int bucket_count = 1<<m_BucketCountLog;
523  if (2*entry_count >= bucket_count) {
524  // we need to grow
525  buckets = m_Buckets;
526  AllocateBuckets(m_BucketCountLog+1);
527  } else if (allow_shrink && (5*entry_count < bucket_count) && m_BucketCountLog > 4) {
528  // we need to shrink
529  buckets = m_Buckets;
530  AllocateBuckets(m_BucketCountLog-1);
531  }
532  if (buckets) {
533  m_EntryCount = 0;
534  for (unsigned int i=0; i<bucket_count; i++) {
535  if (buckets[i]) AddEntry(buckets[i]);
536  }
537  delete[] buckets;
538  }
539 }
540 
541 /*----------------------------------------------------------------------
542 | NPT_HashMap<K,V,HF>::Clear
543 +---------------------------------------------------------------------*/
544 template <typename K, typename V, typename HF>
545 NPT_Result
547 {
548  if (m_Buckets) {
549  for (int i=0; i<(1<<m_BucketCountLog); i++) {
550  delete m_Buckets[i];
551  }
552  delete[] m_Buckets;
553  }
554  m_EntryCount = 0;
555  AllocateBuckets(4);
556 
557  return NPT_SUCCESS;
558 }
559 
560 /*----------------------------------------------------------------------
561 | NPT_HashMap<K,V,HF>::GetEntries
562 +---------------------------------------------------------------------*/
563 template <typename K, typename V, typename HF>
566 {
567  for (int i=0; i<(1<<m_BucketCountLog); i++) {
568  if (m_Buckets[i]) {
569  return Iterator(&m_Buckets[i], this);
570  }
571  }
572  return Iterator(NULL, this);
573 }
574 
575 /*----------------------------------------------------------------------
576 | NPT_HashMap<K,V,HF>::GetEntry
577 +---------------------------------------------------------------------*/
578 template <typename K, typename V, typename HF>
580 NPT_HashMap<K,V,HF>::GetEntry(const K& key, NPT_UInt32* position) const
581 {
582  NPT_UInt32 hash_value = m_Hasher(key);
583  NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
584  NPT_UInt32 cursor = hash_value & mask;
585  while (m_Buckets[cursor]) {
586  Entry* entry = m_Buckets[cursor];
587  if (entry->m_HashValue == hash_value &&
588  entry->m_Key == key) {
589  if (position) *position = cursor;
590  return entry;
591  }
592  cursor = (cursor + 1) & mask;
593  }
594 
595  return NULL;
596 }
597 
598 /*----------------------------------------------------------------------
599 | NPT_HashMap<K,V,HF>::AddEntry
600 +---------------------------------------------------------------------*/
601 template <typename K, typename V, typename HF>
602 NPT_Result
604 {
605  AdjustBuckets(m_EntryCount+1);
606 
607  NPT_UInt32 hash_value = entry->m_HashValue;
608  NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
609  NPT_UInt32 cursor = hash_value & mask;
610  while (m_Buckets[cursor]) {
611  cursor = (cursor + 1) & mask;
612  }
613  m_Buckets[cursor] = entry;
614  ++m_EntryCount;
615 
616  return NPT_SUCCESS;
617 }
618 
619 /*----------------------------------------------------------------------
620 | NPT_HashMap<K,V,HF>::Put
621 +---------------------------------------------------------------------*/
622 template <typename K, typename V, typename HF>
623 NPT_Result
624 NPT_HashMap<K,V,HF>::Put(const K& key, const V& value)
625 {
626  Entry* entry = GetEntry(key);
627  if (entry == NULL) {
628  // no existing entry for that key, create one
629  return AddEntry(new Entry(m_Hasher(key), key, value));
630  } else {
631  // replace the existing entry for that key
632  entry->SetValue(value);
633  }
634 
635  return NPT_SUCCESS;
636 }
637 
638 /*----------------------------------------------------------------------
639 | NPT_HashMap<K,V,HF>::Get
640 +---------------------------------------------------------------------*/
641 template <typename K, typename V, typename HF>
642 NPT_Result
643 NPT_HashMap<K,V,HF>::Get(const K& key, V*& value) const
644 {
645  Entry* entry = GetEntry(key);
646  if (entry == NULL) {
647  // no existing entry for that key
648  value = NULL;
649  return NPT_ERROR_NO_SUCH_ITEM;
650  } else {
651  // found an entry with that key
652  value = &entry->m_Value;
653  return NPT_SUCCESS;
654  }
655 }
656 
657 /*----------------------------------------------------------------------
658 | NPT_HashMap<K,V,HF>::HasValue
659 +---------------------------------------------------------------------*/
660 template <typename K, typename V, typename HF>
661 bool
662 NPT_HashMap<K,V,HF>::HasValue(const V& value) const
663 {
664  for (int i=0; i<(1<<m_BucketCountLog); i++) {
665  if (m_Buckets[i] && m_Buckets[i]->m_Value == value) {
666  return true;
667  }
668  }
669 
670  return false;
671 }
672 
673 /*----------------------------------------------------------------------
674 | NPT_HashMap<K,V,HF>::Erase
675 +---------------------------------------------------------------------*/
676 template <typename K, typename V, typename HF>
677 NPT_Result
678 NPT_HashMap<K,V,HF>::Erase(const K& key)
679 {
680  NPT_UInt32 position;
681  Entry* entry = GetEntry(key, &position);
682  if (entry == NULL) {
683  return NPT_ERROR_NO_SUCH_ITEM;
684  }
685 
686  // mark the bucket as unoccupied
687  m_Buckets[position] = NULL;
688 
689  // look for buckets that need to be relocated:
690  // there should be no empty bucket between an entry's ideal hash bucket
691  // and its actual bucket.
692  NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
693  for (NPT_UInt32 cursor = (position+1) & mask; m_Buckets[cursor]; cursor = (cursor + 1) & mask) {
694  NPT_UInt32 target = m_Buckets[cursor]->m_HashValue & mask;
695  // check if target is between position and cursor (modulo the bucket array size)
696  // | position.target.cursor |
697  // |....cursor position.target.| or |.target..cursor position...|
698  if ( (position <= cursor) ?
699  ((position < target) && (target <= cursor)) :
700  ((position < target) || (target <= cursor)) ) {
701  continue;
702  }
703 
704  // move the bucket back
705  m_Buckets[position] = m_Buckets[cursor];
706  m_Buckets[cursor] = NULL;
707  position = cursor;
708  }
709 
710  // cleanup and adjust the counter and buckets
711  delete entry;
712  --m_EntryCount;
713  AdjustBuckets(m_EntryCount, true);
714 
715  return NPT_SUCCESS;
716 }
717 
718 /*----------------------------------------------------------------------
719 | NPT_HashMap<K,V,HF>::operator=
720 +---------------------------------------------------------------------*/
721 template <typename K, typename V, typename HF>
722 const NPT_HashMap<K,V,HF>&
724 {
725  // do nothing if we're assigning to ourselves
726  if (this == &copy) return copy;
727 
728  // destroy all entries
729  Clear();
730 
731  // prepare to receive all the entries
732  AdjustBuckets(copy.m_EntryCount);
733 
734  // copy all entries
735  for (int i=0; i<1<<copy.m_BucketCountLog; i++) {
736  if (copy.m_Buckets[i]) {
737  AddEntry(new Entry(m_Hasher(copy.m_Buckets[i]->GetKey()),
738  copy.m_Buckets[i]->GetKey(),
739  copy.m_Buckets[i]->GetValue()));
740  }
741  }
742 
743  return *this;
744 }
745 
746 /*----------------------------------------------------------------------
747 | NPT_HashMap<K,V,HF>::operator==
748 +---------------------------------------------------------------------*/
749 template <typename K, typename V, typename HF>
750 bool
752 {
753  // quick check
754  if (m_EntryCount != other.m_EntryCount) return false;
755 
756  // compare all entries to all other entries
757  for (int i=0; i<(1<<m_BucketCountLog); i++) {
758  Entry* entry = m_Buckets[i];
759  if (entry == NULL) continue;
760  Entry* other_entry = other.GetEntry(entry->m_Key);
761  if (other_entry == NULL || !(other_entry->m_Value == entry->m_Value)) {
762  return false;
763  }
764  }
765 
766  return true;
767 }
768 
769 /*----------------------------------------------------------------------
770 | NPT_HashMap<K,V,HF>::operator!=
771 +---------------------------------------------------------------------*/
772 template <typename K, typename V, typename HF>
773 bool
775 {
776  return !(*this == other);
777 }
778 
779 /*----------------------------------------------------------------------
780 | NPT_HashMap<K,V>::operator[]
781 +---------------------------------------------------------------------*/
782 template <typename K, typename V, typename HF>
783 V&
785 {
786  Entry* entry = GetEntry(key);
787  if (entry == NULL) {
788  // create a new "default" entry for this key
789  entry = new Entry(m_Hasher(key), key);
790  AddEntry(entry);
791  }
792 
793  return entry->m_Value;
794 }
795 
796 /*----------------------------------------------------------------------
797 | NPT_MapEntryValueDeleter
798 +---------------------------------------------------------------------*/
799 template <class T>
801 public:
802  void operator()(T* entry) const {
803  delete entry->GetValue();
804  }
805 };
806 
807 #endif // _NPT_MAP_H_
Definition: NptMap.h:325
Definition: NptMap.h:321
Definition: NptMap.h:354
Definition: NptMap.h:47
Definition: NptMap.h:51
Definition: NptList.h:63
Definition: NptMap.h:800
Definition: NptList.h:54
Definition: NptCommon.h:45