linked-list: Change return value of find_first() and signature of its callback
This avoids the unportable five pointer hack.
This commit is contained in:
@@ -47,6 +47,17 @@ struct element_t {
|
||||
element_t *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
bool linked_list_match_str(void *item, va_list args)
|
||||
{
|
||||
char *a = item, *b;
|
||||
|
||||
VA_ARGS_VGET(args, b);
|
||||
return streq(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty linked list object.
|
||||
*/
|
||||
@@ -371,26 +382,41 @@ METHOD(linked_list_t, remove_at, void,
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(linked_list_t, find_first, status_t,
|
||||
private_linked_list_t *this, linked_list_match_t match,
|
||||
void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
|
||||
METHOD(linked_list_t, find_first, bool,
|
||||
private_linked_list_t *this, linked_list_match_t match, void **item, ...)
|
||||
{
|
||||
element_t *current = this->first;
|
||||
va_list args;
|
||||
bool matched = FALSE;
|
||||
|
||||
if (!match && !item)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (current)
|
||||
{
|
||||
if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
|
||||
(!match && item && current->value == *item))
|
||||
if (match)
|
||||
{
|
||||
va_start(args, item);
|
||||
matched = match(current->value, args);
|
||||
va_end(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
matched = current->value == *item;
|
||||
}
|
||||
if (matched)
|
||||
{
|
||||
if (item != NULL)
|
||||
{
|
||||
*item = current->value;
|
||||
}
|
||||
return SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return NOT_FOUND;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(linked_list_t, invoke_offset, void,
|
||||
@@ -548,7 +574,7 @@ linked_list_t *linked_list_create()
|
||||
.reset_enumerator = (void*)_reset_enumerator,
|
||||
.get_first = _get_first,
|
||||
.get_last = _get_last,
|
||||
.find_first = (void*)_find_first,
|
||||
.find_first = _find_first,
|
||||
.insert_first = _insert_first,
|
||||
.insert_last = _insert_last,
|
||||
.insert_before = (void*)_insert_before,
|
||||
|
||||
@@ -28,15 +28,22 @@ typedef struct linked_list_t linked_list_t;
|
||||
#include <collections/enumerator.h>
|
||||
|
||||
/**
|
||||
* Method to match elements in a linked list (used in find_* functions)
|
||||
* Function to match elements in a linked list
|
||||
*
|
||||
* @param item current list item
|
||||
* @param ... user supplied data (only pointers, at most 5)
|
||||
* @return
|
||||
* - TRUE, if the item matched
|
||||
* - FALSE, otherwise
|
||||
* @param args user supplied data
|
||||
* @return TRUE, if the item matched, FALSE otherwise
|
||||
*/
|
||||
typedef bool (*linked_list_match_t)(void *item, ...);
|
||||
typedef bool (*linked_list_match_t)(void *item, va_list args);
|
||||
|
||||
/**
|
||||
* Helper function to match a string in a linked list of strings
|
||||
*
|
||||
* @param item list item (char*)
|
||||
* @param args user supplied data (char*)
|
||||
* @return
|
||||
*/
|
||||
bool linked_list_match_str(void *item, va_list args);
|
||||
|
||||
/**
|
||||
* Function to be invoked on elements in a linked list
|
||||
@@ -167,21 +174,20 @@ struct linked_list_t {
|
||||
*
|
||||
* The first object passed to the match function is the current list item,
|
||||
* followed by the user supplied data.
|
||||
* If the supplied function returns TRUE this function returns SUCCESS, and
|
||||
* the current object is returned in the third parameter, otherwise,
|
||||
* If the supplied function returns TRUE so does this function, and the
|
||||
* current object is returned in the third parameter (if given), otherwise,
|
||||
* the next item is checked.
|
||||
*
|
||||
* If match is NULL, *item and the current object are compared.
|
||||
*
|
||||
* @warning Only use pointers as user supplied data.
|
||||
*
|
||||
* @param match comparison function to call on each object, or NULL
|
||||
* @param item the list item, if found
|
||||
* @param ... user data to supply to match function (limited to 5 arguments)
|
||||
* @return SUCCESS if found, NOT_FOUND otherwise
|
||||
* @param item the list item, if found, or NULL
|
||||
* @param ... user data to supply to match function
|
||||
* @return TRUE if found, FALSE otherwise (or if neither match,
|
||||
* nor item is supplied)
|
||||
*/
|
||||
status_t (*find_first) (linked_list_t *this, linked_list_match_t match,
|
||||
void **item, ...);
|
||||
bool (*find_first)(linked_list_t *this, linked_list_match_t match,
|
||||
void **item, ...);
|
||||
|
||||
/**
|
||||
* Invoke a method on all of the contained objects.
|
||||
|
||||
@@ -812,11 +812,12 @@ static bool verify_trust_chain(private_credential_manager_t *this,
|
||||
return trusted;
|
||||
}
|
||||
|
||||
/**
|
||||
* List find match function for certificates
|
||||
*/
|
||||
static bool cert_equals(certificate_t *a, certificate_t *b)
|
||||
CALLBACK(cert_equals, bool,
|
||||
certificate_t *a, va_list args)
|
||||
{
|
||||
certificate_t *b;
|
||||
|
||||
VA_ARGS_VGET(args, b);
|
||||
return a->equals(a, b);
|
||||
}
|
||||
|
||||
@@ -896,8 +897,7 @@ METHOD(enumerator_t, trusted_enumerate, bool,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->failed->find_first(this->failed, (void*)cert_equals,
|
||||
NULL, current) == SUCCESS)
|
||||
if (this->failed->find_first(this->failed, cert_equals, NULL, current))
|
||||
{ /* check each candidate only once */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -149,8 +149,12 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
|
||||
cert_data_destroy);
|
||||
}
|
||||
|
||||
static bool certificate_equals(certificate_t *item, certificate_t *cert)
|
||||
CALLBACK(certificate_equals, bool,
|
||||
certificate_t *item, va_list args)
|
||||
{
|
||||
certificate_t *cert;
|
||||
|
||||
VA_ARGS_VGET(args, cert);
|
||||
return item->equals(item, cert);
|
||||
}
|
||||
|
||||
@@ -163,9 +167,8 @@ static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted,
|
||||
{
|
||||
certificate_t *cached;
|
||||
this->lock->write_lock(this->lock);
|
||||
if (this->untrusted->find_first(this->untrusted,
|
||||
(linked_list_match_t)certificate_equals,
|
||||
(void**)&cached, cert) == SUCCESS)
|
||||
if (this->untrusted->find_first(this->untrusted, certificate_equals,
|
||||
(void**)&cached, cert))
|
||||
{
|
||||
cert->destroy(cert);
|
||||
cert = cached->get_ref(cached);
|
||||
@@ -201,9 +204,8 @@ METHOD(mem_cred_t, get_cert_ref, certificate_t*,
|
||||
certificate_t *cached;
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
if (this->untrusted->find_first(this->untrusted,
|
||||
(linked_list_match_t)certificate_equals,
|
||||
(void**)&cached, cert) == SUCCESS)
|
||||
if (this->untrusted->find_first(this->untrusted, certificate_equals,
|
||||
(void**)&cached, cert))
|
||||
{
|
||||
cert->destroy(cert);
|
||||
cert = cached->get_ref(cached);
|
||||
|
||||
@@ -811,11 +811,12 @@ METHOD(crypto_factory_t, remove_dh, void,
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* match algorithms of an entry?
|
||||
*/
|
||||
static bool entry_match(entry_t *a, entry_t *b)
|
||||
CALLBACK(entry_match, bool,
|
||||
entry_t *a, va_list args)
|
||||
{
|
||||
entry_t *b;
|
||||
|
||||
VA_ARGS_VGET(args, b);
|
||||
return a->algo == b->algo;
|
||||
}
|
||||
|
||||
@@ -828,7 +829,7 @@ CALLBACK(unique_check, bool,
|
||||
|
||||
while (orig->enumerate(orig, &entry))
|
||||
{
|
||||
if (list->find_first(list, (void*)entry_match, NULL, entry) == SUCCESS)
|
||||
if (list->find_first(list, entry_match, NULL, entry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -606,18 +606,14 @@ static void load_provided(private_plugin_loader_t *this,
|
||||
provided_feature_t *provided,
|
||||
int level);
|
||||
|
||||
/**
|
||||
* Used to find a loaded feature
|
||||
*/
|
||||
static bool is_feature_loaded(provided_feature_t *item)
|
||||
CALLBACK(is_feature_loaded, bool,
|
||||
provided_feature_t *item, va_list args)
|
||||
{
|
||||
return item->loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find a loadable feature
|
||||
*/
|
||||
static bool is_feature_loadable(provided_feature_t *item)
|
||||
CALLBACK(is_feature_loadable, bool,
|
||||
provided_feature_t *item, va_list args)
|
||||
{
|
||||
return !item->loading && !item->loaded && !item->failed;
|
||||
}
|
||||
@@ -630,8 +626,7 @@ static bool loaded_feature_matches(registered_feature_t *a,
|
||||
{
|
||||
if (plugin_feature_matches(a->feature, b->feature))
|
||||
{
|
||||
return b->plugins->find_first(b->plugins, (void*)is_feature_loaded,
|
||||
NULL) == SUCCESS;
|
||||
return b->plugins->find_first(b->plugins, is_feature_loaded, NULL);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -644,8 +639,7 @@ static bool loadable_feature_equals(registered_feature_t *a,
|
||||
{
|
||||
if (plugin_feature_equals(a->feature, b->feature))
|
||||
{
|
||||
return b->plugins->find_first(b->plugins, (void*)is_feature_loadable,
|
||||
NULL) == SUCCESS;
|
||||
return b->plugins->find_first(b->plugins, is_feature_loadable, NULL);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -658,8 +652,7 @@ static bool loadable_feature_matches(registered_feature_t *a,
|
||||
{
|
||||
if (plugin_feature_matches(a->feature, b->feature))
|
||||
{
|
||||
return b->plugins->find_first(b->plugins, (void*)is_feature_loadable,
|
||||
NULL) == SUCCESS;
|
||||
return b->plugins->find_first(b->plugins, is_feature_loadable, NULL);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1011,8 +1004,8 @@ static void purge_plugins(private_plugin_loader_t *this)
|
||||
{ /* feature interface not supported */
|
||||
continue;
|
||||
}
|
||||
if (entry->features->find_first(entry->features,
|
||||
(void*)is_feature_loaded, NULL) != SUCCESS)
|
||||
if (!entry->features->find_first(entry->features, is_feature_loaded,
|
||||
NULL))
|
||||
{
|
||||
DBG2(DBG_LIB, "unloading plugin '%s' without loaded features",
|
||||
entry->plugin->get_name(entry->plugin));
|
||||
@@ -1062,6 +1055,15 @@ static bool find_plugin(char *path, char *name, char *buf, char **file)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CALLBACK(find_plugin_cb, bool,
|
||||
char *path, va_list args)
|
||||
{
|
||||
char *name, *buf, **file;
|
||||
|
||||
VA_ARGS_VGET(args, name, buf, file);
|
||||
return find_plugin(path, name, buf, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to sort plugins by priority
|
||||
*/
|
||||
@@ -1244,8 +1246,8 @@ METHOD(plugin_loader_t, load_plugins, bool,
|
||||
}
|
||||
if (this->paths)
|
||||
{
|
||||
this->paths->find_first(this->paths, (void*)find_plugin, NULL,
|
||||
token, buf, &file);
|
||||
this->paths->find_first(this->paths, find_plugin_cb, NULL, token,
|
||||
buf, &file);
|
||||
}
|
||||
if (!file)
|
||||
{
|
||||
|
||||
@@ -183,26 +183,48 @@ END_TEST
|
||||
* find
|
||||
*/
|
||||
|
||||
static bool match_a_b(void *item, void *a, void *b)
|
||||
CALLBACK(find_a_b, bool,
|
||||
void *item, va_list args)
|
||||
{
|
||||
void *a, *b;
|
||||
|
||||
VA_ARGS_VGET(args, a, b);
|
||||
ck_assert(a == (void*)1);
|
||||
ck_assert(b == (void*)2);
|
||||
return item == a || item == b;
|
||||
}
|
||||
|
||||
CALLBACK(find_a, bool,
|
||||
void *item, va_list args)
|
||||
{
|
||||
void *a;
|
||||
|
||||
VA_ARGS_VGET(args, a);
|
||||
return match_a(item, a);
|
||||
}
|
||||
|
||||
CALLBACK(find_b, bool,
|
||||
void *item, va_list args)
|
||||
{
|
||||
void *b;
|
||||
|
||||
VA_ARGS_VGET(args, b);
|
||||
return match_b(item, b);
|
||||
}
|
||||
|
||||
START_TEST(test_find)
|
||||
{
|
||||
void *a = (void*)1, *b = (void*)2;
|
||||
|
||||
ck_assert(list->find_first(list, NULL, &a) == NOT_FOUND);
|
||||
ck_assert(!list->find_first(list, NULL, &a));
|
||||
list->insert_last(list, a);
|
||||
ck_assert(list->find_first(list, NULL, &a) == SUCCESS);
|
||||
ck_assert(list->find_first(list, NULL, &b) == NOT_FOUND);
|
||||
ck_assert(list->find_first(list, NULL, &a));
|
||||
ck_assert(!list->find_first(list, NULL, &b));
|
||||
list->insert_last(list, b);
|
||||
ck_assert(list->find_first(list, NULL, &a) == SUCCESS);
|
||||
ck_assert(list->find_first(list, NULL, &b) == SUCCESS);
|
||||
ck_assert(list->find_first(list, NULL, &a));
|
||||
ck_assert(list->find_first(list, NULL, &b));
|
||||
|
||||
ck_assert(list->find_first(list, NULL, NULL) == NOT_FOUND);
|
||||
ck_assert(!list->find_first(list, NULL, NULL));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -210,29 +232,57 @@ START_TEST(test_find_callback)
|
||||
{
|
||||
void *a = (void*)1, *b = (void*)2, *x = NULL;
|
||||
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_a_b, &x, a, b) == NOT_FOUND);
|
||||
ck_assert(!list->find_first(list, find_a_b, &x, a, b));
|
||||
list->insert_last(list, a);
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_a, NULL, a) == SUCCESS);
|
||||
ck_assert(list->find_first(list, find_a, NULL, a));
|
||||
x = NULL;
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_a, &x, a) == SUCCESS);
|
||||
ck_assert(list->find_first(list, find_a, &x, a));
|
||||
ck_assert(a == x);
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_b, &x, b) == NOT_FOUND);
|
||||
ck_assert(!list->find_first(list, find_b, &x, b));
|
||||
ck_assert(a == x);
|
||||
x = NULL;
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_a_b, &x, a, b) == SUCCESS);
|
||||
ck_assert(list->find_first(list, find_a_b, &x, a, b));
|
||||
ck_assert(a == x);
|
||||
|
||||
list->insert_last(list, b);
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_a, &x, a) == SUCCESS);
|
||||
ck_assert(list->find_first(list, find_a, &x, a));
|
||||
ck_assert(a == x);
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_b, &x, b) == SUCCESS);
|
||||
ck_assert(list->find_first(list, find_b, &x, b));
|
||||
ck_assert(b == x);
|
||||
x = NULL;
|
||||
ck_assert(list->find_first(list, (linked_list_match_t)match_a_b, &x, a, b) == SUCCESS);
|
||||
ck_assert(list->find_first(list, find_a_b, &x, a, b));
|
||||
ck_assert(a == x);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
CALLBACK(find_args, bool,
|
||||
void *item, va_list args)
|
||||
{
|
||||
uint64_t d, e;
|
||||
level_t c;
|
||||
int *a, b;
|
||||
|
||||
VA_ARGS_VGET(args, a, b, c, d, e);
|
||||
ck_assert_int_eq(*a, 1);
|
||||
ck_assert_int_eq(b, 2);
|
||||
ck_assert_int_eq(c, LEVEL_PRIVATE);
|
||||
ck_assert_int_eq(d, UINT64_MAX);
|
||||
ck_assert_int_eq(e, UINT64_MAX-1);
|
||||
return item == a;
|
||||
}
|
||||
|
||||
START_TEST(test_find_callback_args)
|
||||
{
|
||||
int a = 1, b = 2, *x;
|
||||
uint64_t d = UINT64_MAX;
|
||||
|
||||
list->insert_last(list, &a);
|
||||
ck_assert(list->find_first(list, find_args, (void**)&x, &a, b,
|
||||
LEVEL_PRIVATE, d, UINT64_MAX-1));
|
||||
ck_assert_int_eq(a, *x);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*******************************************************************************
|
||||
* invoke
|
||||
*/
|
||||
@@ -464,6 +514,7 @@ Suite *linked_list_suite_create()
|
||||
tcase_add_checked_fixture(tc, setup_list, teardown_list);
|
||||
tcase_add_test(tc, test_find);
|
||||
tcase_add_test(tc, test_find_callback);
|
||||
tcase_add_test(tc, test_find_callback_args);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("invoke");
|
||||
|
||||
Reference in New Issue
Block a user