summaryrefslogtreecommitdiff
path: root/src/third_party/boost-1.56.0/boost/unordered/detail/unique.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/boost-1.56.0/boost/unordered/detail/unique.hpp')
-rw-r--r--src/third_party/boost-1.56.0/boost/unordered/detail/unique.hpp628
1 files changed, 628 insertions, 0 deletions
diff --git a/src/third_party/boost-1.56.0/boost/unordered/detail/unique.hpp b/src/third_party/boost-1.56.0/boost/unordered/detail/unique.hpp
new file mode 100644
index 00000000000..f76ca5a6a50
--- /dev/null
+++ b/src/third_party/boost-1.56.0/boost/unordered/detail/unique.hpp
@@ -0,0 +1,628 @@
+
+// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
+// Copyright (C) 2005-2011 Daniel James
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
+#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
+#endif
+
+#include <boost/unordered/detail/table.hpp>
+#include <boost/unordered/detail/extract_key.hpp>
+#include <boost/throw_exception.hpp>
+#include <stdexcept>
+
+namespace boost { namespace unordered { namespace detail {
+
+ template <typename A, typename T> struct unique_node;
+ template <typename T> struct ptr_node;
+ template <typename Types> struct table_impl;
+
+ template <typename A, typename T>
+ struct unique_node :
+ boost::unordered::detail::value_base<T>
+ {
+ typedef typename ::boost::unordered::detail::rebind_wrap<
+ A, unique_node<A, T> >::type allocator;
+ typedef typename ::boost::unordered::detail::
+ allocator_traits<allocator>::pointer node_pointer;
+ typedef node_pointer link_pointer;
+
+ link_pointer next_;
+ std::size_t hash_;
+
+ unique_node() :
+ next_(),
+ hash_(0)
+ {}
+
+ void init(node_pointer)
+ {
+ }
+
+ private:
+ unique_node& operator=(unique_node const&);
+ };
+
+ template <typename T>
+ struct ptr_node :
+ boost::unordered::detail::ptr_bucket
+ {
+ typedef T value_type;
+ typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef ptr_node<T>* node_pointer;
+ typedef ptr_bucket* link_pointer;
+
+ std::size_t hash_;
+ boost::unordered::detail::value_base<T> value_base_;
+
+ ptr_node() :
+ bucket_base(),
+ hash_(0)
+ {}
+
+ void init(node_pointer)
+ {
+ }
+
+ void* address() { return value_base_.address(); }
+ value_type& value() { return value_base_.value(); }
+ value_type* value_ptr() { return value_base_.value_ptr(); }
+
+ private:
+ ptr_node& operator=(ptr_node const&);
+ };
+
+ // If the allocator uses raw pointers use ptr_node
+ // Otherwise use node.
+
+ template <typename A, typename T, typename NodePtr, typename BucketPtr>
+ struct pick_node2
+ {
+ typedef boost::unordered::detail::unique_node<A, T> node;
+
+ typedef typename boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A, node>::type
+ >::pointer node_pointer;
+
+ typedef boost::unordered::detail::bucket<node_pointer> bucket;
+ typedef node_pointer link_pointer;
+ };
+
+ template <typename A, typename T>
+ struct pick_node2<A, T,
+ boost::unordered::detail::ptr_node<T>*,
+ boost::unordered::detail::ptr_bucket*>
+ {
+ typedef boost::unordered::detail::ptr_node<T> node;
+ typedef boost::unordered::detail::ptr_bucket bucket;
+ typedef bucket* link_pointer;
+ };
+
+ template <typename A, typename T>
+ struct pick_node
+ {
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_node<T> >::type
+ > tentative_node_traits;
+
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_bucket >::type
+ > tentative_bucket_traits;
+
+ typedef pick_node2<A, T,
+ typename tentative_node_traits::pointer,
+ typename tentative_bucket_traits::pointer> pick;
+
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+ };
+
+ template <typename A, typename T, typename H, typename P>
+ struct set
+ {
+ typedef boost::unordered::detail::set<A, T, H, P> types;
+
+ typedef A allocator;
+ typedef T value_type;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef T key_type;
+
+ typedef boost::unordered::detail::allocator_traits<allocator> traits;
+ typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::table_impl<types> table;
+ typedef boost::unordered::detail::set_extractor<value_type> extractor;
+
+ typedef typename boost::unordered::detail::pick_policy<T>::type policy;
+ };
+
+ template <typename A, typename K, typename M, typename H, typename P>
+ struct map
+ {
+ typedef boost::unordered::detail::map<A, K, M, H, P> types;
+
+ typedef A allocator;
+ typedef std::pair<K const, M> value_type;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef K key_type;
+
+ typedef boost::unordered::detail::allocator_traits<allocator>
+ traits;
+ typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::table_impl<types> table;
+ typedef boost::unordered::detail::map_extractor<key_type, value_type>
+ extractor;
+
+ typedef typename boost::unordered::detail::pick_policy<K>::type policy;
+ };
+
+ template <typename Types>
+ struct table_impl : boost::unordered::detail::table<Types>
+ {
+ typedef boost::unordered::detail::table<Types> table;
+ typedef typename table::value_type value_type;
+ typedef typename table::bucket bucket;
+ typedef typename table::policy policy;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::node_allocator node_allocator;
+ typedef typename table::node_allocator_traits node_allocator_traits;
+ typedef typename table::bucket_pointer bucket_pointer;
+ typedef typename table::link_pointer link_pointer;
+ typedef typename table::hasher hasher;
+ typedef typename table::key_equal key_equal;
+ typedef typename table::key_type key_type;
+ typedef typename table::node_constructor node_constructor;
+ typedef typename table::extractor extractor;
+ typedef typename table::iterator iterator;
+ typedef typename table::c_iterator c_iterator;
+
+ typedef std::pair<iterator, bool> emplace_return;
+
+ // Constructors
+
+ table_impl(std::size_t n,
+ hasher const& hf,
+ key_equal const& eq,
+ node_allocator const& a)
+ : table(n, hf, eq, a)
+ {}
+
+ table_impl(table_impl const& x)
+ : table(x, node_allocator_traits::
+ select_on_container_copy_construction(x.node_alloc()))
+ {
+ this->init(x);
+ }
+
+ table_impl(table_impl const& x,
+ node_allocator const& a)
+ : table(x, a)
+ {
+ this->init(x);
+ }
+
+ table_impl(table_impl& x,
+ boost::unordered::detail::move_tag m)
+ : table(x, m)
+ {}
+
+ table_impl(table_impl& x,
+ node_allocator const& a,
+ boost::unordered::detail::move_tag m)
+ : table(x, a, m)
+ {
+ this->move_init(x);
+ }
+
+ // Accessors
+
+ template <class Key, class Pred>
+ iterator find_node_impl(
+ std::size_t key_hash,
+ Key const& k,
+ Pred const& eq) const
+ {
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ iterator n = this->begin(bucket_index);
+
+ for (;;)
+ {
+ if (!n.node_) return n;
+
+ std::size_t node_hash = n.node_->hash_;
+ if (key_hash == node_hash)
+ {
+ if (eq(k, this->get_key(*n)))
+ return n;
+ }
+ else
+ {
+ if (this->hash_to_bucket(node_hash) != bucket_index)
+ return iterator();
+ }
+
+ ++n;
+ }
+ }
+
+ std::size_t count(key_type const& k) const
+ {
+ return this->find_node(k).node_ ? 1 : 0;
+ }
+
+ value_type& at(key_type const& k) const
+ {
+ if (this->size_) {
+ iterator it = this->find_node(k);
+ if (it.node_) return *it;
+ }
+
+ boost::throw_exception(
+ std::out_of_range("Unable to find key in unordered_map."));
+ }
+
+ std::pair<iterator, iterator>
+ equal_range(key_type const& k) const
+ {
+ iterator n = this->find_node(k);
+ iterator n2 = n;
+ if (n2.node_) ++n2;
+ return std::make_pair(n, n2);
+ }
+
+ // equals
+
+ bool equals(table_impl const& other) const
+ {
+ if(this->size_ != other.size_) return false;
+
+ for(iterator n1 = this->begin(); n1.node_; ++n1)
+ {
+ iterator n2 = other.find_matching_node(n1);
+
+ if (!n2.node_ || *n1 != *n2)
+ return false;
+ }
+
+ return true;
+ }
+
+ // Emplace/Insert
+
+ inline iterator add_node(
+ node_constructor& a,
+ std::size_t key_hash)
+ {
+ node_pointer n = a.release();
+ n->hash_ = key_hash;
+
+ bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
+
+ if (!b->next_)
+ {
+ link_pointer start_node = this->get_previous_start();
+
+ if (start_node->next_) {
+ this->get_bucket(this->hash_to_bucket(
+ static_cast<node_pointer>(start_node->next_)->hash_)
+ )->next_ = n;
+ }
+
+ b->next_ = start_node;
+ n->next_ = start_node->next_;
+ start_node->next_ = n;
+ }
+ else
+ {
+ n->next_ = b->next_->next_;
+ b->next_->next_ = n;
+ }
+
+ ++this->size_;
+ return iterator(n);
+ }
+
+ value_type& operator[](key_type const& k)
+ {
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
+
+ if (pos.node_) return *pos;
+
+ // Create the node before rehashing in case it throws an
+ // exception (need strong safety in such a case).
+ node_constructor a(this->node_alloc());
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
+ boost::unordered::piecewise_construct,
+ boost::make_tuple(k),
+ boost::make_tuple()));
+
+ this->reserve_for_insert(this->size_ + 1);
+ return *add_node(a, key_hash);
+ }
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ emplace_return emplace(boost::unordered::detail::emplace_args1<
+ boost::unordered::detail::please_ignore_this_overload> const&)
+ {
+ BOOST_ASSERT(false);
+ return emplace_return(this->begin(), false);
+ }
+# else
+ emplace_return emplace(
+ boost::unordered::detail::please_ignore_this_overload const&)
+ {
+ BOOST_ASSERT(false);
+ return emplace_return(this->begin(), false);
+ }
+# endif
+#endif
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ return emplace_impl(
+ extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
+ BOOST_UNORDERED_EMPLACE_FORWARD);
+#else
+ return emplace_impl(
+ extractor::extract(args.a0, args.a1),
+ BOOST_UNORDERED_EMPLACE_FORWARD);
+#endif
+ }
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <typename A0>
+ emplace_return emplace(
+ boost::unordered::detail::emplace_args1<A0> const& args)
+ {
+ return emplace_impl(extractor::extract(args.a0), args);
+ }
+#endif
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace_impl(key_type const& k,
+ BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
+
+ if (pos.node_) return emplace_return(pos, false);
+
+ // Create the node before rehashing in case it throws an
+ // exception (need strong safety in such a case).
+ node_constructor a(this->node_alloc());
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ this->reserve_for_insert(this->size_ + 1);
+ return emplace_return(this->add_node(a, key_hash), true);
+ }
+
+ emplace_return emplace_impl_with_node(node_constructor& a)
+ {
+ key_type const& k = this->get_key(a.value());
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
+
+ if (pos.node_) return emplace_return(pos, false);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ this->reserve_for_insert(this->size_ + 1);
+ return emplace_return(this->add_node(a, key_hash), true);
+ }
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ // Don't have a key, so construct the node first in order
+ // to be able to lookup the position.
+ node_constructor a(this->node_alloc());
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
+ return emplace_impl_with_node(a);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Insert range methods
+ //
+ // if hash function throws, or inserting > 1 element, basic exception
+ // safety strong otherwise
+
+ template <class InputIt>
+ void insert_range(InputIt i, InputIt j)
+ {
+ if(i != j)
+ return insert_range_impl(extractor::extract(*i), i, j);
+ }
+
+ template <class InputIt>
+ void insert_range_impl(key_type const& k, InputIt i, InputIt j)
+ {
+ node_constructor a(this->node_alloc());
+
+ insert_range_impl2(a, k, i, j);
+
+ while(++i != j) {
+ // Note: can't use get_key as '*i' might not be value_type - it
+ // could be a pair with first_types as key_type without const or
+ // a different second_type.
+ //
+ // TODO: Might be worth storing the value_type instead of the
+ // key here. Could be more efficient if '*i' is expensive. Could
+ // be less efficient if copying the full value_type is
+ // expensive.
+ insert_range_impl2(a, extractor::extract(*i), i, j);
+ }
+ }
+
+ template <class InputIt>
+ void insert_range_impl2(node_constructor& a, key_type const& k,
+ InputIt i, InputIt j)
+ {
+ // No side effects in this initial code
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
+
+ if (!pos.node_) {
+ a.construct_with_value2(*i);
+ if(this->size_ + 1 > this->max_load_)
+ this->reserve_for_insert(this->size_ +
+ boost::unordered::detail::insert_size(i, j));
+
+ // Nothing after this point can throw.
+ this->add_node(a, key_hash);
+ }
+ }
+
+ template <class InputIt>
+ void insert_range_impl(no_key, InputIt i, InputIt j)
+ {
+ node_constructor a(this->node_alloc());
+
+ do {
+ a.construct_with_value2(*i);
+ emplace_impl_with_node(a);
+ } while(++i != j);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Erase
+ //
+ // no throw
+
+ std::size_t erase_key(key_type const& k)
+ {
+ if(!this->size_) return 0;
+
+ std::size_t key_hash = this->hash(k);
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ link_pointer prev = this->get_previous_start(bucket_index);
+ if (!prev) return 0;
+
+ for (;;)
+ {
+ if (!prev->next_) return 0;
+ std::size_t node_hash =
+ static_cast<node_pointer>(prev->next_)->hash_;
+ if (this->hash_to_bucket(node_hash) != bucket_index)
+ return 0;
+ if (node_hash == key_hash &&
+ this->key_eq()(k, this->get_key(
+ static_cast<node_pointer>(prev->next_)->value())))
+ break;
+ prev = prev->next_;
+ }
+
+ link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
+
+ std::size_t deleted_count = this->delete_nodes(prev, end);
+ this->fix_bucket(bucket_index, prev);
+ return deleted_count;
+ }
+
+ iterator erase(c_iterator r)
+ {
+ BOOST_ASSERT(r.node_);
+ iterator next(r.node_);
+ ++next;
+ erase_nodes(r.node_, next.node_);
+ return next;
+ }
+
+ iterator erase_range(c_iterator r1, c_iterator r2)
+ {
+ if (r1 == r2) return iterator(r2.node_);
+ erase_nodes(r1.node_, r2.node_);
+ return iterator(r2.node_);
+ }
+
+ void erase_nodes(node_pointer i, node_pointer j)
+ {
+ std::size_t bucket_index = this->hash_to_bucket(i->hash_);
+
+ // Find the node before i.
+ link_pointer prev = this->get_previous_start(bucket_index);
+ while(prev->next_ != i) prev = prev->next_;
+
+ // Delete the nodes.
+ do {
+ this->delete_node(prev);
+ bucket_index = this->fix_bucket(bucket_index, prev);
+ } while (prev->next_ != j);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // fill_buckets
+
+ template <class NodeCreator>
+ static void fill_buckets(iterator n, table& dst,
+ NodeCreator& creator)
+ {
+ link_pointer prev = dst.get_previous_start();
+
+ while (n.node_) {
+ node_pointer node = creator.create(*n);
+ node->hash_ = n.node_->hash_;
+ prev->next_ = node;
+ ++dst.size_;
+ ++n;
+
+ prev = place_in_bucket(dst, prev);
+ }
+ }
+
+ // strong otherwise exception safety
+ void rehash_impl(std::size_t num_buckets)
+ {
+ BOOST_ASSERT(this->buckets_);
+
+ this->create_buckets(num_buckets);
+ link_pointer prev = this->get_previous_start();
+ while (prev->next_)
+ prev = place_in_bucket(*this, prev);
+ }
+
+ // Iterate through the nodes placing them in the correct buckets.
+ // pre: prev->next_ is not null.
+ static link_pointer place_in_bucket(table& dst, link_pointer prev)
+ {
+ node_pointer n = static_cast<node_pointer>(prev->next_);
+ bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
+
+ if (!b->next_) {
+ b->next_ = prev;
+ return n;
+ }
+ else {
+ prev->next_ = n->next_;
+ n->next_ = b->next_->next_;
+ b->next_->next_ = n;
+ return prev;
+ }
+ }
+ };
+}}}
+
+#endif