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.
Files changed (289) hide show
  1. package/DEPLOYMENT.md +22 -15
  2. package/README.md +37 -27
  3. package/binding.gyp +5 -7
  4. package/build_scripts/bootstrap.js +2 -1
  5. package/build_scripts/out/build.js +46 -68
  6. package/build_scripts/out/build_model.js +1 -1
  7. package/build_scripts/out/{build_ya.js → build_native.js} +1 -1
  8. package/build_scripts/out/ci.js +5 -5
  9. package/build_scripts/out/config.js +32 -18
  10. package/build_scripts/out/install.js +5 -3
  11. package/build_scripts/out/package_prepublish.js +1 -1
  12. package/build_scripts/out/packaging.js +1 -19
  13. package/build_scripts/out/run_tests.js +1 -1
  14. package/build_scripts/out/test.js +8 -3
  15. package/config.json +18 -11
  16. package/inc/catboost/libs/model_interface/c_api.h +349 -3
  17. package/lib/catboost.d.ts +65 -21
  18. package/package.json +4 -4
  19. package/src/api_helpers.cpp +100 -24
  20. package/src/api_helpers.h +8 -7
  21. package/src/api_module.cpp +1 -2
  22. package/src/model.cpp +483 -83
  23. package/src/model.h +24 -9
  24. package/inc/contrib/libs/cxxsupp/system_stl/include/stlfwd +0 -14
  25. package/inc/util/charset/recode_result.h +0 -9
  26. package/inc/util/charset/unicode_table.h +0 -123
  27. package/inc/util/charset/unidata.h +0 -421
  28. package/inc/util/charset/utf8.h +0 -384
  29. package/inc/util/charset/wide.h +0 -843
  30. package/inc/util/charset/wide_specific.h +0 -22
  31. package/inc/util/datetime/base.h +0 -669
  32. package/inc/util/datetime/constants.h +0 -7
  33. package/inc/util/datetime/cputimer.h +0 -124
  34. package/inc/util/datetime/parser.h +0 -292
  35. package/inc/util/datetime/systime.h +0 -47
  36. package/inc/util/datetime/uptime.h +0 -8
  37. package/inc/util/digest/city.h +0 -88
  38. package/inc/util/digest/fnv.h +0 -73
  39. package/inc/util/digest/multi.h +0 -14
  40. package/inc/util/digest/murmur.h +0 -57
  41. package/inc/util/digest/numeric.h +0 -86
  42. package/inc/util/digest/sequence.h +0 -48
  43. package/inc/util/draft/date.h +0 -129
  44. package/inc/util/draft/datetime.h +0 -184
  45. package/inc/util/draft/enum.h +0 -136
  46. package/inc/util/draft/holder_vector.h +0 -102
  47. package/inc/util/draft/ip.h +0 -131
  48. package/inc/util/draft/matrix.h +0 -108
  49. package/inc/util/draft/memory.h +0 -40
  50. package/inc/util/folder/dirent_win.h +0 -46
  51. package/inc/util/folder/dirut.h +0 -121
  52. package/inc/util/folder/filelist.h +0 -81
  53. package/inc/util/folder/fts.h +0 -108
  54. package/inc/util/folder/iterator.h +0 -109
  55. package/inc/util/folder/lstat_win.h +0 -20
  56. package/inc/util/folder/path.h +0 -225
  57. package/inc/util/folder/pathsplit.h +0 -113
  58. package/inc/util/folder/tempdir.h +0 -42
  59. package/inc/util/generic/adaptor.h +0 -134
  60. package/inc/util/generic/algorithm.h +0 -765
  61. package/inc/util/generic/array_ref.h +0 -282
  62. package/inc/util/generic/array_size.h +0 -24
  63. package/inc/util/generic/benchmark/vector_count_ctor/f.h +0 -9
  64. package/inc/util/generic/bitmap.h +0 -1115
  65. package/inc/util/generic/bitops.h +0 -459
  66. package/inc/util/generic/bt_exception.h +0 -24
  67. package/inc/util/generic/buffer.h +0 -232
  68. package/inc/util/generic/cast.h +0 -176
  69. package/inc/util/generic/deque.h +0 -24
  70. package/inc/util/generic/explicit_type.h +0 -42
  71. package/inc/util/generic/fastqueue.h +0 -55
  72. package/inc/util/generic/flags.h +0 -244
  73. package/inc/util/generic/function.h +0 -103
  74. package/inc/util/generic/fwd.h +0 -171
  75. package/inc/util/generic/guid.h +0 -61
  76. package/inc/util/generic/hash.h +0 -2032
  77. package/inc/util/generic/hash_primes.h +0 -140
  78. package/inc/util/generic/hash_set.h +0 -490
  79. package/inc/util/generic/hide_ptr.h +0 -3
  80. package/inc/util/generic/intrlist.h +0 -876
  81. package/inc/util/generic/is_in.h +0 -53
  82. package/inc/util/generic/iterator.h +0 -137
  83. package/inc/util/generic/iterator_range.h +0 -105
  84. package/inc/util/generic/lazy_value.h +0 -66
  85. package/inc/util/generic/list.h +0 -22
  86. package/inc/util/generic/map.h +0 -44
  87. package/inc/util/generic/mapfindptr.h +0 -60
  88. package/inc/util/generic/maybe.h +0 -713
  89. package/inc/util/generic/maybe_traits.h +0 -164
  90. package/inc/util/generic/mem_copy.h +0 -55
  91. package/inc/util/generic/noncopyable.h +0 -38
  92. package/inc/util/generic/object_counter.h +0 -53
  93. package/inc/util/generic/ptr.h +0 -1113
  94. package/inc/util/generic/queue.h +0 -57
  95. package/inc/util/generic/refcount.h +0 -162
  96. package/inc/util/generic/reserve.h +0 -11
  97. package/inc/util/generic/scope.h +0 -65
  98. package/inc/util/generic/serialized_enum.h +0 -406
  99. package/inc/util/generic/set.h +0 -42
  100. package/inc/util/generic/singleton.h +0 -136
  101. package/inc/util/generic/size_literals.h +0 -65
  102. package/inc/util/generic/stack.h +0 -18
  103. package/inc/util/generic/store_policy.h +0 -120
  104. package/inc/util/generic/strbase.h +0 -612
  105. package/inc/util/generic/strbuf.h +0 -552
  106. package/inc/util/generic/strfcpy.h +0 -17
  107. package/inc/util/generic/string.h +0 -1572
  108. package/inc/util/generic/string_hash.h +0 -21
  109. package/inc/util/generic/string_ut.h +0 -1175
  110. package/inc/util/generic/type_name.h +0 -34
  111. package/inc/util/generic/typelist.h +0 -114
  112. package/inc/util/generic/typetraits.h +0 -325
  113. package/inc/util/generic/utility.h +0 -132
  114. package/inc/util/generic/va_args.h +0 -400
  115. package/inc/util/generic/variant.h +0 -631
  116. package/inc/util/generic/variant_traits.h +0 -171
  117. package/inc/util/generic/vector.h +0 -119
  118. package/inc/util/generic/xrange.h +0 -258
  119. package/inc/util/generic/yexception.h +0 -212
  120. package/inc/util/generic/yexception_ut.h +0 -14
  121. package/inc/util/generic/ylimits.h +0 -92
  122. package/inc/util/generic/ymath.h +0 -206
  123. package/inc/util/memory/addstorage.h +0 -93
  124. package/inc/util/memory/alloc.h +0 -27
  125. package/inc/util/memory/blob.h +0 -296
  126. package/inc/util/memory/mmapalloc.h +0 -8
  127. package/inc/util/memory/pool.h +0 -432
  128. package/inc/util/memory/segmented_string_pool.h +0 -194
  129. package/inc/util/memory/segpool_alloc.h +0 -118
  130. package/inc/util/memory/smallobj.h +0 -141
  131. package/inc/util/memory/tempbuf.h +0 -111
  132. package/inc/util/network/address.h +0 -136
  133. package/inc/util/network/endpoint.h +0 -61
  134. package/inc/util/network/hostip.h +0 -16
  135. package/inc/util/network/init.h +0 -60
  136. package/inc/util/network/interface.h +0 -17
  137. package/inc/util/network/iovec.h +0 -65
  138. package/inc/util/network/ip.h +0 -116
  139. package/inc/util/network/nonblock.h +0 -8
  140. package/inc/util/network/pair.h +0 -9
  141. package/inc/util/network/poller.h +0 -58
  142. package/inc/util/network/pollerimpl.h +0 -707
  143. package/inc/util/network/sock.h +0 -608
  144. package/inc/util/network/socket.h +0 -421
  145. package/inc/util/random/common_ops.h +0 -130
  146. package/inc/util/random/easy.h +0 -47
  147. package/inc/util/random/entropy.h +0 -21
  148. package/inc/util/random/fast.h +0 -101
  149. package/inc/util/random/init_atfork.h +0 -3
  150. package/inc/util/random/lcg_engine.h +0 -66
  151. package/inc/util/random/mersenne.h +0 -46
  152. package/inc/util/random/mersenne32.h +0 -50
  153. package/inc/util/random/mersenne64.h +0 -50
  154. package/inc/util/random/normal.h +0 -38
  155. package/inc/util/random/random.h +0 -30
  156. package/inc/util/random/shuffle.h +0 -39
  157. package/inc/util/str_stl.h +0 -266
  158. package/inc/util/stream/aligned.h +0 -99
  159. package/inc/util/stream/buffer.h +0 -119
  160. package/inc/util/stream/buffered.h +0 -225
  161. package/inc/util/stream/debug.h +0 -53
  162. package/inc/util/stream/direct_io.h +0 -43
  163. package/inc/util/stream/file.h +0 -108
  164. package/inc/util/stream/format.h +0 -444
  165. package/inc/util/stream/fwd.h +0 -100
  166. package/inc/util/stream/hex.h +0 -8
  167. package/inc/util/stream/holder.h +0 -44
  168. package/inc/util/stream/input.h +0 -273
  169. package/inc/util/stream/labeled.h +0 -19
  170. package/inc/util/stream/length.h +0 -100
  171. package/inc/util/stream/mem.h +0 -255
  172. package/inc/util/stream/multi.h +0 -32
  173. package/inc/util/stream/null.h +0 -61
  174. package/inc/util/stream/output.h +0 -304
  175. package/inc/util/stream/pipe.h +0 -112
  176. package/inc/util/stream/printf.h +0 -25
  177. package/inc/util/stream/str.h +0 -207
  178. package/inc/util/stream/tee.h +0 -28
  179. package/inc/util/stream/tempbuf.h +0 -21
  180. package/inc/util/stream/tokenizer.h +0 -214
  181. package/inc/util/stream/trace.h +0 -60
  182. package/inc/util/stream/walk.h +0 -35
  183. package/inc/util/stream/zerocopy.h +0 -91
  184. package/inc/util/stream/zerocopy_output.h +0 -57
  185. package/inc/util/stream/zlib.h +0 -173
  186. package/inc/util/string/ascii.h +0 -236
  187. package/inc/util/string/builder.h +0 -39
  188. package/inc/util/string/cast.h +0 -347
  189. package/inc/util/string/cstriter.h +0 -14
  190. package/inc/util/string/escape.h +0 -70
  191. package/inc/util/string/hex.h +0 -59
  192. package/inc/util/string/join.h +0 -194
  193. package/inc/util/string/printf.h +0 -13
  194. package/inc/util/string/reverse.h +0 -16
  195. package/inc/util/string/split.h +0 -1080
  196. package/inc/util/string/strip.h +0 -257
  197. package/inc/util/string/strspn.h +0 -65
  198. package/inc/util/string/subst.h +0 -56
  199. package/inc/util/string/type.h +0 -50
  200. package/inc/util/string/util.h +0 -195
  201. package/inc/util/string/vector.h +0 -132
  202. package/inc/util/system/align.h +0 -50
  203. package/inc/util/system/atexit.h +0 -22
  204. package/inc/util/system/atomic.h +0 -51
  205. package/inc/util/system/atomic_gcc.h +0 -90
  206. package/inc/util/system/atomic_ops.h +0 -189
  207. package/inc/util/system/atomic_win.h +0 -114
  208. package/inc/util/system/backtrace.h +0 -39
  209. package/inc/util/system/byteorder.h +0 -186
  210. package/inc/util/system/compat.h +0 -84
  211. package/inc/util/system/compiler.h +0 -620
  212. package/inc/util/system/condvar.h +0 -71
  213. package/inc/util/system/context.h +0 -181
  214. package/inc/util/system/context_aarch64.h +0 -8
  215. package/inc/util/system/context_i686.h +0 -9
  216. package/inc/util/system/context_x86.h +0 -12
  217. package/inc/util/system/context_x86_64.h +0 -7
  218. package/inc/util/system/cpu_id.h +0 -159
  219. package/inc/util/system/daemon.h +0 -28
  220. package/inc/util/system/datetime.h +0 -98
  221. package/inc/util/system/defaults.h +0 -149
  222. package/inc/util/system/demangle.h +0 -5
  223. package/inc/util/system/demangle_impl.h +0 -23
  224. package/inc/util/system/direct_io.h +0 -71
  225. package/inc/util/system/dynlib.h +0 -119
  226. package/inc/util/system/env.h +0 -32
  227. package/inc/util/system/error.h +0 -95
  228. package/inc/util/system/event.h +0 -122
  229. package/inc/util/system/execpath.h +0 -17
  230. package/inc/util/system/fasttime.h +0 -6
  231. package/inc/util/system/fhandle.h +0 -27
  232. package/inc/util/system/file.h +0 -210
  233. package/inc/util/system/file_lock.h +0 -34
  234. package/inc/util/system/filemap.h +0 -383
  235. package/inc/util/system/flock.h +0 -35
  236. package/inc/util/system/fs.h +0 -156
  237. package/inc/util/system/fs_win.h +0 -29
  238. package/inc/util/system/fstat.h +0 -46
  239. package/inc/util/system/getpid.h +0 -12
  240. package/inc/util/system/guard.h +0 -179
  241. package/inc/util/system/hi_lo.h +0 -139
  242. package/inc/util/system/hostname.h +0 -10
  243. package/inc/util/system/hp_timer.h +0 -36
  244. package/inc/util/system/info.h +0 -12
  245. package/inc/util/system/interrupt_signals.h +0 -22
  246. package/inc/util/system/madvise.h +0 -30
  247. package/inc/util/system/maxlen.h +0 -32
  248. package/inc/util/system/mem_info.h +0 -18
  249. package/inc/util/system/mincore.h +0 -38
  250. package/inc/util/system/mktemp.h +0 -11
  251. package/inc/util/system/mlock.h +0 -43
  252. package/inc/util/system/mutex.h +0 -67
  253. package/inc/util/system/nice.h +0 -3
  254. package/inc/util/system/pipe.h +0 -90
  255. package/inc/util/system/platform.h +0 -246
  256. package/inc/util/system/progname.h +0 -13
  257. package/inc/util/system/protect.h +0 -25
  258. package/inc/util/system/rusage.h +0 -26
  259. package/inc/util/system/rwlock.h +0 -78
  260. package/inc/util/system/sanitizers.h +0 -122
  261. package/inc/util/system/sem.h +0 -41
  262. package/inc/util/system/shellcommand.h +0 -472
  263. package/inc/util/system/shmat.h +0 -32
  264. package/inc/util/system/sigset.h +0 -78
  265. package/inc/util/system/spin_wait.h +0 -10
  266. package/inc/util/system/spinlock.h +0 -121
  267. package/inc/util/system/src_location.h +0 -25
  268. package/inc/util/system/src_root.h +0 -68
  269. package/inc/util/system/sys_alloc.h +0 -43
  270. package/inc/util/system/sysstat.h +0 -52
  271. package/inc/util/system/tempfile.h +0 -34
  272. package/inc/util/system/thread.h +0 -167
  273. package/inc/util/system/tls.h +0 -307
  274. package/inc/util/system/types.h +0 -119
  275. package/inc/util/system/unaligned_mem.h +0 -67
  276. package/inc/util/system/user.h +0 -5
  277. package/inc/util/system/utime.h +0 -6
  278. package/inc/util/system/valgrind.h +0 -48
  279. package/inc/util/system/winint.h +0 -43
  280. package/inc/util/system/yassert.h +0 -121
  281. package/inc/util/system/yield.h +0 -4
  282. package/inc/util/thread/factory.h +0 -65
  283. package/inc/util/thread/fwd.h +0 -30
  284. package/inc/util/thread/lfqueue.h +0 -406
  285. package/inc/util/thread/lfstack.h +0 -188
  286. package/inc/util/thread/pool.h +0 -388
  287. package/inc/util/thread/singleton.h +0 -42
  288. package/inc/util/ysafeptr.h +0 -427
  289. package/inc/util/ysaveload.h +0 -700
@@ -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
- }