Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBastien Montagne <bastien@blender.org>2021-11-19 16:39:40 +0300
committerBastien Montagne <bastien@blender.org>2021-11-19 17:41:36 +0300
commitd6ea881a741a254b6f4e931ea25047d3f51686d0 (patch)
treeacd9b37713733c54b71a0768454b54067bee0272 /source
parent04ec36f677d47e3a70baa944bb26fc03d5e8d52e (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenlib/BLI_listbase.h4
-rw-r--r--source/blender/blenlib/intern/listbase.c31
-rw-r--r--source/blender/blenlib/tests/BLI_listbase_test.cc58
3 files changed, 93 insertions, 0 deletions
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
@@ -826,6 +826,37 @@ void *BLI_listbase_bytes_rfind(const ListBase *listbase,
}
/**
+ * 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 */