diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
commit | 2d37894b1b037cf24231090eda8589bbb44fb6fc (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h | |
parent | 718c552901d703c502ccbefdfc3c9028d608b947 (diff) | |
download | ydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h')
-rw-r--r-- | contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h | 1006 |
1 files changed, 503 insertions, 503 deletions
diff --git a/contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h b/contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h index f8480ce979..ac18b4b95a 100644 --- a/contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h +++ b/contrib/libs/poco/Foundation/include/Poco/LinearHashTable.h @@ -1,503 +1,503 @@ -// -// LinearHashTable.h -// -// Library: Foundation -// Package: Hashing -// Module: LinearHashTable -// -// Definition of the LinearHashTable class. -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#ifndef Foundation_LinearHashTable_INCLUDED -#define Foundation_LinearHashTable_INCLUDED - - -#include "Poco/Foundation.h" -#include "Poco/Hash.h" -#include <functional> -#include <algorithm> -#include <vector> -#include <utility> -#include <cstddef> - - -namespace Poco { - - -template <class Value, class HashFunc = Hash<Value> > -class LinearHashTable - /// This class implements a linear hash table. - /// - /// In a linear hash table, the available address space - /// grows or shrinks dynamically. A linar hash table thus - /// supports any number of insertions or deletions without - /// lookup or insertion performance deterioration. - /// - /// Linear hashing was discovered by Witold Litwin in 1980 - /// and described in the paper LINEAR HASHING: A NEW TOOL FOR FILE AND TABLE ADDRESSING. - /// - /// For more information on linear hashing, see <http://en.wikipedia.org/wiki/Linear_hash>. - /// - /// The LinearHashTable is not thread safe. - /// - /// Value must support comparison for equality. - /// - /// Find, insert and delete operations are basically O(1) with regard - /// to the total number of elements in the table, and O(N) with regard - /// to the number of elements in the bucket where the element is stored. - /// On average, every bucket stores one element; the exact number depends - /// on the quality of the hash function. In most cases, the maximum number of - /// elements in a bucket should not exceed 3. -{ -public: - typedef Value ValueType; - typedef Value& Reference; - typedef const Value& ConstReference; - typedef Value* Pointer; - typedef const Value* ConstPointer; - typedef HashFunc Hash; - typedef std::vector<Value> Bucket; - typedef std::vector<Bucket> BucketVec; - typedef typename Bucket::iterator BucketIterator; - typedef typename BucketVec::iterator BucketVecIterator; - - class ConstIterator: public std::iterator<std::forward_iterator_tag, Value> - { - public: - ConstIterator(): _initialized(false) - { - } - - ConstIterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt): - _vecIt(vecIt), - _endIt(endIt), - _buckIt(buckIt), - _initialized(true) - { - } - - ConstIterator(const ConstIterator& it): - _vecIt(it._vecIt), - _endIt(it._endIt), - _buckIt(it._buckIt), - _initialized(it._initialized) - - { - } - - ConstIterator& operator = (const ConstIterator& it) - { - ConstIterator tmp(it); - swap(tmp); - return *this; - } - - void swap(ConstIterator& it) - { - using std::swap; - // uninitialized iterators crash when swapped - if (_initialized) - { - swap(_vecIt, it._vecIt); - swap(_endIt, it._endIt); - swap(_buckIt, it._buckIt); - swap(_initialized, it._initialized); - } - else - { - _vecIt = it._vecIt; - _endIt = it._endIt; - _buckIt = it._buckIt; - _initialized = it._initialized; - } - } - - bool operator == (const ConstIterator& it) const - { - return _vecIt == it._vecIt && (_vecIt == _endIt || _buckIt == it._buckIt); - } - - bool operator != (const ConstIterator& it) const - { - return _vecIt != it._vecIt || (_vecIt != _endIt && _buckIt != it._buckIt); - } - - const typename Bucket::value_type& operator * () const - { - return *_buckIt; - } - - const typename Bucket::value_type* operator -> () const - { - return &*_buckIt; - } - - ConstIterator& operator ++ () // prefix - { - if (_vecIt != _endIt) - { - ++_buckIt; - while (_vecIt != _endIt && _buckIt == _vecIt->end()) - { - ++_vecIt; - if (_vecIt != _endIt) _buckIt = _vecIt->begin(); - } - } - return *this; - } - - ConstIterator operator ++ (int) // postfix - { - ConstIterator tmp(*this); - ++*this; - return tmp; - } - - protected: - BucketVecIterator _vecIt; - BucketVecIterator _endIt; - BucketIterator _buckIt; - bool _initialized; - - friend class LinearHashTable; - }; - - class Iterator: public ConstIterator - { - public: - Iterator() - { - } - - Iterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt): - ConstIterator(vecIt, endIt, buckIt) - { - } - - Iterator(const Iterator& it): - ConstIterator(it) - { - } - - Iterator& operator = (const Iterator& it) - { - Iterator tmp(it); - ConstIterator::swap(tmp); - return *this; - } - - void swap(Iterator& it) - { - ConstIterator::swap(it); - } - - typename Bucket::value_type& operator * () - { - return *this->_buckIt; - } - - const typename Bucket::value_type& operator * () const - { - return *this->_buckIt; - } - - typename Bucket::value_type* operator -> () - { - return &*this->_buckIt; - } - - const typename Bucket::value_type* operator -> () const - { - return &*this->_buckIt; - } - - Iterator& operator ++ () // prefix - { - ConstIterator::operator ++ (); - return *this; - } - - Iterator operator ++ (int) // postfix - { - Iterator tmp(*this); - ++*this; - return tmp; - } - - friend class LinearHashTable; - }; - - LinearHashTable(std::size_t initialReserve = 64): - _split(0), - _front(1), - _size(0) - /// Creates the LinearHashTable, using the given initialReserve. - { - _buckets.reserve(calcSize(initialReserve)); - _buckets.push_back(Bucket()); - } - - LinearHashTable(const LinearHashTable& table): - _buckets(table._buckets), - _split(table._split), - _front(table._front), - _size(table._size) - /// Creates the LinearHashTable by copying another one. - { - } - - ~LinearHashTable() - /// Destroys the LinearHashTable. - { - } - - LinearHashTable& operator = (const LinearHashTable& table) - /// Assigns another LinearHashTable. - { - LinearHashTable tmp(table); - swap(tmp); - return *this; - } - - void swap(LinearHashTable& table) - /// Swaps the LinearHashTable with another one. - { - using std::swap; - swap(_buckets, table._buckets); - swap(_split, table._split); - swap(_front, table._front); - swap(_size, table._size); - } - - ConstIterator begin() const - /// Returns an iterator pointing to the first entry, if one exists. - { - BucketVecIterator it(_buckets.begin()); - BucketVecIterator end(_buckets.end()); - while (it != end && it->empty()) - { - ++it; - } - if (it == end) - return this->end(); - else - return ConstIterator(it, end, it->begin()); - } - - ConstIterator end() const - /// Returns an iterator pointing to the end of the table. - { - return ConstIterator(_buckets.end(), _buckets.end(), _buckets.front().end()); - } - - Iterator begin() - /// Returns an iterator pointing to the first entry, if one exists. - { - BucketVecIterator it(_buckets.begin()); - BucketVecIterator end(_buckets.end()); - while (it != end && it->empty()) - { - ++it; - } - if (it == end) - return this->end(); - else - return Iterator(it, end, it->begin()); - } - - Iterator end() - /// Returns an iterator pointing to the end of the table. - { - return Iterator(_buckets.end(), _buckets.end(), _buckets.front().end()); - } - - ConstIterator find(const Value& value) const - /// Finds an entry in the table. - { - std::size_t addr = bucketAddress(value); - BucketVecIterator it(_buckets.begin() + addr); - BucketIterator buckIt(std::find(it->begin(), it->end(), value)); - if (buckIt != it->end()) - return ConstIterator(it, _buckets.end(), buckIt); - else - return end(); - } - - Iterator find(const Value& value) - /// Finds an entry in the table. - { - std::size_t addr = bucketAddress(value); - BucketVecIterator it(_buckets.begin() + addr); - BucketIterator buckIt(std::find(it->begin(), it->end(), value)); - if (buckIt != it->end()) - return Iterator(it, _buckets.end(), buckIt); - else - return end(); - } - - std::size_t count(const Value& value) const - /// Returns the number of elements with the given - /// value, with is either 1 or 0. - { - return find(value) != end() ? 1 : 0; - } - - std::pair<Iterator, bool> insert(const Value& value) - /// Inserts an element into the table. - /// - /// If the element already exists in the table, - /// a pair(iterator, false) with iterator pointing to the - /// existing element is returned. - /// Otherwise, the element is inserted an a - /// pair(iterator, true) with iterator - /// pointing to the new element is returned. - { - std::size_t hash = _hash(value); - std::size_t addr = bucketAddressForHash(hash); - BucketVecIterator it(_buckets.begin() + addr); - BucketIterator buckIt(std::find(it->begin(), it->end(), value)); - if (buckIt == it->end()) - { - split(); - addr = bucketAddressForHash(hash); - it = _buckets.begin() + addr; - buckIt = it->insert(it->end(), value); - ++_size; - return std::make_pair(Iterator(it, _buckets.end(), buckIt), true); - } - else - { - return std::make_pair(Iterator(it, _buckets.end(), buckIt), false); - } - } - - void erase(Iterator it) - /// Erases the element pointed to by it. - { - if (it != end()) - { - it._vecIt->erase(it._buckIt); - --_size; - merge(); - } - } - - void erase(const Value& value) - /// Erases the element with the given value, if it exists. - { - Iterator it = find(value); - erase(it); - } - - void clear() - /// Erases all elements. - { - LinearHashTable empty; - swap(empty); - } - - std::size_t size() const - /// Returns the number of elements in the table. - { - return _size; - } - - bool empty() const - /// Returns true iff the table is empty. - { - return _size == 0; - } - - std::size_t buckets() const - /// Returns the number of allocated buckets. - { - return _buckets.size(); - } - -protected: - std::size_t bucketAddress(const Value& value) const - { - std::size_t n = _hash(value); - if (n % _front >= _split) - return n % _front; - else - return n % (2*_front); - } - - std::size_t bucketAddressForHash(std::size_t hash) - { - if (hash % _front >= _split) - return hash % _front; - else - return hash % (2*_front); - } - - void split() - { - if (_split == _front) - { - _split = 0; - _front *= 2; - _buckets.reserve(_front*2); - } - Bucket tmp; - _buckets.push_back(tmp); - _buckets[_split].swap(tmp); - ++_split; - for (BucketIterator it = tmp.begin(); it != tmp.end(); ++it) - { - using std::swap; - std::size_t addr = bucketAddress(*it); - _buckets[addr].push_back(Value()); - swap(*it, _buckets[addr].back()); - } - } - - void merge() - { - if (_split == 0) - { - _front /= 2; - _split = _front; - } - --_split; - Bucket tmp; - tmp.swap(_buckets.back()); - _buckets.pop_back(); - for (BucketIterator it = tmp.begin(); it != tmp.end(); ++it) - { - using std::swap; - std::size_t addr = bucketAddress(*it); - _buckets[addr].push_back(Value()); - swap(*it, _buckets[addr].back()); - } - } - - static std::size_t calcSize(std::size_t initialSize) - { - std::size_t size = 32; - while (size < initialSize) size *= 2; - return size; - } - -private: - // Evil hack: _buckets must be mutable because both ConstIterator and Iterator hold - // ordinary iterator's (not const_iterator's). - mutable BucketVec _buckets; - std::size_t _split; - std::size_t _front; - std::size_t _size; - HashFunc _hash; -}; - - -} // namespace Poco - - -#endif // Foundation_LinearHashTable_INCLUDED +// +// LinearHashTable.h +// +// Library: Foundation +// Package: Hashing +// Module: LinearHashTable +// +// Definition of the LinearHashTable class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Foundation_LinearHashTable_INCLUDED +#define Foundation_LinearHashTable_INCLUDED + + +#include "Poco/Foundation.h" +#include "Poco/Hash.h" +#include <functional> +#include <algorithm> +#include <vector> +#include <utility> +#include <cstddef> + + +namespace Poco { + + +template <class Value, class HashFunc = Hash<Value> > +class LinearHashTable + /// This class implements a linear hash table. + /// + /// In a linear hash table, the available address space + /// grows or shrinks dynamically. A linar hash table thus + /// supports any number of insertions or deletions without + /// lookup or insertion performance deterioration. + /// + /// Linear hashing was discovered by Witold Litwin in 1980 + /// and described in the paper LINEAR HASHING: A NEW TOOL FOR FILE AND TABLE ADDRESSING. + /// + /// For more information on linear hashing, see <http://en.wikipedia.org/wiki/Linear_hash>. + /// + /// The LinearHashTable is not thread safe. + /// + /// Value must support comparison for equality. + /// + /// Find, insert and delete operations are basically O(1) with regard + /// to the total number of elements in the table, and O(N) with regard + /// to the number of elements in the bucket where the element is stored. + /// On average, every bucket stores one element; the exact number depends + /// on the quality of the hash function. In most cases, the maximum number of + /// elements in a bucket should not exceed 3. +{ +public: + typedef Value ValueType; + typedef Value& Reference; + typedef const Value& ConstReference; + typedef Value* Pointer; + typedef const Value* ConstPointer; + typedef HashFunc Hash; + typedef std::vector<Value> Bucket; + typedef std::vector<Bucket> BucketVec; + typedef typename Bucket::iterator BucketIterator; + typedef typename BucketVec::iterator BucketVecIterator; + + class ConstIterator: public std::iterator<std::forward_iterator_tag, Value> + { + public: + ConstIterator(): _initialized(false) + { + } + + ConstIterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt): + _vecIt(vecIt), + _endIt(endIt), + _buckIt(buckIt), + _initialized(true) + { + } + + ConstIterator(const ConstIterator& it): + _vecIt(it._vecIt), + _endIt(it._endIt), + _buckIt(it._buckIt), + _initialized(it._initialized) + + { + } + + ConstIterator& operator = (const ConstIterator& it) + { + ConstIterator tmp(it); + swap(tmp); + return *this; + } + + void swap(ConstIterator& it) + { + using std::swap; + // uninitialized iterators crash when swapped + if (_initialized) + { + swap(_vecIt, it._vecIt); + swap(_endIt, it._endIt); + swap(_buckIt, it._buckIt); + swap(_initialized, it._initialized); + } + else + { + _vecIt = it._vecIt; + _endIt = it._endIt; + _buckIt = it._buckIt; + _initialized = it._initialized; + } + } + + bool operator == (const ConstIterator& it) const + { + return _vecIt == it._vecIt && (_vecIt == _endIt || _buckIt == it._buckIt); + } + + bool operator != (const ConstIterator& it) const + { + return _vecIt != it._vecIt || (_vecIt != _endIt && _buckIt != it._buckIt); + } + + const typename Bucket::value_type& operator * () const + { + return *_buckIt; + } + + const typename Bucket::value_type* operator -> () const + { + return &*_buckIt; + } + + ConstIterator& operator ++ () // prefix + { + if (_vecIt != _endIt) + { + ++_buckIt; + while (_vecIt != _endIt && _buckIt == _vecIt->end()) + { + ++_vecIt; + if (_vecIt != _endIt) _buckIt = _vecIt->begin(); + } + } + return *this; + } + + ConstIterator operator ++ (int) // postfix + { + ConstIterator tmp(*this); + ++*this; + return tmp; + } + + protected: + BucketVecIterator _vecIt; + BucketVecIterator _endIt; + BucketIterator _buckIt; + bool _initialized; + + friend class LinearHashTable; + }; + + class Iterator: public ConstIterator + { + public: + Iterator() + { + } + + Iterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt): + ConstIterator(vecIt, endIt, buckIt) + { + } + + Iterator(const Iterator& it): + ConstIterator(it) + { + } + + Iterator& operator = (const Iterator& it) + { + Iterator tmp(it); + ConstIterator::swap(tmp); + return *this; + } + + void swap(Iterator& it) + { + ConstIterator::swap(it); + } + + typename Bucket::value_type& operator * () + { + return *this->_buckIt; + } + + const typename Bucket::value_type& operator * () const + { + return *this->_buckIt; + } + + typename Bucket::value_type* operator -> () + { + return &*this->_buckIt; + } + + const typename Bucket::value_type* operator -> () const + { + return &*this->_buckIt; + } + + Iterator& operator ++ () // prefix + { + ConstIterator::operator ++ (); + return *this; + } + + Iterator operator ++ (int) // postfix + { + Iterator tmp(*this); + ++*this; + return tmp; + } + + friend class LinearHashTable; + }; + + LinearHashTable(std::size_t initialReserve = 64): + _split(0), + _front(1), + _size(0) + /// Creates the LinearHashTable, using the given initialReserve. + { + _buckets.reserve(calcSize(initialReserve)); + _buckets.push_back(Bucket()); + } + + LinearHashTable(const LinearHashTable& table): + _buckets(table._buckets), + _split(table._split), + _front(table._front), + _size(table._size) + /// Creates the LinearHashTable by copying another one. + { + } + + ~LinearHashTable() + /// Destroys the LinearHashTable. + { + } + + LinearHashTable& operator = (const LinearHashTable& table) + /// Assigns another LinearHashTable. + { + LinearHashTable tmp(table); + swap(tmp); + return *this; + } + + void swap(LinearHashTable& table) + /// Swaps the LinearHashTable with another one. + { + using std::swap; + swap(_buckets, table._buckets); + swap(_split, table._split); + swap(_front, table._front); + swap(_size, table._size); + } + + ConstIterator begin() const + /// Returns an iterator pointing to the first entry, if one exists. + { + BucketVecIterator it(_buckets.begin()); + BucketVecIterator end(_buckets.end()); + while (it != end && it->empty()) + { + ++it; + } + if (it == end) + return this->end(); + else + return ConstIterator(it, end, it->begin()); + } + + ConstIterator end() const + /// Returns an iterator pointing to the end of the table. + { + return ConstIterator(_buckets.end(), _buckets.end(), _buckets.front().end()); + } + + Iterator begin() + /// Returns an iterator pointing to the first entry, if one exists. + { + BucketVecIterator it(_buckets.begin()); + BucketVecIterator end(_buckets.end()); + while (it != end && it->empty()) + { + ++it; + } + if (it == end) + return this->end(); + else + return Iterator(it, end, it->begin()); + } + + Iterator end() + /// Returns an iterator pointing to the end of the table. + { + return Iterator(_buckets.end(), _buckets.end(), _buckets.front().end()); + } + + ConstIterator find(const Value& value) const + /// Finds an entry in the table. + { + std::size_t addr = bucketAddress(value); + BucketVecIterator it(_buckets.begin() + addr); + BucketIterator buckIt(std::find(it->begin(), it->end(), value)); + if (buckIt != it->end()) + return ConstIterator(it, _buckets.end(), buckIt); + else + return end(); + } + + Iterator find(const Value& value) + /// Finds an entry in the table. + { + std::size_t addr = bucketAddress(value); + BucketVecIterator it(_buckets.begin() + addr); + BucketIterator buckIt(std::find(it->begin(), it->end(), value)); + if (buckIt != it->end()) + return Iterator(it, _buckets.end(), buckIt); + else + return end(); + } + + std::size_t count(const Value& value) const + /// Returns the number of elements with the given + /// value, with is either 1 or 0. + { + return find(value) != end() ? 1 : 0; + } + + std::pair<Iterator, bool> insert(const Value& value) + /// Inserts an element into the table. + /// + /// If the element already exists in the table, + /// a pair(iterator, false) with iterator pointing to the + /// existing element is returned. + /// Otherwise, the element is inserted an a + /// pair(iterator, true) with iterator + /// pointing to the new element is returned. + { + std::size_t hash = _hash(value); + std::size_t addr = bucketAddressForHash(hash); + BucketVecIterator it(_buckets.begin() + addr); + BucketIterator buckIt(std::find(it->begin(), it->end(), value)); + if (buckIt == it->end()) + { + split(); + addr = bucketAddressForHash(hash); + it = _buckets.begin() + addr; + buckIt = it->insert(it->end(), value); + ++_size; + return std::make_pair(Iterator(it, _buckets.end(), buckIt), true); + } + else + { + return std::make_pair(Iterator(it, _buckets.end(), buckIt), false); + } + } + + void erase(Iterator it) + /// Erases the element pointed to by it. + { + if (it != end()) + { + it._vecIt->erase(it._buckIt); + --_size; + merge(); + } + } + + void erase(const Value& value) + /// Erases the element with the given value, if it exists. + { + Iterator it = find(value); + erase(it); + } + + void clear() + /// Erases all elements. + { + LinearHashTable empty; + swap(empty); + } + + std::size_t size() const + /// Returns the number of elements in the table. + { + return _size; + } + + bool empty() const + /// Returns true iff the table is empty. + { + return _size == 0; + } + + std::size_t buckets() const + /// Returns the number of allocated buckets. + { + return _buckets.size(); + } + +protected: + std::size_t bucketAddress(const Value& value) const + { + std::size_t n = _hash(value); + if (n % _front >= _split) + return n % _front; + else + return n % (2*_front); + } + + std::size_t bucketAddressForHash(std::size_t hash) + { + if (hash % _front >= _split) + return hash % _front; + else + return hash % (2*_front); + } + + void split() + { + if (_split == _front) + { + _split = 0; + _front *= 2; + _buckets.reserve(_front*2); + } + Bucket tmp; + _buckets.push_back(tmp); + _buckets[_split].swap(tmp); + ++_split; + for (BucketIterator it = tmp.begin(); it != tmp.end(); ++it) + { + using std::swap; + std::size_t addr = bucketAddress(*it); + _buckets[addr].push_back(Value()); + swap(*it, _buckets[addr].back()); + } + } + + void merge() + { + if (_split == 0) + { + _front /= 2; + _split = _front; + } + --_split; + Bucket tmp; + tmp.swap(_buckets.back()); + _buckets.pop_back(); + for (BucketIterator it = tmp.begin(); it != tmp.end(); ++it) + { + using std::swap; + std::size_t addr = bucketAddress(*it); + _buckets[addr].push_back(Value()); + swap(*it, _buckets[addr].back()); + } + } + + static std::size_t calcSize(std::size_t initialSize) + { + std::size_t size = 32; + while (size < initialSize) size *= 2; + return size; + } + +private: + // Evil hack: _buckets must be mutable because both ConstIterator and Iterator hold + // ordinary iterator's (not const_iterator's). + mutable BucketVec _buckets; + std::size_t _split; + std::size_t _front; + std::size_t _size; + HashFunc _hash; +}; + + +} // namespace Poco + + +#endif // Foundation_LinearHashTable_INCLUDED |