/* * Copyright (c) 2018 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_INTERNAL_RBTREE_POLICIES #define LIBCPP_INTERNAL_RBTREE_POLICIES #include #include namespace std::aux { struct rbtree_single_policy { template static typename Tree::size_type count(const Tree& tree, const Key& key) { return tree.find(key) == tree.end() ? 0 : 1; } template static typename Tree::size_type erase(Tree& tree, const Key& key) { using size_type = typename Tree::size_type; auto it = tree.find(key); if (it == tree.end()) return size_type{}; else tree.delete_node(it.node()); return size_type{1}; // This is the multi version -.- /* size_type res{}; */ /* while (tree.keys_equal(tree.get_key(*it), key)) */ /* { */ /* auto node = it.node(); */ /* ++it; */ /* tree->delete_node(node); */ /* ++res; */ /* } */ /* return res; */ } template static typename Tree::iterator lower_bound(Tree& tree, const Key& key) { using iterator = typename Tree::iterator; auto node = tree.find_parent_for_insertion(key); iterator it{node, false}; auto beg = tree.begin(); auto end = tree.end(); if (tree.key_compare_(tree.get_key(*it), key)) { // Predecessor. if (it != end) return ++it; else return it; } else if (tree.key_compare_(key, tree.get_key(*it))) { // Successor. if (it != beg) return --it; else return it; } else // Perfect match. return it; return it; } template static typename Tree::const_iterator lower_bound_const(const Tree& tree, const Key& key) { using const_iterator = typename Tree::const_iterator; auto node = tree.find_parent_for_insertion(key); const_iterator it{node, false}; auto beg = tree.begin(); auto end = tree.end(); if (tree.key_compare_(tree.get_key(*it), key)) { // Predecessor. if (it != end) return ++it; else return it; } else if (tree.key_compare_(key, tree.get_key(*it))) { // Successor. if (it != beg) return --it; else return it; } else // Perfect match. return it; return it; } template static typename Tree::iterator upper_bound(Tree& tree, const Key& key) { /** * If key isn't in the tree, we get it's * successor or tree.end(). If key is * in the tree, we get it. * In the first case, the successor is also * the upper bound, so we just return it, * otherwise (as long as it != end()) we * increment. */ auto it = lower_bound(tree, key); if (it == tree.end()) return it; else if (tree.keys_equal(key, *it)) return ++it; else return it; } template static typename Tree::const_iterator upper_bound_const(const Tree& tree, const Key& key) { /** * If key isn't in the tree, we get it's * successor or tree.end(). If key is * in the tree, we get it. * In the first case, the successor is also * the upper bound, so we just return it, * otherwise (as long as it != end()) we * increment. */ auto it = lower_bound_const(tree, key); if (it == tree.end()) return it; else if (tree.keys_equal(key, *it)) return ++it; else return it; } template static pair< typename Tree::iterator, typename Tree::iterator > equal_range(Tree& tree, const Key& key) { return make_pair( lower_bound(tree, key), upper_bound(tree, key) ); } template static pair< typename Tree::const_iterator, typename Tree::const_iterator > equal_range_const(const Tree& tree, const Key& key) { return make_pair( lower_bound_const(tree, key), upper_bound_const(tree, key) ); } /** * Note: We have to duplicate code for emplace, insert(const&) * and insert(&&) here, because the node (which makes distinction * between the arguments) is only created if the value isn't * in the tree already. */ template static pair< typename Tree::iterator, bool > emplace(Tree& tree, Args&&... args) { using value_type = typename Tree::value_type; using iterator = typename Tree::iterator; using node_type = typename Tree::node_type; auto val = value_type{forward(args)...}; auto parent = tree.find_parent_for_insertion(val); if (!parent) { tree.root_ = new node_type{move(val)}; return make_pair(iterator{tree.root_}, true); } if (tree.keys_equal(tree.get_key(parent->value), tree.get_key(val))) return make_pair(iterator{parent}, false); auto node = new node_type{move(val)}; if (tree.keys_comp(tree.get_key(val), parent->value)) parent->add_left_child(node); else parent->add_right_child(node); return make_pair(iterator{node}, true); } template static pair< typename Tree::iterator, bool > insert(Tree& tree, const Value& val) { using iterator = typename Tree::iterator; using node_type = typename Tree::node_type; auto parent = tree.find_parent_for_insertion(val); if (!parent) { tree.root_ = new node_type{val}; return make_pair(iterator{tree.root_}, true); } if (tree.keys_equal(tree.get_key(parent->value), tree.get_key(val))) return make_pair(iterator{parent}, false); auto node = new node_type{val}; if (tree.keys_comp(tree.get_key(val), parent->value)) parent->add_left_child(node); else parent->add_right_child(node); return make_pair(iterator{node}, true); } template static pair< typename Tree::iterator, bool > insert(Tree& tree, Value&& val) { using iterator = typename Tree::iterator; using node_type = typename Tree::node_type; auto parent = tree.find_parent_for_insertion(val); if (!parent) { tree.root_ = new node_type{forward(val)}; return make_pair(iterator{tree.root_}, true); } if (tree.keys_equal(tree.get_key(parent->value), tree.get_key(val))) return make_pair(iterator{parent}, false); auto node = new node_type{forward(val)}; if (tree.keys_comp(tree.get_key(val), parent->value)) parent->add_left_child(node); else parent->add_right_child(node); return make_pair(iterator{node}, true); } }; struct rbtree_multi_policy { // TODO: }; } #endif