]> git.proxmox.com Git - ceph.git/blame - ceph/src/include/cpp-btree/btree_container.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / include / cpp-btree / btree_container.h
CommitLineData
9f95a23c 1// Copyright 2018 The Abseil Authors.
7c673cae
FG
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
9f95a23c 7// https://www.apache.org/licenses/LICENSE-2.0
7c673cae
FG
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
9f95a23c 15#pragma once
7c673cae 16
9f95a23c
TL
17#include <algorithm>
18#include <initializer_list>
19#include <iterator>
20#include <type_traits>
7c673cae
FG
21#include <utility>
22
23#include "btree.h"
24
9f95a23c 25namespace btree::internal {
7c673cae 26
9f95a23c 27// A common base class for btree_set, btree_map, btree_multiset, and
7c673cae
FG
28// btree_multimap.
29template <typename Tree>
30class btree_container {
9f95a23c 31 using params_type = typename Tree::params_type;
7c673cae 32
9f95a23c
TL
33 protected:
34 // Alias used for heterogeneous lookup functions.
35 // `key_arg<K>` evaluates to `K` when the functors are transparent and to
36 // `key_type` otherwise. It permits template argument deduction on `K` for the
37 // transparent case.
38 template <class Compare>
39 using is_transparent_t = typename Compare::is_transparent;
40 template <class K>
41 using key_arg =
42 std::conditional_t<
43 std::experimental::is_detected_v<is_transparent_t, typename Tree::key_compare>,
44 K,
45 typename Tree::key_type>;
7c673cae
FG
46
47 public:
9f95a23c
TL
48 using key_type = typename Tree::key_type;
49 using value_type = typename Tree::value_type;
50 using size_type = typename Tree::size_type;
51 using difference_type = typename Tree::difference_type;
52 using key_compare = typename Tree::key_compare;
53 using value_compare = typename Tree::value_compare;
54 using allocator_type = typename Tree::allocator_type;
55 using reference = typename Tree::reference;
56 using const_reference = typename Tree::const_reference;
57 using pointer = typename Tree::pointer;
58 using const_pointer = typename Tree::const_pointer;
59 using iterator = typename Tree::iterator;
60 using const_iterator = typename Tree::const_iterator;
61 using reverse_iterator = typename Tree::reverse_iterator;
62 using const_reverse_iterator = typename Tree::const_reverse_iterator;
63
64 // Constructors/assignments.
65 btree_container() : tree_(key_compare(), allocator_type()) {}
66 explicit btree_container(const key_compare &comp,
67 const allocator_type &alloc = allocator_type())
68 : tree_(comp, alloc) {}
69 btree_container(const btree_container &x) = default;
70 btree_container(btree_container &&x) noexcept = default;
71 btree_container &operator=(const btree_container &x) = default;
72 btree_container &operator=(btree_container &&x) noexcept(
73 std::is_nothrow_move_assignable<Tree>::value) = default;
7c673cae
FG
74
75 // Iterator routines.
76 iterator begin() { return tree_.begin(); }
77 const_iterator begin() const { return tree_.begin(); }
9f95a23c 78 const_iterator cbegin() const { return tree_.begin(); }
7c673cae
FG
79 iterator end() { return tree_.end(); }
80 const_iterator end() const { return tree_.end(); }
9f95a23c 81 const_iterator cend() const { return tree_.end(); }
7c673cae
FG
82 reverse_iterator rbegin() { return tree_.rbegin(); }
83 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
9f95a23c 84 const_reverse_iterator crbegin() const { return tree_.rbegin(); }
7c673cae
FG
85 reverse_iterator rend() { return tree_.rend(); }
86 const_reverse_iterator rend() const { return tree_.rend(); }
9f95a23c 87 const_reverse_iterator crend() const { return tree_.rend(); }
7c673cae
FG
88
89 // Lookup routines.
9f95a23c
TL
90 template <typename K = key_type>
91 iterator find(const key_arg<K> &key) {
92 return tree_.find(key);
93 }
94 template <typename K = key_type>
95 const_iterator find(const key_arg<K> &key) const {
96 return tree_.find(key);
97 }
98 template <typename K = key_type>
99 bool contains(const key_arg<K> &key) const {
100 return find(key) != end();
101 }
102 template <typename K = key_type>
103 iterator lower_bound(const key_arg<K> &key) {
7c673cae
FG
104 return tree_.lower_bound(key);
105 }
9f95a23c
TL
106 template <typename K = key_type>
107 const_iterator lower_bound(const key_arg<K> &key) const {
7c673cae
FG
108 return tree_.lower_bound(key);
109 }
9f95a23c
TL
110 template <typename K = key_type>
111 iterator upper_bound(const key_arg<K> &key) {
7c673cae
FG
112 return tree_.upper_bound(key);
113 }
9f95a23c
TL
114 template <typename K = key_type>
115 const_iterator upper_bound(const key_arg<K> &key) const {
7c673cae
FG
116 return tree_.upper_bound(key);
117 }
9f95a23c
TL
118 template <typename K = key_type>
119 std::pair<iterator, iterator> equal_range(const key_arg<K> &key) {
7c673cae
FG
120 return tree_.equal_range(key);
121 }
9f95a23c
TL
122 template <typename K = key_type>
123 std::pair<const_iterator, const_iterator> equal_range(
124 const key_arg<K> &key) const {
7c673cae
FG
125 return tree_.equal_range(key);
126 }
127
9f95a23c
TL
128 // Deletion routines. Note that there is also a deletion routine that is
129 // specific to btree_set_container/btree_multiset_container.
130
131 // Erase the specified iterator from the btree. The iterator must be valid
132 // (i.e. not equal to end()). Return an iterator pointing to the node after
133 // the one that was erased (or end() if none exists).
134 iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); }
135 iterator erase(iterator iter) { return tree_.erase(iter); }
136 iterator erase(const_iterator first, const_iterator last) {
137 return tree_.erase(iterator(first), iterator(last)).second;
7c673cae
FG
138 }
139
9f95a23c
TL
140 public:
141 // Utility routines.
142 void clear() { tree_.clear(); }
143 void swap(btree_container &x) { tree_.swap(x.tree_); }
144 void verify() const { tree_.verify(); }
145
7c673cae
FG
146 // Size routines.
147 size_type size() const { return tree_.size(); }
148 size_type max_size() const { return tree_.max_size(); }
149 bool empty() const { return tree_.empty(); }
9f95a23c
TL
150
151 friend bool operator==(const btree_container &x, const btree_container &y) {
152 if (x.size() != y.size()) return false;
153 return std::equal(x.begin(), x.end(), y.begin());
7c673cae
FG
154 }
155
9f95a23c
TL
156 friend bool operator!=(const btree_container &x, const btree_container &y) {
157 return !(x == y);
7c673cae
FG
158 }
159
9f95a23c
TL
160 friend bool operator<(const btree_container &x, const btree_container &y) {
161 return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
162 }
163
164 friend bool operator>(const btree_container &x, const btree_container &y) {
165 return y < x;
166 }
167
168 friend bool operator<=(const btree_container &x, const btree_container &y) {
169 return !(y < x);
170 }
171
172 friend bool operator>=(const btree_container &x, const btree_container &y) {
173 return !(x < y);
174 }
175
176 // The allocator used by the btree.
177 allocator_type get_allocator() const { return tree_.get_allocator(); }
178
179 // The key comparator used by the btree.
180 key_compare key_comp() const { return tree_.key_comp(); }
181 value_compare value_comp() const { return tree_.value_comp(); }
7c673cae
FG
182
183 protected:
184 Tree tree_;
185};
186
9f95a23c 187// A common base class for btree_set and btree_map.
7c673cae 188template <typename Tree>
9f95a23c
TL
189class btree_set_container : public btree_container<Tree> {
190 using super_type = btree_container<Tree>;
191 using params_type = typename Tree::params_type;
192 using init_type = typename params_type::init_type;
193 using is_key_compare_to = typename params_type::is_key_compare_to;
194 friend class BtreeNodePeer;
7c673cae 195
9f95a23c
TL
196 protected:
197 template <class K>
198 using key_arg = typename super_type::template key_arg<K>;
7c673cae
FG
199
200 public:
9f95a23c
TL
201 using key_type = typename Tree::key_type;
202 using value_type = typename Tree::value_type;
203 using size_type = typename Tree::size_type;
204 using key_compare = typename Tree::key_compare;
205 using allocator_type = typename Tree::allocator_type;
206 using iterator = typename Tree::iterator;
207 using const_iterator = typename Tree::const_iterator;
208
209 // Inherit constructors.
210 using super_type::super_type;
211 btree_set_container() {}
7c673cae
FG
212
213 // Range constructor.
214 template <class InputIterator>
9f95a23c
TL
215 btree_set_container(InputIterator b, InputIterator e,
216 const key_compare &comp = key_compare(),
217 const allocator_type &alloc = allocator_type())
7c673cae
FG
218 : super_type(comp, alloc) {
219 insert(b, e);
220 }
221
9f95a23c
TL
222 // Initializer list constructor.
223 btree_set_container(std::initializer_list<init_type> init,
224 const key_compare &comp = key_compare(),
225 const allocator_type &alloc = allocator_type())
226 : btree_set_container(init.begin(), init.end(), comp, alloc) {}
227
7c673cae 228 // Lookup routines.
9f95a23c
TL
229 template <typename K = key_type>
230 size_type count(const key_arg<K> &key) const {
7c673cae
FG
231 return this->tree_.count_unique(key);
232 }
233
234 // Insertion routines.
9f95a23c
TL
235 std::pair<iterator, bool> insert(const value_type &x) {
236 return this->tree_.insert_unique(params_type::key(x), x);
237 }
238 std::pair<iterator, bool> insert(value_type &&x) {
239 return this->tree_.insert_unique(params_type::key(x), std::move(x));
240 }
241 template <typename... Args>
242 std::pair<iterator, bool> emplace(Args &&... args) {
243 init_type v(std::forward<Args>(args)...);
244 return this->tree_.insert_unique(params_type::key(v), std::move(v));
245 }
246 iterator insert(const_iterator position, const value_type &x) {
247 return this->tree_
248 .insert_hint_unique(iterator(position), params_type::key(x), x)
249 .first;
250 }
251 iterator insert(const_iterator position, value_type &&x) {
252 return this->tree_
253 .insert_hint_unique(iterator(position), params_type::key(x),
254 std::move(x))
255 .first;
256 }
257 template <typename... Args>
258 iterator emplace_hint(const_iterator position, Args &&... args) {
259 init_type v(std::forward<Args>(args)...);
260 return this->tree_
261 .insert_hint_unique(iterator(position), params_type::key(v),
262 std::move(v))
263 .first;
7c673cae
FG
264 }
265 template <typename InputIterator>
266 void insert(InputIterator b, InputIterator e) {
9f95a23c
TL
267 this->tree_.insert_iterator_unique(b, e);
268 }
269 void insert(std::initializer_list<init_type> init) {
270 this->tree_.insert_iterator_unique(init.begin(), init.end());
7c673cae 271 }
7c673cae 272 // Deletion routines.
9f95a23c
TL
273 template <typename K = key_type>
274 size_type erase(const key_arg<K> &key) {
7c673cae
FG
275 return this->tree_.erase_unique(key);
276 }
9f95a23c
TL
277 using super_type::erase;
278
279 // Merge routines.
280 // Moves elements from `src` into `this`. If the element already exists in
281 // `this`, it is left unmodified in `src`.
282 template <
283 typename T,
284 typename std::enable_if_t<
285 std::conjunction_v<
286 std::is_same<value_type, typename T::value_type>,
287 std::is_same<allocator_type, typename T::allocator_type>,
288 std::is_same<typename params_type::is_map_container,
289 typename T::params_type::is_map_container>>,
290 int> = 0>
291 void merge(btree_container<T> &src) { // NOLINT
292 for (auto src_it = src.begin(); src_it != src.end();) {
293 if (insert(std::move(*src_it)).second) {
294 src_it = src.erase(src_it);
295 } else {
296 ++src_it;
297 }
298 }
7c673cae 299 }
9f95a23c
TL
300
301 template <
302 typename T,
303 typename std::enable_if_t<
304 std::conjunction_v<
305 std::is_same<value_type, typename T::value_type>,
306 std::is_same<allocator_type, typename T::allocator_type>,
307 std::is_same<typename params_type::is_map_container,
308 typename T::params_type::is_map_container>>,
309 int> = 0>
310 void merge(btree_container<T> &&src) {
311 merge(src);
7c673cae
FG
312 }
313};
314
315// A common base class for btree_map and safe_btree_map.
9f95a23c 316// Base class for btree_map.
7c673cae 317template <typename Tree>
9f95a23c
TL
318class btree_map_container : public btree_set_container<Tree> {
319 using super_type = btree_set_container<Tree>;
320 using params_type = typename Tree::params_type;
7c673cae 321
9f95a23c
TL
322 protected:
323 template <class K>
324 using key_arg = typename super_type::template key_arg<K>;
7c673cae
FG
325
326 public:
9f95a23c
TL
327 using key_type = typename Tree::key_type;
328 using mapped_type = typename params_type::mapped_type;
329 using value_type = typename Tree::value_type;
330 using key_compare = typename Tree::key_compare;
331 using allocator_type = typename Tree::allocator_type;
332 using iterator = typename Tree::iterator;
333 using const_iterator = typename Tree::const_iterator;
334
335 // Inherit constructors.
336 using super_type::super_type;
337 btree_map_container() {}
7c673cae
FG
338
339 // Insertion routines.
9f95a23c
TL
340 template <typename... Args>
341 std::pair<iterator, bool> try_emplace(const key_type &k, Args &&... args) {
342 return this->tree_.insert_unique(
343 k, std::piecewise_construct, std::forward_as_tuple(k),
344 std::forward_as_tuple(std::forward<Args>(args)...));
345 }
346 template <typename... Args>
347 std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args) {
348 // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
349 // and then using `k` unsequenced. This is safe because the move is into a
350 // forwarding reference and insert_unique guarantees that `key` is never
351 // referenced after consuming `args`.
352 const key_type& key_ref = k;
353 return this->tree_.insert_unique(
354 key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)),
355 std::forward_as_tuple(std::forward<Args>(args)...));
356 }
357 template <typename... Args>
358 iterator try_emplace(const_iterator hint, const key_type &k,
359 Args &&... args) {
360 return this->tree_
361 .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
362 std::forward_as_tuple(k),
363 std::forward_as_tuple(std::forward<Args>(args)...))
364 .first;
365 }
366 template <typename... Args>
367 iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args) {
368 // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
369 // and then using `k` unsequenced. This is safe because the move is into a
370 // forwarding reference and insert_hint_unique guarantees that `key` is
371 // never referenced after consuming `args`.
372 const key_type& key_ref = k;
373 return this->tree_
374 .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct,
375 std::forward_as_tuple(std::move(k)),
376 std::forward_as_tuple(std::forward<Args>(args)...))
377 .first;
378 }
379 mapped_type &operator[](const key_type &k) {
380 return try_emplace(k).first->second;
381 }
382 mapped_type &operator[](key_type &&k) {
383 return try_emplace(std::move(k)).first->second;
384 }
385
386 template <typename K = key_type>
387 mapped_type &at(const key_arg<K> &key) {
388 auto it = this->find(key);
389 if (it == this->end())
390 throw std::out_of_range("btree_map::at");
391 return it->second;
392 }
393 template <typename K = key_type>
394 const mapped_type &at(const key_arg<K> &key) const {
395 auto it = this->find(key);
396 if (it == this->end())
397 throw std::out_of_range("btree_map::at");
398 return it->second;
7c673cae
FG
399 }
400};
401
402// A common base class for btree_multiset and btree_multimap.
403template <typename Tree>
9f95a23c
TL
404class btree_multiset_container : public btree_container<Tree> {
405 using super_type = btree_container<Tree>;
406 using params_type = typename Tree::params_type;
407 using init_type = typename params_type::init_type;
408 using is_key_compare_to = typename params_type::is_key_compare_to;
7c673cae 409
9f95a23c
TL
410 template <class K>
411 using key_arg = typename super_type::template key_arg<K>;
7c673cae
FG
412
413 public:
9f95a23c
TL
414 using key_type = typename Tree::key_type;
415 using value_type = typename Tree::value_type;
416 using size_type = typename Tree::size_type;
417 using key_compare = typename Tree::key_compare;
418 using allocator_type = typename Tree::allocator_type;
419 using iterator = typename Tree::iterator;
420 using const_iterator = typename Tree::const_iterator;
9f95a23c
TL
421
422 // Inherit constructors.
423 using super_type::super_type;
424 btree_multiset_container() {}
7c673cae
FG
425
426 // Range constructor.
427 template <class InputIterator>
9f95a23c
TL
428 btree_multiset_container(InputIterator b, InputIterator e,
429 const key_compare &comp = key_compare(),
430 const allocator_type &alloc = allocator_type())
7c673cae
FG
431 : super_type(comp, alloc) {
432 insert(b, e);
433 }
434
9f95a23c
TL
435 // Initializer list constructor.
436 btree_multiset_container(std::initializer_list<init_type> init,
437 const key_compare &comp = key_compare(),
438 const allocator_type &alloc = allocator_type())
439 : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
440
7c673cae 441 // Lookup routines.
9f95a23c
TL
442 template <typename K = key_type>
443 size_type count(const key_arg<K> &key) const {
7c673cae
FG
444 return this->tree_.count_multi(key);
445 }
446
447 // Insertion routines.
9f95a23c
TL
448 iterator insert(const value_type &x) { return this->tree_.insert_multi(x); }
449 iterator insert(value_type &&x) {
450 return this->tree_.insert_multi(std::move(x));
7c673cae 451 }
9f95a23c
TL
452 iterator insert(const_iterator position, const value_type &x) {
453 return this->tree_.insert_hint_multi(iterator(position), x);
454 }
455 iterator insert(const_iterator position, value_type &&x) {
456 return this->tree_.insert_hint_multi(iterator(position), std::move(x));
7c673cae
FG
457 }
458 template <typename InputIterator>
459 void insert(InputIterator b, InputIterator e) {
9f95a23c
TL
460 this->tree_.insert_iterator_multi(b, e);
461 }
462 void insert(std::initializer_list<init_type> init) {
463 this->tree_.insert_iterator_multi(init.begin(), init.end());
464 }
465 template <typename... Args>
466 iterator emplace(Args &&... args) {
467 return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
468 }
469 template <typename... Args>
470 iterator emplace_hint(const_iterator position, Args &&... args) {
471 return this->tree_.insert_hint_multi(
472 iterator(position), init_type(std::forward<Args>(args)...));
473 }
7c673cae
FG
474
475 // Deletion routines.
9f95a23c
TL
476 template <typename K = key_type>
477 size_type erase(const key_arg<K> &key) {
7c673cae
FG
478 return this->tree_.erase_multi(key);
479 }
9f95a23c
TL
480 using super_type::erase;
481
482 // Merge routines.
483 // Moves all elements from `src` into `this`.
484 template <
485 typename T,
486 typename std::enable_if_t<
487 std::conjunction_v<
488 std::is_same<value_type, typename T::value_type>,
489 std::is_same<allocator_type, typename T::allocator_type>,
490 std::is_same<typename params_type::is_map_container,
491 typename T::params_type::is_map_container>>,
492 int> = 0>
493 void merge(btree_container<T> &src) { // NOLINT
494 insert(std::make_move_iterator(src.begin()),
495 std::make_move_iterator(src.end()));
496 src.clear();
497 }
498
499 template <
500 typename T,
501 typename std::enable_if_t<
502 std::conjunction_v<
503 std::is_same<value_type, typename T::value_type>,
504 std::is_same<allocator_type, typename T::allocator_type>,
505 std::is_same<typename params_type::is_map_container,
506 typename T::params_type::is_map_container>>,
507 int> = 0>
508 void merge(btree_container<T> &&src) {
509 merge(src);
7c673cae
FG
510 }
511};
512
9f95a23c
TL
513// A base class for btree_multimap.
514template <typename Tree>
515class btree_multimap_container : public btree_multiset_container<Tree> {
516 using super_type = btree_multiset_container<Tree>;
517 using params_type = typename Tree::params_type;
7c673cae 518
9f95a23c
TL
519 public:
520 using mapped_type = typename params_type::mapped_type;
521
522 // Inherit constructors.
523 using super_type::super_type;
524 btree_multimap_container() {}
525};
526} // namespace btree::internal