[Bf-blender-cvs] [9c14039a8f4] master: BLI ListBase: Add new 'SplitAfter' given link util.

Bastien Montagne noreply at git.blender.org
Mon Feb 6 17:58:51 CET 2023


Commit: 9c14039a8f4b5f00d84caf41b83175d8b4deda2d
Author: Bastien Montagne
Date:   Mon Feb 6 17:54:18 2023 +0100
Branches: master
https://developer.blender.org/rB9c14039a8f4b5f00d84caf41b83175d8b4deda2d

BLI ListBase: Add new 'SplitAfter' given link util.

Allows to easily split a ListBase by moving the part after given link
into a new ListBase.

===================================================================

M	source/blender/blenlib/BLI_listbase.h
M	source/blender/blenlib/intern/listbase.cc
M	source/blender/blenlib/tests/BLI_listbase_test.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 6a41fce27b3..f819413c7ce 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -243,6 +243,16 @@ void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL
  * Moves the entire contents of \a src at the beginning of \a dst.
  */
 void BLI_movelisttolist_reverse(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
+/**
+ * Split `original_listbase` after given `vlink`, putting the remaining of the list into given
+ * `split_listbase`.
+ *
+ * \note If `vlink` is nullptr, it is considered as 'the item before the first item', so the whole
+ * list is moved from `original_listbase` to `split_listbase`.
+ */
+void BLI_listbase_split_after(struct ListBase *original_listbase,
+                              struct ListBase *split_listbase,
+                              void *vlink) ATTR_NONNULL(1, 2);
 /**
  * Sets dst to a duplicate of the entire contents of src. dst may be the same as src.
  */
diff --git a/source/blender/blenlib/intern/listbase.cc b/source/blender/blenlib/intern/listbase.cc
index 6812a12c9f0..3b549cf68c4 100644
--- a/source/blender/blenlib/intern/listbase.cc
+++ b/source/blender/blenlib/intern/listbase.cc
@@ -57,6 +57,35 @@ void BLI_movelisttolist_reverse(ListBase *dst, ListBase *src)
   src->first = src->last = nullptr;
 }
 
+void BLI_listbase_split_after(ListBase *original_listbase, ListBase *split_listbase, void *vlink)
+{
+  BLI_assert(BLI_listbase_is_empty(split_listbase));
+  BLI_assert(vlink == nullptr || BLI_findindex(original_listbase, vlink) >= 0);
+
+  if (vlink == original_listbase->last) {
+    /* Nothing to split, and `split_listbase` is assumed already empty (see assert above). */
+    return;
+  }
+
+  if (vlink == nullptr) {
+    /* Move everything into `split_listbase`. */
+    SWAP(ListBase, *original_listbase, *split_listbase);
+    return;
+  }
+
+  Link *link = static_cast<Link *>(vlink);
+  Link *next_link = link->next;
+  BLI_assert(next_link != nullptr);
+  Link *last_link = static_cast<Link *>(original_listbase->last);
+
+  original_listbase->last = link;
+  split_listbase->first = next_link;
+  split_listbase->last = last_link;
+
+  link->next = nullptr;
+  next_link->prev = nullptr;
+}
+
 void BLI_addhead(ListBase *listbase, void *vlink)
 {
   Link *link = static_cast<Link *>(vlink);
diff --git a/source/blender/blenlib/tests/BLI_listbase_test.cc b/source/blender/blenlib/tests/BLI_listbase_test.cc
index abdd4f90221..c5a2904505c 100644
--- a/source/blender/blenlib/tests/BLI_listbase_test.cc
+++ b/source/blender/blenlib/tests/BLI_listbase_test.cc
@@ -187,6 +187,77 @@ TEST(listbase, FromLink)
   BLI_freelistN(&lb);
 }
 
+TEST(listbase, SplitAfter)
+{
+  ListBase lb;
+  ListBase split_after_lb;
+  void *link1 = MEM_callocN(sizeof(Link), "link1");
+  void *link2 = MEM_callocN(sizeof(Link), "link2");
+
+  /* Empty list */
+  BLI_listbase_clear(&lb);
+  BLI_listbase_clear(&split_after_lb);
+
+  BLI_listbase_split_after(&lb, &split_after_lb, nullptr);
+  EXPECT_EQ(BLI_listbase_is_empty(&split_after_lb), true);
+  EXPECT_BLI_ASSERT(BLI_listbase_split_after(&lb, &split_after_lb, link1), "");
+
+  /* One link */
+  BLI_listbase_clear(&lb);
+  BLI_listbase_clear(&split_after_lb);
+  BLI_addtail(&lb, link1);
+
+  BLI_listbase_split_after(&lb, &split_after_lb, nullptr);
+  EXPECT_EQ(BLI_listbase_is_empty(&lb), true);
+  EXPECT_EQ(BLI_listbase_count(&split_after_lb), 1);
+  EXPECT_EQ(BLI_findindex(&split_after_lb, link1), 0);
+  EXPECT_EQ(split_after_lb.first, link1);
+  EXPECT_EQ(split_after_lb.last, link1);
+
+  BLI_listbase_clear(&lb);
+  BLI_listbase_clear(&split_after_lb);
+  BLI_addtail(&lb, link1);
+
+  BLI_listbase_split_after(&lb, &split_after_lb, link1);
+  EXPECT_EQ(BLI_listbase_count(&lb), 1);
+  EXPECT_EQ(BLI_findindex(&lb, link1), 0);
+  EXPECT_EQ(lb.first, link1);
+  EXPECT_EQ(lb.last, link1);
+  EXPECT_EQ(BLI_listbase_is_empty(&split_after_lb), true);
+
+  /* Two links */
+  BLI_listbase_clear(&lb);
+  BLI_listbase_clear(&split_after_lb);
+  BLI_addtail(&lb, link1);
+  BLI_addtail(&lb, link2);
+
+  BLI_listbase_split_after(&lb, &split_after_lb, nullptr);
+  EXPECT_EQ(BLI_listbase_is_empty(&lb), true);
+  EXPECT_EQ(BLI_listbase_count(&split_after_lb), 2);
+  EXPECT_EQ(BLI_findindex(&split_after_lb, link1), 0);
+  EXPECT_EQ(BLI_findindex(&split_after_lb, link2), 1);
+  EXPECT_EQ(split_after_lb.first, link1);
+  EXPECT_EQ(split_after_lb.last, link2);
+
+  BLI_listbase_clear(&lb);
+  BLI_listbase_clear(&split_after_lb);
+  BLI_addtail(&lb, link1);
+  BLI_addtail(&lb, link2);
+
+  BLI_listbase_split_after(&lb, &split_after_lb, link1);
+  EXPECT_EQ(BLI_listbase_count(&lb), 1);
+  EXPECT_EQ(BLI_findindex(&lb, link1), 0);
+  EXPECT_EQ(lb.first, link1);
+  EXPECT_EQ(lb.last, link1);
+  EXPECT_EQ(BLI_listbase_count(&split_after_lb), 1);
+  EXPECT_EQ(BLI_findindex(&split_after_lb, link2), 0);
+  EXPECT_EQ(split_after_lb.first, link2);
+  EXPECT_EQ(split_after_lb.last, link2);
+
+  BLI_freelistN(&lb);
+  BLI_freelistN(&split_after_lb);
+}
+
 /* -------------------------------------------------------------------- */
 /* Sort utilities & test */



More information about the Bf-blender-cvs mailing list