forked from boostorg/unordered
Support node_handle
This commit is contained in:
@@ -3800,6 +3800,46 @@ struct table_impl : boost::unordered::detail::table<Types>
|
||||
}
|
||||
}
|
||||
|
||||
template <typename NodeType, typename InsertReturnType>
|
||||
void move_insert_node_type(NodeType& np, InsertReturnType& result)
|
||||
{
|
||||
if (np) {
|
||||
const_key_type& k = this->get_key(np.ptr_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos) {
|
||||
result.node = boost::move(np);
|
||||
result.position = iterator(pos);
|
||||
} else {
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
result.position = iterator(this->add_node(np.ptr_, key_hash));
|
||||
result.inserted = true;
|
||||
np.ptr_ = node_pointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename NodeType>
|
||||
iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
|
||||
{
|
||||
if (!np) {
|
||||
return iterator();
|
||||
}
|
||||
const_key_type& k = this->get_key(np.ptr_->value());
|
||||
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
|
||||
return iterator(hint.node_);
|
||||
}
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
if (!pos) {
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
pos = this->add_node(np.ptr_, key_hash);
|
||||
np.ptr_ = node_pointer();
|
||||
}
|
||||
return iterator(pos);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Insert range methods
|
||||
//
|
||||
@@ -3876,39 +3916,87 @@ struct table_impl : boost::unordered::detail::table<Types>
|
||||
} while (++i != j);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Extract
|
||||
|
||||
inline node_pointer extract_by_key(const_key_type& k)
|
||||
{
|
||||
if (!this->size_) {
|
||||
return node_pointer();
|
||||
}
|
||||
std::size_t key_hash = this->hash(k);
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
|
||||
if (!prev) {
|
||||
return node_pointer();
|
||||
}
|
||||
node_pointer n = next_node(prev);
|
||||
prev->next_ = n->next_;
|
||||
--this->size_;
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
n->next_ = link_pointer();
|
||||
return n;
|
||||
}
|
||||
|
||||
inline node_pointer extract_by_iterator(c_iterator i)
|
||||
{
|
||||
node_pointer n = i.node_;
|
||||
BOOST_ASSERT(n);
|
||||
std::size_t key_hash = n->hash_;
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
while (prev->next_ != n) {
|
||||
prev = prev->next_;
|
||||
}
|
||||
prev->next_ = n->next_;
|
||||
--this->size_;
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
n->next_ = link_pointer();
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Erase
|
||||
//
|
||||
// no throw
|
||||
|
||||
link_pointer find_previous_node(
|
||||
const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
|
||||
{
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
if (!prev) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!prev->next_) {
|
||||
return link_pointer();
|
||||
}
|
||||
std::size_t node_hash = next_node(prev)->hash_;
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index) {
|
||||
return link_pointer();
|
||||
}
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(next_node(prev)->value()))) {
|
||||
return prev;
|
||||
}
|
||||
prev = prev->next_;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t erase_key(const_key_type& 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);
|
||||
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
|
||||
if (!prev)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
if (!prev->next_)
|
||||
return 0;
|
||||
std::size_t node_hash = next_node(prev)->hash_;
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return 0;
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(next_node(prev)->value())))
|
||||
break;
|
||||
prev = prev->next_;
|
||||
}
|
||||
|
||||
link_pointer end = next_node(prev)->next_;
|
||||
|
||||
std::size_t deleted_count = this->delete_nodes(prev, end);
|
||||
this->delete_nodes(prev, end);
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
return deleted_count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
iterator erase(c_iterator r)
|
||||
@@ -4459,6 +4547,45 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
|
||||
this->add_node(a.release(), key_hash, position);
|
||||
}
|
||||
|
||||
template <typename NodeType> iterator move_insert_node_type(NodeType& np)
|
||||
{
|
||||
iterator result;
|
||||
|
||||
if (np) {
|
||||
const_key_type& k = this->get_key(np.ptr_->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
result = iterator(this->add_node(np.ptr_, key_hash, pos));
|
||||
np.ptr_ = node_pointer();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename NodeType>
|
||||
iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
|
||||
{
|
||||
iterator result;
|
||||
|
||||
if (np) {
|
||||
const_key_type& k = this->get_key(np.ptr_->value());
|
||||
|
||||
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
result = iterator(this->add_using_hint(np.ptr_, hint.node_));
|
||||
} else {
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
result = iterator(this->add_node(np.ptr_, key_hash, pos));
|
||||
}
|
||||
np.ptr_ = node_pointer();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Insert range methods
|
||||
|
||||
@@ -4499,11 +4626,95 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Extract
|
||||
|
||||
inline node_pointer extract_by_key(const_key_type& k)
|
||||
{
|
||||
if (!this->size_) {
|
||||
return node_pointer();
|
||||
}
|
||||
std::size_t key_hash = this->hash(k);
|
||||
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
|
||||
if (!prev) {
|
||||
return node_pointer();
|
||||
}
|
||||
node_pointer n = next_node(prev);
|
||||
|
||||
if (n->group_prev_ != n) {
|
||||
node_pointer next = next_node(n);
|
||||
next->group_prev_ = n->group_prev_;
|
||||
n->group_prev_ = n;
|
||||
}
|
||||
|
||||
prev->next_ = n->next_;
|
||||
--this->size_;
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
n->next_ = link_pointer();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
inline node_pointer extract_by_iterator(c_iterator n)
|
||||
{
|
||||
node_pointer i = n.node_;
|
||||
BOOST_ASSERT(i);
|
||||
node_pointer j(next_node(i));
|
||||
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
|
||||
// Split the groups containing 'i' and 'j'.
|
||||
// And get the pointer to the node before i while
|
||||
// we're at it.
|
||||
link_pointer prev = split_groups(i, j);
|
||||
|
||||
// If we don't have a 'prev' it means that i is at the
|
||||
// beginning of a block, so search through the blocks in the
|
||||
// same bucket.
|
||||
if (!prev) {
|
||||
prev = this->get_previous_start(bucket_index);
|
||||
while (prev->next_ != i) {
|
||||
prev = next_node(prev)->group_prev_;
|
||||
}
|
||||
}
|
||||
|
||||
prev->next_ = i->next_;
|
||||
--this->size_;
|
||||
this->fix_bucket(bucket_index, prev);
|
||||
i->next_ = link_pointer();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Erase
|
||||
//
|
||||
// no throw
|
||||
|
||||
link_pointer find_previous_node(
|
||||
const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
|
||||
{
|
||||
link_pointer prev = this->get_previous_start(bucket_index);
|
||||
if (!prev) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!prev->next_) {
|
||||
return link_pointer();
|
||||
}
|
||||
node_pointer first_node = next_node(prev);
|
||||
std::size_t node_hash = first_node->hash_;
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index) {
|
||||
return link_pointer();
|
||||
}
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(first_node->value()))) {
|
||||
return prev;
|
||||
}
|
||||
prev = first_node->group_prev_;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t erase_key(const_key_type& k)
|
||||
{
|
||||
if (!this->size_)
|
||||
@@ -4511,25 +4722,11 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
|
||||
|
||||
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);
|
||||
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
|
||||
if (!prev)
|
||||
return 0;
|
||||
|
||||
node_pointer first_node;
|
||||
|
||||
for (;;) {
|
||||
if (!prev->next_)
|
||||
return 0;
|
||||
first_node = next_node(prev);
|
||||
std::size_t node_hash = first_node->hash_;
|
||||
if (this->hash_to_bucket(node_hash) != bucket_index)
|
||||
return 0;
|
||||
if (node_hash == key_hash &&
|
||||
this->key_eq()(k, this->get_key(first_node->value())))
|
||||
break;
|
||||
prev = first_node->group_prev_;
|
||||
}
|
||||
|
||||
node_pointer first_node = next_node(prev);
|
||||
link_pointer end = first_node->group_prev_->next_;
|
||||
|
||||
std::size_t deleted_count = this->delete_nodes(prev, end);
|
||||
|
||||
Reference in New Issue
Block a user