From da8a2d232053383bebb9c9f483a674a8e1021a57 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Mon, 14 Apr 2014 19:49:22 +0200 Subject: [PATCH] llist utils: Added sdb_llist_remove_by_name(). This function removes the first entry with the specified name. --- src/include/utils/llist.h | 19 ++++++++++++++++--- src/utils/llist.c | 23 +++++++++++++++++++++++ t/utils/llist_test.c | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/include/utils/llist.h b/src/include/utils/llist.h index 9356190..f557c9d 100644 --- a/src/include/utils/llist.h +++ b/src/include/utils/llist.h @@ -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 diff --git a/src/utils/llist.c b/src/utils/llist.c index f009bcd..069c14e 100644 --- a/src/utils/llist.c +++ b/src/utils/llist.c @@ -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) { diff --git a/t/utils/llist_test.c b/t/utils/llist_test.c index 06b9970..8a6052e 100644 --- a/t/utils/llist_test.c +++ b/t/utils/llist_test.c @@ -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); -- 2.30.2