Evo C++ Library v0.5.1
maphash.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_maphash_h
9 #define INCL_evo_maphash_h
10 
11 #include "map.h"
12 #include "array.h"
13 #include "ptrlist.h"
14 #include "impl/hash.h"
15 
16 // Disable certain MSVC warnings for this file
17 #if defined(_MSC_VER)
18  #pragma warning(push)
19  #pragma warning(disable:4457)
20 #endif
21 
22 namespace evo {
25 
27 
28 // Internal implementation macros -- only used in this file
30 #define EVO_IMPL_MAPHASH_SIZEMASK(SIZE) (SIZE - 1)
31 #define EVO_IMPL_MAPHASH_THRESHOLD(SIZE) ((SIZE / 10) * 7)
32 
34 
207 template<class TKey, class TValue, class THash=CompareHash<TKey>, class TSize=SizeT>
208 class MapHash : public Map<TKey,TValue,TSize> {
209 protected:
211 
212 public:
214 #if defined(_MSC_VER) || defined(EVO_OLDCC) // avoid errors with older compilers and MSVC
216  typedef typename MapBaseType::Size Size;
217  typedef typename MapBaseType::Key Key;
218  typedef typename MapBaseType::Value Value;
219  typedef typename MapBaseType::Item Item;
220  typedef typename MapBaseType::IterKey IterKey;
221  typedef typename MapBaseType::IterItem IterItem;
222 #else
224  using typename Map<TKey,TValue,TSize>::Size;
225  using typename Map<TKey,TValue,TSize>::Key;
226  using typename Map<TKey,TValue,TSize>::Value;
227  using typename Map<TKey,TValue,TSize>::Item;
228  using typename Map<TKey,TValue,TSize>::IterKey;
229  using typename Map<TKey,TValue,TSize>::IterItem;
230 #endif
232  typedef THash Hash;
233 
236 
238  MapHash() : Map<TKey,TValue,TSize>(false)
239  { }
240 
244  MapHash(const MapBaseType& src) : Map<TKey,TValue,TSize>(false) {
245  for (typename MapBaseType::Iter iter(src); iter; ++iter)
247  }
248 
252  MapHash(const ThisType& src) : Map<TKey,TValue,TSize>(false), buckets_(src.buckets_), data_(src.data_) {
253  size_ = src.size_;
254  }
255 
256 #if defined(EVO_CPP11)
257  using typename MapBaseType::InitPair;
258 
262  MapHash(const std::initializer_list<InitPair>& init) : MapHash() {
263  assert( init.size() < IntegerT<Size>::MAX );
264  capacitymin((Size)init.size());
265  for (const auto& item : init)
266  add(item.key, item.value);
267  }
268 
272  MapHash(ThisType&& src) : Map<TKey,TValue,TSize>(false), buckets_(std::move(src.buckets_)), data_(std::move(src.data_)) {
273  MapBaseType::size_ = src.MapBaseType::size_;
274  src.MapBaseType::size_ = 0;
275  }
276 
281  ThisType& operator=(ThisType&& src) {
282  buckets_ = std::move(src.buckets_);
283  data_ = std::move(src.data_);
284  MapBaseType::size_ = src.MapBaseType::size_;
285  src.MapBaseType::size_ = 0;
286  return *this;
287  }
288 #endif
289 
291  const ThisType& asconst() const {
292  return *this;
293  }
294 
295  // SET
296 
298  ThisType& operator=(const MapBaseType& src)
299  { set(src); return *this; }
300 
307  ThisType& operator=(const ThisType& src)
308  { set(src); return *this; }
309 
310  ThisType& set()
311  { buckets_.set(); size_ = 0; return *this; }
312 
313  ThisType& set(const MapBaseType& src) {
314  clear();
315  for (typename MapBaseType::Iter iter(src); iter; ++iter)
317  return *this;
318  }
319 
320  ThisType& set(const ThisType& src) {
321  buckets_.set(src.buckets_);
322  data_ = src.data_;
323  size_ = src.size_;
324  return *this;
325  }
326 
327  ThisType& setempty()
328  { buckets_.setempty(); size_ = 0; return *this; }
329 
330  ThisType& clear()
331  { buckets_.clear(); size_ = 0; return *this; }
332 
333  // INFO
334 
335  bool null() const
336  { return buckets_.null(); }
337 
338  bool shared() const
339  { return buckets_.shared(); }
340 
341  Size capacity() const
342  { return buckets_.size(); }
343 
344  // COMPARE
345 
346  using MapBaseType::operator==;
347  using MapBaseType::operator!=;
348 
349  // FIND
350 
352  Iter cbegin() const
353  { return Iter(*this); }
354 
356  Iter cend() const
357  { return Iter(); }
358 
360  IterM begin()
361  { return IterM(*this); }
362 
364  Iter begin() const
365  { return Iter(*this); }
366 
368  IterM end()
369  { return IterM(); }
370 
372  Iter end() const
373  { return Iter(); }
374 
375  bool contains(const Key& key) const
376  { return (find(key) != NULL); }
377 
378  const Value* find(const Key& key) const {
379  if (size_ > 0) {
380  const Bucket* bucket = buckets_.item( data_.hash(key) & data_.sizemask );
381  if (bucket != NULL) {
382  if (key == bucket->first.first) {
383  return &bucket->first.second;
384  } else {
385  Size index;
386  const Item* item = bucket->search(index, key, data_);
387  if (item != NULL)
388  return &item->second;
389  }
390  }
391  }
392  return NULL;
393  }
394 
395  Value* findM(const Key& key) {
396  if (size_ > 0) {
397  Bucket* bucket = buckets_.itemM( data_.hash(key) & data_.sizemask );
398  if (bucket != NULL) {
399  if (key == bucket->first.first) {
400  return &bucket->first.second;
401  } else {
402  Size index;
403  Item* item = (Item*)bucket->search(index, key, data_);
404  if (item != NULL)
405  return &item->second;
406  }
407  }
408  }
409  return NULL;
410  }
411 
413  Iter iter(const Key& key) const {
414  if (size_ > 0) {
415  IterKey iterkey( data_.hash(key) & data_.sizemask );
416  const Bucket* bucket = buckets_.item(iterkey.a);
417  if (bucket != NULL) {
418  if (bucket->first.first == key) {
419  return Iter(*this, iterkey, (IterItem*)&bucket->first);
420  } else {
421  const IterItem* item = (IterItem*)bucket->search(iterkey.b, key, data_);
422  if (item != NULL) {
423  ++iterkey.b;
424  return Iter(*this, iterkey, item);
425  }
426  }
427  }
428  }
429  return Iter(*this, iterEND);
430  }
431 
433  IterM iterM(const Key& key) {
434  if (size_ > 0) {
435  IterKey iterkey( data_.hash(key) & data_.sizemask );
436  Bucket* bucket = buckets_.itemM(iterkey.a);
437  if (bucket != NULL) {
438  if (bucket->first.first == key) {
439  return IterM(*this, iterkey, (IterItem*)&bucket->first);
440  } else {
441  IterItem* item = (IterItem*)bucket->search(iterkey.b, key, data_);
442  if (item != NULL) {
443  ++iterkey.b;
444  return IterM(*this, iterkey, item);
445  }
446  }
447  }
448  }
449  return IterM(*this, iterEND);
450  }
451 
452  Item& getitem(const Key& key, bool* created=NULL) {
453  if (data_.threshold == 0) {
454  // Empty, resize buckets
455  buckets_.resize(SIZE_INIT);
456  data_.sizemask = EVO_IMPL_MAPHASH_SIZEMASK(SIZE_INIT);
457  data_.threshold = EVO_IMPL_MAPHASH_THRESHOLD(SIZE_INIT);
458  } else if (size_ >= data_.threshold) {
459  // Reached size threshold, time to grow
460  Size newsize = buckets_.size() << 1;
461  data_.sizemask = EVO_IMPL_MAPHASH_SIZEMASK(newsize);
462  data_.threshold = EVO_IMPL_MAPHASH_THRESHOLD(newsize);
463 
464  // Grow and rehash
465  Buckets oldbuckets;
466  buckets_.swap(oldbuckets);
467  buckets_.resize(newsize);
468 
469  bool created;
470  const Bucket* bucket;
471  const Bucket** cur = (const Bucket**)oldbuckets.data();
472  for (const Bucket** end=cur+oldbuckets.size(); cur < end; ++cur) {
473  if ((bucket=*cur) != NULL) {
474  for (Size i=0, iend=bucket->others.size(); i <= iend; ++i) {
475  const Item* item = (i == 0 ? &bucket->first : &bucket->others[i-1]);
476  Bucket* newbucket = buckets_.getitem(data_.hash(item->first) & data_.sizemask, &created);
477  if (created)
478  newbucket->first = *item;
479  else {
480  Size index;
481  Item* newitem = (Item*)newbucket->search(index, item->first, data_);
482  if (newitem == NULL)
483  newbucket->others.insert(index, *item);
484  else
485  newitem->second = item->second;
486  }
487  }
488  }
489  }
490  }
491 
492  // Get item, create if needed
493  bool created_item;
494  Item* item;
495  Bucket* bucket = buckets_.getitem((data_.hash(key) & data_.sizemask), &created_item);
496  if (created_item) {
497  ++size_;
498  item = &bucket->first;
499  item->first = key;
500  } else if (bucket->first.first == key) {
501  item = &bucket->first;
502  } else {
503  Size index;
504  item = (Item*)bucket->search(index, key, data_);
505  if (item == NULL) {
506  created_item = true;
507  ++size_;
508  item = (Item*)&(bucket->others[bucket->others.insertnew(index, 1)]);
509  item->first = key;
510  }
511  }
512  if (created != NULL)
513  *created = created_item;
514  return *item;
515  }
516 
518  Value& get(const Key& key, bool* created=NULL)
519  { return getitem(key, created).second; }
520 
521  // INFO_SET
522 
524  Value& operator[](const Key& key)
525  { return getitem(key, NULL).second; }
526 
527  ThisType& unshare()
528  { buckets_.unshare(); return *this; }
529 
538  ThisType& capacity(Size size) {
539  const Size cursize = buckets_.size();
540  if (size != cursize) {
541  // Find new size (must be power of 2)
542  Size newsize = SIZE_INIT;
543  while (newsize < size) newsize <<= 1;
544  while (newsize < size_) newsize <<= 1;
545 
546  if (newsize != cursize) {
547  // Reached size threshold, time to grow
548  data_.sizemask = EVO_IMPL_MAPHASH_SIZEMASK(newsize);
549  data_.threshold = EVO_IMPL_MAPHASH_THRESHOLD(newsize);
550  if (size_ == 0) {
551  // Empty, just resize buckets
552  buckets_.resize(newsize);
553  } else {
554  // Resize and rehash
555  Buckets oldbuckets;
556  buckets_.swap(oldbuckets);
557  buckets_.resize(newsize);
558 
559  bool created;
560  const Bucket* bucket;
561  const Bucket** cur = (const Bucket**)oldbuckets.data();
562  for (const Bucket** end=cur+oldbuckets.size(); cur < end; ++cur) {
563  if ((bucket=*cur) != NULL) {
564  for (Size i=0, iend=bucket->others.size(); i <= iend; ++i) {
565  const Item* item = (i == 0 ? &bucket->first : &bucket->others[i-1]);
566  Bucket* newbucket = buckets_.getitem(data_.hash(item->first) & data_.sizemask, &created);
567  if (created)
568  newbucket->first = *item;
569  else {
570  Size index;
571  Item* newitem = (Item*)newbucket->search(index, item->first, data_);
572  if (newitem == NULL)
573  newbucket->others.insert(index, *item);
574  else
575  newitem->second = item->second;
576  }
577  }
578  }
579  }
580  }
581  }
582  }
583  return *this;
584  }
585 
590  ThisType& capacitymin(Size min) {
591  if (min > buckets_.size())
592  capacity(min);
593  return *this;
594  }
595 
597  ThisType& reserve(Size size)
598  { return capacitymin(size_ + size); }
599 
600  // RESIZE
601 
612  void resize(Size size) {
613  Size newsize = MIN_SIZE;
614  while (newsize < size) newsize <<= 1;
615  if (newsize != buckets_.size()) {
616  data_.sizemask = EVO_IMPL_MAPHASH_SIZEMASK(newsize);
617  data_.threshold = EVO_IMPL_MAPHASH_THRESHOLD(newsize);
618  Buckets oldbuckets;
619  buckets_.swap(oldbuckets);
620  buckets_.resize(newsize);
621 
622  bool created;
623  const Bucket* bucket;
624  const Bucket** cur = (const Bucket**)oldbuckets.data();
625  for (const Bucket** end=cur+oldbuckets.size(); cur < end; ++cur) {
626  if ((bucket=*cur) != NULL) {
627  for (Size i=0, iend=bucket->others.size(); i <= iend; ++i) {
628  const Item* item = (i == 0 ? &bucket->first : &bucket->others[i-1]);
629  Bucket* newbucket = buckets_.getitem(data_.hash(item->first) & data_.sizemask, &created);
630  if (created)
631  newbucket->first = *item;
632  else {
633  Size index;
634  Item* newitem = (Item*)newbucket->search(index, item->first, data_);
635  if (newitem == NULL)
636  newbucket->others.insert(index, *item);
637  else
638  newitem->second = item->second;
639  }
640  }
641  }
642  }
643  }
644  }
645 
646  // ADD
647 
648  Item& add(const Key& key, const Value& value, bool update=true) {
649  bool created_val;
650  Item& upditem = getitem(key, &created_val);
651  if (created_val || update)
652  upditem.second = value;
653  return upditem;
654  }
655 
656  Item& add(const Item& item, bool update=true)
657  { return add(item.first, item.second, update); }
658 
659  ThisType& add(const MapBaseType& map, bool update=true) {
660  if (this != &map) {
661  reserve(map.size());
662  for (typename MapBaseType::Iter iter(map); iter; ++iter)
663  add(iter->first, iter->second, update);
664  }
665  return *this;
666  }
667 
668  // REMOVE
669 
670  bool remove(const Key& key) {
671  bool result;
672  Size bucket_index = data_.hash(key) & data_.sizemask;
673  Bucket* bucket = buckets_.itemM(bucket_index);
674  if (bucket != NULL) {
675  Size index;
676  if (bucket->first.first == key) {
677  if (bucket->others.size() > 0) {
678  // Remove "first" and replace with last item in "others"
679  Item* item1 = &bucket->first;
680  Item* item2 = bucket->others.data();
681  EVO_IMPL_CONTAINER_SWAP(item1, item2, Item);
682  bucket->others.remove(0);
683  } else
684  // Remove bucket since "first" is only item
685  buckets_.remove(bucket_index);
686  result = true;
687  --size_;
688  } else if (bucket->search(index, key, data_) != NULL) {
689  // Remove from "others"
690  bucket->others.remove(index);
691  result = true;
692  --size_;
693  } else
694  result = false;
695  } else
696  result = false;
697  return result;
698  }
699 
700  bool remove(typename MapBaseType::IterM& iter, IteratorDir dir=iterNONE)
701  { return remove((IterM&)iter, dir); }
702 
703  bool remove(IterM& iter, IteratorDir dir=iterNONE) {
704  if (iter && this == &iter.getParent()) {
705  IterKey& iterkey = iter.getKey();
706  assert( iterkey.a < buckets_.size() );
707  Bucket* bucket = buckets_.itemM(iterkey.a);
708  assert( bucket != NULL );
709  if (iterkey.b > 0) {
710  // Remove from "others"
711  bucket->others.remove(iterkey.b-1);
712  } else {
713  if (bucket->others.size() > 0) {
714  // Remove "first" and replace with last item in "others"
715  Item* item1 = &bucket->first;
716  Item* item2 = bucket->others.data();
717  EVO_IMPL_CONTAINER_SWAP(item1, item2, Item);
718  bucket->others.remove(0);
719  } else {
720  // Remove bucket since "first" is only item
721  buckets_.remove(iterkey.a);
722  bucket = NULL;
723  }
724  }
725 
726  // Update size and iterator
727  if (--size_ > 0 && dir != iterNONE) {
728  if (dir == iterRV) {
729  // Previous
730  if (iterkey.b > 0 && bucket != NULL) {
731  iter.setData( (IterItem*)(--iterkey.b == 0 ? &(bucket->first) : &(bucket->others[iterkey.b-1])) );
732  } else {
733  bucket = (Bucket*)buckets_.iterPrev(iterkey.a);
734  if (bucket != NULL) {
735  iterkey.b = bucket->others.size();
736  iter.setData( (IterItem*)(iterkey.b == 0 ? &bucket->first : &(bucket->others[iterkey.b-1])) );
737  } else
738  iter = iterEND;
739  }
740  } else {
741  // Next
742  if (bucket != NULL && iterkey.b <= bucket->others.size()) {
743  iter.setData( (IterItem*)(iterkey.b == 0 ? &bucket->first : &(bucket->others[iterkey.b-1])) );
744  } else {
745  iterkey.b = 0;
746  if ((bucket=(Bucket*)buckets_.iterNext(iterkey.a)) != NULL)
747  iter.setData( (IterItem*)&bucket->first );
748  else
749  iter = iterEND;
750  }
751  }
752  } else
753  iter = iterEND;
754  return true;
755  }
756  return false;
757  }
758 
759  // INTERNAL
760 
761  // Testing methods
763 #if EVO_UNIT_TEST_MODE
764  Size utCollisions() const {
765  Size count = 0;
766  for (typename Buckets::Iter iter(buckets_); iter; ++iter)
767  count += iter->others.size();
768  return count;
769  }
770 #endif
771 
773  // Iterator support methods
775  void iterInitMutable()
776  { buckets_.unshare(); }
777  const IterItem* iterFirst(IterKey& key) const {
778  key.b = 0;
779  if (size_ > 0)
780  return (IterItem*)&(buckets_.iterFirst(key.a)->first);
781  key.a = END;
782  return NULL;
783  }
784  const IterItem* iterNext(IterKey& key) const {
785  if (key.a != END) {
786  const Bucket* bucket = buckets_.item(key.a);
787  if (++key.b <= bucket->others.size())
788  return (IterItem*)&(bucket->others[key.b-1]);
789  key.b = 0;
790  if ((bucket=buckets_.iterNext(key.a)) != NULL)
791  return (IterItem*)&bucket->first;
792  }
793  return NULL;
794  }
795  const IterItem* iterLast(IterKey& key) const {
796  if (size_ > 0) {
797  const Bucket* bucket = buckets_.iterLast(key.a);
798  assert( bucket != NULL );
799  key.b = bucket->others.size();
800  return (IterItem*)(key.b == 0 ? &bucket->first : &(bucket->others[key.b-1]));
801  }
802  key.a = END;
803  key.b = 0;
804  return NULL;
805 
806  }
807  const IterItem* iterPrev(IterKey& key) const {
808  if (key.a != END) {
809  if (key.b > 0) {
810  return (IterItem*)(--key.b == 0 ? &(buckets_.item(key.a)->first) : &(buckets_.item(key.a)->others[key.b-1]));
811  } else {
812  const Bucket* bucket = buckets_.iterPrev(key.a);
813  if (bucket != NULL) {
814  key.b = bucket->others.size();
815  return (IterItem*)(key.b == 0 ? &bucket->first : &(bucket->others[key.b-1]));
816  }
817  }
818  key.a = END;
819  }
820  return NULL;
821  }
824 protected:
825  const Item* getiter(IterKey& iterkey, const Key& key) const {
826  if (size_ > 0) {
827  iterkey.a = (data_.hash(key) & data_.sizemask);
828  const Bucket* bucket = buckets_.item(iterkey.a);
829  if (bucket != NULL) {
830  if (bucket->first.first == key) {
831  iterkey.b = 0;
832  return &bucket->first;
833  } else {
834  const Item* item = bucket->search(iterkey.b, key, data_);
835  if (item != NULL) {
836  ++iterkey.b;
837  return item;
838  }
839  }
840  }
841  }
842  iterkey.a = END;
843  iterkey.b = 0;
844  return NULL;
845  }
846 
847 private:
848  static const Size SIZE_INIT = 64; // initial hash size -- must be power of 2
849  static const Size MIN_SIZE = 8; // minimum hash size -- must be power of 2
850 
851  struct Bucket {
852  Item first;
853  Array<Item> others;
854 
855  Bucket() {
856  }
857  Bucket(const Bucket& src) : first(src.first), others(src.others) {
858  }
859 
860  // Search "others" for key, using compare, set index (insertion point if not found)
861  const Item* search(Size& index, const Key& key, const typename Hash::CompareBase& compare) const {
862  int cmp;
863  Size left = 0, right = others.size(), mid = 0;
864  const Item* items = others.data();
865  while (left < right) {
866  mid = left + ((right-left) / 2);
867  const Item* item = items + mid;
868  cmp = compare(key, item->first);
869  if (cmp < 0) {
870  right = mid;
871  } else if (cmp == 0) {
872  index = mid;
873  return item;
874  } else
875  left = mid + 1;
876  }
877  index = left;
878  return NULL;
879  }
880 
881  private:
882  // Copying is done via copy constructor
883  Bucket& operator=(const Bucket&) EVO_ONCPP11(= delete);
884  };
885 
887 
888  Buckets buckets_;
889 
890  // Use inheritance to reduce size bloat with empty Hash
891  struct Data : public THash {
892  Size sizemask;
893  Size threshold;
894 
895  Data() : sizemask(0), threshold(0) {
896  }
897  Data(const Data& data) : Hash(data), sizemask(data.sizemask), threshold(data.threshold) {
898  }
899  Data& operator=(const Data& data) {
900  THash::operator=(data);
901  sizemask = data.sizemask;
902  threshold = data.threshold;
903  return *this;
904  }
905 
906  #if defined(EVO_CPP11)
907  Data(Data&& data) : THash(std::move((THash&&)data)), sizemask(data.sizemask), threshold(data.threshold) {
908  data.sizemask = 0;
909  data.threshold = 0;
910  }
911  Data& operator=(Data&& data) {
912  THash::operator=(std::move((THash&&)data));
913  sizemask = data.sizemask;
914  threshold = data.threshold;
915  data.sizemask = 0;
916  data.threshold = 0;
917  return *this;
918  }
919  #endif
920  };
921 
922  Data data_;
923 };
924 
925 #undef EVO_IMPL_MAPHASH_SIZEMASK
926 #undef EVO_IMPL_MAPHASH_THRESHOLD
927 
929 
930 #if defined(INCL_evo_string_h) || defined(DOXYGEN)
931 
936 #endif
937 
939 
940 }
941 #if defined(_MSC_VER)
942  #pragma warning(pop)
943 #endif
944 #endif
bool shared() const
Get whether shared.
Definition: maphash.h:338
Iter cbegin() const
Get iterator at first item (const).
Definition: maphash.h:352
ThisType & reserve(Size size)
Reserve space for new items.
Definition: maphash.h:597
Item & add(const Item &item, bool update=true)
Add or update using given item.
Definition: maphash.h:656
Pair< Key, Value > Item
Item type (key/value pair)
Definition: map.h:137
ThisType & operator=(const ThisType &src)
Assignment operator.
Definition: maphash.h:307
Item getitem(const Key &key, bool *created=NULL)
Get item for key, creating if needed (mutable).
Definition: ptrlist.h:717
Size size() const
Get size.
Definition: array.h:453
IteratorBi< ThisType >::Const Iter
Iterator (const) - IteratorBi.
Definition: maphash.h:234
const A & a() const
Get first value (const).
Definition: pair.h:102
Map< TKey, TValue, TSize > MapBaseType
Map base type
Definition: map.h:133
Size capacity() const
Get map capacity.
Definition: maphash.h:341
Size size_
Map size (number of items, automatically updated by concrete set members)
Definition: map.h:180
Iter iter(const Key &key) const
Find (lookup) iterator for given key (const).
Definition: maphash.h:413
#define EVO_CONTAINER_TYPE
Identify current class/struct as an EvoContainer.
Definition: meta.h:482
Iter begin() const
Get iterator at first item (const).
Definition: maphash.h:364
const Value * find(const Key &key) const
Find (lookup) value for given key (const).
Definition: maphash.h:378
T first(T val1, T val2)
Definition: alg.h:85
Random access iterator.
Definition: iter.h:904
ThisType & add(const MapBaseType &map, bool update=true)
Definition: maphash.h:659
MapHash(const ThisType &src)
Copy constructor.
Definition: maphash.h:252
Item & getitem(const Key &key, bool *created=NULL)
Get map item for key (mutable).
Definition: maphash.h:452
#define EVO_ONCPP11(EXPR)
Compile EXPR only if C++11 support is detected, otherwise this is a no-op.
Definition: sys.h:259
Evo implementation detail: Hashing support.
ThisType & operator=(ThisType &&src)
Move assignment operator (C++11).
Definition: maphash.h:281
ThisType & unshare()
Make sure data is not shared by allocating new buffer if needed (modifier).
Definition: ptrlist.h:790
bool contains(const Key &key) const
Get whether map contains the given key.
Definition: maphash.h:375
ThisType & capacity(Size size)
Set hash map size (capacity).
Definition: maphash.h:538
Item & add(const Key &key, const Value &value, bool update=true)
Add or update using given key and value.
Definition: maphash.h:648
Iter cend() const
Get iterator at end (const).
Definition: maphash.h:356
Value & operator[](const Key &key)
Get item value for key (mutable).
Definition: maphash.h:524
Evo Pointer List.
Basic integer type.
Definition: type.h:980
const B & b() const
Get second value (const).
Definition: pair.h:126
Evo Array container.
TKey Key
Key type.
Definition: map.h:135
MapHash(const MapBaseType &src)
Copy constructor.
Definition: maphash.h:244
IterM iterM(const Key &key)
Find (lookup) iterator for given key (mutable).
Definition: maphash.h:433
ThisType & setempty()
Set as empty but not null.
Definition: maphash.h:327
const T * data() const
Get data pointer (const).
Definition: array.h:469
MapHash< String, String > StrHash
MapHash using String keys and values.
Definition: maphash.h:935
bool null() const
Get whether null.
Definition: ptrlist.h:400
ThisType & resize(Size newsize)
Resize while preserving existing data (modifier).
Definition: ptrlist.h:814
ThisType & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: maphash.h:527
Bidirectional iterator.
Definition: iter.h:611
TA first
First value (same as a() and key())
Definition: pair.h:42
void swap(ThisType &list)
Swap with another list.
Definition: ptrlist.h:1085
const Item * getiter(IterKey &iterkey, const Key &key) const
Used by base class to get data to initialize iterator.
Definition: maphash.h:825
ThisType & setempty()
Set as empty but not null.
Definition: ptrlist.h:385
static const EndT END
Special integer value for indicating end of items or no item.
Definition: type.h:1846
TValue Value
Value type.
Definition: map.h:136
IterM begin()
Get iterator at first item (mutable).
Definition: maphash.h:360
IteratorDir
Iterator direction value.
Definition: iter.h:27
MapHash< TKey, TValue, THash, TSize > ThisType
This type.
Definition: maphash.h:231
bool shared() const
Get whether shared.
Definition: ptrlist.h:428
Reverse iterator direction.
Definition: iter.h:30
MapHash()
Constructor.
Definition: maphash.h:238
Evo C++ Library namespace.
Definition: alg.h:11
No iterator direction.
Definition: iter.h:28
IteratorBi< ThisType > IterM
Iterator (mutable) - IteratorBi.
Definition: maphash.h:235
TSize Size
Size type for size values (must be unsigned integer) – default: SizeT.
Definition: map.h:134
const Item first() const
Get first non-null item (const).
Definition: ptrlist.h:474
Size size() const
Get map size (number of items).
Definition: map.h:272
Item itemM(Key index)
Get item at position (mutable).
Definition: ptrlist.h:780
IterM end()
Get iterator at end.
Definition: maphash.h:368
End iterator position.
Definition: iter.h:23
ThisType & operator=(const MapBaseType &src)
Assignment operator.
Definition: maphash.h:298
MapHash(ThisType &&src)
Move constructor (C++11).
Definition: maphash.h:272
const ThisType & asconst() const
Explicitly use a const reference to this.
Definition: maphash.h:291
Value * findM(const Key &key)
Find (lookup) value for given key (mutable).
Definition: maphash.h:395
Evo Map interface.
ThisType & clear()
Clear by removing all items.
Definition: ptrlist.h:313
bool null() const
Get whether map is null.
Definition: maphash.h:335
ThisType & remove(Key key)
Remove item and set as null (modifier).
Definition: ptrlist.h:987
THash Hash
Hashing type – default: CompareHash.
Definition: maphash.h:232
const Item item(Key index) const
Get item at position (const).
Definition: ptrlist.h:461
void resize(Size size)
Set hash map size (capacity) directly.
Definition: maphash.h:612
Stores a key/value pair of independent objects or values.
Definition: pair.h:32
Size size() const
Get list size.
Definition: ptrlist.h:414
ThisType & set()
Set as null and empty.
Definition: ptrlist.h:339
Iter end() const
Get iterator at end (const).
Definition: maphash.h:372
const Item * data() const
Get data pointer for direct access (const).
Definition: ptrlist.h:437
ThisType & clear()
Clear by removing all items.
Definition: maphash.h:330
ThisType & capacitymin(Size min)
Set map capacity to at least given minimum.
Definition: maphash.h:590
Associative container holding key/value pairs for fast lookup.
Definition: map.h:129
T & min(T &a, T &b)
Returns lowest of given values.
Definition: alg.h:26
MapHash(const std::initializer_list< InitPair > &init)
< Used with initializer_list constructor (C++11)
Definition: maphash.h:262
Map implemented as a hash table.
Definition: maphash.h:208
TB second
Second value (same as b() and value())
Definition: pair.h:43
Initializer key/value pair, used with initializer (C++11).
Definition: map.h:162