c-list: add c_list_split()
Add a new function c_list_split(), splitting an existing list in two. It reverse c_list_splice(). Original-by: Michele Dionisio (rework to allow empty lists to be split and simplify the tests) Signed-off-by: David Rheinsberg <david.rheinsberg@gmail.com>main
parent
76900e4e36
commit
b86ba656ac
1
AUTHORS
1
AUTHORS
|
@ -36,5 +36,6 @@ AUTHORS: (ordered alphabetically)
|
|||
Danilo Horta <danilo.horta@pm.me>
|
||||
David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
Lucas De Marchi <lucas.de.marchi@gmail.com>
|
||||
Michele Dionisio
|
||||
Thomas Haller <thaller@redhat.com>
|
||||
Tom Gundersen <teg@jklm.no>
|
||||
|
|
3
NEWS.md
3
NEWS.md
|
@ -4,6 +4,9 @@
|
|||
|
||||
* The minimum required meson version is now 0.60.0.
|
||||
|
||||
* New function c_list_split() is added. It reverses c_list_splice()
|
||||
and thus allows to split a list in half.
|
||||
|
||||
* TBD
|
||||
|
||||
Contributions from: David Rheinsberg
|
||||
|
|
25
src/c-list.h
25
src/c-list.h
|
@ -259,6 +259,31 @@ static inline void c_list_splice(CList *target, CList *source) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* c_list_split() - split one list in two
|
||||
* @source: the list to split
|
||||
* @where: new starting element of newlist
|
||||
* @target: new list
|
||||
*
|
||||
* This splits @source in two. All elements following @where (including @where)
|
||||
* are moved to @target, replacing any old list. If @where points to @source
|
||||
* (i.e., the end of the list), @target will be empty.
|
||||
*/
|
||||
static inline void c_list_split(CList *source, CList *where, CList *target) {
|
||||
if (where == source) {
|
||||
*target = (CList)C_LIST_INIT(*target);
|
||||
} else {
|
||||
target->next = where;
|
||||
target->prev = source->prev;
|
||||
|
||||
where->prev->next = source;
|
||||
source->prev = where->prev;
|
||||
|
||||
where->prev = target;
|
||||
target->prev->next = target;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* c_list_first() - return pointer to first element, or NULL if empty
|
||||
* @list: list to operate on, or NULL
|
||||
|
|
|
@ -17,7 +17,8 @@ typedef struct {
|
|||
} Node;
|
||||
|
||||
static void test_api(void) {
|
||||
CList *list_iter, *list_safe, list = C_LIST_INIT(list);
|
||||
CList *list_iter, *list_safe;
|
||||
CList list = C_LIST_INIT(list), list2 = C_LIST_INIT(list2);
|
||||
Node node = { .id = 0, .link = C_LIST_INIT(node.link) };
|
||||
|
||||
assert(c_list_init(&list) == &list);
|
||||
|
@ -68,7 +69,7 @@ static void test_api(void) {
|
|||
c_list_unlink(&node.link);
|
||||
assert(!c_list_is_linked(&node.link));
|
||||
|
||||
/* swap / splice list operators */
|
||||
/* swap / splice / split list operators */
|
||||
|
||||
c_list_swap(&list, &list);
|
||||
assert(c_list_is_empty(&list));
|
||||
|
@ -76,6 +77,10 @@ static void test_api(void) {
|
|||
c_list_splice(&list, &list);
|
||||
assert(c_list_is_empty(&list));
|
||||
|
||||
c_list_split(&list, &list, &list2);
|
||||
assert(c_list_is_empty(&list));
|
||||
assert(c_list_is_empty(&list2));
|
||||
|
||||
/* direct/raw iterators */
|
||||
|
||||
c_list_for_each(list_iter, &list)
|
||||
|
|
|
@ -11,6 +11,18 @@
|
|||
#include <string.h>
|
||||
#include "c-list.h"
|
||||
|
||||
static void assert_list_integrity(CList *list) {
|
||||
CList *iter;
|
||||
|
||||
iter = list;
|
||||
do {
|
||||
assert(iter->next->prev == iter);
|
||||
assert(iter->prev->next == iter);
|
||||
|
||||
iter = iter->next;
|
||||
} while (iter != list);
|
||||
}
|
||||
|
||||
static void test_iterators(void) {
|
||||
CList *iter, *safe, a, b, list = C_LIST_INIT(list);
|
||||
unsigned int i;
|
||||
|
@ -158,6 +170,85 @@ static void test_splice(void) {
|
|||
assert(c_list_last(&target) == &e2);
|
||||
}
|
||||
|
||||
static void test_split(void) {
|
||||
CList e1, e2;
|
||||
|
||||
/* split empty list */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_split(&source, &source, &target);
|
||||
assert(c_list_is_empty(&source));
|
||||
assert(c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 1-element list excluding the element */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_split(&source, &source, &target);
|
||||
assert(!c_list_is_empty(&source));
|
||||
assert(c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 1-element list including the element */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_split(&source, &e1, &target);
|
||||
assert(c_list_is_empty(&source));
|
||||
assert(!c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 2-element list excluding the elements */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_link_tail(&source, &e2);
|
||||
c_list_split(&source, &source, &target);
|
||||
assert(!c_list_is_empty(&source));
|
||||
assert(c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 2-element list including one element */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_link_tail(&source, &e2);
|
||||
c_list_split(&source, &e2, &target);
|
||||
assert(!c_list_is_empty(&source));
|
||||
assert(!c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 2-element list including both elements */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_link_tail(&source, &e2);
|
||||
c_list_split(&source, &e1, &target);
|
||||
assert(c_list_is_empty(&source));
|
||||
assert(!c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void test_flush(void) {
|
||||
CList e1 = C_LIST_INIT(e1), e2 = C_LIST_INIT(e2);
|
||||
CList list1 = C_LIST_INIT(list1), list2 = C_LIST_INIT(list2);
|
||||
|
@ -220,6 +311,7 @@ int main(void) {
|
|||
test_iterators();
|
||||
test_swap();
|
||||
test_splice();
|
||||
test_split();
|
||||
test_flush();
|
||||
test_macros();
|
||||
test_gnu();
|
||||
|
|
Loading…
Reference in New Issue