From 2a6893efb4e9b124bb0f50b6bda2ee610db930f9 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Mon, 28 May 2018 21:22:14 +0200 Subject: [PATCH] Add method _splice_at for singly list. --- README.md | 6 ++++++ m-list.h | 37 +++++++++++++++++++++++++++++++++++-- tests/test-mlist.c | 17 +++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e773c7fe..7cf2a779 100644 --- a/README.md +++ b/README.md @@ -788,6 +788,12 @@ After wise, 'it' points to the next element of the list. Move the element pointed by 'it' (which is an iterator of 'list2') from the list 'list2' to the back position of 'list1'. After wise, 'it' points to the next element of 'list2'. +##### void name\_splice\_at(name\_t list1, name\_it\_t it1, name\_t list2, name\_it\_t it2) + +Move the element pointed by 'it2' (which is an iterator of 'list2') from the list 'list2' to the position just after 'it1' in the list 'list1'. +After wise, 'it2' points to the next element of 'list2'. +If 'it1' is the end position, it inserts it at the first element (just like \_insert\_at). + ##### void name\_splice(name\_t list1, name\_t list2) Move all the element of 'list2' into 'list1", moving the last element diff --git a/m-list.h b/m-list.h index 544650bd..7653b096 100644 --- a/m-list.h +++ b/m-list.h @@ -491,7 +491,7 @@ assert (it != NULL); \ assert (it->current != NULL); \ assert (M_C(name, _sublist_p)(ov, it)); \ - /* Remove it from ov */ \ + /* Remove the item 'it' from the list 'ov' */ \ struct M_C(name, _s) *current = it->current; \ struct M_C(name, _s) *next = current->next; \ if (it->previous == NULL) { \ @@ -499,11 +499,44 @@ } else { \ it->previous->next = next; \ } \ - /* Update it to next element */ \ + /* Update the item 'it' to point to the next element */ \ it->current = next; \ /* Move current in nv */ \ current->next = *nv; \ *nv = current; \ + } \ + \ + static inline void \ + M_C(name, _splice_at)(list_t nlist, list_it_t npos, \ + list_t olist, list_it_t opos) \ + { \ + LISTI_CONTRACT(nlist); \ + LISTI_CONTRACT(olist); \ + assert (npos != NULL); \ + assert (opos != NULL); \ + assert (M_C(name, _sublist_p)(nlist, npos)); \ + assert (M_C(name, _sublist_p)(olist, opos)); \ + /* Remove the item 'opos' from the list 'olist' */ \ + struct M_C(name, _s) *current = opos->current; \ + struct M_C(name, _s) *next = current->next; \ + if (opos->previous == NULL) { \ + *olist = next; \ + } else { \ + opos->previous->next = next; \ + } \ + /* Update 'opos' to point to the next element */ \ + opos->current = next; \ + /* Insert 'current' into 'nlist' just after 'npos' */ \ + struct M_C(name, _s) *previous = npos->current; \ + if (M_UNLIKELY (previous == NULL)) { \ + current->next = *nlist; \ + *nlist = current; \ + } else { \ + current->next = previous->next; \ + previous->next = current; \ + } \ + LISTI_CONTRACT(nlist); \ + LISTI_CONTRACT(olist); \ } \ \ static inline void \ diff --git a/tests/test-mlist.c b/tests/test-mlist.c index 4da44c59..62f7a94f 100644 --- a/tests/test-mlist.c +++ b/tests/test-mlist.c @@ -190,6 +190,23 @@ static void test_uint(void) assert (x == 1478963); assert (s == *list_uint_back(v)); + list_uint_clean(v); + list_uint_clean(v2); + for(unsigned int i = 0; i < 10; i++) + list_uint_push_back (v, i); + list_uint_it (u, v); + list_uint_it_end (u2, v2); + for(unsigned int i = 0; i < 10; i++) { + list_uint_splice_at (v2, u2, v, u); + } + assert (list_uint_empty_p(v)); + assert (list_uint_size (v2) == 10); + s = 0; + for M_EACH(item, v2, LIST_UINT_OPLIST) { + assert (*item == s); + s ++; + } + list_uint_clear(v); list_uint_clear(v2); }