Code

llist utils: Added sdb_llist_remove_by_name().
authorSebastian Harl <sh@tokkee.org>
Mon, 14 Apr 2014 17:49:22 +0000 (19:49 +0200)
committerSebastian Harl <sh@tokkee.org>
Mon, 14 Apr 2014 17:49:22 +0000 (19:49 +0200)
This function removes the first entry with the specified name.

src/include/utils/llist.h
src/utils/llist.c
t/utils/llist_test.c

index 93561906b6056a272f468c9c87187469004b8246..f557c9d41c63800ead40925f1414b7da02d80334 100644 (file)
@@ -157,9 +157,9 @@ sdb_llist_search_by_name(sdb_llist_t *list, const char *key);
 
 /*
  * sdb_llist_remove:
- * Removes and returns the first matchin element of the list. The ref-count of
- * the item will not be changed, that is, if the element will not be used any
- * further, it should be de-referenced by the caller.
+ * Removes and returns the first matching element of the list. The ref-count
+ * of the item will not be changed, that is, if the element will not be used
+ * any further, it should be de-referenced by the caller.
  *
  * Returns:
  *  - a pointer to the first matching object
@@ -169,6 +169,19 @@ sdb_object_t *
 sdb_llist_remove(sdb_llist_t *list,
                sdb_llist_lookup_cb lookup, const void *user_data);
 
+/*
+ * sdb_llist_remove_by_name:
+ * Removes and returns the first element whose name matches the specified key.
+ * The ref-count of the item will not be changed, that is, if the element will
+ * not be used any further, it should be de-referenced by the caller.
+ *
+ * Returns:
+ *  - a pointer to the first matching object
+ *  - NULL else
+ */
+sdb_object_t *
+sdb_llist_remove_by_name(sdb_llist_t *list, const char *key);
+
 /*
  * sdb_llist_shift:
  * Removes and returns the first element of the list. The ref-count of the
index f009bcdac43cd30b3ccd51c0d79f953018f16e04..069c14eee204c6f6570286dc0d9a46532a5f747b 100644 (file)
@@ -383,6 +383,29 @@ sdb_llist_remove(sdb_llist_t *list,
        return obj;
 } /* sdb_llist_remove */
 
+sdb_object_t *
+sdb_llist_remove_by_name(sdb_llist_t *list, const char *key)
+{
+       sdb_llist_elem_t *elem;
+       sdb_object_t *obj = NULL;
+
+       if (! list)
+               return NULL;
+
+       pthread_rwlock_rdlock(&list->lock);
+
+       for (elem = list->head; elem; elem = elem->next)
+               if ((key == elem->obj->name)
+                               || (! strcasecmp(elem->obj->name, key)))
+                       break;
+
+       if (elem)
+               obj = sdb_llist_remove_elem(list, elem);
+       pthread_rwlock_unlock(&list->lock);
+
+       return obj;
+} /* sdb_llist_remove_by_name */
+
 sdb_object_t *
 sdb_llist_shift(sdb_llist_t *list)
 {
index 06b9970bfd1475d94990b97c640673bde1cef770..8a6052e8fcb5b5d06c4446f8b5745a87407df283 100644 (file)
@@ -177,8 +177,8 @@ START_TEST(test_llist_get)
        for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
                sdb_object_t *check = sdb_llist_get(list, i);
                fail_unless(check == &golden_data[i],
-                               "sdb_llist_get() = NULL; expected: %p",
-                               &golden_data[i]);
+                               "sdb_llist_get() = %p; expected: %p",
+                               check, &golden_data[i]);
                fail_unless(check->ref_cnt == 3,
                                "sdb_llist_get() didn't increment reference count; got: %i; "
                                "expected: 3", check->ref_cnt);
@@ -187,6 +187,35 @@ START_TEST(test_llist_get)
 }
 END_TEST
 
+START_TEST(test_remove_by_name)
+{
+       /* "random" indexes */
+       int indexes[] = { 4, 5, 3, 6, 2, 0, 1 };
+       size_t i;
+
+       populate();
+
+       for (i = 0; i < SDB_STATIC_ARRAY_LEN(indexes); ++i) {
+               sdb_object_t *check;
+
+               fail_unless((size_t)indexes[i] < SDB_STATIC_ARRAY_LEN(golden_data),
+                               "INTERNAL ERROR: invalid index %i", indexes[i]);
+
+               check = sdb_llist_remove_by_name(list, golden_data[indexes[i]].name);
+               fail_unless(check == &golden_data[indexes[i]],
+                               "sdb_llist_remove_by_name() = %p; expected: %p",
+                               check, &golden_data[indexes[i]]);
+               fail_unless(check->ref_cnt == 2,
+                               "sdb_llist_remove_by_name() returned unexpected reference "
+                               "count; got: %i; expected: 2", check->ref_cnt);
+
+               check = sdb_llist_remove_by_name(list, golden_data[indexes[i]].name);
+               fail_unless(check == NULL,
+                               "sdb_llist_remove_by_name() did not remove the element");
+       }
+}
+END_TEST
+
 static int
 dummy_lookup(const sdb_object_t __attribute__((unused)) *obj,
                const void __attribute__((unused)) *user_data)
@@ -336,6 +365,7 @@ util_llist_suite(void)
        tcase_add_test(tc, test_llist_insert);
        tcase_add_test(tc, test_validate_insert);
        tcase_add_test(tc, test_llist_get);
+       tcase_add_test(tc, test_remove_by_name);
        tcase_add_test(tc, test_llist_search);
        tcase_add_test(tc, test_llist_shift);
        tcase_add_test(tc, test_llist_iter);