aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/hash.h
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:15 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:15 +0300
commit72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch)
treeda2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /util/generic/hash.h
parent778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff)
downloadydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'util/generic/hash.h')
-rw-r--r--util/generic/hash.h2088
1 files changed, 1044 insertions, 1044 deletions
diff --git a/util/generic/hash.h b/util/generic/hash.h
index e46db21fa9..532cf16b68 100644
--- a/util/generic/hash.h
+++ b/util/generic/hash.h
@@ -1,45 +1,45 @@
-#pragma once
-
+#pragma once
+
#include "fwd.h"
#include "mapfindptr.h"
#include <util/memory/alloc.h>
#include <util/system/type_name.h>
-#include <util/system/yassert.h>
-#include <util/str_stl.h>
-#include "yexception.h"
-#include "typetraits.h"
-#include "utility.h"
-
-#include <algorithm>
+#include <util/system/yassert.h>
+#include <util/str_stl.h>
+#include "yexception.h"
+#include "typetraits.h"
+#include "utility.h"
+
+#include <algorithm>
#include <initializer_list>
#include <memory>
#include <tuple>
#include <utility>
-
-#include <cstdlib>
-
+
+#include <cstdlib>
+
#include "hash_primes.h"
-struct TSelect1st {
- template <class TPair>
- inline const typename TPair::first_type& operator()(const TPair& x) const {
- return x.first;
- }
-};
-
+struct TSelect1st {
+ template <class TPair>
+ inline const typename TPair::first_type& operator()(const TPair& x) const {
+ return x.first;
+ }
+};
+
template <class Value>
struct __yhashtable_node {
- /** If the first bit is not set, then this is a pointer to the next node in
- * the list of nodes for the current bucket. Otherwise this is a pointer of
+ /** If the first bit is not set, then this is a pointer to the next node in
+ * the list of nodes for the current bucket. Otherwise this is a pointer of
* type __yhashtable_node**, pointing back into the buckets array.
- *
- * This trick makes it possible to use only one node pointer in a hash table
- * iterator. */
+ *
+ * This trick makes it possible to use only one node pointer in a hash table
+ * iterator. */
__yhashtable_node* next;
- /** Value stored in a node. */
- Value val;
+ /** Value stored in a node. */
+ Value val;
__yhashtable_node& operator=(const __yhashtable_node&) = delete;
};
@@ -64,41 +64,41 @@ struct __yhashtable_iterator {
using const_iterator = __yhashtable_const_iterator<Value>;
using node = __yhashtable_node<Value>;
- using iterator_category = std::forward_iterator_tag;
+ using iterator_category = std::forward_iterator_tag;
using value_type = Value;
using difference_type = ptrdiff_t;
using size_type = size_t;
using reference = Value&;
using pointer = Value*;
- node* cur;
+ node* cur;
explicit __yhashtable_iterator(node* n)
- : cur(n)
- {
- } /*y*/
+ : cur(n)
+ {
+ } /*y*/
__yhashtable_iterator() = default;
- reference operator*() const {
- return cur->val;
- }
- pointer operator->() const {
- return &(operator*());
- }
- iterator& operator++();
- iterator operator++(int);
- bool operator==(const iterator& it) const {
- return cur == it.cur;
- }
- bool operator!=(const iterator& it) const {
- return cur != it.cur;
- }
- bool IsEnd() const {
- return !cur;
- }
+ reference operator*() const {
+ return cur->val;
+ }
+ pointer operator->() const {
+ return &(operator*());
+ }
+ iterator& operator++();
+ iterator operator++(int);
+ bool operator==(const iterator& it) const {
+ return cur == it.cur;
+ }
+ bool operator!=(const iterator& it) const {
+ return cur != it.cur;
+ }
+ bool IsEnd() const {
+ return !cur;
+ }
Y_FORCE_INLINE explicit operator bool() const noexcept {
return cur != nullptr;
- }
+ }
};
template <class Value>
@@ -107,45 +107,45 @@ struct __yhashtable_const_iterator {
using const_iterator = __yhashtable_const_iterator<Value>;
using node = __yhashtable_node<Value>;
- using iterator_category = std::forward_iterator_tag;
+ using iterator_category = std::forward_iterator_tag;
using value_type = Value;
using difference_type = ptrdiff_t;
using size_type = size_t;
using reference = const Value&;
using pointer = const Value*;
- const node* cur;
+ const node* cur;
explicit __yhashtable_const_iterator(const node* n)
- : cur(n)
- {
- }
+ : cur(n)
+ {
+ }
__yhashtable_const_iterator() {
- }
+ }
__yhashtable_const_iterator(const iterator& it)
- : cur(it.cur)
- {
- }
- reference operator*() const {
- return cur->val;
- }
- pointer operator->() const {
- return &(operator*());
- }
- const_iterator& operator++();
- const_iterator operator++(int);
- bool operator==(const const_iterator& it) const {
- return cur == it.cur;
- }
- bool operator!=(const const_iterator& it) const {
- return cur != it.cur;
- }
- bool IsEnd() const {
- return !cur;
- }
+ : cur(it.cur)
+ {
+ }
+ reference operator*() const {
+ return cur->val;
+ }
+ pointer operator->() const {
+ return &(operator*());
+ }
+ const_iterator& operator++();
+ const_iterator operator++(int);
+ bool operator==(const const_iterator& it) const {
+ return cur == it.cur;
+ }
+ bool operator!=(const const_iterator& it) const {
+ return cur != it.cur;
+ }
+ bool IsEnd() const {
+ return !cur;
+ }
Y_FORCE_INLINE explicit operator bool() const noexcept {
return cur != nullptr;
- }
+ }
};
/**
@@ -153,27 +153,27 @@ struct __yhashtable_const_iterator {
* use case of empty allocators. This is achieved thanks to the application of
* empty base class optimization (aka EBCO).
*/
-template <class Alloc>
+template <class Alloc>
class _allocator_base: private Alloc {
public:
_allocator_base(const Alloc& other)
: Alloc(other)
- {
- }
-
- Alloc& _get_alloc() {
- return static_cast<Alloc&>(*this);
- }
- const Alloc& _get_alloc() const {
- return static_cast<const Alloc&>(*this);
- }
- void _set_alloc(const Alloc& allocator) {
- _get_alloc() = allocator;
- }
-
- void swap(_allocator_base& other) {
- DoSwap(_get_alloc(), other._get_alloc());
- }
+ {
+ }
+
+ Alloc& _get_alloc() {
+ return static_cast<Alloc&>(*this);
+ }
+ const Alloc& _get_alloc() const {
+ return static_cast<const Alloc&>(*this);
+ }
+ void _set_alloc(const Alloc& allocator) {
+ _get_alloc() = allocator;
+ }
+
+ void swap(_allocator_base& other) {
+ DoSwap(_get_alloc(), other._get_alloc());
+ }
};
/**
@@ -202,11 +202,11 @@ public:
*
* Unused space at the end of the memory block may not be present.
*/
-template <class T, class Alloc>
+template <class T, class Alloc>
class _yhashtable_buckets: private _allocator_base<Alloc> {
using base_type = _allocator_base<Alloc>;
- static_assert(sizeof(T) == sizeof(size_t), "T is expected to be the same size as size_t.");
+ static_assert(sizeof(T) == sizeof(size_t), "T is expected to be the same size as size_t.");
public:
using allocator_type = Alloc;
@@ -225,76 +225,76 @@ public:
: base_type(other)
, Data(nullptr)
, Size()
- {
- }
+ {
+ }
~_yhashtable_buckets() {
Y_ASSERT(!Data);
- }
+ }
void initialize_dynamic(TBucketDivisor size) {
Y_ASSERT(!Data);
Data = this->_get_alloc().allocate(size() + 2) + 1;
- Size = size;
+ Size = size;
*reinterpret_cast<size_type*>(Data - 1) = size() + 2;
- }
+ }
- void deinitialize_dynamic() {
+ void deinitialize_dynamic() {
Y_ASSERT(Data);
- this->_get_alloc().deallocate(Data - 1, *reinterpret_cast<size_type*>(Data - 1));
- Data = pointer();
+ this->_get_alloc().deallocate(Data - 1, *reinterpret_cast<size_type*>(Data - 1));
+ Data = pointer();
Size = TBucketDivisor();
- }
+ }
void initialize_static(pointer data, TBucketDivisor size) {
Y_ASSERT(!Data && data && size() >= 1);
- Data = data;
- Size = size;
- }
+ Data = data;
+ Size = size;
+ }
- void deinitialize_static() {
+ void deinitialize_static() {
Y_ASSERT(Data);
- Data = pointer();
+ Data = pointer();
Size = TBucketDivisor();
- }
+ }
void resize_noallocate(TBucketDivisor size) {
Y_ASSERT(size() <= capacity());
- Size = size;
- }
+ Size = size;
+ }
- iterator begin() {
- return Data;
- }
- const_iterator begin() const {
- return Data;
- }
- iterator end() {
+ iterator begin() {
+ return Data;
+ }
+ const_iterator begin() const {
+ return Data;
+ }
+ iterator end() {
return Data + Size();
- }
- const_iterator end() const {
+ }
+ const_iterator end() const {
return Data + Size();
- }
+ }
- pointer data() {
- return Data;
- }
- const_pointer data() const {
- return Data;
- }
+ pointer data() {
+ return Data;
+ }
+ const_pointer data() const {
+ return Data;
+ }
- size_type size() const {
+ size_type size() const {
return Size();
- }
- size_type capacity() const {
- return *reinterpret_cast<size_type*>(Data - 1);
- }
+ }
+ size_type capacity() const {
+ return *reinterpret_cast<size_type*>(Data - 1);
+ }
TBucketDivisor ExtSize() const {
return Size;
}
@@ -302,33 +302,33 @@ public:
return +Size.Hint;
}
- allocator_type get_allocator() const {
- return this->_get_alloc();
- }
+ allocator_type get_allocator() const {
+ return this->_get_alloc();
+ }
- const_reference operator[](size_type index) const {
+ const_reference operator[](size_type index) const {
Y_ASSERT(index <= Size());
- return *(Data + index);
- }
+ return *(Data + index);
+ }
- reference operator[](size_type index) {
+ reference operator[](size_type index) {
Y_ASSERT(index <= Size());
- return *(Data + index);
- }
+ return *(Data + index);
+ }
void swap(_yhashtable_buckets& other) {
- base_type::swap(other);
- DoSwap(Data, other.Data);
- DoSwap(Size, other.Size);
- }
+ base_type::swap(other);
+ DoSwap(Data, other.Data);
+ DoSwap(Size, other.Size);
+ }
private:
- /** Pointer to the first element of the buckets array. */
- pointer Data;
+ /** Pointer to the first element of the buckets array. */
+ pointer Data;
- /** Size of the buckets array. Doesn't take the marker element at the end into account. */
+ /** Size of the buckets array. Doesn't take the marker element at the end into account. */
TBucketDivisor Size;
};
@@ -350,52 +350,52 @@ private:
template <class HashFcn, class ExtractKey, class EqualKey, class Alloc, bool IsEmpty = std::is_empty<HashFcn>::value&& std::is_empty<ExtractKey>::value&& std::is_empty<EqualKey>::value>
class _yhashtable_base: public _allocator_base<Alloc> {
using base_type = _allocator_base<Alloc>;
-
+
public:
_yhashtable_base(const HashFcn& hash, const ExtractKey& extract, const EqualKey& equals, const Alloc& alloc)
- : base_type(alloc)
+ : base_type(alloc)
, hash_(hash)
, extract_(extract)
, equals_(equals)
- {
- }
+ {
+ }
- const EqualKey& _get_key_eq() const {
+ const EqualKey& _get_key_eq() const {
return equals_;
- }
- EqualKey& _get_key_eq() {
+ }
+ EqualKey& _get_key_eq() {
return equals_;
- }
- void _set_key_eq(const EqualKey& equals) {
+ }
+ void _set_key_eq(const EqualKey& equals) {
this->equals_ = equals;
- }
+ }
- const ExtractKey& _get_key_extract() const {
+ const ExtractKey& _get_key_extract() const {
return extract_;
- }
- ExtractKey& _get_key_extract() {
+ }
+ ExtractKey& _get_key_extract() {
return extract_;
- }
- void _set_key_extract(const ExtractKey& extract) {
+ }
+ void _set_key_extract(const ExtractKey& extract) {
this->extract_ = extract;
- }
+ }
- const HashFcn& _get_hash_fun() const {
+ const HashFcn& _get_hash_fun() const {
return hash_;
- }
- HashFcn& _get_hash_fun() {
+ }
+ HashFcn& _get_hash_fun() {
return hash_;
- }
- void _set_hash_fun(const HashFcn& hash) {
+ }
+ void _set_hash_fun(const HashFcn& hash) {
this->hash_ = hash;
- }
+ }
void swap(_yhashtable_base& other) {
- base_type::swap(other);
+ base_type::swap(other);
DoSwap(equals_, other.equals_);
DoSwap(extract_, other.extract_);
DoSwap(hash_, other.hash_);
- }
+ }
private:
HashFcn hash_;
@@ -403,37 +403,37 @@ private:
EqualKey equals_;
};
-template <class HashFcn, class ExtractKey, class EqualKey, class Alloc>
+template <class HashFcn, class ExtractKey, class EqualKey, class Alloc>
class _yhashtable_base<HashFcn, ExtractKey, EqualKey, Alloc, true>: public _allocator_base<Alloc> {
using base_type = _allocator_base<Alloc>;
public:
_yhashtable_base(const HashFcn&, const ExtractKey&, const EqualKey&, const Alloc& alloc)
- : base_type(alloc)
- {
- }
-
- EqualKey _get_key_eq() const {
- return EqualKey();
- }
- void _set_key_eq(const EqualKey&) {
- }
-
- ExtractKey _get_key_extract() const {
- return ExtractKey();
- }
- void _set_key_extract(const ExtractKey&) {
- }
-
- HashFcn _get_hash_fun() const {
- return HashFcn();
- }
- void _set_hash_fun(const HashFcn&) {
- }
+ : base_type(alloc)
+ {
+ }
+
+ EqualKey _get_key_eq() const {
+ return EqualKey();
+ }
+ void _set_key_eq(const EqualKey&) {
+ }
+
+ ExtractKey _get_key_extract() const {
+ return ExtractKey();
+ }
+ void _set_key_extract(const ExtractKey&) {
+ }
+
+ HashFcn _get_hash_fun() const {
+ return HashFcn();
+ }
+ void _set_hash_fun(const HashFcn&) {
+ }
void swap(_yhashtable_base& other) {
- base_type::swap(other);
- }
+ base_type::swap(other);
+ }
};
template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
@@ -473,42 +473,42 @@ public:
using reference = value_type&;
using const_reference = const value_type&;
- node_allocator_type& GetNodeAllocator() {
- return this->_get_alloc();
- }
- const node_allocator_type& GetNodeAllocator() const {
- return this->_get_alloc();
- }
- key_equal key_eq() const {
- return this->_get_key_eq();
- }
+ node_allocator_type& GetNodeAllocator() {
+ return this->_get_alloc();
+ }
+ const node_allocator_type& GetNodeAllocator() const {
+ return this->_get_alloc();
+ }
+ key_equal key_eq() const {
+ return this->_get_key_eq();
+ }
hasher hash_function() const {
- return this->_get_hash_fun();
- }
+ return this->_get_hash_fun();
+ }
private:
- template <class KeyL, class KeyR>
- bool equals(const KeyL& l, const KeyR& r) const {
- return this->_get_key_eq()(l, r);
- }
+ template <class KeyL, class KeyR>
+ bool equals(const KeyL& l, const KeyR& r) const {
+ return this->_get_key_eq()(l, r);
+ }
- /* This method is templated to postpone instantiation of key extraction functor. */
- template <class ValueL>
+ /* This method is templated to postpone instantiation of key extraction functor. */
+ template <class ValueL>
auto get_key(const ValueL& value) const -> decltype(ExtractKey()(value)) {
- return this->_get_key_extract()(value);
- }
+ return this->_get_key_extract()(value);
+ }
- node* get_node() {
+ node* get_node() {
node* result = this->_get_alloc().allocate(1);
Y_ASSERT((reinterpret_cast<uintptr_t>(result) & 1) == 0); /* We're using the last bit of the node pointer. */
return result;
- }
- void put_node(node* p) {
- this->_get_alloc().deallocate(p, 1);
- }
+ }
+ void put_node(node* p) {
+ this->_get_alloc().deallocate(p, 1);
+ }
- buckets_type buckets;
- size_type num_elements;
+ buckets_type buckets;
+ size_type num_elements;
public:
using iterator = __yhashtable_iterator<Value>;
@@ -520,66 +520,66 @@ public:
public:
THashTable()
- : base_type(HashFcn(), ExtractKey(), EqualKey(), node_allocator_type())
- , buckets(nodep_allocator_type())
- , num_elements(0)
- {
- initialize_buckets(buckets, 0);
- }
+ : base_type(HashFcn(), ExtractKey(), EqualKey(), node_allocator_type())
+ , buckets(nodep_allocator_type())
+ , num_elements(0)
+ {
+ initialize_buckets(buckets, 0);
+ }
THashTable(size_type n, const HashFcn& hf, const EqualKey& eql, const ExtractKey& ext)
- : base_type(hf, ext, eql, node_allocator_type())
- , buckets(nodep_allocator_type())
- , num_elements(0)
- {
- initialize_buckets(buckets, n);
- }
+ : base_type(hf, ext, eql, node_allocator_type())
+ , buckets(nodep_allocator_type())
+ , num_elements(0)
+ {
+ initialize_buckets(buckets, n);
+ }
THashTable(size_type n, const HashFcn& hf, const EqualKey& eql)
- : base_type(hf, ExtractKey(), eql, node_allocator_type())
- , buckets(nodep_allocator_type())
- , num_elements(0)
- {
- initialize_buckets(buckets, n);
- }
-
- template <class TAllocParam>
+ : base_type(hf, ExtractKey(), eql, node_allocator_type())
+ , buckets(nodep_allocator_type())
+ , num_elements(0)
+ {
+ initialize_buckets(buckets, n);
+ }
+
+ template <class TAllocParam>
THashTable(size_type n, const HashFcn& hf, const EqualKey& eql, TAllocParam* allocParam)
- : base_type(hf, ExtractKey(), eql, allocParam)
- , buckets(allocParam)
- , num_elements(0)
- {
- initialize_buckets(buckets, n);
+ : base_type(hf, ExtractKey(), eql, allocParam)
+ , buckets(allocParam)
+ , num_elements(0)
+ {
+ initialize_buckets(buckets, n);
}
THashTable(const THashTable& ht)
- : base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
- , buckets(ht.buckets.get_allocator())
- , num_elements(0)
- {
- if (ht.empty()) {
- initialize_buckets(buckets, 0);
+ : base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
+ , buckets(ht.buckets.get_allocator())
+ , num_elements(0)
+ {
+ if (ht.empty()) {
+ initialize_buckets(buckets, 0);
} else {
initialize_buckets_dynamic(buckets, ht.buckets.ExtSize());
- copy_from_dynamic(ht);
+ copy_from_dynamic(ht);
}
- }
+ }
THashTable(THashTable&& ht) noexcept
- : base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
- , buckets(ht.buckets.get_allocator())
- , num_elements(0)
- {
- initialize_buckets(buckets, 0);
- this->swap(ht);
+ : base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
+ , buckets(ht.buckets.get_allocator())
+ , num_elements(0)
+ {
+ initialize_buckets(buckets, 0);
+ this->swap(ht);
}
THashTable& operator=(const THashTable& ht) {
- if (&ht != this) {
- basic_clear();
- this->_set_hash_fun(ht._get_hash_fun());
- this->_set_key_eq(ht._get_key_eq());
- this->_set_key_extract(ht._get_key_extract());
+ if (&ht != this) {
+ basic_clear();
+ this->_set_hash_fun(ht._get_hash_fun());
+ this->_set_key_eq(ht._get_key_eq());
+ this->_set_key_extract(ht._get_key_extract());
/* We don't copy allocator for a reason. */
if (ht.empty()) {
@@ -590,237 +590,237 @@ public:
deinitialize_buckets(buckets);
initialize_buckets(buckets, 0);
} else {
- if (buckets.capacity() > ht.buckets.size()) {
+ if (buckets.capacity() > ht.buckets.size()) {
buckets.resize_noallocate(ht.buckets.ExtSize());
- } else {
- deinitialize_buckets(buckets);
+ } else {
+ deinitialize_buckets(buckets);
initialize_buckets_dynamic(buckets, ht.buckets.ExtSize());
- }
+ }
- copy_from_dynamic(ht);
- }
- }
- return *this;
- }
+ copy_from_dynamic(ht);
+ }
+ }
+ return *this;
+ }
THashTable& operator=(THashTable&& ht) noexcept {
basic_clear();
swap(ht);
- return *this;
- }
+ return *this;
+ }
~THashTable() {
- basic_clear();
- deinitialize_buckets(buckets);
- }
+ basic_clear();
+ deinitialize_buckets(buckets);
+ }
size_type size() const noexcept {
- return num_elements;
- }
+ return num_elements;
+ }
size_type max_size() const noexcept {
- return size_type(-1);
- }
+ return size_type(-1);
+ }
- Y_PURE_FUNCTION bool empty() const noexcept {
- return size() == 0;
- }
+ Y_PURE_FUNCTION bool empty() const noexcept {
+ return size() == 0;
+ }
void swap(THashTable& ht) {
- base_type::swap(ht);
- buckets.swap(ht.buckets);
- DoSwap(num_elements, ht.num_elements);
- }
-
- iterator begin() {
- for (size_type n = 0; n < buckets.size(); ++n) /*y*/
- if (buckets[n])
- return iterator(buckets[n]); /*y*/
- return end();
- }
-
- iterator end() {
+ base_type::swap(ht);
+ buckets.swap(ht.buckets);
+ DoSwap(num_elements, ht.num_elements);
+ }
+
+ iterator begin() {
+ for (size_type n = 0; n < buckets.size(); ++n) /*y*/
+ if (buckets[n])
+ return iterator(buckets[n]); /*y*/
+ return end();
+ }
+
+ iterator end() {
return iterator(nullptr);
- } /*y*/
-
- const_iterator begin() const {
- for (size_type n = 0; n < buckets.size(); ++n) /*y*/
- if (buckets[n])
- return const_iterator(buckets[n]); /*y*/
- return end();
- }
-
- const_iterator end() const {
+ } /*y*/
+
+ const_iterator begin() const {
+ for (size_type n = 0; n < buckets.size(); ++n) /*y*/
+ if (buckets[n])
+ return const_iterator(buckets[n]); /*y*/
+ return end();
+ }
+
+ const_iterator end() const {
return const_iterator(nullptr);
- } /*y*/
-
+ } /*y*/
+
public:
- size_type bucket_count() const {
- return buckets.size();
- } /*y*/
+ size_type bucket_count() const {
+ return buckets.size();
+ } /*y*/
size_type bucket_size(size_type bucket) const {
- size_type result = 0;
- if (const node* cur = buckets[bucket])
- for (; !((uintptr_t)cur & 1); cur = cur->next)
- result += 1;
- return result;
- }
-
- template <class OtherValue>
+ size_type result = 0;
+ if (const node* cur = buckets[bucket])
+ for (; !((uintptr_t)cur & 1); cur = cur->next)
+ result += 1;
+ return result;
+ }
+
+ template <class OtherValue>
std::pair<iterator, bool> insert_unique(const OtherValue& obj) {
reserve(num_elements + 1);
- return insert_unique_noresize(obj);
- }
+ return insert_unique_noresize(obj);
+ }
- template <class OtherValue>
+ template <class OtherValue>
iterator insert_equal(const OtherValue& obj) {
reserve(num_elements + 1);
return emplace_equal_noresize(obj);
- }
+ }
template <typename... Args>
- iterator emplace_equal(Args&&... args) {
+ iterator emplace_equal(Args&&... args) {
reserve(num_elements + 1);
return emplace_equal_noresize(std::forward<Args>(args)...);
}
- template <class OtherValue>
+ template <class OtherValue>
iterator insert_direct(const OtherValue& obj, insert_ctx ins) {
return emplace_direct(ins, obj);
}
template <typename... Args>
- iterator emplace_direct(insert_ctx ins, Args&&... args) {
+ iterator emplace_direct(insert_ctx ins, Args&&... args) {
bool resized = reserve(num_elements + 1);
node* tmp = new_node(std::forward<Args>(args)...);
- if (resized) {
- find_i(get_key(tmp->val), ins);
- }
- tmp->next = *ins ? *ins : (node*)((uintptr_t)(ins + 1) | 1);
- *ins = tmp;
- ++num_elements;
- return iterator(tmp);
+ if (resized) {
+ find_i(get_key(tmp->val), ins);
+ }
+ tmp->next = *ins ? *ins : (node*)((uintptr_t)(ins + 1) | 1);
+ *ins = tmp;
+ ++num_elements;
+ return iterator(tmp);
}
template <typename... Args>
- std::pair<iterator, bool> emplace_unique(Args&&... args) {
+ std::pair<iterator, bool> emplace_unique(Args&&... args) {
reserve(num_elements + 1);
return emplace_unique_noresize(std::forward<Args>(args)...);
}
template <typename... Args>
- std::pair<iterator, bool> emplace_unique_noresize(Args&&... args);
+ std::pair<iterator, bool> emplace_unique_noresize(Args&&... args);
template <class OtherValue>
std::pair<iterator, bool> insert_unique_noresize(const OtherValue& obj);
template <typename... Args>
- iterator emplace_equal_noresize(Args&&... args);
-
- template <class InputIterator>
- void insert_unique(InputIterator f, InputIterator l) {
- insert_unique(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
- }
-
- template <class InputIterator>
- void insert_equal(InputIterator f, InputIterator l) {
- insert_equal(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
- }
-
- template <class InputIterator>
- void insert_unique(InputIterator f, InputIterator l, std::input_iterator_tag) {
- for (; f != l; ++f)
- insert_unique(*f);
- }
-
- template <class InputIterator>
- void insert_equal(InputIterator f, InputIterator l, std::input_iterator_tag) {
- for (; f != l; ++f)
- insert_equal(*f);
- }
-
- template <class ForwardIterator>
- void insert_unique(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
- difference_type n = std::distance(f, l);
+ iterator emplace_equal_noresize(Args&&... args);
+
+ template <class InputIterator>
+ void insert_unique(InputIterator f, InputIterator l) {
+ insert_unique(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
+ }
+
+ template <class InputIterator>
+ void insert_equal(InputIterator f, InputIterator l) {
+ insert_equal(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
+ }
+
+ template <class InputIterator>
+ void insert_unique(InputIterator f, InputIterator l, std::input_iterator_tag) {
+ for (; f != l; ++f)
+ insert_unique(*f);
+ }
+
+ template <class InputIterator>
+ void insert_equal(InputIterator f, InputIterator l, std::input_iterator_tag) {
+ for (; f != l; ++f)
+ insert_equal(*f);
+ }
+
+ template <class ForwardIterator>
+ void insert_unique(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
+ difference_type n = std::distance(f, l);
reserve(num_elements + n);
- for (; n > 0; --n, ++f)
- insert_unique_noresize(*f);
- }
+ for (; n > 0; --n, ++f)
+ insert_unique_noresize(*f);
+ }
- template <class ForwardIterator>
- void insert_equal(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
- difference_type n = std::distance(f, l);
+ template <class ForwardIterator>
+ void insert_equal(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
+ difference_type n = std::distance(f, l);
reserve(num_elements + n);
- for (; n > 0; --n, ++f)
+ for (; n > 0; --n, ++f)
emplace_equal_noresize(*f);
- }
+ }
- template <class OtherValue>
+ template <class OtherValue>
reference find_or_insert(const OtherValue& v);
- template <class OtherKey>
+ template <class OtherKey>
iterator find(const OtherKey& key) {
- size_type n = bkt_num_key(key);
- node* first;
- for (first = buckets[n];
- first && !equals(get_key(first->val), key);
+ size_type n = bkt_num_key(key);
+ node* first;
+ for (first = buckets[n];
+ first && !equals(get_key(first->val), key);
first = ((uintptr_t)first->next & 1) ? nullptr : first->next) /*y*/
- {
- }
- return iterator(first); /*y*/
- }
-
- template <class OtherKey>
+ {
+ }
+ return iterator(first); /*y*/
+ }
+
+ template <class OtherKey>
const_iterator find(const OtherKey& key) const {
- size_type n = bkt_num_key(key);
- const node* first;
- for (first = buckets[n];
- first && !equals(get_key(first->val), key);
+ size_type n = bkt_num_key(key);
+ const node* first;
+ for (first = buckets[n];
+ first && !equals(get_key(first->val), key);
first = ((uintptr_t)first->next & 1) ? nullptr : first->next) /*y*/
- {
- }
- return const_iterator(first); /*y*/
- }
+ {
+ }
+ return const_iterator(first); /*y*/
+ }
- template <class OtherKey>
+ template <class OtherKey>
iterator find_i(const OtherKey& key, insert_ctx& ins);
- template <class OtherKey>
+ template <class OtherKey>
size_type count(const OtherKey& key) const {
- const size_type n = bkt_num_key(key);
- size_type result = 0;
+ const size_type n = bkt_num_key(key);
+ size_type result = 0;
- if (const node* cur = buckets[n])
- for (; !((uintptr_t)cur & 1); cur = cur->next)
- if (equals(get_key(cur->val), key))
- ++result;
- return result;
- }
+ if (const node* cur = buckets[n])
+ for (; !((uintptr_t)cur & 1); cur = cur->next)
+ if (equals(get_key(cur->val), key))
+ ++result;
+ return result;
+ }
- template <class OtherKey>
+ template <class OtherKey>
std::pair<iterator, iterator> equal_range(const OtherKey& key);
- template <class OtherKey>
+ template <class OtherKey>
std::pair<const_iterator, const_iterator> equal_range(const OtherKey& key) const;
- template <class OtherKey>
+ template <class OtherKey>
size_type erase(const OtherKey& key);
- template <class OtherKey>
+ template <class OtherKey>
size_type erase_one(const OtherKey& key);
// void (instead of iterator) is intended, see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2023.pdf
- void erase(const iterator& it);
- void erase(iterator first, iterator last);
+ void erase(const iterator& it);
+ void erase(iterator first, iterator last);
- void erase(const const_iterator& it);
- void erase(const_iterator first, const_iterator last);
+ void erase(const const_iterator& it);
+ void erase(const_iterator first, const_iterator last);
bool reserve(size_type num_elements_hint);
- void basic_clear();
+ void basic_clear();
/**
* Clears the hashtable without deallocating the nodes.
@@ -837,119 +837,119 @@ public:
num_elements = 0;
}
- // implemented in save_stl.h
- template <class KeySaver>
+ // implemented in save_stl.h
+ template <class KeySaver>
int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const;
- void clear(size_type downsize) {
- basic_clear();
+ void clear(size_type downsize) {
+ basic_clear();
- if (downsize < buckets.size()) {
+ if (downsize < buckets.size()) {
const TBucketDivisor newSize = HashBucketCountExt(downsize);
if (newSize() < buckets.size()) {
Y_ASSERT(newSize() >= 7); /* We cannot downsize static buckets. */
buckets.resize_noallocate(newSize);
- }
- }
- }
-
- /**
- * Clears the hashtable and tries to reasonably downsize it. Note that
- * downsizing is mainly for the following use case:
- *
+ }
+ }
+ }
+
+ /**
+ * Clears the hashtable and tries to reasonably downsize it. Note that
+ * downsizing is mainly for the following use case:
+ *
* THashTable hash;
- * for(...) {
- * if (someCond())
- * hash.clear();
- * hash.insert(...);
- * }
- *
- * Here if at some point `hash` gets really big, then all the following calls
- * to `clear` become really slow as they have to iterate through all the the
- * empty buckets. This is worked around by squeezing the buckets array a little
- * bit with every `clear` call.
- *
- * Alternatively, the user can call `basic_clear`, which doesn't do the
- * downsizing.
- */
- void clear() {
- if (num_elements)
- clear((num_elements * 2 + buckets.size()) / 3);
+ * for(...) {
+ * if (someCond())
+ * hash.clear();
+ * hash.insert(...);
+ * }
+ *
+ * Here if at some point `hash` gets really big, then all the following calls
+ * to `clear` become really slow as they have to iterate through all the the
+ * empty buckets. This is worked around by squeezing the buckets array a little
+ * bit with every `clear` call.
+ *
+ * Alternatively, the user can call `basic_clear`, which doesn't do the
+ * downsizing.
+ */
+ void clear() {
+ if (num_elements)
+ clear((num_elements * 2 + buckets.size()) / 3);
}
private:
- static void initialize_buckets(buckets_type& buckets, size_type sizeHint) {
- if (sizeHint == 0) {
+ static void initialize_buckets(buckets_type& buckets, size_type sizeHint) {
+ if (sizeHint == 0) {
buckets.initialize_static(reinterpret_cast<node**>(const_cast<void**>(_yhashtable_empty_data)) + 1, TBucketDivisor::One());
- } else {
+ } else {
TBucketDivisor size = HashBucketCountExt(sizeHint);
Y_ASSERT(size() >= 7);
- initialize_buckets_dynamic(buckets, size);
- }
+ initialize_buckets_dynamic(buckets, size);
+ }
}
static void initialize_buckets_dynamic(buckets_type& buckets, TBucketDivisor size) {
- buckets.initialize_dynamic(size);
+ buckets.initialize_dynamic(size);
memset(buckets.data(), 0, size() * sizeof(*buckets.data()));
buckets[size()] = (node*)1;
- }
+ }
- static void deinitialize_buckets(buckets_type& buckets) {
- if (buckets.size() == 1) {
- buckets.deinitialize_static();
- } else {
- buckets.deinitialize_dynamic();
- }
+ static void deinitialize_buckets(buckets_type& buckets) {
+ if (buckets.size() == 1) {
+ buckets.deinitialize_static();
+ } else {
+ buckets.deinitialize_dynamic();
+ }
}
- static void clear_buckets(buckets_type& buckets) {
- memset(buckets.data(), 0, buckets.size() * sizeof(*buckets.data()));
- }
+ static void clear_buckets(buckets_type& buckets) {
+ memset(buckets.data(), 0, buckets.size() * sizeof(*buckets.data()));
+ }
- template <class OtherKey>
+ template <class OtherKey>
size_type bkt_num_key(const OtherKey& key) const {
return bkt_num_key(key, buckets.ExtSize());
- }
+ }
- template <class OtherValue>
+ template <class OtherValue>
size_type bkt_num(const OtherValue& obj) const {
- return bkt_num_key(get_key(obj));
- }
+ return bkt_num_key(get_key(obj));
+ }
- template <class OtherKey>
+ template <class OtherKey>
size_type bkt_num_key(const OtherKey& key, TBucketDivisor n) const {
const size_type bucket = n.Remainder(this->_get_hash_fun()(key));
Y_ASSERT((0 <= bucket) && (bucket < n()));
return bucket;
- }
+ }
- template <class OtherValue>
+ template <class OtherValue>
size_type bkt_num(const OtherValue& obj, TBucketDivisor n) const {
- return bkt_num_key(get_key(obj), n);
- }
+ return bkt_num_key(get_key(obj), n);
+ }
template <typename... Args>
- node* new_node(Args&&... val) {
- node* n = get_node();
- n->next = (node*)1; /*y*/ // just for a case
- try {
+ node* new_node(Args&&... val) {
+ node* n = get_node();
+ n->next = (node*)1; /*y*/ // just for a case
+ try {
new (static_cast<void*>(&n->val)) Value(std::forward<Args>(val)...);
- } catch (...) {
- put_node(n);
- throw;
- }
- return n;
- }
-
- void delete_node(node* n) {
- n->val.~Value();
- //n->next = (node*) 0xDeadBeeful;
+ } catch (...) {
+ put_node(n);
+ throw;
+ }
+ return n;
+ }
+
+ void delete_node(node* n) {
+ n->val.~Value();
+ //n->next = (node*) 0xDeadBeeful;
put_node(n);
}
- void erase_bucket(const size_type n, node* first, node* last);
- void erase_bucket(const size_type n, node* last);
+ void erase_bucket(const size_type n, node* first, node* last);
+ void erase_bucket(const size_type n, node* last);
void copy_from_dynamic(const THashTable& ht);
};
@@ -959,7 +959,7 @@ __yhashtable_iterator<V>& __yhashtable_iterator<V>::operator++() {
Y_ASSERT(cur);
cur = cur->next;
if ((uintptr_t)cur & 1) {
- node** bucket = (node**)((uintptr_t)cur & ~1);
+ node** bucket = (node**)((uintptr_t)cur & ~1);
while (*bucket == nullptr)
++bucket;
Y_ASSERT(*bucket != nullptr);
@@ -970,9 +970,9 @@ __yhashtable_iterator<V>& __yhashtable_iterator<V>::operator++() {
template <class V>
inline __yhashtable_iterator<V> __yhashtable_iterator<V>::operator++(int) {
- iterator tmp = *this;
- ++*this;
- return tmp;
+ iterator tmp = *this;
+ ++*this;
+ return tmp;
}
template <class V>
@@ -980,7 +980,7 @@ __yhashtable_const_iterator<V>& __yhashtable_const_iterator<V>::operator++() {
Y_ASSERT(cur);
cur = cur->next;
if ((uintptr_t)cur & 1) {
- node** bucket = (node**)((uintptr_t)cur & ~1);
+ node** bucket = (node**)((uintptr_t)cur & ~1);
while (*bucket == nullptr)
++bucket;
Y_ASSERT(*bucket != nullptr);
@@ -991,15 +991,15 @@ __yhashtable_const_iterator<V>& __yhashtable_const_iterator<V>::operator++() {
template <class V>
inline __yhashtable_const_iterator<V> __yhashtable_const_iterator<V>::operator++(int) {
- const_iterator tmp = *this;
- ++*this;
- return tmp;
+ const_iterator tmp = *this;
+ ++*this;
+ return tmp;
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <typename... Args>
std::pair<typename THashTable<V, K, HF, Ex, Eq, A>::iterator, bool> THashTable<V, K, HF, Ex, Eq, A>::emplace_unique_noresize(Args&&... args) {
- auto deleter = [&](node* tmp) { delete_node(tmp); };
+ auto deleter = [&](node* tmp) { delete_node(tmp); };
node* tmp = new_node(std::forward<Args>(args)...);
std::unique_ptr<node, decltype(deleter)> guard(tmp, deleter);
@@ -1021,45 +1021,45 @@ std::pair<typename THashTable<V, K, HF, Ex, Eq, A>::iterator, bool> THashTable<V
template <class V, class K, class HF, class Ex, class Eq, class A>
template <class OtherValue>
std::pair<typename THashTable<V, K, HF, Ex, Eq, A>::iterator, bool> THashTable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const OtherValue& obj) {
- const size_type n = bkt_num(obj);
- node* first = buckets[n];
+ const size_type n = bkt_num(obj);
+ node* first = buckets[n];
- if (first) /*y*/
- for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
- if (equals(get_key(cur->val), get_key(obj)))
+ if (first) /*y*/
+ for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
+ if (equals(get_key(cur->val), get_key(obj)))
return std::pair<iterator, bool>(iterator(cur), false); /*y*/
- node* tmp = new_node(obj);
- tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
- buckets[n] = tmp;
- ++num_elements;
+ node* tmp = new_node(obj);
+ tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
+ buckets[n] = tmp;
+ ++num_elements;
return std::pair<iterator, bool>(iterator(tmp), true); /*y*/
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <typename... Args>
__yhashtable_iterator<V> THashTable<V, K, HF, Ex, Eq, A>::emplace_equal_noresize(Args&&... args) {
- auto deleter = [&](node* tmp) { delete_node(tmp); };
+ auto deleter = [&](node* tmp) { delete_node(tmp); };
node* tmp = new_node(std::forward<Args>(args)...);
std::unique_ptr<node, decltype(deleter)> guard(tmp, deleter);
const size_type n = bkt_num(tmp->val);
- node* first = buckets[n];
+ node* first = buckets[n];
- if (first) /*y*/
- for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
+ if (first) /*y*/
+ for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
if (equals(get_key(cur->val), get_key(tmp->val))) {
guard.release();
- tmp->next = cur->next;
- cur->next = tmp;
- ++num_elements;
- return iterator(tmp); /*y*/
- }
+ tmp->next = cur->next;
+ cur->next = tmp;
+ ++num_elements;
+ return iterator(tmp); /*y*/
+ }
guard.release();
- tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
- buckets[n] = tmp;
- ++num_elements;
- return iterator(tmp); /*y*/
+ tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
+ buckets[n] = tmp;
+ ++num_elements;
+ return iterator(tmp); /*y*/
}
template <class V, class K, class HF, class Ex, class Eq, class A>
@@ -1067,327 +1067,327 @@ template <class OtherValue>
typename THashTable<V, K, HF, Ex, Eq, A>::reference THashTable<V, K, HF, Ex, Eq, A>::find_or_insert(const OtherValue& v) {
reserve(num_elements + 1);
- size_type n = bkt_num_key(get_key(v));
- node* first = buckets[n];
+ size_type n = bkt_num_key(get_key(v));
+ node* first = buckets[n];
- if (first) /*y*/
- for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
- if (equals(get_key(cur->val), get_key(v)))
- return cur->val;
+ if (first) /*y*/
+ for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
+ if (equals(get_key(cur->val), get_key(v)))
+ return cur->val;
- node* tmp = new_node(v);
- tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
- buckets[n] = tmp;
- ++num_elements;
- return tmp->val;
+ node* tmp = new_node(v);
+ tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
+ buckets[n] = tmp;
+ ++num_elements;
+ return tmp->val;
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <class OtherKey>
__yhashtable_iterator<V> THashTable<V, K, HF, Ex, Eq, A>::find_i(const OtherKey& key, insert_ctx& ins) {
- size_type n = bkt_num_key(key);
- ins = &buckets[n];
- node* first = buckets[n];
-
- if (first) /*y*/
- for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
- if (equals(get_key(cur->val), key))
- return iterator(cur); /*y*/
- return end();
+ size_type n = bkt_num_key(key);
+ ins = &buckets[n];
+ node* first = buckets[n];
+
+ if (first) /*y*/
+ for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
+ if (equals(get_key(cur->val), key))
+ return iterator(cur); /*y*/
+ return end();
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <class OtherKey>
std::pair<__yhashtable_iterator<V>, __yhashtable_iterator<V>> THashTable<V, K, HF, Ex, Eq, A>::equal_range(const OtherKey& key) {
using pii = std::pair<iterator, iterator>;
- const size_type n = bkt_num_key(key);
- node* first = buckets[n];
-
- if (first) /*y*/
- for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
- if (equals(get_key(first->val), key)) {
- for (node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
- if (!equals(get_key(cur->val), key))
- return pii(iterator(first), iterator(cur)); /*y*/
- for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
- if (buckets[m])
- return pii(iterator(first), /*y*/
- iterator(buckets[m])); /*y*/
- return pii(iterator(first), end()); /*y*/
- }
- }
- return pii(end(), end());
+ const size_type n = bkt_num_key(key);
+ node* first = buckets[n];
+
+ if (first) /*y*/
+ for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
+ if (equals(get_key(first->val), key)) {
+ for (node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
+ if (!equals(get_key(cur->val), key))
+ return pii(iterator(first), iterator(cur)); /*y*/
+ for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
+ if (buckets[m])
+ return pii(iterator(first), /*y*/
+ iterator(buckets[m])); /*y*/
+ return pii(iterator(first), end()); /*y*/
+ }
+ }
+ return pii(end(), end());
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <class OtherKey>
std::pair<__yhashtable_const_iterator<V>, __yhashtable_const_iterator<V>> THashTable<V, K, HF, Ex, Eq, A>::equal_range(const OtherKey& key) const {
using pii = std::pair<const_iterator, const_iterator>;
- const size_type n = bkt_num_key(key);
- const node* first = buckets[n];
-
- if (first) /*y*/
- for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
- if (equals(get_key(first->val), key)) {
- for (const node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
- if (!equals(get_key(cur->val), key))
- return pii(const_iterator(first), /*y*/
- const_iterator(cur)); /*y*/
- for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
- if (buckets[m])
- return pii(const_iterator(first /*y*/),
- const_iterator(buckets[m] /*y*/));
- return pii(const_iterator(first /*y*/), end());
- }
- }
- return pii(end(), end());
+ const size_type n = bkt_num_key(key);
+ const node* first = buckets[n];
+
+ if (first) /*y*/
+ for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
+ if (equals(get_key(first->val), key)) {
+ for (const node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
+ if (!equals(get_key(cur->val), key))
+ return pii(const_iterator(first), /*y*/
+ const_iterator(cur)); /*y*/
+ for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
+ if (buckets[m])
+ return pii(const_iterator(first /*y*/),
+ const_iterator(buckets[m] /*y*/));
+ return pii(const_iterator(first /*y*/), end());
+ }
+ }
+ return pii(end(), end());
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <class OtherKey>
typename THashTable<V, K, HF, Ex, Eq, A>::size_type THashTable<V, K, HF, Ex, Eq, A>::erase(const OtherKey& key) {
- const size_type n = bkt_num_key(key);
- node* first = buckets[n];
- size_type erased = 0;
-
- if (first) {
- node* cur = first;
- node* next = cur->next;
- while (!((uintptr_t)next & 1)) { /*y*/
- if (equals(get_key(next->val), key)) {
- cur->next = next->next;
- ++erased;
- --num_elements;
- delete_node(next);
- next = cur->next;
- } else {
- cur = next;
- next = cur->next;
- }
- }
- if (equals(get_key(first->val), key)) {
+ const size_type n = bkt_num_key(key);
+ node* first = buckets[n];
+ size_type erased = 0;
+
+ if (first) {
+ node* cur = first;
+ node* next = cur->next;
+ while (!((uintptr_t)next & 1)) { /*y*/
+ if (equals(get_key(next->val), key)) {
+ cur->next = next->next;
+ ++erased;
+ --num_elements;
+ delete_node(next);
+ next = cur->next;
+ } else {
+ cur = next;
+ next = cur->next;
+ }
+ }
+ if (equals(get_key(first->val), key)) {
buckets[n] = ((uintptr_t)first->next & 1) ? nullptr : first->next; /*y*/
- ++erased;
- --num_elements;
- delete_node(first);
- }
+ ++erased;
+ --num_elements;
+ delete_node(first);
+ }
}
- return erased;
+ return erased;
}
template <class V, class K, class HF, class Ex, class Eq, class A>
template <class OtherKey>
typename THashTable<V, K, HF, Ex, Eq, A>::size_type THashTable<V, K, HF, Ex, Eq, A>::erase_one(const OtherKey& key) {
- const size_type n = bkt_num_key(key);
- node* first = buckets[n];
-
- if (first) {
- node* cur = first;
- node* next = cur->next;
- while (!((uintptr_t)next & 1)) { /*y*/
- if (equals(get_key(next->val), key)) {
- cur->next = next->next;
- --num_elements;
- delete_node(next);
- return 1;
- } else {
- cur = next;
- next = cur->next;
- }
- }
- if (equals(get_key(first->val), key)) {
+ const size_type n = bkt_num_key(key);
+ node* first = buckets[n];
+
+ if (first) {
+ node* cur = first;
+ node* next = cur->next;
+ while (!((uintptr_t)next & 1)) { /*y*/
+ if (equals(get_key(next->val), key)) {
+ cur->next = next->next;
+ --num_elements;
+ delete_node(next);
+ return 1;
+ } else {
+ cur = next;
+ next = cur->next;
+ }
+ }
+ if (equals(get_key(first->val), key)) {
buckets[n] = ((uintptr_t)first->next & 1) ? nullptr : first->next; /*y*/
- --num_elements;
- delete_node(first);
- return 1;
- }
+ --num_elements;
+ delete_node(first);
+ return 1;
+ }
}
- return 0;
+ return 0;
}
template <class V, class K, class HF, class Ex, class Eq, class A>
void THashTable<V, K, HF, Ex, Eq, A>::erase(const iterator& it) {
- if (node* const p = it.cur) {
- const size_type n = bkt_num(p->val);
- node* cur = buckets[n];
+ if (node* const p = it.cur) {
+ const size_type n = bkt_num(p->val);
+ node* cur = buckets[n];
- if (cur == p) {
+ if (cur == p) {
buckets[n] = ((uintptr_t)cur->next & 1) ? nullptr : cur->next; /*y*/
- delete_node(cur);
- --num_elements;
- } else {
- node* next = cur->next;
- while (!((uintptr_t)next & 1)) {
- if (next == p) {
- cur->next = next->next;
- delete_node(next);
- --num_elements;
- break;
- } else {
- cur = next;
- next = cur->next;
- }
- }
+ delete_node(cur);
+ --num_elements;
+ } else {
+ node* next = cur->next;
+ while (!((uintptr_t)next & 1)) {
+ if (next == p) {
+ cur->next = next->next;
+ delete_node(next);
+ --num_elements;
+ break;
+ } else {
+ cur = next;
+ next = cur->next;
+ }
+ }
}
}
}
template <class V, class K, class HF, class Ex, class Eq, class A>
void THashTable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last) {
- size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size(); /*y*/
- size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size(); /*y*/
-
- if (first.cur == last.cur)
- return;
- else if (f_bucket == l_bucket)
- erase_bucket(f_bucket, first.cur, last.cur);
- else {
+ size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size(); /*y*/
+ size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size(); /*y*/
+
+ if (first.cur == last.cur)
+ return;
+ else if (f_bucket == l_bucket)
+ erase_bucket(f_bucket, first.cur, last.cur);
+ else {
erase_bucket(f_bucket, first.cur, nullptr);
- for (size_type n = f_bucket + 1; n < l_bucket; ++n)
+ for (size_type n = f_bucket + 1; n < l_bucket; ++n)
erase_bucket(n, nullptr);
- if (l_bucket != buckets.size()) /*y*/
- erase_bucket(l_bucket, last.cur);
- }
+ if (l_bucket != buckets.size()) /*y*/
+ erase_bucket(l_bucket, last.cur);
+ }
}
template <class V, class K, class HF, class Ex, class Eq, class A>
inline void
THashTable<V, K, HF, Ex, Eq, A>::erase(const_iterator first, const_iterator last) {
- erase(iterator(const_cast<node*>(first.cur)), iterator(const_cast<node*>(last.cur)));
+ erase(iterator(const_cast<node*>(first.cur)), iterator(const_cast<node*>(last.cur)));
}
template <class V, class K, class HF, class Ex, class Eq, class A>
inline void THashTable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it) {
- erase(iterator(const_cast<node*>(it.cur)));
+ erase(iterator(const_cast<node*>(it.cur)));
}
template <class V, class K, class HF, class Ex, class Eq, class A>
bool THashTable<V, K, HF, Ex, Eq, A>::reserve(size_type num_elements_hint) {
- const size_type old_n = buckets.size(); /*y*/
- if (num_elements_hint + 1 > old_n) {
+ const size_type old_n = buckets.size(); /*y*/
+ if (num_elements_hint + 1 > old_n) {
if (old_n != 1 && num_elements_hint <= old_n) // TODO: this if is for backwards compatibility down to order-in-buckets level. Can be safely removed.
return false;
const TBucketDivisor n = HashBucketCountExt(num_elements_hint + 1, buckets.BucketDivisorHint() + 1);
if (n() > old_n) {
- buckets_type tmp(buckets.get_allocator());
- initialize_buckets_dynamic(tmp, n);
-#ifdef __STL_USE_EXCEPTIONS
- try {
-#endif /* __STL_USE_EXCEPTIONS */
- for (size_type bucket = 0; bucket < old_n; ++bucket) {
- node* first = buckets[bucket];
- while (first) {
- size_type new_bucket = bkt_num(first->val, n);
- node* next = first->next;
+ buckets_type tmp(buckets.get_allocator());
+ initialize_buckets_dynamic(tmp, n);
+#ifdef __STL_USE_EXCEPTIONS
+ try {
+#endif /* __STL_USE_EXCEPTIONS */
+ for (size_type bucket = 0; bucket < old_n; ++bucket) {
+ node* first = buckets[bucket];
+ while (first) {
+ size_type new_bucket = bkt_num(first->val, n);
+ node* next = first->next;
buckets[bucket] = ((uintptr_t)next & 1) ? nullptr : next; /*y*/
- next = tmp[new_bucket];
- first->next = next ? next : (node*)((uintptr_t) & (tmp[new_bucket + 1]) | 1); /*y*/
- tmp[new_bucket] = first;
- first = buckets[bucket];
- }
- }
-
- buckets.swap(tmp);
- deinitialize_buckets(tmp);
-
- return true;
-#ifdef __STL_USE_EXCEPTIONS
- } catch (...) {
- for (size_type bucket = 0; bucket < tmp.size() - 1; ++bucket) {
- while (tmp[bucket]) {
- node* next = tmp[bucket]->next;
- delete_node(tmp[bucket]);
+ next = tmp[new_bucket];
+ first->next = next ? next : (node*)((uintptr_t) & (tmp[new_bucket + 1]) | 1); /*y*/
+ tmp[new_bucket] = first;
+ first = buckets[bucket];
+ }
+ }
+
+ buckets.swap(tmp);
+ deinitialize_buckets(tmp);
+
+ return true;
+#ifdef __STL_USE_EXCEPTIONS
+ } catch (...) {
+ for (size_type bucket = 0; bucket < tmp.size() - 1; ++bucket) {
+ while (tmp[bucket]) {
+ node* next = tmp[bucket]->next;
+ delete_node(tmp[bucket]);
tmp[bucket] = ((uintptr_t)next & 1) ? nullptr : next /*y*/;
- }
- }
- throw;
- }
-#endif /* __STL_USE_EXCEPTIONS */
+ }
+ }
+ throw;
+ }
+#endif /* __STL_USE_EXCEPTIONS */
}
}
-
- return false;
+
+ return false;
}
template <class V, class K, class HF, class Ex, class Eq, class A>
void THashTable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* first, node* last) {
- node* cur = buckets[n];
- if (cur == first)
- erase_bucket(n, last);
- else {
- node* next;
- for (next = cur->next; next != first; cur = next, next = cur->next)
- ;
- while (next != last) { /*y; 3.1*/
- cur->next = next->next;
- delete_node(next);
+ node* cur = buckets[n];
+ if (cur == first)
+ erase_bucket(n, last);
+ else {
+ node* next;
+ for (next = cur->next; next != first; cur = next, next = cur->next)
+ ;
+ while (next != last) { /*y; 3.1*/
+ cur->next = next->next;
+ delete_node(next);
next = ((uintptr_t)cur->next & 1) ? nullptr : cur->next; /*y*/
- --num_elements;
- }
+ --num_elements;
+ }
}
}
template <class V, class K, class HF, class Ex, class Eq, class A>
void THashTable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last) {
- node* cur = buckets[n];
- while (cur != last) {
- node* next = cur->next;
- delete_node(cur);
+ node* cur = buckets[n];
+ while (cur != last) {
+ node* next = cur->next;
+ delete_node(cur);
cur = ((uintptr_t)next & 1) ? nullptr : next; /*y*/
- buckets[n] = cur;
- --num_elements;
- }
+ buckets[n] = cur;
+ --num_elements;
+ }
}
template <class V, class K, class HF, class Ex, class Eq, class A>
void THashTable<V, K, HF, Ex, Eq, A>::basic_clear() {
- if (!num_elements) {
- return;
- }
-
- node** first = buckets.begin();
- node** last = buckets.end();
- for (; first < last; ++first) {
- node* cur = *first;
- if (cur) { /*y*/
- while (!((uintptr_t)cur & 1)) { /*y*/
- node* next = cur->next;
- delete_node(cur);
- cur = next;
- }
+ if (!num_elements) {
+ return;
+ }
+
+ node** first = buckets.begin();
+ node** last = buckets.end();
+ for (; first < last; ++first) {
+ node* cur = *first;
+ if (cur) { /*y*/
+ while (!((uintptr_t)cur & 1)) { /*y*/
+ node* next = cur->next;
+ delete_node(cur);
+ cur = next;
+ }
*first = nullptr;
- }
+ }
}
- num_elements = 0;
+ num_elements = 0;
}
template <class V, class K, class HF, class Ex, class Eq, class A>
void THashTable<V, K, HF, Ex, Eq, A>::copy_from_dynamic(const THashTable& ht) {
Y_ASSERT(buckets.size() == ht.buckets.size() && !ht.empty());
-#ifdef __STL_USE_EXCEPTIONS
- try {
-#endif /* __STL_USE_EXCEPTIONS */
- for (size_type i = 0; i < ht.buckets.size(); ++i) { /*y*/
- if (const node* cur = ht.buckets[i]) {
- node* copy = new_node(cur->val);
- buckets[i] = copy;
-
- for (node* next = cur->next; !((uintptr_t)next & 1); cur = next, next = cur->next) {
- copy->next = new_node(next->val);
- copy = copy->next;
- }
- copy->next = (node*)((uintptr_t)&buckets[i + 1] | 1); /*y*/
- }
+#ifdef __STL_USE_EXCEPTIONS
+ try {
+#endif /* __STL_USE_EXCEPTIONS */
+ for (size_type i = 0; i < ht.buckets.size(); ++i) { /*y*/
+ if (const node* cur = ht.buckets[i]) {
+ node* copy = new_node(cur->val);
+ buckets[i] = copy;
+
+ for (node* next = cur->next; !((uintptr_t)next & 1); cur = next, next = cur->next) {
+ copy->next = new_node(next->val);
+ copy = copy->next;
+ }
+ copy->next = (node*)((uintptr_t)&buckets[i + 1] | 1); /*y*/
+ }
}
- num_elements = ht.num_elements;
-#ifdef __STL_USE_EXCEPTIONS
- } catch (...) {
- basic_clear();
- throw;
+ num_elements = ht.num_elements;
+#ifdef __STL_USE_EXCEPTIONS
+ } catch (...) {
+ basic_clear();
+ throw;
}
-#endif /* __STL_USE_EXCEPTIONS */
+#endif /* __STL_USE_EXCEPTIONS */
}
namespace NPrivate {
@@ -1419,13 +1419,13 @@ namespace NPrivate {
}
[[noreturn]] void ThrowKeyNotFoundInHashTableException(const TStringBuf keyRepresentation);
-}
+}
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
class THashMap: public TMapOps<THashMap<Key, T, HashFcn, EqualKey, Alloc>> {
private:
using ht = THashTable<std::pair<const Key, T>, Key, HashFcn, TSelect1st, EqualKey, Alloc>;
- ht rep;
+ ht rep;
public:
using key_type = typename ht::key_type;
@@ -1449,64 +1449,64 @@ public:
hasher hash_function() const {
return rep.hash_function();
- }
- key_equal key_eq() const {
- return rep.key_eq();
- }
+ }
+ key_equal key_eq() const {
+ return rep.key_eq();
+ }
public:
THashMap()
- : rep(0, hasher(), key_equal())
- {
- }
- template <class TAllocParam>
+ : rep(0, hasher(), key_equal())
+ {
+ }
+ template <class TAllocParam>
explicit THashMap(TAllocParam* allocParam, size_type n = 0)
: rep(n, hasher(), key_equal(), allocParam)
- {
- }
+ {
+ }
explicit THashMap(size_type n)
- : rep(n, hasher(), key_equal())
- {
- }
+ : rep(n, hasher(), key_equal())
+ {
+ }
THashMap(size_type n, const hasher& hf)
- : rep(n, hf, key_equal())
- {
- }
+ : rep(n, hf, key_equal())
+ {
+ }
THashMap(size_type n, const hasher& hf, const key_equal& eql)
- : rep(n, hf, eql)
- {
- }
- template <class TAllocParam>
+ : rep(n, hf, eql)
+ {
+ }
+ template <class TAllocParam>
explicit THashMap(size_type n, TAllocParam* allocParam)
- : rep(n, hasher(), key_equal(), allocParam)
- {
- }
- template <class InputIterator>
+ : rep(n, hasher(), key_equal(), allocParam)
+ {
+ }
+ template <class InputIterator>
THashMap(InputIterator f, InputIterator l)
- : rep(0, hasher(), key_equal())
- {
- rep.insert_unique(f, l);
- }
- template <class InputIterator>
+ : rep(0, hasher(), key_equal())
+ {
+ rep.insert_unique(f, l);
+ }
+ template <class InputIterator>
THashMap(InputIterator f, InputIterator l, size_type n)
- : rep(n, hasher(), key_equal())
- {
- rep.insert_unique(f, l);
- }
- template <class InputIterator>
+ : rep(n, hasher(), key_equal())
+ {
+ rep.insert_unique(f, l);
+ }
+ template <class InputIterator>
THashMap(InputIterator f, InputIterator l, size_type n,
- const hasher& hf)
- : rep(n, hf, key_equal())
- {
- rep.insert_unique(f, l);
- }
- template <class InputIterator>
+ const hasher& hf)
+ : rep(n, hf, key_equal())
+ {
+ rep.insert_unique(f, l);
+ }
+ template <class InputIterator>
THashMap(InputIterator f, InputIterator l, size_type n,
- const hasher& hf, const key_equal& eql)
- : rep(n, hf, eql)
- {
- rep.insert_unique(f, l);
- }
+ const hasher& hf, const key_equal& eql)
+ : rep(n, hf, eql)
+ {
+ rep.insert_unique(f, l);
+ }
THashMap(const std::initializer_list<std::pair<Key, T>>& list)
: rep(list.size(), hasher(), key_equal())
@@ -1518,47 +1518,47 @@ public:
// THashMap has implicit copy/move constructors and copy-/move-assignment operators
// because its implementation is backed by THashTable.
- // See hash_ut.cpp
+ // See hash_ut.cpp
public:
size_type size() const noexcept {
- return rep.size();
- }
+ return rep.size();
+ }
yssize_t ysize() const noexcept {
return (yssize_t)rep.size();
- }
+ }
size_type max_size() const noexcept {
- return rep.max_size();
- }
-
- Y_PURE_FUNCTION bool empty() const noexcept {
- return rep.empty();
- }
- explicit operator bool() const noexcept {
- return !empty();
- }
+ return rep.max_size();
+ }
+
+ Y_PURE_FUNCTION bool empty() const noexcept {
+ return rep.empty();
+ }
+ explicit operator bool() const noexcept {
+ return !empty();
+ }
void swap(THashMap& hs) {
- rep.swap(hs.rep);
- }
-
- iterator begin() {
- return rep.begin();
- }
- iterator end() {
- return rep.end();
- }
- const_iterator begin() const {
- return rep.begin();
- }
- const_iterator end() const {
- return rep.end();
- }
- const_iterator cbegin() const {
- return rep.begin();
- }
- const_iterator cend() const {
- return rep.end();
- }
+ rep.swap(hs.rep);
+ }
+
+ iterator begin() {
+ return rep.begin();
+ }
+ iterator end() {
+ return rep.end();
+ }
+ const_iterator begin() const {
+ return rep.begin();
+ }
+ const_iterator end() const {
+ return rep.end();
+ }
+ const_iterator cbegin() const {
+ return rep.begin();
+ }
+ const_iterator cend() const {
+ return rep.end();
+ }
public:
template <class InputIterator>
@@ -1567,11 +1567,11 @@ public:
}
std::pair<iterator, bool> insert(const value_type& obj) {
- return rep.insert_unique(obj);
- }
+ return rep.insert_unique(obj);
+ }
template <typename... Args>
- std::pair<iterator, bool> emplace(Args&&... args) {
+ std::pair<iterator, bool> emplace(Args&&... args) {
return rep.emplace_unique(std::forward<Args>(args)...);
}
@@ -1584,10 +1584,10 @@ public:
return rep.emplace_unique_noresize(std::forward<Args>(args)...);
}
- template <class TheObj>
- iterator insert_direct(const TheObj& obj, const insert_ctx& ins) {
- return rep.insert_direct(obj, ins);
- }
+ template <class TheObj>
+ iterator insert_direct(const TheObj& obj, const insert_ctx& ins) {
+ return rep.insert_direct(obj, ins);
+ }
template <typename... Args>
iterator emplace_direct(const insert_ctx& ins, Args&&... args) {
@@ -1600,29 +1600,29 @@ public:
iterator it = find(key, ctx);
if (it == end()) {
it = rep.emplace_direct(ctx, std::piecewise_construct,
- std::forward_as_tuple(std::forward<TKey>(key)),
- std::forward_as_tuple(std::forward<Args>(args)...));
+ std::forward_as_tuple(std::forward<TKey>(key)),
+ std::forward_as_tuple(std::forward<Args>(args)...));
return {it, true};
}
return {it, false};
}
- template <class TheKey>
- iterator find(const TheKey& key) {
- return rep.find(key);
- }
-
- template <class TheKey>
- const_iterator find(const TheKey& key) const {
- return rep.find(key);
- }
-
- template <class TheKey>
- iterator find(const TheKey& key, insert_ctx& ins) {
- return rep.find_i(key, ins);
- }
-
- template <class TheKey>
+ template <class TheKey>
+ iterator find(const TheKey& key) {
+ return rep.find(key);
+ }
+
+ template <class TheKey>
+ const_iterator find(const TheKey& key) const {
+ return rep.find(key);
+ }
+
+ template <class TheKey>
+ iterator find(const TheKey& key, insert_ctx& ins) {
+ return rep.find_i(key, ins);
+ }
+
+ template <class TheKey>
bool contains(const TheKey& key) const {
return rep.find(key) != rep.end();
}
@@ -1635,103 +1635,103 @@ public:
return rep.find_i(key, ins) != rep.end();
}
- template <class TKey>
- T& operator[](const TKey& key) {
+ template <class TKey>
+ T& operator[](const TKey& key) {
insert_ctx ctx = nullptr;
- iterator it = find(key, ctx);
-
- if (it != end()) {
- return it->second;
- }
-
+ iterator it = find(key, ctx);
+
+ if (it != end()) {
+ return it->second;
+ }
+
return rep.emplace_direct(ctx, std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple())->second;
- }
+ }
- template <class TheKey>
- const T& at(const TheKey& key) const {
+ template <class TheKey>
+ const T& at(const TheKey& key) const {
using namespace ::NPrivate;
- const_iterator it = find(key);
+ const_iterator it = find(key);
if (Y_UNLIKELY(it == end())) {
::NPrivate::ThrowKeyNotFoundInHashTableException(MapKeyToString(key));
- }
-
- return it->second;
+ }
+
+ return it->second;
}
- template <class TheKey>
- T& at(const TheKey& key) {
+ template <class TheKey>
+ T& at(const TheKey& key) {
using namespace ::NPrivate;
- iterator it = find(key);
+ iterator it = find(key);
if (Y_UNLIKELY(it == end())) {
::NPrivate::ThrowKeyNotFoundInHashTableException(MapKeyToString(key));
- }
+ }
- return it->second;
+ return it->second;
}
- template <class TKey>
- size_type count(const TKey& key) const {
- return rep.count(key);
- }
+ template <class TKey>
+ size_type count(const TKey& key) const {
+ return rep.count(key);
+ }
- template <class TKey>
+ template <class TKey>
std::pair<iterator, iterator> equal_range(const TKey& key) {
- return rep.equal_range(key);
- }
+ return rep.equal_range(key);
+ }
- template <class TKey>
+ template <class TKey>
std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const {
- return rep.equal_range(key);
- }
-
- template <class TKey>
- size_type erase(const TKey& key) {
- return rep.erase_one(key);
- }
-
- void erase(iterator it) {
- rep.erase(it);
- }
- void erase(iterator f, iterator l) {
- rep.erase(f, l);
- }
- void clear() {
- rep.clear();
- }
- void clear(size_t downsize_hint) {
- rep.clear(downsize_hint);
- }
- void basic_clear() {
- rep.basic_clear();
- }
+ return rep.equal_range(key);
+ }
+
+ template <class TKey>
+ size_type erase(const TKey& key) {
+ return rep.erase_one(key);
+ }
+
+ void erase(iterator it) {
+ rep.erase(it);
+ }
+ void erase(iterator f, iterator l) {
+ rep.erase(f, l);
+ }
+ void clear() {
+ rep.clear();
+ }
+ void clear(size_t downsize_hint) {
+ rep.clear(downsize_hint);
+ }
+ void basic_clear() {
+ rep.basic_clear();
+ }
void release_nodes() {
rep.release_nodes();
}
-
- // if (stHash != NULL) bucket_count() must be equal to stHash->bucket_count()
- template <class KeySaver>
+
+ // if (stHash != NULL) bucket_count() must be equal to stHash->bucket_count()
+ template <class KeySaver>
int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const {
return rep.template save_for_st<KeySaver>(stream, ks, stHash);
- }
+ }
public:
void reserve(size_type hint) {
rep.reserve(hint);
- }
- size_type bucket_count() const {
- return rep.bucket_count();
- }
+ }
+ size_type bucket_count() const {
+ return rep.bucket_count();
+ }
size_type bucket_size(size_type n) const {
return rep.bucket_size(n);
- }
- node_allocator_type& GetNodeAllocator() {
- return rep.GetNodeAllocator();
- }
- const node_allocator_type& GetNodeAllocator() const {
- return rep.GetNodeAllocator();
- }
+ }
+ node_allocator_type& GetNodeAllocator() {
+ return rep.GetNodeAllocator();
+ }
+ const node_allocator_type& GetNodeAllocator() const {
+ return rep.GetNodeAllocator();
+ }
};
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
@@ -1739,7 +1739,7 @@ inline bool operator==(const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm1, co
if (hm1.size() != hm2.size()) {
return false;
}
- for (const auto& it1 : hm1) {
+ for (const auto& it1 : hm1) {
auto it2 = hm2.find(it1.first);
if ((it2 == hm2.end()) || !(it1 == *it2)) {
return false;
@@ -1757,7 +1757,7 @@ template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
class THashMultiMap {
private:
using ht = THashTable<std::pair<const Key, T>, Key, HashFcn, TSelect1st, EqualKey, Alloc>;
- ht rep;
+ ht rep;
public:
using key_type = typename ht::key_type;
@@ -1780,58 +1780,58 @@ public:
hasher hash_function() const {
return rep.hash_function();
- }
- key_equal key_eq() const {
- return rep.key_eq();
- }
+ }
+ key_equal key_eq() const {
+ return rep.key_eq();
+ }
public:
THashMultiMap()
- : rep(0, hasher(), key_equal())
- {
- }
- template <typename TAllocParam>
+ : rep(0, hasher(), key_equal())
+ {
+ }
+ template <typename TAllocParam>
explicit THashMultiMap(TAllocParam* allocParam)
- : rep(0, hasher(), key_equal(), allocParam)
- {
- }
+ : rep(0, hasher(), key_equal(), allocParam)
+ {
+ }
explicit THashMultiMap(size_type n)
- : rep(n, hasher(), key_equal())
- {
- }
+ : rep(n, hasher(), key_equal())
+ {
+ }
THashMultiMap(size_type n, const hasher& hf)
- : rep(n, hf, key_equal())
- {
- }
+ : rep(n, hf, key_equal())
+ {
+ }
THashMultiMap(size_type n, const hasher& hf, const key_equal& eql)
- : rep(n, hf, eql)
- {
- }
+ : rep(n, hf, eql)
+ {
+ }
- template <class InputIterator>
+ template <class InputIterator>
THashMultiMap(InputIterator f, InputIterator l)
- : rep(0, hasher(), key_equal())
- {
- rep.insert_equal(f, l);
- }
- template <class InputIterator>
+ : rep(0, hasher(), key_equal())
+ {
+ rep.insert_equal(f, l);
+ }
+ template <class InputIterator>
THashMultiMap(InputIterator f, InputIterator l, size_type n)
- : rep(n, hasher(), key_equal())
- {
- rep.insert_equal(f, l);
- }
- template <class InputIterator>
+ : rep(n, hasher(), key_equal())
+ {
+ rep.insert_equal(f, l);
+ }
+ template <class InputIterator>
THashMultiMap(InputIterator f, InputIterator l, size_type n, const hasher& hf)
- : rep(n, hf, key_equal())
- {
- rep.insert_equal(f, l);
- }
- template <class InputIterator>
+ : rep(n, hf, key_equal())
+ {
+ rep.insert_equal(f, l);
+ }
+ template <class InputIterator>
THashMultiMap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const key_equal& eql)
- : rep(n, hf, eql)
- {
- rep.insert_equal(f, l);
- }
+ : rep(n, hf, eql)
+ {
+ rep.insert_equal(f, l);
+ }
THashMultiMap(std::initializer_list<std::pair<Key, T>> list)
: rep(list.size(), hasher(), key_equal())
@@ -1843,47 +1843,47 @@ public:
// THashMultiMap has implicit copy/move constructors and copy-/move-assignment operators
// because its implementation is backed by THashTable.
- // See hash_ut.cpp
+ // See hash_ut.cpp
public:
- size_type size() const {
- return rep.size();
- }
+ size_type size() const {
+ return rep.size();
+ }
yssize_t ysize() const {
return (yssize_t)rep.size();
- }
- size_type max_size() const {
- return rep.max_size();
- }
-
- Y_PURE_FUNCTION bool empty() const {
- return rep.empty();
- }
- explicit operator bool() const noexcept {
- return !empty();
- }
+ }
+ size_type max_size() const {
+ return rep.max_size();
+ }
+
+ Y_PURE_FUNCTION bool empty() const {
+ return rep.empty();
+ }
+ explicit operator bool() const noexcept {
+ return !empty();
+ }
void swap(THashMultiMap& hs) {
- rep.swap(hs.rep);
- }
-
- iterator begin() {
- return rep.begin();
- }
- iterator end() {
- return rep.end();
- }
- const_iterator begin() const {
- return rep.begin();
- }
- const_iterator end() const {
- return rep.end();
- }
- const_iterator cbegin() const {
- return rep.begin();
- }
- const_iterator cend() const {
- return rep.end();
- }
+ rep.swap(hs.rep);
+ }
+
+ iterator begin() {
+ return rep.begin();
+ }
+ iterator end() {
+ return rep.end();
+ }
+ const_iterator begin() const {
+ return rep.begin();
+ }
+ const_iterator end() const {
+ return rep.end();
+ }
+ const_iterator cbegin() const {
+ return rep.begin();
+ }
+ const_iterator cend() const {
+ return rep.end();
+ }
public:
template <class InputIterator>
@@ -1891,18 +1891,18 @@ public:
rep.insert_equal(f, l);
}
- iterator insert(const value_type& obj) {
- return rep.insert_equal(obj);
- }
+ iterator insert(const value_type& obj) {
+ return rep.insert_equal(obj);
+ }
template <typename... Args>
- iterator emplace(Args&&... args) {
+ iterator emplace(Args&&... args) {
return rep.emplace_equal(std::forward<Args>(args)...);
}
- iterator insert_noresize(const value_type& obj) {
+ iterator insert_noresize(const value_type& obj) {
return rep.emplace_equal_noresize(obj);
- }
+ }
template <typename... Args>
iterator emplace_noresize(Args&&... args) {
@@ -1919,15 +1919,15 @@ public:
return rep.emplace_direct(ins, std::forward<Args>(args)...);
}
- template <class TKey>
+ template <class TKey>
const_iterator find(const TKey& key) const {
- return rep.find(key);
- }
+ return rep.find(key);
+ }
- template <class TKey>
+ template <class TKey>
iterator find(const TKey& key) {
- return rep.find(key);
- }
+ return rep.find(key);
+ }
template <class TheKey>
iterator find(const TheKey& key, insert_ctx& ins) {
@@ -1939,39 +1939,39 @@ public:
return rep.find(key) != rep.end();
}
- template <class TKey>
- size_type count(const TKey& key) const {
- return rep.count(key);
- }
-
- template <class TKey>
+ template <class TKey>
+ size_type count(const TKey& key) const {
+ return rep.count(key);
+ }
+
+ template <class TKey>
std::pair<iterator, iterator> equal_range(const TKey& key) {
- return rep.equal_range(key);
- }
-
- template <class TKey>
+ return rep.equal_range(key);
+ }
+
+ template <class TKey>
std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const {
- return rep.equal_range(key);
- }
-
- size_type erase(const key_type& key) {
- return rep.erase(key);
- }
- void erase(iterator it) {
- rep.erase(it);
- }
- void erase(iterator f, iterator l) {
- rep.erase(f, l);
- }
- void clear() {
- rep.clear();
- }
- void clear(size_t downsize_hint) {
- rep.clear(downsize_hint);
- }
- void basic_clear() {
- rep.basic_clear();
- }
+ return rep.equal_range(key);
+ }
+
+ size_type erase(const key_type& key) {
+ return rep.erase(key);
+ }
+ void erase(iterator it) {
+ rep.erase(it);
+ }
+ void erase(iterator f, iterator l) {
+ rep.erase(f, l);
+ }
+ void clear() {
+ rep.clear();
+ }
+ void clear(size_t downsize_hint) {
+ rep.clear(downsize_hint);
+ }
+ void basic_clear() {
+ rep.basic_clear();
+ }
void release_nodes() {
rep.release_nodes();
}
@@ -1985,13 +1985,13 @@ public:
public:
void reserve(size_type hint) {
rep.reserve(hint);
- }
- size_type bucket_count() const {
- return rep.bucket_count();
- }
+ }
+ size_type bucket_count() const {
+ return rep.bucket_count();
+ }
size_type bucket_size(size_type n) const {
return rep.bucket_size(n);
- }
+ }
};
template <class Key, class T, class HF, class EqKey, class Alloc>
@@ -2008,8 +2008,8 @@ inline bool operator==(const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm1, const
TEqualRange eq1 = hm1.equal_range(it->first);
TEqualRange eq2 = hm2.equal_range(it->first);
if (std::distance(eq1.first, eq1.second) != std::distance(eq2.first, eq2.second) ||
- !std::is_permutation(eq1.first, eq1.second, eq2.first))
- {
+ !std::is_permutation(eq1.first, eq1.second, eq2.first))
+ {
return false;
}
it = eq1.second;