catboost 1.25.1 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEPLOYMENT.md +22 -15
- package/README.md +37 -27
- package/binding.gyp +5 -7
- package/build_scripts/bootstrap.js +2 -1
- package/build_scripts/out/build.js +46 -68
- package/build_scripts/out/build_model.js +1 -1
- package/build_scripts/out/{build_ya.js → build_native.js} +1 -1
- package/build_scripts/out/ci.js +5 -5
- package/build_scripts/out/config.js +32 -18
- package/build_scripts/out/install.js +5 -3
- package/build_scripts/out/package_prepublish.js +1 -1
- package/build_scripts/out/packaging.js +1 -19
- package/build_scripts/out/run_tests.js +1 -1
- package/build_scripts/out/test.js +8 -3
- package/config.json +18 -11
- package/inc/catboost/libs/model_interface/c_api.h +349 -3
- package/lib/catboost.d.ts +65 -21
- package/package.json +4 -4
- package/src/api_helpers.cpp +100 -24
- package/src/api_helpers.h +8 -7
- package/src/api_module.cpp +1 -2
- package/src/model.cpp +483 -83
- package/src/model.h +24 -9
- package/inc/contrib/libs/cxxsupp/system_stl/include/stlfwd +0 -14
- package/inc/util/charset/recode_result.h +0 -9
- package/inc/util/charset/unicode_table.h +0 -123
- package/inc/util/charset/unidata.h +0 -421
- package/inc/util/charset/utf8.h +0 -384
- package/inc/util/charset/wide.h +0 -843
- package/inc/util/charset/wide_specific.h +0 -22
- package/inc/util/datetime/base.h +0 -669
- package/inc/util/datetime/constants.h +0 -7
- package/inc/util/datetime/cputimer.h +0 -124
- package/inc/util/datetime/parser.h +0 -292
- package/inc/util/datetime/systime.h +0 -47
- package/inc/util/datetime/uptime.h +0 -8
- package/inc/util/digest/city.h +0 -88
- package/inc/util/digest/fnv.h +0 -73
- package/inc/util/digest/multi.h +0 -14
- package/inc/util/digest/murmur.h +0 -57
- package/inc/util/digest/numeric.h +0 -86
- package/inc/util/digest/sequence.h +0 -48
- package/inc/util/draft/date.h +0 -129
- package/inc/util/draft/datetime.h +0 -184
- package/inc/util/draft/enum.h +0 -136
- package/inc/util/draft/holder_vector.h +0 -102
- package/inc/util/draft/ip.h +0 -131
- package/inc/util/draft/matrix.h +0 -108
- package/inc/util/draft/memory.h +0 -40
- package/inc/util/folder/dirent_win.h +0 -46
- package/inc/util/folder/dirut.h +0 -121
- package/inc/util/folder/filelist.h +0 -81
- package/inc/util/folder/fts.h +0 -108
- package/inc/util/folder/iterator.h +0 -109
- package/inc/util/folder/lstat_win.h +0 -20
- package/inc/util/folder/path.h +0 -225
- package/inc/util/folder/pathsplit.h +0 -113
- package/inc/util/folder/tempdir.h +0 -42
- package/inc/util/generic/adaptor.h +0 -134
- package/inc/util/generic/algorithm.h +0 -765
- package/inc/util/generic/array_ref.h +0 -282
- package/inc/util/generic/array_size.h +0 -24
- package/inc/util/generic/benchmark/vector_count_ctor/f.h +0 -9
- package/inc/util/generic/bitmap.h +0 -1115
- package/inc/util/generic/bitops.h +0 -459
- package/inc/util/generic/bt_exception.h +0 -24
- package/inc/util/generic/buffer.h +0 -232
- package/inc/util/generic/cast.h +0 -176
- package/inc/util/generic/deque.h +0 -24
- package/inc/util/generic/explicit_type.h +0 -42
- package/inc/util/generic/fastqueue.h +0 -55
- package/inc/util/generic/flags.h +0 -244
- package/inc/util/generic/function.h +0 -103
- package/inc/util/generic/fwd.h +0 -171
- package/inc/util/generic/guid.h +0 -61
- package/inc/util/generic/hash.h +0 -2032
- package/inc/util/generic/hash_primes.h +0 -140
- package/inc/util/generic/hash_set.h +0 -490
- package/inc/util/generic/hide_ptr.h +0 -3
- package/inc/util/generic/intrlist.h +0 -876
- package/inc/util/generic/is_in.h +0 -53
- package/inc/util/generic/iterator.h +0 -137
- package/inc/util/generic/iterator_range.h +0 -105
- package/inc/util/generic/lazy_value.h +0 -66
- package/inc/util/generic/list.h +0 -22
- package/inc/util/generic/map.h +0 -44
- package/inc/util/generic/mapfindptr.h +0 -60
- package/inc/util/generic/maybe.h +0 -713
- package/inc/util/generic/maybe_traits.h +0 -164
- package/inc/util/generic/mem_copy.h +0 -55
- package/inc/util/generic/noncopyable.h +0 -38
- package/inc/util/generic/object_counter.h +0 -53
- package/inc/util/generic/ptr.h +0 -1113
- package/inc/util/generic/queue.h +0 -57
- package/inc/util/generic/refcount.h +0 -162
- package/inc/util/generic/reserve.h +0 -11
- package/inc/util/generic/scope.h +0 -65
- package/inc/util/generic/serialized_enum.h +0 -406
- package/inc/util/generic/set.h +0 -42
- package/inc/util/generic/singleton.h +0 -136
- package/inc/util/generic/size_literals.h +0 -65
- package/inc/util/generic/stack.h +0 -18
- package/inc/util/generic/store_policy.h +0 -120
- package/inc/util/generic/strbase.h +0 -612
- package/inc/util/generic/strbuf.h +0 -552
- package/inc/util/generic/strfcpy.h +0 -17
- package/inc/util/generic/string.h +0 -1572
- package/inc/util/generic/string_hash.h +0 -21
- package/inc/util/generic/string_ut.h +0 -1175
- package/inc/util/generic/type_name.h +0 -34
- package/inc/util/generic/typelist.h +0 -114
- package/inc/util/generic/typetraits.h +0 -325
- package/inc/util/generic/utility.h +0 -132
- package/inc/util/generic/va_args.h +0 -400
- package/inc/util/generic/variant.h +0 -631
- package/inc/util/generic/variant_traits.h +0 -171
- package/inc/util/generic/vector.h +0 -119
- package/inc/util/generic/xrange.h +0 -258
- package/inc/util/generic/yexception.h +0 -212
- package/inc/util/generic/yexception_ut.h +0 -14
- package/inc/util/generic/ylimits.h +0 -92
- package/inc/util/generic/ymath.h +0 -206
- package/inc/util/memory/addstorage.h +0 -93
- package/inc/util/memory/alloc.h +0 -27
- package/inc/util/memory/blob.h +0 -296
- package/inc/util/memory/mmapalloc.h +0 -8
- package/inc/util/memory/pool.h +0 -432
- package/inc/util/memory/segmented_string_pool.h +0 -194
- package/inc/util/memory/segpool_alloc.h +0 -118
- package/inc/util/memory/smallobj.h +0 -141
- package/inc/util/memory/tempbuf.h +0 -111
- package/inc/util/network/address.h +0 -136
- package/inc/util/network/endpoint.h +0 -61
- package/inc/util/network/hostip.h +0 -16
- package/inc/util/network/init.h +0 -60
- package/inc/util/network/interface.h +0 -17
- package/inc/util/network/iovec.h +0 -65
- package/inc/util/network/ip.h +0 -116
- package/inc/util/network/nonblock.h +0 -8
- package/inc/util/network/pair.h +0 -9
- package/inc/util/network/poller.h +0 -58
- package/inc/util/network/pollerimpl.h +0 -707
- package/inc/util/network/sock.h +0 -608
- package/inc/util/network/socket.h +0 -421
- package/inc/util/random/common_ops.h +0 -130
- package/inc/util/random/easy.h +0 -47
- package/inc/util/random/entropy.h +0 -21
- package/inc/util/random/fast.h +0 -101
- package/inc/util/random/init_atfork.h +0 -3
- package/inc/util/random/lcg_engine.h +0 -66
- package/inc/util/random/mersenne.h +0 -46
- package/inc/util/random/mersenne32.h +0 -50
- package/inc/util/random/mersenne64.h +0 -50
- package/inc/util/random/normal.h +0 -38
- package/inc/util/random/random.h +0 -30
- package/inc/util/random/shuffle.h +0 -39
- package/inc/util/str_stl.h +0 -266
- package/inc/util/stream/aligned.h +0 -99
- package/inc/util/stream/buffer.h +0 -119
- package/inc/util/stream/buffered.h +0 -225
- package/inc/util/stream/debug.h +0 -53
- package/inc/util/stream/direct_io.h +0 -43
- package/inc/util/stream/file.h +0 -108
- package/inc/util/stream/format.h +0 -444
- package/inc/util/stream/fwd.h +0 -100
- package/inc/util/stream/hex.h +0 -8
- package/inc/util/stream/holder.h +0 -44
- package/inc/util/stream/input.h +0 -273
- package/inc/util/stream/labeled.h +0 -19
- package/inc/util/stream/length.h +0 -100
- package/inc/util/stream/mem.h +0 -255
- package/inc/util/stream/multi.h +0 -32
- package/inc/util/stream/null.h +0 -61
- package/inc/util/stream/output.h +0 -304
- package/inc/util/stream/pipe.h +0 -112
- package/inc/util/stream/printf.h +0 -25
- package/inc/util/stream/str.h +0 -207
- package/inc/util/stream/tee.h +0 -28
- package/inc/util/stream/tempbuf.h +0 -21
- package/inc/util/stream/tokenizer.h +0 -214
- package/inc/util/stream/trace.h +0 -60
- package/inc/util/stream/walk.h +0 -35
- package/inc/util/stream/zerocopy.h +0 -91
- package/inc/util/stream/zerocopy_output.h +0 -57
- package/inc/util/stream/zlib.h +0 -173
- package/inc/util/string/ascii.h +0 -236
- package/inc/util/string/builder.h +0 -39
- package/inc/util/string/cast.h +0 -347
- package/inc/util/string/cstriter.h +0 -14
- package/inc/util/string/escape.h +0 -70
- package/inc/util/string/hex.h +0 -59
- package/inc/util/string/join.h +0 -194
- package/inc/util/string/printf.h +0 -13
- package/inc/util/string/reverse.h +0 -16
- package/inc/util/string/split.h +0 -1080
- package/inc/util/string/strip.h +0 -257
- package/inc/util/string/strspn.h +0 -65
- package/inc/util/string/subst.h +0 -56
- package/inc/util/string/type.h +0 -50
- package/inc/util/string/util.h +0 -195
- package/inc/util/string/vector.h +0 -132
- package/inc/util/system/align.h +0 -50
- package/inc/util/system/atexit.h +0 -22
- package/inc/util/system/atomic.h +0 -51
- package/inc/util/system/atomic_gcc.h +0 -90
- package/inc/util/system/atomic_ops.h +0 -189
- package/inc/util/system/atomic_win.h +0 -114
- package/inc/util/system/backtrace.h +0 -39
- package/inc/util/system/byteorder.h +0 -186
- package/inc/util/system/compat.h +0 -84
- package/inc/util/system/compiler.h +0 -620
- package/inc/util/system/condvar.h +0 -71
- package/inc/util/system/context.h +0 -181
- package/inc/util/system/context_aarch64.h +0 -8
- package/inc/util/system/context_i686.h +0 -9
- package/inc/util/system/context_x86.h +0 -12
- package/inc/util/system/context_x86_64.h +0 -7
- package/inc/util/system/cpu_id.h +0 -159
- package/inc/util/system/daemon.h +0 -28
- package/inc/util/system/datetime.h +0 -98
- package/inc/util/system/defaults.h +0 -149
- package/inc/util/system/demangle.h +0 -5
- package/inc/util/system/demangle_impl.h +0 -23
- package/inc/util/system/direct_io.h +0 -71
- package/inc/util/system/dynlib.h +0 -119
- package/inc/util/system/env.h +0 -32
- package/inc/util/system/error.h +0 -95
- package/inc/util/system/event.h +0 -122
- package/inc/util/system/execpath.h +0 -17
- package/inc/util/system/fasttime.h +0 -6
- package/inc/util/system/fhandle.h +0 -27
- package/inc/util/system/file.h +0 -210
- package/inc/util/system/file_lock.h +0 -34
- package/inc/util/system/filemap.h +0 -383
- package/inc/util/system/flock.h +0 -35
- package/inc/util/system/fs.h +0 -156
- package/inc/util/system/fs_win.h +0 -29
- package/inc/util/system/fstat.h +0 -46
- package/inc/util/system/getpid.h +0 -12
- package/inc/util/system/guard.h +0 -179
- package/inc/util/system/hi_lo.h +0 -139
- package/inc/util/system/hostname.h +0 -10
- package/inc/util/system/hp_timer.h +0 -36
- package/inc/util/system/info.h +0 -12
- package/inc/util/system/interrupt_signals.h +0 -22
- package/inc/util/system/madvise.h +0 -30
- package/inc/util/system/maxlen.h +0 -32
- package/inc/util/system/mem_info.h +0 -18
- package/inc/util/system/mincore.h +0 -38
- package/inc/util/system/mktemp.h +0 -11
- package/inc/util/system/mlock.h +0 -43
- package/inc/util/system/mutex.h +0 -67
- package/inc/util/system/nice.h +0 -3
- package/inc/util/system/pipe.h +0 -90
- package/inc/util/system/platform.h +0 -246
- package/inc/util/system/progname.h +0 -13
- package/inc/util/system/protect.h +0 -25
- package/inc/util/system/rusage.h +0 -26
- package/inc/util/system/rwlock.h +0 -78
- package/inc/util/system/sanitizers.h +0 -122
- package/inc/util/system/sem.h +0 -41
- package/inc/util/system/shellcommand.h +0 -472
- package/inc/util/system/shmat.h +0 -32
- package/inc/util/system/sigset.h +0 -78
- package/inc/util/system/spin_wait.h +0 -10
- package/inc/util/system/spinlock.h +0 -121
- package/inc/util/system/src_location.h +0 -25
- package/inc/util/system/src_root.h +0 -68
- package/inc/util/system/sys_alloc.h +0 -43
- package/inc/util/system/sysstat.h +0 -52
- package/inc/util/system/tempfile.h +0 -34
- package/inc/util/system/thread.h +0 -167
- package/inc/util/system/tls.h +0 -307
- package/inc/util/system/types.h +0 -119
- package/inc/util/system/unaligned_mem.h +0 -67
- package/inc/util/system/user.h +0 -5
- package/inc/util/system/utime.h +0 -6
- package/inc/util/system/valgrind.h +0 -48
- package/inc/util/system/winint.h +0 -43
- package/inc/util/system/yassert.h +0 -121
- package/inc/util/system/yield.h +0 -4
- package/inc/util/thread/factory.h +0 -65
- package/inc/util/thread/fwd.h +0 -30
- package/inc/util/thread/lfqueue.h +0 -406
- package/inc/util/thread/lfstack.h +0 -188
- package/inc/util/thread/pool.h +0 -388
- package/inc/util/thread/singleton.h +0 -42
- package/inc/util/ysafeptr.h +0 -427
- package/inc/util/ysaveload.h +0 -700
package/inc/util/generic/hash.h
DELETED
|
@@ -1,2032 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "fwd.h"
|
|
4
|
-
#include "mapfindptr.h"
|
|
5
|
-
|
|
6
|
-
#include <util/memory/alloc.h>
|
|
7
|
-
#include <util/system/yassert.h>
|
|
8
|
-
#include <util/str_stl.h>
|
|
9
|
-
#include "yexception.h"
|
|
10
|
-
#include "typetraits.h"
|
|
11
|
-
#include "utility.h"
|
|
12
|
-
#include "type_name.h"
|
|
13
|
-
|
|
14
|
-
#include <algorithm>
|
|
15
|
-
#include <initializer_list>
|
|
16
|
-
#include <memory>
|
|
17
|
-
#include <tuple>
|
|
18
|
-
#include <utility>
|
|
19
|
-
|
|
20
|
-
#include <cstdlib>
|
|
21
|
-
|
|
22
|
-
#include "hash_primes.h"
|
|
23
|
-
|
|
24
|
-
struct TSelect1st {
|
|
25
|
-
template <class TPair>
|
|
26
|
-
inline const typename TPair::first_type& operator()(const TPair& x) const {
|
|
27
|
-
return x.first;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
template <class Value>
|
|
32
|
-
struct __yhashtable_node {
|
|
33
|
-
/** If the first bit is not set, then this is a pointer to the next node in
|
|
34
|
-
* the list of nodes for the current bucket. Otherwise this is a pointer of
|
|
35
|
-
* type __yhashtable_node**, pointing back into the buckets array.
|
|
36
|
-
*
|
|
37
|
-
* This trick makes it possible to use only one node pointer in a hash table
|
|
38
|
-
* iterator. */
|
|
39
|
-
__yhashtable_node* next;
|
|
40
|
-
|
|
41
|
-
/** Value stored in a node. */
|
|
42
|
-
Value val;
|
|
43
|
-
|
|
44
|
-
__yhashtable_node& operator=(const __yhashtable_node&) = delete;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
template <class Value, class Key, class HashFcn,
|
|
48
|
-
class ExtractKey, class EqualKey, class Alloc>
|
|
49
|
-
class THashTable;
|
|
50
|
-
|
|
51
|
-
template <class Key, class T, class HashFcn,
|
|
52
|
-
class EqualKey, typename size_type_f>
|
|
53
|
-
class sthash;
|
|
54
|
-
|
|
55
|
-
template <class Value>
|
|
56
|
-
struct __yhashtable_iterator;
|
|
57
|
-
|
|
58
|
-
template <class Value>
|
|
59
|
-
struct __yhashtable_const_iterator;
|
|
60
|
-
|
|
61
|
-
template <class Value>
|
|
62
|
-
struct __yhashtable_iterator {
|
|
63
|
-
using iterator = __yhashtable_iterator<Value>;
|
|
64
|
-
using const_iterator = __yhashtable_const_iterator<Value>;
|
|
65
|
-
using node = __yhashtable_node<Value>;
|
|
66
|
-
|
|
67
|
-
using iterator_category = std::forward_iterator_tag;
|
|
68
|
-
using value_type = Value;
|
|
69
|
-
using difference_type = ptrdiff_t;
|
|
70
|
-
using size_type = size_t;
|
|
71
|
-
using reference = Value&;
|
|
72
|
-
using pointer = Value*;
|
|
73
|
-
|
|
74
|
-
node* cur;
|
|
75
|
-
|
|
76
|
-
explicit __yhashtable_iterator(node* n)
|
|
77
|
-
: cur(n)
|
|
78
|
-
{
|
|
79
|
-
} /*y*/
|
|
80
|
-
__yhashtable_iterator() {
|
|
81
|
-
}
|
|
82
|
-
reference operator*() const {
|
|
83
|
-
return cur->val;
|
|
84
|
-
}
|
|
85
|
-
pointer operator->() const {
|
|
86
|
-
return &(operator*());
|
|
87
|
-
}
|
|
88
|
-
iterator& operator++();
|
|
89
|
-
iterator operator++(int);
|
|
90
|
-
bool operator==(const iterator& it) const {
|
|
91
|
-
return cur == it.cur;
|
|
92
|
-
}
|
|
93
|
-
bool operator!=(const iterator& it) const {
|
|
94
|
-
return cur != it.cur;
|
|
95
|
-
}
|
|
96
|
-
bool IsEnd() const {
|
|
97
|
-
return !cur;
|
|
98
|
-
}
|
|
99
|
-
Y_FORCE_INLINE explicit operator bool() const noexcept {
|
|
100
|
-
return cur != nullptr;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
template <class Value>
|
|
105
|
-
struct __yhashtable_const_iterator {
|
|
106
|
-
using iterator = __yhashtable_iterator<Value>;
|
|
107
|
-
using const_iterator = __yhashtable_const_iterator<Value>;
|
|
108
|
-
using node = __yhashtable_node<Value>;
|
|
109
|
-
|
|
110
|
-
using iterator_category = std::forward_iterator_tag;
|
|
111
|
-
using value_type = Value;
|
|
112
|
-
using difference_type = ptrdiff_t;
|
|
113
|
-
using size_type = size_t;
|
|
114
|
-
using reference = const Value&;
|
|
115
|
-
using pointer = const Value*;
|
|
116
|
-
|
|
117
|
-
const node* cur;
|
|
118
|
-
|
|
119
|
-
explicit __yhashtable_const_iterator(const node* n)
|
|
120
|
-
: cur(n)
|
|
121
|
-
{
|
|
122
|
-
}
|
|
123
|
-
__yhashtable_const_iterator() {
|
|
124
|
-
}
|
|
125
|
-
__yhashtable_const_iterator(const iterator& it)
|
|
126
|
-
: cur(it.cur)
|
|
127
|
-
{
|
|
128
|
-
}
|
|
129
|
-
reference operator*() const {
|
|
130
|
-
return cur->val;
|
|
131
|
-
}
|
|
132
|
-
pointer operator->() const {
|
|
133
|
-
return &(operator*());
|
|
134
|
-
}
|
|
135
|
-
const_iterator& operator++();
|
|
136
|
-
const_iterator operator++(int);
|
|
137
|
-
bool operator==(const const_iterator& it) const {
|
|
138
|
-
return cur == it.cur;
|
|
139
|
-
}
|
|
140
|
-
bool operator!=(const const_iterator& it) const {
|
|
141
|
-
return cur != it.cur;
|
|
142
|
-
}
|
|
143
|
-
bool IsEnd() const {
|
|
144
|
-
return !cur;
|
|
145
|
-
}
|
|
146
|
-
Y_FORCE_INLINE explicit operator bool() const noexcept {
|
|
147
|
-
return cur != nullptr;
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* This class saves some space in allocator-based containers for the most common
|
|
153
|
-
* use case of empty allocators. This is achieved thanks to the application of
|
|
154
|
-
* empty base class optimization (aka EBCO).
|
|
155
|
-
*/
|
|
156
|
-
template <class Alloc>
|
|
157
|
-
class _allocator_base: private Alloc {
|
|
158
|
-
public:
|
|
159
|
-
_allocator_base(const Alloc& other)
|
|
160
|
-
: Alloc(other)
|
|
161
|
-
{
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
Alloc& _get_alloc() {
|
|
165
|
-
return static_cast<Alloc&>(*this);
|
|
166
|
-
}
|
|
167
|
-
const Alloc& _get_alloc() const {
|
|
168
|
-
return static_cast<const Alloc&>(*this);
|
|
169
|
-
}
|
|
170
|
-
void _set_alloc(const Alloc& allocator) {
|
|
171
|
-
_get_alloc() = allocator;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
void swap(_allocator_base& other) {
|
|
175
|
-
DoSwap(_get_alloc(), other._get_alloc());
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Wrapper for an array of THashTable buckets.
|
|
181
|
-
*
|
|
182
|
-
* Is better than vector for this particular use case. Main differences:
|
|
183
|
-
* - Occupies one less word on stack.
|
|
184
|
-
* - Doesn't even try to initialize its elements. It is THashTable's responsibility.
|
|
185
|
-
* - Presents a better interface in relation to THashTable's marker element trick.
|
|
186
|
-
*
|
|
187
|
-
* Internally this class is just a pointer-size pair, and the data on the heap
|
|
188
|
-
* has the following structure:
|
|
189
|
-
*
|
|
190
|
-
* +----------+----------------------+----------+-------------------------+
|
|
191
|
-
* | raw_size | elements ... | marker | unused space [optional] |
|
|
192
|
-
* +----------+----------------------+----------+-------------------------+
|
|
193
|
-
* ^ ^
|
|
194
|
-
* | |
|
|
195
|
-
* Data points here end() points here
|
|
196
|
-
*
|
|
197
|
-
* `raw_size` stores the size of the allocated memory block. It is used to
|
|
198
|
-
* support resizing without reallocation.
|
|
199
|
-
*
|
|
200
|
-
* `marker` is a special marker element that is set by the THashTable that is
|
|
201
|
-
* then used in iterator implementation to know when the end is reached.
|
|
202
|
-
*
|
|
203
|
-
* Unused space at the end of the memory block may not be present.
|
|
204
|
-
*/
|
|
205
|
-
template <class T, class Alloc>
|
|
206
|
-
class _yhashtable_buckets: private _allocator_base<Alloc> {
|
|
207
|
-
using base_type = _allocator_base<Alloc>;
|
|
208
|
-
|
|
209
|
-
static_assert(sizeof(T) == sizeof(size_t), "T is expected to be the same size as size_t.");
|
|
210
|
-
|
|
211
|
-
public:
|
|
212
|
-
using allocator_type = Alloc;
|
|
213
|
-
using value_type = T;
|
|
214
|
-
using pointer = T*;
|
|
215
|
-
using const_pointer = const T*;
|
|
216
|
-
using reference = T&;
|
|
217
|
-
using const_reference = const T&;
|
|
218
|
-
using iterator = pointer;
|
|
219
|
-
using const_iterator = const_pointer;
|
|
220
|
-
using size_type = size_t;
|
|
221
|
-
using difference_type = ptrdiff_t;
|
|
222
|
-
using TBucketDivisor = ::NPrivate::THashDivisor;
|
|
223
|
-
|
|
224
|
-
_yhashtable_buckets(const Alloc& other)
|
|
225
|
-
: base_type(other)
|
|
226
|
-
, Data(nullptr)
|
|
227
|
-
, Size()
|
|
228
|
-
{
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
~_yhashtable_buckets() {
|
|
232
|
-
Y_ASSERT(!Data);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
void initialize_dynamic(TBucketDivisor size) {
|
|
236
|
-
Y_ASSERT(!Data);
|
|
237
|
-
|
|
238
|
-
Data = this->_get_alloc().allocate(size() + 2) + 1;
|
|
239
|
-
Size = size;
|
|
240
|
-
|
|
241
|
-
*reinterpret_cast<size_type*>(Data - 1) = size() + 2;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
void deinitialize_dynamic() {
|
|
245
|
-
Y_ASSERT(Data);
|
|
246
|
-
|
|
247
|
-
this->_get_alloc().deallocate(Data - 1, *reinterpret_cast<size_type*>(Data - 1));
|
|
248
|
-
Data = pointer();
|
|
249
|
-
Size = TBucketDivisor();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
void initialize_static(pointer data, TBucketDivisor size) {
|
|
253
|
-
Y_ASSERT(!Data && data && size() >= 1);
|
|
254
|
-
|
|
255
|
-
Data = data;
|
|
256
|
-
Size = size;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
void deinitialize_static() {
|
|
260
|
-
Y_ASSERT(Data);
|
|
261
|
-
|
|
262
|
-
Data = pointer();
|
|
263
|
-
Size = TBucketDivisor();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
void resize_noallocate(TBucketDivisor size) {
|
|
267
|
-
Y_ASSERT(size() <= capacity());
|
|
268
|
-
|
|
269
|
-
Size = size;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
iterator begin() {
|
|
273
|
-
return Data;
|
|
274
|
-
}
|
|
275
|
-
const_iterator begin() const {
|
|
276
|
-
return Data;
|
|
277
|
-
}
|
|
278
|
-
iterator end() {
|
|
279
|
-
return Data + Size();
|
|
280
|
-
}
|
|
281
|
-
const_iterator end() const {
|
|
282
|
-
return Data + Size();
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
pointer data() {
|
|
286
|
-
return Data;
|
|
287
|
-
}
|
|
288
|
-
const_pointer data() const {
|
|
289
|
-
return Data;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
size_type size() const {
|
|
293
|
-
return Size();
|
|
294
|
-
}
|
|
295
|
-
size_type capacity() const {
|
|
296
|
-
return *reinterpret_cast<size_type*>(Data - 1);
|
|
297
|
-
}
|
|
298
|
-
TBucketDivisor ExtSize() const {
|
|
299
|
-
return Size;
|
|
300
|
-
}
|
|
301
|
-
int BucketDivisorHint() const {
|
|
302
|
-
return +Size.Hint;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
allocator_type get_allocator() const {
|
|
306
|
-
return this->_get_alloc();
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const_reference operator[](size_type index) const {
|
|
310
|
-
Y_ASSERT(index <= Size());
|
|
311
|
-
|
|
312
|
-
return *(Data + index);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
reference operator[](size_type index) {
|
|
316
|
-
Y_ASSERT(index <= Size());
|
|
317
|
-
|
|
318
|
-
return *(Data + index);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
void swap(_yhashtable_buckets& other) {
|
|
322
|
-
base_type::swap(other);
|
|
323
|
-
DoSwap(Data, other.Data);
|
|
324
|
-
DoSwap(Size, other.Size);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
private:
|
|
328
|
-
/** Pointer to the first element of the buckets array. */
|
|
329
|
-
pointer Data;
|
|
330
|
-
|
|
331
|
-
/** Size of the buckets array. Doesn't take the marker element at the end into account. */
|
|
332
|
-
TBucketDivisor Size;
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* This class saves one word in THashTable for the most common use case of empty
|
|
337
|
-
* functors. The exact implementation picks a specialization with storage allocated
|
|
338
|
-
* for the functors if those are non-empty, and another specialization that creates
|
|
339
|
-
* functors on the fly if they are empty. It is expected that empty functors have
|
|
340
|
-
* trivial constructors.
|
|
341
|
-
*
|
|
342
|
-
* Note that this is basically the only way to do it portably. Another option is
|
|
343
|
-
* multiple inheritance from empty functors, but MSVC's empty base class
|
|
344
|
-
* optimization chokes up on multiple empty bases, and we're already using
|
|
345
|
-
* EBCO in _allocator_base.
|
|
346
|
-
*
|
|
347
|
-
* Note that there are no specializations for the case when only one or two
|
|
348
|
-
* of the functors are empty as this is a case that's just way too rare.
|
|
349
|
-
*/
|
|
350
|
-
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>
|
|
351
|
-
class _yhashtable_base: public _allocator_base<Alloc> {
|
|
352
|
-
using base_type = _allocator_base<Alloc>;
|
|
353
|
-
|
|
354
|
-
public:
|
|
355
|
-
_yhashtable_base(const HashFcn& hash, const ExtractKey& extract, const EqualKey& equals, const Alloc& alloc)
|
|
356
|
-
: base_type(alloc)
|
|
357
|
-
, hash_(hash)
|
|
358
|
-
, extract_(extract)
|
|
359
|
-
, equals_(equals)
|
|
360
|
-
{
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const EqualKey& _get_key_eq() const {
|
|
364
|
-
return equals_;
|
|
365
|
-
}
|
|
366
|
-
EqualKey& _get_key_eq() {
|
|
367
|
-
return equals_;
|
|
368
|
-
}
|
|
369
|
-
void _set_key_eq(const EqualKey& equals) {
|
|
370
|
-
this->equals_ = equals;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const ExtractKey& _get_key_extract() const {
|
|
374
|
-
return extract_;
|
|
375
|
-
}
|
|
376
|
-
ExtractKey& _get_key_extract() {
|
|
377
|
-
return extract_;
|
|
378
|
-
}
|
|
379
|
-
void _set_key_extract(const ExtractKey& extract) {
|
|
380
|
-
this->extract_ = extract;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const HashFcn& _get_hash_fun() const {
|
|
384
|
-
return hash_;
|
|
385
|
-
}
|
|
386
|
-
HashFcn& _get_hash_fun() {
|
|
387
|
-
return hash_;
|
|
388
|
-
}
|
|
389
|
-
void _set_hash_fun(const HashFcn& hash) {
|
|
390
|
-
this->hash_ = hash;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
void swap(_yhashtable_base& other) {
|
|
394
|
-
base_type::swap(other);
|
|
395
|
-
DoSwap(equals_, other.equals_);
|
|
396
|
-
DoSwap(extract_, other.extract_);
|
|
397
|
-
DoSwap(hash_, other.hash_);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
private:
|
|
401
|
-
HashFcn hash_;
|
|
402
|
-
ExtractKey extract_;
|
|
403
|
-
EqualKey equals_;
|
|
404
|
-
};
|
|
405
|
-
|
|
406
|
-
template <class HashFcn, class ExtractKey, class EqualKey, class Alloc>
|
|
407
|
-
class _yhashtable_base<HashFcn, ExtractKey, EqualKey, Alloc, true>: public _allocator_base<Alloc> {
|
|
408
|
-
using base_type = _allocator_base<Alloc>;
|
|
409
|
-
|
|
410
|
-
public:
|
|
411
|
-
_yhashtable_base(const HashFcn&, const ExtractKey&, const EqualKey&, const Alloc& alloc)
|
|
412
|
-
: base_type(alloc)
|
|
413
|
-
{
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
EqualKey _get_key_eq() const {
|
|
417
|
-
return EqualKey();
|
|
418
|
-
}
|
|
419
|
-
void _set_key_eq(const EqualKey&) {
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
ExtractKey _get_key_extract() const {
|
|
423
|
-
return ExtractKey();
|
|
424
|
-
}
|
|
425
|
-
void _set_key_extract(const ExtractKey&) {
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
HashFcn _get_hash_fun() const {
|
|
429
|
-
return HashFcn();
|
|
430
|
-
}
|
|
431
|
-
void _set_hash_fun(const HashFcn&) {
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
void swap(_yhashtable_base& other) {
|
|
435
|
-
base_type::swap(other);
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
|
|
439
|
-
template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
|
|
440
|
-
struct _yhashtable_traits {
|
|
441
|
-
using node = __yhashtable_node<Value>;
|
|
442
|
-
|
|
443
|
-
using node_allocator_type = TReboundAllocator<Alloc, node>;
|
|
444
|
-
using nodep_allocator_type = TReboundAllocator<Alloc, node*>;
|
|
445
|
-
|
|
446
|
-
using base_type = _yhashtable_base<HashFcn, ExtractKey, EqualKey, node_allocator_type>;
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
extern const void* const _yhashtable_empty_data[];
|
|
450
|
-
|
|
451
|
-
template <class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
|
|
452
|
-
class THashTable: private _yhashtable_traits<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>::base_type {
|
|
453
|
-
using traits_type = _yhashtable_traits<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
|
|
454
|
-
using base_type = typename traits_type::base_type;
|
|
455
|
-
using node = typename traits_type::node;
|
|
456
|
-
using nodep_allocator_type = typename traits_type::nodep_allocator_type;
|
|
457
|
-
using buckets_type = _yhashtable_buckets<node*, nodep_allocator_type>;
|
|
458
|
-
using TBucketDivisor = ::NPrivate::THashDivisor;
|
|
459
|
-
|
|
460
|
-
public:
|
|
461
|
-
using key_type = Key;
|
|
462
|
-
using value_type = Value;
|
|
463
|
-
using hasher = HashFcn;
|
|
464
|
-
using key_equal = EqualKey;
|
|
465
|
-
using key_extract = ExtractKey;
|
|
466
|
-
using allocator_type = Alloc;
|
|
467
|
-
using node_allocator_type = typename traits_type::node_allocator_type;
|
|
468
|
-
|
|
469
|
-
using size_type = size_t;
|
|
470
|
-
using difference_type = ptrdiff_t;
|
|
471
|
-
using pointer = value_type*;
|
|
472
|
-
using const_pointer = const value_type*;
|
|
473
|
-
using reference = value_type&;
|
|
474
|
-
using const_reference = const value_type&;
|
|
475
|
-
|
|
476
|
-
node_allocator_type& GetNodeAllocator() {
|
|
477
|
-
return this->_get_alloc();
|
|
478
|
-
}
|
|
479
|
-
const node_allocator_type& GetNodeAllocator() const {
|
|
480
|
-
return this->_get_alloc();
|
|
481
|
-
}
|
|
482
|
-
key_equal key_eq() const {
|
|
483
|
-
return this->_get_key_eq();
|
|
484
|
-
}
|
|
485
|
-
hasher hash_function() const {
|
|
486
|
-
return this->_get_hash_fun();
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
private:
|
|
490
|
-
template <class KeyL, class KeyR>
|
|
491
|
-
bool equals(const KeyL& l, const KeyR& r) const {
|
|
492
|
-
return this->_get_key_eq()(l, r);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/* This method is templated to postpone instantiation of key extraction functor. */
|
|
496
|
-
template <class ValueL>
|
|
497
|
-
auto get_key(const ValueL& value) const -> decltype(ExtractKey()(value)) {
|
|
498
|
-
return this->_get_key_extract()(value);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
node* get_node() {
|
|
502
|
-
node* result = this->_get_alloc().allocate(1);
|
|
503
|
-
Y_ASSERT((reinterpret_cast<uintptr_t>(result) & 1) == 0); /* We're using the last bit of the node pointer. */
|
|
504
|
-
return result;
|
|
505
|
-
}
|
|
506
|
-
void put_node(node* p) {
|
|
507
|
-
this->_get_alloc().deallocate(p, 1);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
buckets_type buckets;
|
|
511
|
-
size_type num_elements;
|
|
512
|
-
|
|
513
|
-
public:
|
|
514
|
-
using iterator = __yhashtable_iterator<Value>;
|
|
515
|
-
using const_iterator = __yhashtable_const_iterator<Value>;
|
|
516
|
-
using insert_ctx = node**;
|
|
517
|
-
|
|
518
|
-
friend struct __yhashtable_iterator<Value>;
|
|
519
|
-
friend struct __yhashtable_const_iterator<Value>;
|
|
520
|
-
|
|
521
|
-
public:
|
|
522
|
-
THashTable()
|
|
523
|
-
: base_type(HashFcn(), ExtractKey(), EqualKey(), node_allocator_type())
|
|
524
|
-
, buckets(nodep_allocator_type())
|
|
525
|
-
, num_elements(0)
|
|
526
|
-
{
|
|
527
|
-
initialize_buckets(buckets, 0);
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
THashTable(size_type n, const HashFcn& hf, const EqualKey& eql, const ExtractKey& ext)
|
|
531
|
-
: base_type(hf, ext, eql, node_allocator_type())
|
|
532
|
-
, buckets(nodep_allocator_type())
|
|
533
|
-
, num_elements(0)
|
|
534
|
-
{
|
|
535
|
-
initialize_buckets(buckets, n);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
THashTable(size_type n, const HashFcn& hf, const EqualKey& eql)
|
|
539
|
-
: base_type(hf, ExtractKey(), eql, node_allocator_type())
|
|
540
|
-
, buckets(nodep_allocator_type())
|
|
541
|
-
, num_elements(0)
|
|
542
|
-
{
|
|
543
|
-
initialize_buckets(buckets, n);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
template <class TAllocParam>
|
|
547
|
-
THashTable(size_type n, const HashFcn& hf, const EqualKey& eql, TAllocParam* allocParam)
|
|
548
|
-
: base_type(hf, ExtractKey(), eql, allocParam)
|
|
549
|
-
, buckets(allocParam)
|
|
550
|
-
, num_elements(0)
|
|
551
|
-
{
|
|
552
|
-
initialize_buckets(buckets, n);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
THashTable(const THashTable& ht)
|
|
556
|
-
: base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
|
|
557
|
-
, buckets(ht.buckets.get_allocator())
|
|
558
|
-
, num_elements(0)
|
|
559
|
-
{
|
|
560
|
-
if (ht.empty()) {
|
|
561
|
-
initialize_buckets(buckets, 0);
|
|
562
|
-
} else {
|
|
563
|
-
initialize_buckets_dynamic(buckets, ht.buckets.ExtSize());
|
|
564
|
-
copy_from_dynamic(ht);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
THashTable(THashTable&& ht) noexcept
|
|
569
|
-
: base_type(ht._get_hash_fun(), ht._get_key_extract(), ht._get_key_eq(), ht._get_alloc())
|
|
570
|
-
, buckets(ht.buckets.get_allocator())
|
|
571
|
-
, num_elements(0)
|
|
572
|
-
{
|
|
573
|
-
initialize_buckets(buckets, 0);
|
|
574
|
-
this->swap(ht);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
THashTable& operator=(const THashTable& ht) {
|
|
578
|
-
if (&ht != this) {
|
|
579
|
-
basic_clear();
|
|
580
|
-
this->_set_hash_fun(ht._get_hash_fun());
|
|
581
|
-
this->_set_key_eq(ht._get_key_eq());
|
|
582
|
-
this->_set_key_extract(ht._get_key_extract());
|
|
583
|
-
/* We don't copy allocator for a reason. */
|
|
584
|
-
|
|
585
|
-
if (ht.empty()) {
|
|
586
|
-
/* Some of the old code in Arcadia works around the behavior in
|
|
587
|
-
* clear() by invoking operator= with empty hash as an argument.
|
|
588
|
-
* It's expected that this will deallocate the buckets array, so
|
|
589
|
-
* this is what we have to do here. */
|
|
590
|
-
deinitialize_buckets(buckets);
|
|
591
|
-
initialize_buckets(buckets, 0);
|
|
592
|
-
} else {
|
|
593
|
-
if (buckets.capacity() > ht.buckets.size()) {
|
|
594
|
-
buckets.resize_noallocate(ht.buckets.ExtSize());
|
|
595
|
-
} else {
|
|
596
|
-
deinitialize_buckets(buckets);
|
|
597
|
-
initialize_buckets_dynamic(buckets, ht.buckets.ExtSize());
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
copy_from_dynamic(ht);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
return *this;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
THashTable& operator=(THashTable&& ht) noexcept {
|
|
607
|
-
basic_clear();
|
|
608
|
-
swap(ht);
|
|
609
|
-
|
|
610
|
-
return *this;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
~THashTable() {
|
|
614
|
-
basic_clear();
|
|
615
|
-
deinitialize_buckets(buckets);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
size_type size() const noexcept {
|
|
619
|
-
return num_elements;
|
|
620
|
-
}
|
|
621
|
-
size_type max_size() const noexcept {
|
|
622
|
-
return size_type(-1);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
Y_PURE_FUNCTION
|
|
626
|
-
bool empty() const noexcept {
|
|
627
|
-
return size() == 0;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
void swap(THashTable& ht) {
|
|
631
|
-
base_type::swap(ht);
|
|
632
|
-
buckets.swap(ht.buckets);
|
|
633
|
-
DoSwap(num_elements, ht.num_elements);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
iterator begin() {
|
|
637
|
-
for (size_type n = 0; n < buckets.size(); ++n) /*y*/
|
|
638
|
-
if (buckets[n])
|
|
639
|
-
return iterator(buckets[n]); /*y*/
|
|
640
|
-
return end();
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
iterator end() {
|
|
644
|
-
return iterator(nullptr);
|
|
645
|
-
} /*y*/
|
|
646
|
-
|
|
647
|
-
const_iterator begin() const {
|
|
648
|
-
for (size_type n = 0; n < buckets.size(); ++n) /*y*/
|
|
649
|
-
if (buckets[n])
|
|
650
|
-
return const_iterator(buckets[n]); /*y*/
|
|
651
|
-
return end();
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
const_iterator end() const {
|
|
655
|
-
return const_iterator(nullptr);
|
|
656
|
-
} /*y*/
|
|
657
|
-
|
|
658
|
-
public:
|
|
659
|
-
size_type bucket_count() const {
|
|
660
|
-
return buckets.size();
|
|
661
|
-
} /*y*/
|
|
662
|
-
|
|
663
|
-
size_type bucket_size(size_type bucket) const {
|
|
664
|
-
size_type result = 0;
|
|
665
|
-
if (const node* cur = buckets[bucket])
|
|
666
|
-
for (; !((uintptr_t)cur & 1); cur = cur->next)
|
|
667
|
-
result += 1;
|
|
668
|
-
return result;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
template <class OtherValue>
|
|
672
|
-
std::pair<iterator, bool> insert_unique(const OtherValue& obj) {
|
|
673
|
-
reserve(num_elements + 1);
|
|
674
|
-
return insert_unique_noresize(obj);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
template <class OtherValue>
|
|
678
|
-
iterator insert_equal(const OtherValue& obj) {
|
|
679
|
-
reserve(num_elements + 1);
|
|
680
|
-
return emplace_equal_noresize(obj);
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
template <typename... Args>
|
|
684
|
-
iterator emplace_equal(Args&&... args) {
|
|
685
|
-
reserve(num_elements + 1);
|
|
686
|
-
return emplace_equal_noresize(std::forward<Args>(args)...);
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
template <class OtherValue>
|
|
690
|
-
iterator insert_direct(const OtherValue& obj, insert_ctx ins) {
|
|
691
|
-
return emplace_direct(ins, obj);
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
template <typename... Args>
|
|
695
|
-
iterator emplace_direct(insert_ctx ins, Args&&... args) {
|
|
696
|
-
bool resized = reserve(num_elements + 1);
|
|
697
|
-
node* tmp = new_node(std::forward<Args>(args)...);
|
|
698
|
-
if (resized) {
|
|
699
|
-
find_i(get_key(tmp->val), ins);
|
|
700
|
-
}
|
|
701
|
-
tmp->next = *ins ? *ins : (node*)((uintptr_t)(ins + 1) | 1);
|
|
702
|
-
*ins = tmp;
|
|
703
|
-
++num_elements;
|
|
704
|
-
return iterator(tmp);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
template <typename... Args>
|
|
708
|
-
std::pair<iterator, bool> emplace_unique(Args&&... args) {
|
|
709
|
-
reserve(num_elements + 1);
|
|
710
|
-
return emplace_unique_noresize(std::forward<Args>(args)...);
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
template <typename... Args>
|
|
714
|
-
std::pair<iterator, bool> emplace_unique_noresize(Args&&... args);
|
|
715
|
-
|
|
716
|
-
template <class OtherValue>
|
|
717
|
-
std::pair<iterator, bool> insert_unique_noresize(const OtherValue& obj);
|
|
718
|
-
|
|
719
|
-
template <typename... Args>
|
|
720
|
-
iterator emplace_equal_noresize(Args&&... args);
|
|
721
|
-
|
|
722
|
-
template <class InputIterator>
|
|
723
|
-
void insert_unique(InputIterator f, InputIterator l) {
|
|
724
|
-
insert_unique(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
template <class InputIterator>
|
|
728
|
-
void insert_equal(InputIterator f, InputIterator l) {
|
|
729
|
-
insert_equal(f, l, typename std::iterator_traits<InputIterator>::iterator_category());
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
template <class InputIterator>
|
|
733
|
-
void insert_unique(InputIterator f, InputIterator l, std::input_iterator_tag) {
|
|
734
|
-
for (; f != l; ++f)
|
|
735
|
-
insert_unique(*f);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
template <class InputIterator>
|
|
739
|
-
void insert_equal(InputIterator f, InputIterator l, std::input_iterator_tag) {
|
|
740
|
-
for (; f != l; ++f)
|
|
741
|
-
insert_equal(*f);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
template <class ForwardIterator>
|
|
745
|
-
void insert_unique(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
|
|
746
|
-
difference_type n = std::distance(f, l);
|
|
747
|
-
|
|
748
|
-
reserve(num_elements + n);
|
|
749
|
-
for (; n > 0; --n, ++f)
|
|
750
|
-
insert_unique_noresize(*f);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
template <class ForwardIterator>
|
|
754
|
-
void insert_equal(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) {
|
|
755
|
-
difference_type n = std::distance(f, l);
|
|
756
|
-
|
|
757
|
-
reserve(num_elements + n);
|
|
758
|
-
for (; n > 0; --n, ++f)
|
|
759
|
-
emplace_equal_noresize(*f);
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
template <class OtherValue>
|
|
763
|
-
reference find_or_insert(const OtherValue& v);
|
|
764
|
-
|
|
765
|
-
template <class OtherKey>
|
|
766
|
-
iterator find(const OtherKey& key) {
|
|
767
|
-
size_type n = bkt_num_key(key);
|
|
768
|
-
node* first;
|
|
769
|
-
for (first = buckets[n];
|
|
770
|
-
first && !equals(get_key(first->val), key);
|
|
771
|
-
first = ((uintptr_t)first->next & 1) ? nullptr : first->next) /*y*/
|
|
772
|
-
{
|
|
773
|
-
}
|
|
774
|
-
return iterator(first); /*y*/
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
template <class OtherKey>
|
|
778
|
-
const_iterator find(const OtherKey& key) const {
|
|
779
|
-
size_type n = bkt_num_key(key);
|
|
780
|
-
const node* first;
|
|
781
|
-
for (first = buckets[n];
|
|
782
|
-
first && !equals(get_key(first->val), key);
|
|
783
|
-
first = ((uintptr_t)first->next & 1) ? nullptr : first->next) /*y*/
|
|
784
|
-
{
|
|
785
|
-
}
|
|
786
|
-
return const_iterator(first); /*y*/
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
template <class OtherKey>
|
|
790
|
-
iterator find_i(const OtherKey& key, insert_ctx& ins);
|
|
791
|
-
|
|
792
|
-
template <class OtherKey>
|
|
793
|
-
size_type count(const OtherKey& key) const {
|
|
794
|
-
const size_type n = bkt_num_key(key);
|
|
795
|
-
size_type result = 0;
|
|
796
|
-
|
|
797
|
-
if (const node* cur = buckets[n])
|
|
798
|
-
for (; !((uintptr_t)cur & 1); cur = cur->next)
|
|
799
|
-
if (equals(get_key(cur->val), key))
|
|
800
|
-
++result;
|
|
801
|
-
return result;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
template <class OtherKey>
|
|
805
|
-
std::pair<iterator, iterator> equal_range(const OtherKey& key);
|
|
806
|
-
|
|
807
|
-
template <class OtherKey>
|
|
808
|
-
std::pair<const_iterator, const_iterator> equal_range(const OtherKey& key) const;
|
|
809
|
-
|
|
810
|
-
template <class OtherKey>
|
|
811
|
-
size_type erase(const OtherKey& key);
|
|
812
|
-
|
|
813
|
-
template <class OtherKey>
|
|
814
|
-
size_type erase_one(const OtherKey& key);
|
|
815
|
-
|
|
816
|
-
// void (instead of iterator) is intended, see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2023.pdf
|
|
817
|
-
void erase(const iterator& it);
|
|
818
|
-
void erase(iterator first, iterator last);
|
|
819
|
-
|
|
820
|
-
void erase(const const_iterator& it);
|
|
821
|
-
void erase(const_iterator first, const_iterator last);
|
|
822
|
-
|
|
823
|
-
bool reserve(size_type num_elements_hint);
|
|
824
|
-
void basic_clear();
|
|
825
|
-
|
|
826
|
-
/**
|
|
827
|
-
* Clears the hashtable without deallocating the nodes.
|
|
828
|
-
*
|
|
829
|
-
* This might come in handy with non-standard allocators, e.g. a pool
|
|
830
|
-
* allocator with a pool that is then cleared manually, thus releasing all
|
|
831
|
-
* the nodes at once.
|
|
832
|
-
*/
|
|
833
|
-
void release_nodes() {
|
|
834
|
-
if (empty())
|
|
835
|
-
return; /* Need this check because empty buckets may reside in read-only memory. */
|
|
836
|
-
|
|
837
|
-
clear_buckets(buckets);
|
|
838
|
-
num_elements = 0;
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
// implemented in save_stl.h
|
|
842
|
-
template <class KeySaver>
|
|
843
|
-
int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const;
|
|
844
|
-
|
|
845
|
-
void clear(size_type downsize) {
|
|
846
|
-
basic_clear();
|
|
847
|
-
|
|
848
|
-
if (downsize < buckets.size()) {
|
|
849
|
-
const TBucketDivisor newSize = HashBucketCountExt(downsize);
|
|
850
|
-
if (newSize() < buckets.size()) {
|
|
851
|
-
Y_ASSERT(newSize() >= 7); /* We cannot downsize static buckets. */
|
|
852
|
-
buckets.resize_noallocate(newSize);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
/**
|
|
858
|
-
* Clears the hashtable and tries to reasonably downsize it. Note that
|
|
859
|
-
* downsizing is mainly for the following use case:
|
|
860
|
-
*
|
|
861
|
-
* THashTable hash;
|
|
862
|
-
* for(...) {
|
|
863
|
-
* if (someCond())
|
|
864
|
-
* hash.clear();
|
|
865
|
-
* hash.insert(...);
|
|
866
|
-
* }
|
|
867
|
-
*
|
|
868
|
-
* Here if at some point `hash` gets really big, then all the following calls
|
|
869
|
-
* to `clear` become really slow as they have to iterate through all the the
|
|
870
|
-
* empty buckets. This is worked around by squeezing the buckets array a little
|
|
871
|
-
* bit with every `clear` call.
|
|
872
|
-
*
|
|
873
|
-
* Alternatively, the user can call `basic_clear`, which doesn't do the
|
|
874
|
-
* downsizing.
|
|
875
|
-
*/
|
|
876
|
-
void clear() {
|
|
877
|
-
if (num_elements)
|
|
878
|
-
clear((num_elements * 2 + buckets.size()) / 3);
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
private:
|
|
882
|
-
static void initialize_buckets(buckets_type& buckets, size_type sizeHint) {
|
|
883
|
-
if (sizeHint == 0) {
|
|
884
|
-
buckets.initialize_static(reinterpret_cast<node**>(const_cast<void**>(_yhashtable_empty_data)) + 1, TBucketDivisor::One());
|
|
885
|
-
} else {
|
|
886
|
-
TBucketDivisor size = HashBucketCountExt(sizeHint);
|
|
887
|
-
Y_ASSERT(size() >= 7);
|
|
888
|
-
|
|
889
|
-
initialize_buckets_dynamic(buckets, size);
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
static void initialize_buckets_dynamic(buckets_type& buckets, TBucketDivisor size) {
|
|
894
|
-
buckets.initialize_dynamic(size);
|
|
895
|
-
memset(buckets.data(), 0, size() * sizeof(*buckets.data()));
|
|
896
|
-
buckets[size()] = (node*)1;
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
static void deinitialize_buckets(buckets_type& buckets) {
|
|
900
|
-
if (buckets.size() == 1) {
|
|
901
|
-
buckets.deinitialize_static();
|
|
902
|
-
} else {
|
|
903
|
-
buckets.deinitialize_dynamic();
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
static void clear_buckets(buckets_type& buckets) {
|
|
908
|
-
memset(buckets.data(), 0, buckets.size() * sizeof(*buckets.data()));
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
template <class OtherKey>
|
|
912
|
-
size_type bkt_num_key(const OtherKey& key) const {
|
|
913
|
-
return bkt_num_key(key, buckets.ExtSize());
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
template <class OtherValue>
|
|
917
|
-
size_type bkt_num(const OtherValue& obj) const {
|
|
918
|
-
return bkt_num_key(get_key(obj));
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
template <class OtherKey>
|
|
922
|
-
size_type bkt_num_key(const OtherKey& key, TBucketDivisor n) const {
|
|
923
|
-
const size_type bucket = n.Remainder(this->_get_hash_fun()(key));
|
|
924
|
-
Y_ASSERT((0 <= bucket) && (bucket < n()));
|
|
925
|
-
return bucket;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
template <class OtherValue>
|
|
929
|
-
size_type bkt_num(const OtherValue& obj, TBucketDivisor n) const {
|
|
930
|
-
return bkt_num_key(get_key(obj), n);
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
template <typename... Args>
|
|
934
|
-
node* new_node(Args&&... val) {
|
|
935
|
-
node* n = get_node();
|
|
936
|
-
n->next = (node*)1; /*y*/ // just for a case
|
|
937
|
-
try {
|
|
938
|
-
new (static_cast<void*>(&n->val)) Value(std::forward<Args>(val)...);
|
|
939
|
-
} catch (...) {
|
|
940
|
-
put_node(n);
|
|
941
|
-
throw;
|
|
942
|
-
}
|
|
943
|
-
return n;
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
void delete_node(node* n) {
|
|
947
|
-
n->val.~Value();
|
|
948
|
-
//n->next = (node*) 0xDeadBeeful;
|
|
949
|
-
put_node(n);
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
void erase_bucket(const size_type n, node* first, node* last);
|
|
953
|
-
void erase_bucket(const size_type n, node* last);
|
|
954
|
-
|
|
955
|
-
void copy_from_dynamic(const THashTable& ht);
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
template <class V>
|
|
959
|
-
__yhashtable_iterator<V>& __yhashtable_iterator<V>::operator++() {
|
|
960
|
-
Y_ASSERT(cur);
|
|
961
|
-
cur = cur->next;
|
|
962
|
-
if ((uintptr_t)cur & 1) {
|
|
963
|
-
node** bucket = (node**)((uintptr_t)cur & ~1);
|
|
964
|
-
while (*bucket == nullptr)
|
|
965
|
-
++bucket;
|
|
966
|
-
Y_ASSERT(*bucket != nullptr);
|
|
967
|
-
cur = (node*)((uintptr_t)*bucket & ~1);
|
|
968
|
-
}
|
|
969
|
-
return *this;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
template <class V>
|
|
973
|
-
inline __yhashtable_iterator<V> __yhashtable_iterator<V>::operator++(int) {
|
|
974
|
-
iterator tmp = *this;
|
|
975
|
-
++*this;
|
|
976
|
-
return tmp;
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
template <class V>
|
|
980
|
-
__yhashtable_const_iterator<V>& __yhashtable_const_iterator<V>::operator++() {
|
|
981
|
-
Y_ASSERT(cur);
|
|
982
|
-
cur = cur->next;
|
|
983
|
-
if ((uintptr_t)cur & 1) {
|
|
984
|
-
node** bucket = (node**)((uintptr_t)cur & ~1);
|
|
985
|
-
while (*bucket == nullptr)
|
|
986
|
-
++bucket;
|
|
987
|
-
Y_ASSERT(*bucket != nullptr);
|
|
988
|
-
cur = (node*)((uintptr_t)*bucket & ~1);
|
|
989
|
-
}
|
|
990
|
-
return *this;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
template <class V>
|
|
994
|
-
inline __yhashtable_const_iterator<V> __yhashtable_const_iterator<V>::operator++(int) {
|
|
995
|
-
const_iterator tmp = *this;
|
|
996
|
-
++*this;
|
|
997
|
-
return tmp;
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1001
|
-
template <typename... Args>
|
|
1002
|
-
std::pair<typename THashTable<V, K, HF, Ex, Eq, A>::iterator, bool> THashTable<V, K, HF, Ex, Eq, A>::emplace_unique_noresize(Args&&... args) {
|
|
1003
|
-
auto deleter = [&](node* tmp) { delete_node(tmp); };
|
|
1004
|
-
node* tmp = new_node(std::forward<Args>(args)...);
|
|
1005
|
-
std::unique_ptr<node, decltype(deleter)> guard(tmp, deleter);
|
|
1006
|
-
|
|
1007
|
-
const size_type n = bkt_num(tmp->val);
|
|
1008
|
-
node* first = buckets[n];
|
|
1009
|
-
|
|
1010
|
-
if (first) /*y*/
|
|
1011
|
-
for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
|
|
1012
|
-
if (equals(get_key(cur->val), get_key(tmp->val)))
|
|
1013
|
-
return std::pair<iterator, bool>(iterator(cur), false); /*y*/
|
|
1014
|
-
|
|
1015
|
-
guard.release();
|
|
1016
|
-
tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
|
|
1017
|
-
buckets[n] = tmp;
|
|
1018
|
-
++num_elements;
|
|
1019
|
-
return std::pair<iterator, bool>(iterator(tmp), true); /*y*/
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1023
|
-
template <class OtherValue>
|
|
1024
|
-
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) {
|
|
1025
|
-
const size_type n = bkt_num(obj);
|
|
1026
|
-
node* first = buckets[n];
|
|
1027
|
-
|
|
1028
|
-
if (first) /*y*/
|
|
1029
|
-
for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
|
|
1030
|
-
if (equals(get_key(cur->val), get_key(obj)))
|
|
1031
|
-
return std::pair<iterator, bool>(iterator(cur), false); /*y*/
|
|
1032
|
-
|
|
1033
|
-
node* tmp = new_node(obj);
|
|
1034
|
-
tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
|
|
1035
|
-
buckets[n] = tmp;
|
|
1036
|
-
++num_elements;
|
|
1037
|
-
return std::pair<iterator, bool>(iterator(tmp), true); /*y*/
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1041
|
-
template <typename... Args>
|
|
1042
|
-
__yhashtable_iterator<V> THashTable<V, K, HF, Ex, Eq, A>::emplace_equal_noresize(Args&&... args) {
|
|
1043
|
-
auto deleter = [&](node* tmp) { delete_node(tmp); };
|
|
1044
|
-
node* tmp = new_node(std::forward<Args>(args)...);
|
|
1045
|
-
std::unique_ptr<node, decltype(deleter)> guard(tmp, deleter);
|
|
1046
|
-
const size_type n = bkt_num(tmp->val);
|
|
1047
|
-
node* first = buckets[n];
|
|
1048
|
-
|
|
1049
|
-
if (first) /*y*/
|
|
1050
|
-
for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
|
|
1051
|
-
if (equals(get_key(cur->val), get_key(tmp->val))) {
|
|
1052
|
-
guard.release();
|
|
1053
|
-
tmp->next = cur->next;
|
|
1054
|
-
cur->next = tmp;
|
|
1055
|
-
++num_elements;
|
|
1056
|
-
return iterator(tmp); /*y*/
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
guard.release();
|
|
1060
|
-
tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
|
|
1061
|
-
buckets[n] = tmp;
|
|
1062
|
-
++num_elements;
|
|
1063
|
-
return iterator(tmp); /*y*/
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1067
|
-
template <class OtherValue>
|
|
1068
|
-
typename THashTable<V, K, HF, Ex, Eq, A>::reference THashTable<V, K, HF, Ex, Eq, A>::find_or_insert(const OtherValue& v) {
|
|
1069
|
-
reserve(num_elements + 1);
|
|
1070
|
-
|
|
1071
|
-
size_type n = bkt_num_key(get_key(v));
|
|
1072
|
-
node* first = buckets[n];
|
|
1073
|
-
|
|
1074
|
-
if (first) /*y*/
|
|
1075
|
-
for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
|
|
1076
|
-
if (equals(get_key(cur->val), get_key(v)))
|
|
1077
|
-
return cur->val;
|
|
1078
|
-
|
|
1079
|
-
node* tmp = new_node(v);
|
|
1080
|
-
tmp->next = first ? first : (node*)((uintptr_t)&buckets[n + 1] | 1); /*y*/
|
|
1081
|
-
buckets[n] = tmp;
|
|
1082
|
-
++num_elements;
|
|
1083
|
-
return tmp->val;
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1087
|
-
template <class OtherKey>
|
|
1088
|
-
__yhashtable_iterator<V> THashTable<V, K, HF, Ex, Eq, A>::find_i(const OtherKey& key, insert_ctx& ins) {
|
|
1089
|
-
size_type n = bkt_num_key(key);
|
|
1090
|
-
ins = &buckets[n];
|
|
1091
|
-
node* first = buckets[n];
|
|
1092
|
-
|
|
1093
|
-
if (first) /*y*/
|
|
1094
|
-
for (node* cur = first; !((uintptr_t)cur & 1); cur = cur->next) /*y*/
|
|
1095
|
-
if (equals(get_key(cur->val), key))
|
|
1096
|
-
return iterator(cur); /*y*/
|
|
1097
|
-
return end();
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1101
|
-
template <class OtherKey>
|
|
1102
|
-
std::pair<__yhashtable_iterator<V>, __yhashtable_iterator<V>> THashTable<V, K, HF, Ex, Eq, A>::equal_range(const OtherKey& key) {
|
|
1103
|
-
using pii = std::pair<iterator, iterator>;
|
|
1104
|
-
const size_type n = bkt_num_key(key);
|
|
1105
|
-
node* first = buckets[n];
|
|
1106
|
-
|
|
1107
|
-
if (first) /*y*/
|
|
1108
|
-
for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
|
|
1109
|
-
if (equals(get_key(first->val), key)) {
|
|
1110
|
-
for (node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
|
|
1111
|
-
if (!equals(get_key(cur->val), key))
|
|
1112
|
-
return pii(iterator(first), iterator(cur)); /*y*/
|
|
1113
|
-
for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
|
|
1114
|
-
if (buckets[m])
|
|
1115
|
-
return pii(iterator(first), /*y*/
|
|
1116
|
-
iterator(buckets[m])); /*y*/
|
|
1117
|
-
return pii(iterator(first), end()); /*y*/
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
return pii(end(), end());
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1124
|
-
template <class OtherKey>
|
|
1125
|
-
std::pair<__yhashtable_const_iterator<V>, __yhashtable_const_iterator<V>> THashTable<V, K, HF, Ex, Eq, A>::equal_range(const OtherKey& key) const {
|
|
1126
|
-
using pii = std::pair<const_iterator, const_iterator>;
|
|
1127
|
-
const size_type n = bkt_num_key(key);
|
|
1128
|
-
const node* first = buckets[n];
|
|
1129
|
-
|
|
1130
|
-
if (first) /*y*/
|
|
1131
|
-
for (; !((uintptr_t)first & 1); first = first->next) { /*y*/
|
|
1132
|
-
if (equals(get_key(first->val), key)) {
|
|
1133
|
-
for (const node* cur = first->next; !((uintptr_t)cur & 1); cur = cur->next)
|
|
1134
|
-
if (!equals(get_key(cur->val), key))
|
|
1135
|
-
return pii(const_iterator(first), /*y*/
|
|
1136
|
-
const_iterator(cur)); /*y*/
|
|
1137
|
-
for (size_type m = n + 1; m < buckets.size(); ++m) /*y*/
|
|
1138
|
-
if (buckets[m])
|
|
1139
|
-
return pii(const_iterator(first /*y*/),
|
|
1140
|
-
const_iterator(buckets[m] /*y*/));
|
|
1141
|
-
return pii(const_iterator(first /*y*/), end());
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
return pii(end(), end());
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1148
|
-
template <class OtherKey>
|
|
1149
|
-
typename THashTable<V, K, HF, Ex, Eq, A>::size_type THashTable<V, K, HF, Ex, Eq, A>::erase(const OtherKey& key) {
|
|
1150
|
-
const size_type n = bkt_num_key(key);
|
|
1151
|
-
node* first = buckets[n];
|
|
1152
|
-
size_type erased = 0;
|
|
1153
|
-
|
|
1154
|
-
if (first) {
|
|
1155
|
-
node* cur = first;
|
|
1156
|
-
node* next = cur->next;
|
|
1157
|
-
while (!((uintptr_t)next & 1)) { /*y*/
|
|
1158
|
-
if (equals(get_key(next->val), key)) {
|
|
1159
|
-
cur->next = next->next;
|
|
1160
|
-
++erased;
|
|
1161
|
-
--num_elements;
|
|
1162
|
-
delete_node(next);
|
|
1163
|
-
next = cur->next;
|
|
1164
|
-
} else {
|
|
1165
|
-
cur = next;
|
|
1166
|
-
next = cur->next;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
if (equals(get_key(first->val), key)) {
|
|
1170
|
-
buckets[n] = ((uintptr_t)first->next & 1) ? nullptr : first->next; /*y*/
|
|
1171
|
-
++erased;
|
|
1172
|
-
--num_elements;
|
|
1173
|
-
delete_node(first);
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
return erased;
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1180
|
-
template <class OtherKey>
|
|
1181
|
-
typename THashTable<V, K, HF, Ex, Eq, A>::size_type THashTable<V, K, HF, Ex, Eq, A>::erase_one(const OtherKey& key) {
|
|
1182
|
-
const size_type n = bkt_num_key(key);
|
|
1183
|
-
node* first = buckets[n];
|
|
1184
|
-
|
|
1185
|
-
if (first) {
|
|
1186
|
-
node* cur = first;
|
|
1187
|
-
node* next = cur->next;
|
|
1188
|
-
while (!((uintptr_t)next & 1)) { /*y*/
|
|
1189
|
-
if (equals(get_key(next->val), key)) {
|
|
1190
|
-
cur->next = next->next;
|
|
1191
|
-
--num_elements;
|
|
1192
|
-
delete_node(next);
|
|
1193
|
-
return 1;
|
|
1194
|
-
} else {
|
|
1195
|
-
cur = next;
|
|
1196
|
-
next = cur->next;
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
if (equals(get_key(first->val), key)) {
|
|
1200
|
-
buckets[n] = ((uintptr_t)first->next & 1) ? nullptr : first->next; /*y*/
|
|
1201
|
-
--num_elements;
|
|
1202
|
-
delete_node(first);
|
|
1203
|
-
return 1;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
return 0;
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1210
|
-
void THashTable<V, K, HF, Ex, Eq, A>::erase(const iterator& it) {
|
|
1211
|
-
if (node* const p = it.cur) {
|
|
1212
|
-
const size_type n = bkt_num(p->val);
|
|
1213
|
-
node* cur = buckets[n];
|
|
1214
|
-
|
|
1215
|
-
if (cur == p) {
|
|
1216
|
-
buckets[n] = ((uintptr_t)cur->next & 1) ? nullptr : cur->next; /*y*/
|
|
1217
|
-
delete_node(cur);
|
|
1218
|
-
--num_elements;
|
|
1219
|
-
} else {
|
|
1220
|
-
node* next = cur->next;
|
|
1221
|
-
while (!((uintptr_t)next & 1)) {
|
|
1222
|
-
if (next == p) {
|
|
1223
|
-
cur->next = next->next;
|
|
1224
|
-
delete_node(next);
|
|
1225
|
-
--num_elements;
|
|
1226
|
-
break;
|
|
1227
|
-
} else {
|
|
1228
|
-
cur = next;
|
|
1229
|
-
next = cur->next;
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1237
|
-
void THashTable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last) {
|
|
1238
|
-
size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size(); /*y*/
|
|
1239
|
-
size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size(); /*y*/
|
|
1240
|
-
|
|
1241
|
-
if (first.cur == last.cur)
|
|
1242
|
-
return;
|
|
1243
|
-
else if (f_bucket == l_bucket)
|
|
1244
|
-
erase_bucket(f_bucket, first.cur, last.cur);
|
|
1245
|
-
else {
|
|
1246
|
-
erase_bucket(f_bucket, first.cur, nullptr);
|
|
1247
|
-
for (size_type n = f_bucket + 1; n < l_bucket; ++n)
|
|
1248
|
-
erase_bucket(n, nullptr);
|
|
1249
|
-
if (l_bucket != buckets.size()) /*y*/
|
|
1250
|
-
erase_bucket(l_bucket, last.cur);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1255
|
-
inline void
|
|
1256
|
-
THashTable<V, K, HF, Ex, Eq, A>::erase(const_iterator first, const_iterator last) {
|
|
1257
|
-
erase(iterator(const_cast<node*>(first.cur)), iterator(const_cast<node*>(last.cur)));
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1261
|
-
inline void THashTable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it) {
|
|
1262
|
-
erase(iterator(const_cast<node*>(it.cur)));
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1266
|
-
bool THashTable<V, K, HF, Ex, Eq, A>::reserve(size_type num_elements_hint) {
|
|
1267
|
-
const size_type old_n = buckets.size(); /*y*/
|
|
1268
|
-
if (num_elements_hint + 1 > old_n) {
|
|
1269
|
-
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.
|
|
1270
|
-
return false;
|
|
1271
|
-
|
|
1272
|
-
const TBucketDivisor n = HashBucketCountExt(num_elements_hint + 1, buckets.BucketDivisorHint() + 1);
|
|
1273
|
-
if (n() > old_n) {
|
|
1274
|
-
buckets_type tmp(buckets.get_allocator());
|
|
1275
|
-
initialize_buckets_dynamic(tmp, n);
|
|
1276
|
-
#ifdef __STL_USE_EXCEPTIONS
|
|
1277
|
-
try {
|
|
1278
|
-
#endif /* __STL_USE_EXCEPTIONS */
|
|
1279
|
-
for (size_type bucket = 0; bucket < old_n; ++bucket) {
|
|
1280
|
-
node* first = buckets[bucket];
|
|
1281
|
-
while (first) {
|
|
1282
|
-
size_type new_bucket = bkt_num(first->val, n);
|
|
1283
|
-
node* next = first->next;
|
|
1284
|
-
buckets[bucket] = ((uintptr_t)next & 1) ? nullptr : next; /*y*/
|
|
1285
|
-
next = tmp[new_bucket];
|
|
1286
|
-
first->next = next ? next : (node*)((uintptr_t) & (tmp[new_bucket + 1]) | 1); /*y*/
|
|
1287
|
-
tmp[new_bucket] = first;
|
|
1288
|
-
first = buckets[bucket];
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
buckets.swap(tmp);
|
|
1293
|
-
deinitialize_buckets(tmp);
|
|
1294
|
-
|
|
1295
|
-
return true;
|
|
1296
|
-
#ifdef __STL_USE_EXCEPTIONS
|
|
1297
|
-
} catch (...) {
|
|
1298
|
-
for (size_type bucket = 0; bucket < tmp.size() - 1; ++bucket) {
|
|
1299
|
-
while (tmp[bucket]) {
|
|
1300
|
-
node* next = tmp[bucket]->next;
|
|
1301
|
-
delete_node(tmp[bucket]);
|
|
1302
|
-
tmp[bucket] = ((uintptr_t)next & 1) ? nullptr : next /*y*/;
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
throw;
|
|
1306
|
-
}
|
|
1307
|
-
#endif /* __STL_USE_EXCEPTIONS */
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
return false;
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1315
|
-
void THashTable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* first, node* last) {
|
|
1316
|
-
node* cur = buckets[n];
|
|
1317
|
-
if (cur == first)
|
|
1318
|
-
erase_bucket(n, last);
|
|
1319
|
-
else {
|
|
1320
|
-
node* next;
|
|
1321
|
-
for (next = cur->next; next != first; cur = next, next = cur->next)
|
|
1322
|
-
;
|
|
1323
|
-
while (next != last) { /*y; 3.1*/
|
|
1324
|
-
cur->next = next->next;
|
|
1325
|
-
delete_node(next);
|
|
1326
|
-
next = ((uintptr_t)cur->next & 1) ? nullptr : cur->next; /*y*/
|
|
1327
|
-
--num_elements;
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1333
|
-
void THashTable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last) {
|
|
1334
|
-
node* cur = buckets[n];
|
|
1335
|
-
while (cur != last) {
|
|
1336
|
-
node* next = cur->next;
|
|
1337
|
-
delete_node(cur);
|
|
1338
|
-
cur = ((uintptr_t)next & 1) ? nullptr : next; /*y*/
|
|
1339
|
-
buckets[n] = cur;
|
|
1340
|
-
--num_elements;
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1345
|
-
void THashTable<V, K, HF, Ex, Eq, A>::basic_clear() {
|
|
1346
|
-
if (!num_elements) {
|
|
1347
|
-
return;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
node** first = buckets.begin();
|
|
1351
|
-
node** last = buckets.end();
|
|
1352
|
-
for (; first < last; ++first) {
|
|
1353
|
-
node* cur = *first;
|
|
1354
|
-
if (cur) { /*y*/
|
|
1355
|
-
while (!((uintptr_t)cur & 1)) { /*y*/
|
|
1356
|
-
node* next = cur->next;
|
|
1357
|
-
delete_node(cur);
|
|
1358
|
-
cur = next;
|
|
1359
|
-
}
|
|
1360
|
-
*first = nullptr;
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
num_elements = 0;
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
template <class V, class K, class HF, class Ex, class Eq, class A>
|
|
1367
|
-
void THashTable<V, K, HF, Ex, Eq, A>::copy_from_dynamic(const THashTable& ht) {
|
|
1368
|
-
Y_ASSERT(buckets.size() == ht.buckets.size() && !ht.empty());
|
|
1369
|
-
|
|
1370
|
-
#ifdef __STL_USE_EXCEPTIONS
|
|
1371
|
-
try {
|
|
1372
|
-
#endif /* __STL_USE_EXCEPTIONS */
|
|
1373
|
-
for (size_type i = 0; i < ht.buckets.size(); ++i) { /*y*/
|
|
1374
|
-
if (const node* cur = ht.buckets[i]) {
|
|
1375
|
-
node* copy = new_node(cur->val);
|
|
1376
|
-
buckets[i] = copy;
|
|
1377
|
-
|
|
1378
|
-
for (node* next = cur->next; !((uintptr_t)next & 1); cur = next, next = cur->next) {
|
|
1379
|
-
copy->next = new_node(next->val);
|
|
1380
|
-
copy = copy->next;
|
|
1381
|
-
}
|
|
1382
|
-
copy->next = (node*)((uintptr_t)&buckets[i + 1] | 1); /*y*/
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
num_elements = ht.num_elements;
|
|
1386
|
-
#ifdef __STL_USE_EXCEPTIONS
|
|
1387
|
-
} catch (...) {
|
|
1388
|
-
basic_clear();
|
|
1389
|
-
throw;
|
|
1390
|
-
}
|
|
1391
|
-
#endif /* __STL_USE_EXCEPTIONS */
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
namespace NPrivate {
|
|
1395
|
-
template <class Key>
|
|
1396
|
-
inline TString MapKeyToString(const Key&) {
|
|
1397
|
-
return TypeName<Key>();
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
TString MapKeyToString(TStringBuf key);
|
|
1401
|
-
TString MapKeyToString(unsigned short key);
|
|
1402
|
-
TString MapKeyToString(short key);
|
|
1403
|
-
TString MapKeyToString(unsigned int key);
|
|
1404
|
-
TString MapKeyToString(int key);
|
|
1405
|
-
TString MapKeyToString(unsigned long key);
|
|
1406
|
-
TString MapKeyToString(long key);
|
|
1407
|
-
TString MapKeyToString(unsigned long long key);
|
|
1408
|
-
TString MapKeyToString(long long key);
|
|
1409
|
-
|
|
1410
|
-
inline TString MapKeyToString(const TString& key) {
|
|
1411
|
-
return MapKeyToString(TStringBuf(key));
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
inline TString MapKeyToString(const char* key) {
|
|
1415
|
-
return MapKeyToString(TStringBuf(key));
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
inline TString MapKeyToString(char* key) {
|
|
1419
|
-
return MapKeyToString(TStringBuf(key));
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
[[noreturn]] void ThrowKeyNotFoundInHashTableException(const TStringBuf keyRepresentation);
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
|
|
1426
|
-
class THashMap: public TMapOps<THashMap<Key, T, HashFcn, EqualKey, Alloc>> {
|
|
1427
|
-
private:
|
|
1428
|
-
using ht = THashTable<std::pair<const Key, T>, Key, HashFcn, TSelect1st, EqualKey, Alloc>;
|
|
1429
|
-
ht rep;
|
|
1430
|
-
|
|
1431
|
-
public:
|
|
1432
|
-
using key_type = typename ht::key_type;
|
|
1433
|
-
using value_type = typename ht::value_type;
|
|
1434
|
-
using hasher = typename ht::hasher;
|
|
1435
|
-
using key_equal = typename ht::key_equal;
|
|
1436
|
-
using allocator_type = typename ht::allocator_type;
|
|
1437
|
-
using node_allocator_type = typename ht::node_allocator_type;
|
|
1438
|
-
using mapped_type = T;
|
|
1439
|
-
|
|
1440
|
-
using size_type = typename ht::size_type;
|
|
1441
|
-
using difference_type = typename ht::difference_type;
|
|
1442
|
-
using pointer = typename ht::pointer;
|
|
1443
|
-
using const_pointer = typename ht::const_pointer;
|
|
1444
|
-
using reference = typename ht::reference;
|
|
1445
|
-
using const_reference = typename ht::const_reference;
|
|
1446
|
-
|
|
1447
|
-
using iterator = typename ht::iterator;
|
|
1448
|
-
using const_iterator = typename ht::const_iterator;
|
|
1449
|
-
using insert_ctx = typename ht::insert_ctx;
|
|
1450
|
-
|
|
1451
|
-
hasher hash_function() const {
|
|
1452
|
-
return rep.hash_function();
|
|
1453
|
-
}
|
|
1454
|
-
key_equal key_eq() const {
|
|
1455
|
-
return rep.key_eq();
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
public:
|
|
1459
|
-
THashMap()
|
|
1460
|
-
: rep(0, hasher(), key_equal())
|
|
1461
|
-
{
|
|
1462
|
-
}
|
|
1463
|
-
template <class TAllocParam>
|
|
1464
|
-
explicit THashMap(TAllocParam* allocParam, size_type n = 0)
|
|
1465
|
-
: rep(n, hasher(), key_equal(), allocParam)
|
|
1466
|
-
{
|
|
1467
|
-
}
|
|
1468
|
-
explicit THashMap(size_type n)
|
|
1469
|
-
: rep(n, hasher(), key_equal())
|
|
1470
|
-
{
|
|
1471
|
-
}
|
|
1472
|
-
THashMap(size_type n, const hasher& hf)
|
|
1473
|
-
: rep(n, hf, key_equal())
|
|
1474
|
-
{
|
|
1475
|
-
}
|
|
1476
|
-
THashMap(size_type n, const hasher& hf, const key_equal& eql)
|
|
1477
|
-
: rep(n, hf, eql)
|
|
1478
|
-
{
|
|
1479
|
-
}
|
|
1480
|
-
template <class TAllocParam>
|
|
1481
|
-
explicit THashMap(size_type n, TAllocParam* allocParam)
|
|
1482
|
-
: rep(n, hasher(), key_equal(), allocParam)
|
|
1483
|
-
{
|
|
1484
|
-
}
|
|
1485
|
-
template <class InputIterator>
|
|
1486
|
-
THashMap(InputIterator f, InputIterator l)
|
|
1487
|
-
: rep(0, hasher(), key_equal())
|
|
1488
|
-
{
|
|
1489
|
-
rep.insert_unique(f, l);
|
|
1490
|
-
}
|
|
1491
|
-
template <class InputIterator>
|
|
1492
|
-
THashMap(InputIterator f, InputIterator l, size_type n)
|
|
1493
|
-
: rep(n, hasher(), key_equal())
|
|
1494
|
-
{
|
|
1495
|
-
rep.insert_unique(f, l);
|
|
1496
|
-
}
|
|
1497
|
-
template <class InputIterator>
|
|
1498
|
-
THashMap(InputIterator f, InputIterator l, size_type n,
|
|
1499
|
-
const hasher& hf)
|
|
1500
|
-
: rep(n, hf, key_equal())
|
|
1501
|
-
{
|
|
1502
|
-
rep.insert_unique(f, l);
|
|
1503
|
-
}
|
|
1504
|
-
template <class InputIterator>
|
|
1505
|
-
THashMap(InputIterator f, InputIterator l, size_type n,
|
|
1506
|
-
const hasher& hf, const key_equal& eql)
|
|
1507
|
-
: rep(n, hf, eql)
|
|
1508
|
-
{
|
|
1509
|
-
rep.insert_unique(f, l);
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
THashMap(const std::initializer_list<std::pair<Key, T>>& list)
|
|
1513
|
-
: rep(list.size(), hasher(), key_equal())
|
|
1514
|
-
{
|
|
1515
|
-
for (const auto& v : list) {
|
|
1516
|
-
rep.insert_unique_noresize(v);
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
// THashMap has implicit copy/move constructors and copy-/move-assignment operators
|
|
1521
|
-
// because its implementation is backed by THashTable.
|
|
1522
|
-
// See hash_ut.cpp
|
|
1523
|
-
|
|
1524
|
-
public:
|
|
1525
|
-
size_type size() const noexcept {
|
|
1526
|
-
return rep.size();
|
|
1527
|
-
}
|
|
1528
|
-
yssize_t ysize() const noexcept {
|
|
1529
|
-
return (yssize_t)rep.size();
|
|
1530
|
-
}
|
|
1531
|
-
size_type max_size() const noexcept {
|
|
1532
|
-
return rep.max_size();
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
Y_PURE_FUNCTION
|
|
1536
|
-
bool empty() const noexcept {
|
|
1537
|
-
return rep.empty();
|
|
1538
|
-
}
|
|
1539
|
-
explicit operator bool() const noexcept {
|
|
1540
|
-
return !empty();
|
|
1541
|
-
}
|
|
1542
|
-
void swap(THashMap& hs) {
|
|
1543
|
-
rep.swap(hs.rep);
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
iterator begin() {
|
|
1547
|
-
return rep.begin();
|
|
1548
|
-
}
|
|
1549
|
-
iterator end() {
|
|
1550
|
-
return rep.end();
|
|
1551
|
-
}
|
|
1552
|
-
const_iterator begin() const {
|
|
1553
|
-
return rep.begin();
|
|
1554
|
-
}
|
|
1555
|
-
const_iterator end() const {
|
|
1556
|
-
return rep.end();
|
|
1557
|
-
}
|
|
1558
|
-
const_iterator cbegin() const {
|
|
1559
|
-
return rep.begin();
|
|
1560
|
-
}
|
|
1561
|
-
const_iterator cend() const {
|
|
1562
|
-
return rep.end();
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
public:
|
|
1566
|
-
template <class InputIterator>
|
|
1567
|
-
void insert(InputIterator f, InputIterator l) {
|
|
1568
|
-
rep.insert_unique(f, l);
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
std::pair<iterator, bool> insert(const value_type& obj) {
|
|
1572
|
-
return rep.insert_unique(obj);
|
|
1573
|
-
}
|
|
1574
|
-
|
|
1575
|
-
template <typename... Args>
|
|
1576
|
-
std::pair<iterator, bool> emplace(Args&&... args) {
|
|
1577
|
-
return rep.emplace_unique(std::forward<Args>(args)...);
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
std::pair<iterator, bool> insert_noresize(const value_type& obj) {
|
|
1581
|
-
return rep.insert_unique_noresize(obj);
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1584
|
-
template <typename... Args>
|
|
1585
|
-
std::pair<iterator, bool> emplace_noresize(Args&&... args) {
|
|
1586
|
-
return rep.emplace_unique_noresize(std::forward<Args>(args)...);
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
template <class TheObj>
|
|
1590
|
-
iterator insert_direct(const TheObj& obj, const insert_ctx& ins) {
|
|
1591
|
-
return rep.insert_direct(obj, ins);
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
template <typename... Args>
|
|
1595
|
-
iterator emplace_direct(const insert_ctx& ins, Args&&... args) {
|
|
1596
|
-
return rep.emplace_direct(ins, std::forward<Args>(args)...);
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
template <typename TKey, typename... Args>
|
|
1600
|
-
std::pair<iterator, bool> try_emplace(TKey&& key, Args&&... args) {
|
|
1601
|
-
insert_ctx ctx = nullptr;
|
|
1602
|
-
iterator it = find(key, ctx);
|
|
1603
|
-
if (it == end()) {
|
|
1604
|
-
it = rep.emplace_direct(ctx, std::piecewise_construct,
|
|
1605
|
-
std::forward_as_tuple(std::forward<TKey>(key)),
|
|
1606
|
-
std::forward_as_tuple(std::forward<Args>(args)...));
|
|
1607
|
-
return {it, true};
|
|
1608
|
-
}
|
|
1609
|
-
return {it, false};
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
|
-
template <class TheKey>
|
|
1613
|
-
iterator find(const TheKey& key) {
|
|
1614
|
-
return rep.find(key);
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
template <class TheKey>
|
|
1618
|
-
const_iterator find(const TheKey& key) const {
|
|
1619
|
-
return rep.find(key);
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
template <class TheKey>
|
|
1623
|
-
iterator find(const TheKey& key, insert_ctx& ins) {
|
|
1624
|
-
return rep.find_i(key, ins);
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
|
-
template <class TheKey>
|
|
1628
|
-
bool contains(const TheKey& key) const {
|
|
1629
|
-
return rep.find(key) != rep.end();
|
|
1630
|
-
}
|
|
1631
|
-
bool contains(const key_type& key) const {
|
|
1632
|
-
return rep.find(key) != rep.end();
|
|
1633
|
-
}
|
|
1634
|
-
|
|
1635
|
-
template <class TheKey>
|
|
1636
|
-
bool contains(const TheKey& key, insert_ctx& ins) {
|
|
1637
|
-
return rep.find_i(key, ins) != rep.end();
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
|
-
template <class TKey>
|
|
1641
|
-
T& operator[](const TKey& key) {
|
|
1642
|
-
insert_ctx ctx = nullptr;
|
|
1643
|
-
iterator it = find(key, ctx);
|
|
1644
|
-
|
|
1645
|
-
if (it != end()) {
|
|
1646
|
-
return it->second;
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
return rep.emplace_direct(ctx, std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple())->second;
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
template <class TheKey>
|
|
1653
|
-
const T& at(const TheKey& key) const {
|
|
1654
|
-
using namespace ::NPrivate;
|
|
1655
|
-
const_iterator it = find(key);
|
|
1656
|
-
|
|
1657
|
-
if (Y_UNLIKELY(it == end())) {
|
|
1658
|
-
::NPrivate::ThrowKeyNotFoundInHashTableException(MapKeyToString(key));
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
return it->second;
|
|
1662
|
-
}
|
|
1663
|
-
|
|
1664
|
-
template <class TheKey>
|
|
1665
|
-
T& at(const TheKey& key) {
|
|
1666
|
-
using namespace ::NPrivate;
|
|
1667
|
-
iterator it = find(key);
|
|
1668
|
-
|
|
1669
|
-
if (Y_UNLIKELY(it == end())) {
|
|
1670
|
-
::NPrivate::ThrowKeyNotFoundInHashTableException(MapKeyToString(key));
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
return it->second;
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
template <class TKey>
|
|
1677
|
-
size_type count(const TKey& key) const {
|
|
1678
|
-
return rep.count(key);
|
|
1679
|
-
}
|
|
1680
|
-
|
|
1681
|
-
template <class TKey>
|
|
1682
|
-
std::pair<iterator, iterator> equal_range(const TKey& key) {
|
|
1683
|
-
return rep.equal_range(key);
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
template <class TKey>
|
|
1687
|
-
std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const {
|
|
1688
|
-
return rep.equal_range(key);
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
template <class TKey>
|
|
1692
|
-
size_type erase(const TKey& key) {
|
|
1693
|
-
return rep.erase_one(key);
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
void erase(iterator it) {
|
|
1697
|
-
rep.erase(it);
|
|
1698
|
-
}
|
|
1699
|
-
void erase(iterator f, iterator l) {
|
|
1700
|
-
rep.erase(f, l);
|
|
1701
|
-
}
|
|
1702
|
-
void clear() {
|
|
1703
|
-
rep.clear();
|
|
1704
|
-
}
|
|
1705
|
-
void clear(size_t downsize_hint) {
|
|
1706
|
-
rep.clear(downsize_hint);
|
|
1707
|
-
}
|
|
1708
|
-
void basic_clear() {
|
|
1709
|
-
rep.basic_clear();
|
|
1710
|
-
}
|
|
1711
|
-
void release_nodes() {
|
|
1712
|
-
rep.release_nodes();
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
|
-
// if (stHash != NULL) bucket_count() must be equal to stHash->bucket_count()
|
|
1716
|
-
template <class KeySaver>
|
|
1717
|
-
int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const {
|
|
1718
|
-
return rep.template save_for_st<KeySaver>(stream, ks, stHash);
|
|
1719
|
-
}
|
|
1720
|
-
|
|
1721
|
-
public:
|
|
1722
|
-
void reserve(size_type hint) {
|
|
1723
|
-
rep.reserve(hint);
|
|
1724
|
-
}
|
|
1725
|
-
size_type bucket_count() const {
|
|
1726
|
-
return rep.bucket_count();
|
|
1727
|
-
}
|
|
1728
|
-
size_type bucket_size(size_type n) const {
|
|
1729
|
-
return rep.bucket_size(n);
|
|
1730
|
-
}
|
|
1731
|
-
node_allocator_type& GetNodeAllocator() {
|
|
1732
|
-
return rep.GetNodeAllocator();
|
|
1733
|
-
}
|
|
1734
|
-
const node_allocator_type& GetNodeAllocator() const {
|
|
1735
|
-
return rep.GetNodeAllocator();
|
|
1736
|
-
}
|
|
1737
|
-
};
|
|
1738
|
-
|
|
1739
|
-
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
|
|
1740
|
-
inline bool operator==(const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm1, const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
|
|
1741
|
-
if (hm1.size() != hm2.size()) {
|
|
1742
|
-
return false;
|
|
1743
|
-
}
|
|
1744
|
-
for (const auto& it1 : hm1) {
|
|
1745
|
-
auto it2 = hm2.find(it1.first);
|
|
1746
|
-
if ((it2 == hm2.end()) || !(it1 == *it2)) {
|
|
1747
|
-
return false;
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
return true;
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1753
|
-
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
|
|
1754
|
-
inline bool operator!=(const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm1, const THashMap<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
|
|
1755
|
-
return !(hm1 == hm2);
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
|
|
1759
|
-
class THashMultiMap {
|
|
1760
|
-
private:
|
|
1761
|
-
using ht = THashTable<std::pair<const Key, T>, Key, HashFcn, TSelect1st, EqualKey, Alloc>;
|
|
1762
|
-
ht rep;
|
|
1763
|
-
|
|
1764
|
-
public:
|
|
1765
|
-
using key_type = typename ht::key_type;
|
|
1766
|
-
using value_type = typename ht::value_type;
|
|
1767
|
-
using hasher = typename ht::hasher;
|
|
1768
|
-
using key_equal = typename ht::key_equal;
|
|
1769
|
-
using mapped_type = T;
|
|
1770
|
-
using allocator_type = typename ht::allocator_type;
|
|
1771
|
-
|
|
1772
|
-
using size_type = typename ht::size_type;
|
|
1773
|
-
using difference_type = typename ht::difference_type;
|
|
1774
|
-
using pointer = typename ht::pointer;
|
|
1775
|
-
using const_pointer = typename ht::const_pointer;
|
|
1776
|
-
using reference = typename ht::reference;
|
|
1777
|
-
using const_reference = typename ht::const_reference;
|
|
1778
|
-
|
|
1779
|
-
using iterator = typename ht::iterator;
|
|
1780
|
-
using const_iterator = typename ht::const_iterator;
|
|
1781
|
-
using insert_ctx = typename ht::insert_ctx;
|
|
1782
|
-
|
|
1783
|
-
hasher hash_function() const {
|
|
1784
|
-
return rep.hash_function();
|
|
1785
|
-
}
|
|
1786
|
-
key_equal key_eq() const {
|
|
1787
|
-
return rep.key_eq();
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
public:
|
|
1791
|
-
THashMultiMap()
|
|
1792
|
-
: rep(0, hasher(), key_equal())
|
|
1793
|
-
{
|
|
1794
|
-
}
|
|
1795
|
-
template <typename TAllocParam>
|
|
1796
|
-
explicit THashMultiMap(TAllocParam* allocParam)
|
|
1797
|
-
: rep(0, hasher(), key_equal(), allocParam)
|
|
1798
|
-
{
|
|
1799
|
-
}
|
|
1800
|
-
explicit THashMultiMap(size_type n)
|
|
1801
|
-
: rep(n, hasher(), key_equal())
|
|
1802
|
-
{
|
|
1803
|
-
}
|
|
1804
|
-
THashMultiMap(size_type n, const hasher& hf)
|
|
1805
|
-
: rep(n, hf, key_equal())
|
|
1806
|
-
{
|
|
1807
|
-
}
|
|
1808
|
-
THashMultiMap(size_type n, const hasher& hf, const key_equal& eql)
|
|
1809
|
-
: rep(n, hf, eql)
|
|
1810
|
-
{
|
|
1811
|
-
}
|
|
1812
|
-
|
|
1813
|
-
template <class InputIterator>
|
|
1814
|
-
THashMultiMap(InputIterator f, InputIterator l)
|
|
1815
|
-
: rep(0, hasher(), key_equal())
|
|
1816
|
-
{
|
|
1817
|
-
rep.insert_equal(f, l);
|
|
1818
|
-
}
|
|
1819
|
-
template <class InputIterator>
|
|
1820
|
-
THashMultiMap(InputIterator f, InputIterator l, size_type n)
|
|
1821
|
-
: rep(n, hasher(), key_equal())
|
|
1822
|
-
{
|
|
1823
|
-
rep.insert_equal(f, l);
|
|
1824
|
-
}
|
|
1825
|
-
template <class InputIterator>
|
|
1826
|
-
THashMultiMap(InputIterator f, InputIterator l, size_type n, const hasher& hf)
|
|
1827
|
-
: rep(n, hf, key_equal())
|
|
1828
|
-
{
|
|
1829
|
-
rep.insert_equal(f, l);
|
|
1830
|
-
}
|
|
1831
|
-
template <class InputIterator>
|
|
1832
|
-
THashMultiMap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const key_equal& eql)
|
|
1833
|
-
: rep(n, hf, eql)
|
|
1834
|
-
{
|
|
1835
|
-
rep.insert_equal(f, l);
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
THashMultiMap(std::initializer_list<std::pair<Key, T>> list)
|
|
1839
|
-
: rep(list.size(), hasher(), key_equal())
|
|
1840
|
-
{
|
|
1841
|
-
for (const auto& v : list) {
|
|
1842
|
-
rep.emplace_equal_noresize(v);
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
// THashMultiMap has implicit copy/move constructors and copy-/move-assignment operators
|
|
1847
|
-
// because its implementation is backed by THashTable.
|
|
1848
|
-
// See hash_ut.cpp
|
|
1849
|
-
|
|
1850
|
-
public:
|
|
1851
|
-
size_type size() const {
|
|
1852
|
-
return rep.size();
|
|
1853
|
-
}
|
|
1854
|
-
yssize_t ysize() const {
|
|
1855
|
-
return (yssize_t)rep.size();
|
|
1856
|
-
}
|
|
1857
|
-
size_type max_size() const {
|
|
1858
|
-
return rep.max_size();
|
|
1859
|
-
}
|
|
1860
|
-
|
|
1861
|
-
Y_PURE_FUNCTION
|
|
1862
|
-
bool empty() const {
|
|
1863
|
-
return rep.empty();
|
|
1864
|
-
}
|
|
1865
|
-
explicit operator bool() const noexcept {
|
|
1866
|
-
return !empty();
|
|
1867
|
-
}
|
|
1868
|
-
void swap(THashMultiMap& hs) {
|
|
1869
|
-
rep.swap(hs.rep);
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
|
-
iterator begin() {
|
|
1873
|
-
return rep.begin();
|
|
1874
|
-
}
|
|
1875
|
-
iterator end() {
|
|
1876
|
-
return rep.end();
|
|
1877
|
-
}
|
|
1878
|
-
const_iterator begin() const {
|
|
1879
|
-
return rep.begin();
|
|
1880
|
-
}
|
|
1881
|
-
const_iterator end() const {
|
|
1882
|
-
return rep.end();
|
|
1883
|
-
}
|
|
1884
|
-
const_iterator cbegin() const {
|
|
1885
|
-
return rep.begin();
|
|
1886
|
-
}
|
|
1887
|
-
const_iterator cend() const {
|
|
1888
|
-
return rep.end();
|
|
1889
|
-
}
|
|
1890
|
-
|
|
1891
|
-
public:
|
|
1892
|
-
template <class InputIterator>
|
|
1893
|
-
void insert(InputIterator f, InputIterator l) {
|
|
1894
|
-
rep.insert_equal(f, l);
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
iterator insert(const value_type& obj) {
|
|
1898
|
-
return rep.insert_equal(obj);
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
template <typename... Args>
|
|
1902
|
-
iterator emplace(Args&&... args) {
|
|
1903
|
-
return rep.emplace_equal(std::forward<Args>(args)...);
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
iterator insert_noresize(const value_type& obj) {
|
|
1907
|
-
return rep.emplace_equal_noresize(obj);
|
|
1908
|
-
}
|
|
1909
|
-
|
|
1910
|
-
template <typename... Args>
|
|
1911
|
-
iterator emplace_noresize(Args&&... args) {
|
|
1912
|
-
return rep.emplace_equal_noresize(std::forward<Args>(args)...);
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
template <class TheObj>
|
|
1916
|
-
iterator insert_direct(const TheObj& obj, const insert_ctx& ins) {
|
|
1917
|
-
return rep.insert_direct(obj, ins);
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
template <typename... Args>
|
|
1921
|
-
iterator emplace_direct(const insert_ctx& ins, Args&&... args) {
|
|
1922
|
-
return rep.emplace_direct(ins, std::forward<Args>(args)...);
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
template <class TKey>
|
|
1926
|
-
const_iterator find(const TKey& key) const {
|
|
1927
|
-
return rep.find(key);
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
template <class TKey>
|
|
1931
|
-
iterator find(const TKey& key) {
|
|
1932
|
-
return rep.find(key);
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
template <class TheKey>
|
|
1936
|
-
iterator find(const TheKey& key, insert_ctx& ins) {
|
|
1937
|
-
return rep.find_i(key, ins);
|
|
1938
|
-
}
|
|
1939
|
-
|
|
1940
|
-
template <class TheKey>
|
|
1941
|
-
bool contains(const TheKey& key) const {
|
|
1942
|
-
return rep.find(key) != rep.end();
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
template <class TKey>
|
|
1946
|
-
size_type count(const TKey& key) const {
|
|
1947
|
-
return rep.count(key);
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
template <class TKey>
|
|
1951
|
-
std::pair<iterator, iterator> equal_range(const TKey& key) {
|
|
1952
|
-
return rep.equal_range(key);
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
template <class TKey>
|
|
1956
|
-
std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const {
|
|
1957
|
-
return rep.equal_range(key);
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
size_type erase(const key_type& key) {
|
|
1961
|
-
return rep.erase(key);
|
|
1962
|
-
}
|
|
1963
|
-
void erase(iterator it) {
|
|
1964
|
-
rep.erase(it);
|
|
1965
|
-
}
|
|
1966
|
-
void erase(iterator f, iterator l) {
|
|
1967
|
-
rep.erase(f, l);
|
|
1968
|
-
}
|
|
1969
|
-
void clear() {
|
|
1970
|
-
rep.clear();
|
|
1971
|
-
}
|
|
1972
|
-
void clear(size_t downsize_hint) {
|
|
1973
|
-
rep.clear(downsize_hint);
|
|
1974
|
-
}
|
|
1975
|
-
void basic_clear() {
|
|
1976
|
-
rep.basic_clear();
|
|
1977
|
-
}
|
|
1978
|
-
void release_nodes() {
|
|
1979
|
-
rep.release_nodes();
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
// if (stHash != NULL) bucket_count() must be equal to stHash->bucket_count()
|
|
1983
|
-
template <class KeySaver>
|
|
1984
|
-
int save_for_st(IOutputStream* stream, KeySaver& ks, sthash<int, int, THash<int>, TEqualTo<int>, typename KeySaver::TSizeType>* stHash = nullptr) const {
|
|
1985
|
-
return rep.template save_for_st<KeySaver>(stream, ks, stHash);
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
public:
|
|
1989
|
-
void reserve(size_type hint) {
|
|
1990
|
-
rep.reserve(hint);
|
|
1991
|
-
}
|
|
1992
|
-
size_type bucket_count() const {
|
|
1993
|
-
return rep.bucket_count();
|
|
1994
|
-
}
|
|
1995
|
-
size_type bucket_size(size_type n) const {
|
|
1996
|
-
return rep.bucket_size(n);
|
|
1997
|
-
}
|
|
1998
|
-
};
|
|
1999
|
-
|
|
2000
|
-
template <class Key, class T, class HF, class EqKey, class Alloc>
|
|
2001
|
-
inline bool operator==(const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm1, const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm2) {
|
|
2002
|
-
// NOTE: copy-pasted from
|
|
2003
|
-
// contrib/libs/cxxsupp/libcxx/include/unordered_map
|
|
2004
|
-
// and adapted to THashMultiMap
|
|
2005
|
-
if (hm1.size() != hm2.size()) {
|
|
2006
|
-
return false;
|
|
2007
|
-
}
|
|
2008
|
-
using const_iterator = typename THashMultiMap<Key, T, HF, EqKey, Alloc>::const_iterator;
|
|
2009
|
-
using TEqualRange = std::pair<const_iterator, const_iterator>;
|
|
2010
|
-
for (const_iterator it = hm1.begin(), end = hm1.end(); it != end;) {
|
|
2011
|
-
TEqualRange eq1 = hm1.equal_range(it->first);
|
|
2012
|
-
TEqualRange eq2 = hm2.equal_range(it->first);
|
|
2013
|
-
if (std::distance(eq1.first, eq1.second) != std::distance(eq2.first, eq2.second) ||
|
|
2014
|
-
!std::is_permutation(eq1.first, eq1.second, eq2.first))
|
|
2015
|
-
{
|
|
2016
|
-
return false;
|
|
2017
|
-
}
|
|
2018
|
-
it = eq1.second;
|
|
2019
|
-
}
|
|
2020
|
-
return true;
|
|
2021
|
-
}
|
|
2022
|
-
|
|
2023
|
-
template <class Key, class T, class HF, class EqKey, class Alloc>
|
|
2024
|
-
inline bool operator!=(const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm1, const THashMultiMap<Key, T, HF, EqKey, Alloc>& hm2) {
|
|
2025
|
-
return !(hm1 == hm2);
|
|
2026
|
-
}
|
|
2027
|
-
|
|
2028
|
-
// Cannot name it just 'Hash' because it clashes with too many class members in the code.
|
|
2029
|
-
template <class T>
|
|
2030
|
-
size_t ComputeHash(const T& value) {
|
|
2031
|
-
return THash<T>{}(value);
|
|
2032
|
-
}
|