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