#pragma once #include #include #include #include #include #include #include #include template < typename Key, typename TCell, typename Hash = DefaultHash, typename Grower = HashTableGrower<>, typename Allocator = HashTableAllocator > class HashSetTable : public HashTable { public: typedef HashSetTable Self; typedef TCell Cell; void merge(const Self & rhs) { if (!this->hasZero() && rhs.hasZero()) { this->setHasZero(); ++this->m_size; } for (size_t i = 0; i < rhs.grower.bufSize(); ++i) if (!rhs.buf[i].isZero(*this)) this->insert(Cell::getKey(rhs.buf[i].getValue())); } void readAndMerge(DB::ReadBuffer & rb) { Cell::State::read(rb); size_t new_size = 0; DB::readVarUInt(new_size, rb); this->resize(new_size); for (size_t i = 0; i < new_size; ++i) { Cell x; x.read(rb); this->insert(Cell::getKey(x.getValue())); } } }; template struct HashSetCellWithSavedHash : public HashTableCell { typedef HashTableCell Base; size_t saved_hash; HashSetCellWithSavedHash() : Base() {} HashSetCellWithSavedHash(const Key & key_, const typename Base::State & state) : Base(key_, state) {} bool keyEquals(const Key & key_) const { return this->key == key_; } bool keyEquals(const HashSetCellWithSavedHash & other) const { return saved_hash == other.saved_hash && this->key == other.key; } void setHash(size_t hash_value) { saved_hash = hash_value; } size_t getHash(const Hash & hash) const { return saved_hash; } }; template < typename Key, typename Hash = DefaultHash, typename Grower = HashTableGrower<>, typename Allocator = HashTableAllocator > using HashSet = HashSetTable, Hash, Grower, Allocator>; template < typename Key, typename Hash = DefaultHash, typename Grower = HashTableGrower<>, typename Allocator = HashTableAllocator > using HashSetWithSavedHash = HashSetTable, Hash, Grower, Allocator>;