util/IntrusiveList: add method splice()
This commit is contained in:
parent
b78d6c9dd7
commit
84fd401d21
@ -526,4 +526,40 @@ public:
|
||||
|
||||
++counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the given range of items of the given list to this one
|
||||
* before the given position.
|
||||
*/
|
||||
void splice(iterator position, IntrusiveList &from,
|
||||
iterator _begin, iterator _end, size_type n) noexcept {
|
||||
if (_begin == _end)
|
||||
return;
|
||||
|
||||
auto &next_node = ToNode(*position);
|
||||
auto &prev_node = ToNode(*std::prev(position));
|
||||
|
||||
auto &first_node = ToNode(*_begin);
|
||||
auto &before_first_node = ToNode(*std::prev(_begin));
|
||||
auto &last_node = ToNode(*std::prev(_end));
|
||||
auto &after_last_node = ToNode(*_end);
|
||||
|
||||
/* remove from the other list */
|
||||
IntrusiveListNode::Connect(before_first_node, after_last_node);
|
||||
from.counter -= n;
|
||||
|
||||
/* insert into this list */
|
||||
IntrusiveListNode::Connect(prev_node, first_node);
|
||||
IntrusiveListNode::Connect(last_node, next_node);
|
||||
counter += n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move all items of the given list to this one before the
|
||||
* given position.
|
||||
*/
|
||||
void splice(iterator position, IntrusiveList &from) noexcept {
|
||||
spice(position, from, from.begin(), from.end(),
|
||||
constant_time_size ? size() : 1);
|
||||
}
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 Max Kellermann <max.kellermann@gmail.com>
|
||||
* Copyright 2020-2022 Max Kellermann <max.kellermann@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Max Kellermann <mk@cm4all.com>
|
||||
@ -89,6 +89,60 @@ TEST(IntrusiveList, Basic)
|
||||
ASSERT_EQ(i, list.begin());
|
||||
--i;
|
||||
ASSERT_EQ(i, list.end());
|
||||
|
||||
IntrusiveList<Item> other_list;
|
||||
Item d, e, f, g;
|
||||
other_list.push_back(d);
|
||||
other_list.push_back(e);
|
||||
other_list.push_back(f);
|
||||
other_list.push_back(g);
|
||||
|
||||
list.splice(std::next(list.begin()), other_list,
|
||||
other_list.iterator_to(e),
|
||||
other_list.iterator_to(g), 2);
|
||||
|
||||
i = other_list.begin();
|
||||
ASSERT_EQ(&*i, &d);
|
||||
++i;
|
||||
ASSERT_EQ(&*i, &g);
|
||||
++i;
|
||||
ASSERT_EQ(i, other_list.end());
|
||||
++i;
|
||||
ASSERT_EQ(&*i, &d);
|
||||
--i;
|
||||
ASSERT_EQ(i, other_list.end());
|
||||
--i;
|
||||
ASSERT_EQ(&*i, &g);
|
||||
--i;
|
||||
ASSERT_EQ(&*i, &d);
|
||||
ASSERT_EQ(i, other_list.begin());
|
||||
|
||||
i = list.begin();
|
||||
ASSERT_EQ(&*i, &a);
|
||||
++i;
|
||||
ASSERT_EQ(&*i, &e);
|
||||
++i;
|
||||
ASSERT_EQ(&*i, &f);
|
||||
++i;
|
||||
ASSERT_EQ(&*i, &c);
|
||||
++i;
|
||||
ASSERT_EQ(i, list.end());
|
||||
++i;
|
||||
ASSERT_EQ(&*i, &a);
|
||||
|
||||
--i;
|
||||
ASSERT_EQ(i, list.end());
|
||||
--i;
|
||||
ASSERT_EQ(&*i, &c);
|
||||
--i;
|
||||
ASSERT_EQ(&*i, &f);
|
||||
--i;
|
||||
ASSERT_EQ(&*i, &e);
|
||||
--i;
|
||||
ASSERT_EQ(&*i, &a);
|
||||
ASSERT_EQ(i, list.begin());
|
||||
--i;
|
||||
ASSERT_EQ(i, list.end());
|
||||
}
|
||||
|
||||
TEST(IntrusiveList, SafeLink)
|
||||
|
Loading…
Reference in New Issue
Block a user