[Bf-blender-cvs] [d6ea881a741] blender-v3.0-release: BLI_listbase: Add utils to search from string or index.

Bastien Montagne noreply at git.blender.org
Fri Nov 19 15:41:41 CET 2021


Commit: d6ea881a741a254b6f4e931ea25047d3f51686d0
Author: Bastien Montagne
Date:   Fri Nov 19 14:39:40 2021 +0100
Branches: blender-v3.0-release
https://developer.blender.org/rBd6ea881a741a254b6f4e931ea25047d3f51686d0

BLI_listbase: Add utils to search from string or index.

If a valid matching string is found, return that item, otherwise
fallback to the item matching the given index, if any.

This will be useful in RNA override code, and potentially other
areas where data in lists can be referenced by their names or indices.

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

M	source/blender/blenlib/BLI_listbase.h
M	source/blender/blenlib/intern/listbase.c
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 345d9d93d03..cf525d1c2af 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -55,6 +55,10 @@ void *BLI_listbase_bytes_find(const ListBase *listbase,
                               const void *bytes,
                               const size_t bytes_size,
                               const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
+void *BLI_listbase_string_or_index_find(const struct ListBase *listbase,
+                                        const char *string,
+                                        const size_t string_offset,
+                                        const int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
 
 /* find backwards */
 void *BLI_rfindlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index 1b16f6b0aee..443bef42cc2 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -825,6 +825,37 @@ void *BLI_listbase_bytes_rfind(const ListBase *listbase,
   return NULL;
 }
 
+/**
+ * Find the first item in the list that matches the given string, or the given index as fallback.
+ *
+ * \note The string is only used is non-NULL and non-empty.
+ *
+ * \return The found item, or NULL.
+ */
+void *BLI_listbase_string_or_index_find(const ListBase *listbase,
+                                        const char *string,
+                                        const size_t string_offset,
+                                        const int index)
+{
+  Link *link = NULL;
+  Link *link_at_index = NULL;
+
+  int index_iter;
+  for (link = listbase->first, index_iter = 0; link; link = link->next, index_iter++) {
+    if (string != NULL && string[0] != '\0') {
+      const char *string_iter = ((const char *)link) + string_offset;
+
+      if (string[0] == string_iter[0] && STREQ(string, string_iter)) {
+        return link;
+      }
+    }
+    if (index_iter == index) {
+      link_at_index = link;
+    }
+  }
+  return link_at_index;
+}
+
 /**
  * Returns the 0-based index of the first element of listbase which contains the specified
  * null-terminated string at the specified offset, or -1 if not found.
diff --git a/source/blender/blenlib/tests/BLI_listbase_test.cc b/source/blender/blenlib/tests/BLI_listbase_test.cc
index 0ba08a0cd48..d66eb214902 100644
--- a/source/blender/blenlib/tests/BLI_listbase_test.cc
+++ b/source/blender/blenlib/tests/BLI_listbase_test.cc
@@ -96,6 +96,64 @@ TEST(listbase, FindLinkOrIndex)
   BLI_freelistN(&lb);
 }
 
+TEST(listbase, FindLinkFromStringOrPointer)
+{
+  struct TestLink {
+    struct TestLink *prev, *next;
+    char name[64];
+    const void *ptr;
+  };
+
+  const char *const link1_name = "Link1";
+  const char *const link2_name = "Link2";
+  const void *const link1_ptr = nullptr;
+  const void *const link2_ptr = link2_name;
+
+  const size_t name_offset = offsetof(struct TestLink, name);
+  const size_t ptr_offset = offsetof(struct TestLink, ptr);
+
+  ListBase lb;
+  struct TestLink *link1 = (struct TestLink *)MEM_callocN(sizeof(TestLink), "link1");
+  BLI_strncpy(link1->name, link1_name, sizeof(link1->name));
+  link1->ptr = link1_ptr;
+  struct TestLink *link2 = (struct TestLink *)MEM_callocN(sizeof(TestLink), "link2");
+  BLI_strncpy(link2->name, link2_name, sizeof(link2->name));
+  link2->ptr = link2_ptr;
+
+  /* Empty list */
+  BLI_listbase_clear(&lb);
+  EXPECT_EQ(BLI_findptr(&lb, link1_ptr, ptr_offset), (void *)nullptr);
+  EXPECT_EQ(BLI_findstring(&lb, link1_name, name_offset), (void *)nullptr);
+  EXPECT_EQ(BLI_rfindptr(&lb, link1_ptr, ptr_offset), (void *)nullptr);
+  EXPECT_EQ(BLI_rfindstring(&lb, link1_name, name_offset), (void *)nullptr);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, link1_name, name_offset, 0), (void *)nullptr);
+
+  /* One link */
+  BLI_addtail(&lb, link1);
+  EXPECT_EQ(BLI_findptr(&lb, link1_ptr, ptr_offset), (void *)link1);
+  EXPECT_EQ(BLI_findstring(&lb, link1_name, name_offset), (void *)link1);
+  EXPECT_EQ(BLI_rfindptr(&lb, link1_ptr, ptr_offset), (void *)link1);
+  EXPECT_EQ(BLI_rfindstring(&lb, link1_name, name_offset), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, link1_name, name_offset, 0), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, "", name_offset, 0), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, nullptr, name_offset, 0), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, nullptr, name_offset, 1), (void *)nullptr);
+
+  /* Two links */
+  BLI_addtail(&lb, link2);
+  EXPECT_EQ(BLI_findptr(&lb, link1_ptr, ptr_offset), (void *)link1);
+  EXPECT_EQ(BLI_findstring(&lb, link1_name, name_offset), (void *)link1);
+  EXPECT_EQ(BLI_rfindptr(&lb, link1_ptr, ptr_offset), (void *)link1);
+  EXPECT_EQ(BLI_rfindstring(&lb, link1_name, name_offset), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, link1_name, name_offset, 0), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, link2_name, name_offset, 0), (void *)link2);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, nullptr, name_offset, 0), (void *)link1);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, nullptr, name_offset, 1), (void *)link2);
+  EXPECT_EQ(BLI_listbase_string_or_index_find(&lb, nullptr, name_offset, -1), (void *)nullptr);
+
+  BLI_freelistN(&lb);
+}
+
 /* -------------------------------------------------------------------- */
 /* Sort utilities & test */



More information about the Bf-blender-cvs mailing list