8 #ifndef INCL_evo_sethash_h 9 #define INCL_evo_sethash_h 166 template<
class TKey,
class THash=CompareHash<TKey>,
class TSize=SizeT>
173 #if defined(_MSC_VER) || defined(EVO_OLDCC) // avoid errors with older compilers and MSVC 179 typedef typename SetBaseType::IterKey IterKey;
180 typedef typename SetBaseType::IterItem IterItem;
214 #if defined(EVO_CPP11) 221 for (
const auto& val : init)
228 SetHash(ThisType&& src) : buckets_(std::move(src.buckets_)), data_(std::move(src.data_)) {
230 src.SetBaseType::size_ = 0;
238 buckets_ = std::move(src.buckets_);
239 data_ = std::move(src.data_);
241 src.SetBaseType::size_ = 0;
255 {
set(src);
return *
this; }
259 {
set(src);
return *
this; }
262 { buckets_.
set();
size_ = 0;
return *
this; }
265 ThisType&
set(
const SetBaseType& src) {
273 ThisType&
set(
const ThisType& src) {
274 buckets_.
set(src.buckets_);
284 { buckets_.
clear();
size_ = 0;
return *
this; }
289 {
return buckets_.
null(); }
292 {
return buckets_.
shared(); }
295 {
return buckets_.
size(); }
314 using SetBaseType::operator==;
315 using SetBaseType::operator!=;
321 if (buckets_.
size() ==
set.buckets_.size())
322 return (buckets_ ==
set.buckets_);
328 {
return !(*
this ==
set); }
334 {
return Iter(*
this); }
342 {
return IterM(*
this); }
346 {
return Iter(*
this); }
357 {
return (search(value) != NULL); }
360 Iter
iter(
const Value& value)
const {
362 IterKey iterkey( data_.hash(value) & data_.sizemask );
363 const Bucket* bucket = buckets_.
item(iterkey.a);
364 if (bucket != NULL) {
365 if (data_(bucket->first, value) == 0) {
366 return Iter(*
this, iterkey, (IterItem*)&bucket->first);
368 const IterItem* item = (IterItem*)bucket->search(iterkey.b, value, data_);
371 return Iter(*
this, iterkey, item);
382 IterKey iterkey( data_.hash(value) & data_.sizemask );
383 Bucket* bucket = buckets_.
itemM(iterkey.a);
384 if (bucket != NULL) {
385 if (data_(bucket->first, value) == 0) {
386 return IterM(*
this, iterkey, (IterItem*)&bucket->first);
388 IterItem* item = (IterItem*)bucket->search(iterkey.b, value, data_);
391 return IterM(*
this, iterkey, item);
399 Value&
get(
const Value& value,
bool* created=NULL) {
400 if (
size_ == 0 || data_.threshold == 0)
403 else if (
size_ >= data_.threshold)
405 rehash(buckets_.
size() << 1);
410 Bucket* bucket = buckets_.
getitem((data_.hash(value) & data_.sizemask), &created_item);
413 item = &bucket->first;
415 }
else if (data_(bucket->first, value) == 0) {
416 item = &bucket->first;
419 item = (Value*)bucket->search(index, value, data_);
423 item = (Value*)&(bucket->others[bucket->others.insert(index, value)]);
427 *created = created_item;
434 { buckets_.
unshare();
return *
this; }
445 const Size cursize = buckets_.
size();
447 if (size != cursize) {
449 Size newsize = SIZE_INIT;
450 while (newsize < size) newsize <<= 1;
451 while (newsize <
size_) newsize <<= 1;
453 if (newsize != cursize)
465 if (min > buckets_.
size())
476 Value&
add(
const Value& value,
bool update=
false) {
478 Value& upditem =
get(value, &created_val);
479 if (!created_val && update)
486 bool remove(
const Value& value) {
488 Size bucket_index = data_.hash(value) & data_.sizemask;
489 Bucket* bucket = buckets_.
itemM(bucket_index);
490 if (bucket != NULL) {
492 if (data_(bucket->first, value) == 0) {
493 if (bucket->others.size() > 0) {
495 Value* item1 = &bucket->first;
496 Value* item2 = bucket->others.data();
497 EVO_IMPL_CONTAINER_SWAP(item1, item2, Item);
498 bucket->others.remove(0);
501 buckets_.
remove(bucket_index);
504 }
else if (bucket->search(index, value, data_) != NULL) {
506 bucket->others.remove(index);
517 {
return remove((IterM&)iter, dir); }
520 if (iter &&
this == &iter.getParent()) {
521 IterKey& iterkey = iter.getKey();
522 assert( iterkey.a < buckets_.
size() );
523 Bucket* bucket = buckets_.
itemM(iterkey.a);
524 assert( bucket != NULL );
527 bucket->others.remove(iterkey.b-1);
529 if (bucket->others.size() > 0) {
531 Value* item1 = &bucket->first;
532 Value* item2 = bucket->others.data();
533 EVO_IMPL_CONTAINER_SWAP(item1, item2, Item);
534 bucket->others.remove(0);
537 buckets_.
remove(iterkey.a);
546 if (iterkey.b > 0 && bucket != NULL) {
547 iter.setData( (IterItem*)(--iterkey.b == 0 ? &(bucket->first) : &(bucket->others[iterkey.b-1])) );
549 bucket = (Bucket*)buckets_.iterPrev(iterkey.a);
550 if (bucket != NULL) {
551 iterkey.b = bucket->others.
size();
552 iter.setData( (IterItem*)(iterkey.b == 0 ? &bucket->first : &(bucket->others[iterkey.b-1])) );
558 if (bucket != NULL && iterkey.b <= bucket->others.size()) {
559 iter.setData( (IterItem*)(iterkey.b == 0 ? &bucket->first : &(bucket->others[iterkey.b-1])) );
562 if ((bucket=(Bucket*)buckets_.iterNext(iterkey.a)) != NULL)
563 iter.setData( (IterItem*)&bucket->first );
579 void iterInitMutable()
581 const IterItem* iterFirst(IterKey& key)
const {
584 return (IterItem*)&(buckets_.iterFirst(key.a)->
first);
588 const IterItem* iterNext(IterKey& key)
const {
590 const Bucket* bucket = buckets_.
item(key.a);
591 if (++key.b <= bucket->others.size())
592 return (IterItem*)&(bucket->others[key.b-1]);
594 if ((bucket=buckets_.iterNext(key.a)) != NULL)
595 return (IterItem*)&bucket->first;
599 const IterItem* iterLast(IterKey& key)
const {
601 const Bucket* bucket = buckets_.iterLast(key.a);
602 assert( bucket != NULL );
603 key.b = bucket->others.size();
604 return (IterItem*)(key.b == 0 ? &bucket->first : &(bucket->others[key.b-1]));
611 const IterItem* iterPrev(IterKey& key)
const {
614 return (IterItem*)(--key.b == 0 ? &(buckets_.
item(key.a)->first) : &(buckets_.
item(key.a)->others[key.b-1]));
616 const Bucket* bucket = buckets_.iterPrev(key.a);
617 if (bucket != NULL) {
618 key.b = bucket->others.
size();
619 return (IterItem*)(key.b == 0 ? &bucket->first : &(bucket->others[key.b-1]));
629 const Value*
getiter(IterKey& iterkey,
const Value& value)
const {
631 iterkey.a = (data_.hash(value) & data_.sizemask);
632 const Bucket* bucket = buckets_.
item(iterkey.a);
633 if (bucket != NULL) {
634 if (data_(bucket->first, value) == 0) {
636 return &bucket->first;
638 const Value* item = bucket->search(iterkey.b, value, data_);
652 static const Size SIZE_INIT = 64;
653 static const Size MIN_SIZE = 8;
661 Bucket(
const Bucket& src) :
first(src.first), others(src.others)
664 {
return (first == data.first && others == data.others); }
667 const Value* search(Size& index,
const Value& key,
const THash& compare)
const {
669 Size left = 0, right = others.
size(), mid = 0;
670 const Value* items = others.
data();
671 while (left < right) {
672 mid = left + ((right-left) / 2);
673 const Value* item = items + mid;
674 cmp = compare(key, *item);
677 }
else if (cmp == 0) {
697 struct Data :
public THash {
701 Data() : sizemask(0), threshold(0) {
704 THash::operator=(src);
705 sizemask = src.sizemask;
706 threshold = src.threshold;
710 #if defined(EVO_CPP11) 712 THash::operator=(std::move(src));
713 sizemask = src.sizemask;
714 threshold = src.threshold;
720 THash::operator=(std::move(src));
721 sizemask = src.sizemask;
722 threshold = src.threshold;
735 void rehash(Size newsize) {
736 const float THRESHOLD = 0.7f;
737 data_.sizemask = newsize - 1;
738 data_.threshold = (
Size)(newsize * THRESHOLD);
749 const Bucket* bucket;
750 const Bucket** cur = (
const Bucket**)oldbuckets.
data();
751 for (
const Bucket**
end=cur+oldbuckets.
size(); cur <
end; ++cur) {
752 if ((bucket=*cur) != NULL) {
753 for (Size i=0, iend=bucket->others.size(); i <= iend; ++i) {
754 const Value* item = (i == 0 ? &bucket->first : &bucket->others[i-1]);
755 Bucket* newbucket = buckets_.
getitem(data_.hash(*item) & data_.sizemask, &created);
757 newbucket->first = *item;
760 Value* newitem = (Value*)newbucket->search(index, *item, data_);
762 newbucket->others.insert(index, *item);
770 const Value* search(
const Value& value)
const {
772 const Bucket* bucket = buckets_.
item( data_.hash(value) & data_.sizemask );
773 if (bucket != NULL) {
774 if (data_(value, bucket->first) == 0) {
775 return &bucket->first;
778 const Value* item = bucket->search(index, value, data_);
790 #if defined(INCL_evo_string_h) || defined(DOXYGEN) Iter end() const
Get iterator at end (const).
Definition: sethash.h:353
Associative container with unique values for fast lookup.
Definition: set.h:119
Item getitem(const Key &key, bool *created=NULL)
Get item for key, creating if needed (mutable).
Definition: ptrlist.h:717
ThisType & capacitymin(Size min)
Set set capacity to at least given minimum.
Definition: sethash.h:464
Size size() const
Get size.
Definition: array.h:453
ThisType & operator=(const SetBaseType &src)
Assignment operator.
Definition: sethash.h:254
ThisType & clear()
Clear by removing all items.
Definition: sethash.h:283
Iter cbegin() const
Get iterator at first item (const).
Definition: sethash.h:333
TKey Item
Item type (same as Value)
Definition: set.h:127
T first(T val1, T val2)
Definition: alg.h:85
Set< TKey, TSize > SetBaseType
Set base type
Definition: set.h:123
#define EVO_ONCPP11(EXPR)
Compile EXPR only if C++11 support is detected, otherwise this is a no-op.
Definition: sys.h:259
Size size() const
Get set size (number of items).
Definition: set.h:230
Evo implementation detail: Hashing support.
Size capacity() const
Get set capacity.
Definition: sethash.h:294
ThisType & setempty()
Set as empty but not null.
Definition: sethash.h:280
ThisType & unshare()
Make sure data is not shared by allocating new buffer if needed (modifier).
Definition: ptrlist.h:790
void swap(T &a, T &b)
Swap contents of given objects.
Definition: sys.h:1602
Basic integer type.
Definition: type.h:980
SetHash(const SetBaseType &src)
Copy constructor.
Definition: sethash.h:203
bool operator==(const ThisType &set) const
Equality operator.
Definition: sethash.h:318
Iter begin() const
Get iterator at first item (const).
Definition: sethash.h:345
Size size_
Set size (number of items, automatically updated by concrete set members)
Definition: set.h:146
ThisType & operator=(ThisType &&src)
Move assignment operator (C++11).
Definition: sethash.h:237
const T * data() const
Get data pointer (const).
Definition: array.h:469
bool ordered() const
Get whether set is ordered.
Definition: sethash.h:297
bool null() const
Get whether null.
Definition: ptrlist.h:400
ThisType & resize(Size newsize)
Resize while preserving existing data (modifier).
Definition: ptrlist.h:814
bool operator!=(const ThisType &set) const
Inequality operator.
Definition: sethash.h:327
SetHash< TKey, THash, TSize > ThisType
This type.
Definition: sethash.h:190
bool null() const
Get whether set is null.
Definition: sethash.h:288
IteratorBi< ThisType > IterM
Iterator (mutable) - IteratorBi.
Definition: sethash.h:194
Bidirectional iterator.
Definition: iter.h:611
Value & add(const Value &value, bool update=false)
Add or update using given item.
Definition: sethash.h:476
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
Hash & get_compare()
Get hash & comparison object being used for hashing and comparisons.
Definition: sethash.h:311
const ThisType & asconst() const
Explicitly use a const reference to this.
Definition: sethash.h:247
IterM iterM(const Value &value)
Find (lookup) iterator for given value (mutable).
Definition: sethash.h:380
IteratorDir
Iterator direction value.
Definition: iter.h:27
ThisType & operator=(const ThisType &src)
Assignment operator.
Definition: sethash.h:258
bool shared() const
Get whether shared.
Definition: ptrlist.h:428
THash Hash
Hashing type – default: CompareHash.
Definition: sethash.h:191
Reverse iterator direction.
Definition: iter.h:30
Evo C++ Library namespace.
Definition: alg.h:11
No iterator direction.
Definition: iter.h:28
SetHash< String > StrSetHash
SetHash using String values.
Definition: sethash.h:795
ThisType & setempty()
Set as empty but not null.
Definition: array.h:422
ThisType & capacity(Size size)
Set hash set capacity (capacity).
Definition: sethash.h:444
IterM end()
Get iterator at end.
Definition: sethash.h:349
ThisType & reserve(Size size)
Reserve space for new items.
Definition: sethash.h:471
TKey Key
Key type (same as Value)
Definition: set.h:125
Iter cend() const
Get iterator at end (const).
Definition: sethash.h:337
TSize Size
Size type for size values (must be unsigned integer) – default: SizeT.
Definition: set.h:124
Iter iter(const Value &value) const
Find (lookup) iterator for given value (const).
Definition: sethash.h:360
ThisType & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: sethash.h:433
const Item first() const
Get first non-null item (const).
Definition: ptrlist.h:474
Item itemM(Key index)
Get item at position (mutable).
Definition: ptrlist.h:780
bool shared() const
Get whether shared.
Definition: sethash.h:291
End iterator position.
Definition: iter.h:23
SetHash()
Constructor.
Definition: sethash.h:197
SetHash(ThisType &&src)
Move constructor (C++11).
Definition: sethash.h:228
TKey Value
Value type.
Definition: set.h:126
ThisType & clear()
Clear by removing all items.
Definition: ptrlist.h:313
bool contains(const Value &value) const
Get whether the set contains the given value.
Definition: sethash.h:356
const Value * getiter(IterKey &iterkey, const Value &value) const
Used by base class to get data to initialize iterator.
Definition: sethash.h:629
const Hash & get_compare() const
Get hash & comparison object being used for hashing and comparisons (const).
Definition: sethash.h:305
ThisType & remove(Key key)
Remove item and set as null (modifier).
Definition: ptrlist.h:987
IteratorBi< ThisType >::Const Iter
Iterator (const) - IteratorBi.
Definition: sethash.h:193
const Item item(Key index) const
Get item at position (const).
Definition: ptrlist.h:461
Size size() const
Get list size.
Definition: ptrlist.h:414
ThisType & set()
Set as null and empty.
Definition: ptrlist.h:339
const Item * data() const
Get data pointer for direct access (const).
Definition: ptrlist.h:437
SetHash(std::initializer_list< Value > init)
Sequence constructor (C++11).
Definition: sethash.h:218
IterM begin()
Get iterator at first item (mutable).
Definition: sethash.h:341
bool operator==(const SetBaseType &set) const
Equality operator.
Definition: set.h:251
SetHash(const ThisType &src)
Copy constructor.
Definition: sethash.h:211
Set implemented as a hash table.
Definition: sethash.h:167
T & min(T &a, T &b)
Returns lowest of given values.
Definition: alg.h:26