linked-list: Add method to compare two lists of objects for equality
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2011 Tobias Brunner
|
* Copyright (C) 2007-2015 Tobias Brunner
|
||||||
* Copyright (C) 2005-2006 Martin Willi
|
* Copyright (C) 2005-2006 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
@@ -433,6 +433,56 @@ METHOD(linked_list_t, clone_offset, linked_list_t*,
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(linked_list_t, equals_offset, bool,
|
||||||
|
private_linked_list_t *this, linked_list_t *other_pub, size_t offset)
|
||||||
|
{
|
||||||
|
private_linked_list_t *other = (private_linked_list_t*)other_pub;
|
||||||
|
element_t *cur_t, *cur_o;
|
||||||
|
|
||||||
|
if (this->count != other->count)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cur_t = this->first;
|
||||||
|
cur_o = other->first;
|
||||||
|
while (cur_t && cur_o)
|
||||||
|
{
|
||||||
|
bool (**method)(void*,void*) = cur_t->value + offset;
|
||||||
|
if (!(*method)(cur_t->value, cur_o->value))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cur_t = cur_t->next;
|
||||||
|
cur_o = cur_o->next;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(linked_list_t, equals_function, bool,
|
||||||
|
private_linked_list_t *this, linked_list_t *other_pub,
|
||||||
|
bool (*fn)(void*,void*))
|
||||||
|
{
|
||||||
|
private_linked_list_t *other = (private_linked_list_t*)other_pub;
|
||||||
|
element_t *cur_t, *cur_o;
|
||||||
|
|
||||||
|
if (this->count != other->count)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cur_t = this->first;
|
||||||
|
cur_o = other->first;
|
||||||
|
while (cur_t && cur_o)
|
||||||
|
{
|
||||||
|
if (!fn(cur_t->value, cur_o->value))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cur_t = cur_t->next;
|
||||||
|
cur_o = cur_o->next;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(linked_list_t, destroy, void,
|
METHOD(linked_list_t, destroy, void,
|
||||||
private_linked_list_t *this)
|
private_linked_list_t *this)
|
||||||
{
|
{
|
||||||
@@ -503,6 +553,8 @@ linked_list_t *linked_list_create()
|
|||||||
.invoke_offset = (void*)_invoke_offset,
|
.invoke_offset = (void*)_invoke_offset,
|
||||||
.invoke_function = (void*)_invoke_function,
|
.invoke_function = (void*)_invoke_function,
|
||||||
.clone_offset = _clone_offset,
|
.clone_offset = _clone_offset,
|
||||||
|
.equals_offset = _equals_offset,
|
||||||
|
.equals_function = _equals_function,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
.destroy_offset = _destroy_offset,
|
.destroy_offset = _destroy_offset,
|
||||||
.destroy_function = _destroy_function,
|
.destroy_function = _destroy_function,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2011 Tobias Brunner
|
* Copyright (C) 2007-2015 Tobias Brunner
|
||||||
* Copyright (C) 2005-2008 Martin Willi
|
* Copyright (C) 2005-2008 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
@@ -217,6 +217,27 @@ struct linked_list_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *(*clone_offset) (linked_list_t *this, size_t offset);
|
linked_list_t *(*clone_offset) (linked_list_t *this, size_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two lists and their objects for equality using the given equals
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* @param other list to compare
|
||||||
|
* @param offset offset of the objects equals method
|
||||||
|
* @return TRUE if lists and objects are equal, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool (*equals_offset) (linked_list_t *this, linked_list_t *other,
|
||||||
|
size_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two lists and their objects for equality using the given function.
|
||||||
|
*
|
||||||
|
* @param other list to compare
|
||||||
|
* @param function function to compare the objects
|
||||||
|
* @return TRUE if lists and objects are equal, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool (*equals_function) (linked_list_t *this, linked_list_t *other,
|
||||||
|
bool (*)(void*,void*));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys a linked_list object.
|
* Destroys a linked_list object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -348,6 +348,91 @@ START_TEST(test_clone_offset)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* equals
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct equals_t equals_t;
|
||||||
|
|
||||||
|
struct equals_t {
|
||||||
|
int val;
|
||||||
|
bool (*equals)(equals_t *a, equals_t *b);
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool equalsfn(equals_t *a, equals_t *b)
|
||||||
|
{
|
||||||
|
return a->val == b->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_equals_offset)
|
||||||
|
{
|
||||||
|
linked_list_t *other;
|
||||||
|
equals_t *x, items[] = {
|
||||||
|
{ .val = 1, .equals = equalsfn, },
|
||||||
|
{ .val = 2, .equals = equalsfn, },
|
||||||
|
{ .val = 3, .equals = equalsfn, },
|
||||||
|
{ .val = 4, .equals = equalsfn, },
|
||||||
|
{ .val = 5, .equals = equalsfn, },
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < countof(items); i++)
|
||||||
|
{
|
||||||
|
list->insert_last(list, &items[i]);
|
||||||
|
}
|
||||||
|
ck_assert(list->equals_offset(list, list, offsetof(equals_t, equals)));
|
||||||
|
other = linked_list_create_from_enumerator(list->create_enumerator(list));
|
||||||
|
ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
|
||||||
|
other->remove_last(other, (void**)&x);
|
||||||
|
ck_assert(!list->equals_offset(list, other, offsetof(equals_t, equals)));
|
||||||
|
list->remove_last(list, (void**)&x);
|
||||||
|
ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
|
||||||
|
other->remove_first(other, (void**)&x);
|
||||||
|
ck_assert(!list->equals_offset(list, other, offsetof(equals_t, equals)));
|
||||||
|
list->remove_first(list, (void**)&x);
|
||||||
|
ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
|
||||||
|
while (list->remove_first(list, (void**)&x) == SUCCESS);
|
||||||
|
while (other->remove_first(other, (void**)&x) == SUCCESS);
|
||||||
|
ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
|
||||||
|
other->destroy(other);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_equals_function)
|
||||||
|
{
|
||||||
|
linked_list_t *other;
|
||||||
|
equals_t *x, items[] = {
|
||||||
|
{ .val = 1, },
|
||||||
|
{ .val = 2, },
|
||||||
|
{ .val = 3, },
|
||||||
|
{ .val = 4, },
|
||||||
|
{ .val = 5, },
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < countof(items); i++)
|
||||||
|
{
|
||||||
|
list->insert_last(list, &items[i]);
|
||||||
|
}
|
||||||
|
ck_assert(list->equals_function(list, list, (void*)equalsfn));
|
||||||
|
other = linked_list_create_from_enumerator(list->create_enumerator(list));
|
||||||
|
ck_assert(list->equals_function(list, other, (void*)equalsfn));
|
||||||
|
other->remove_last(other, (void**)&x);
|
||||||
|
ck_assert(!list->equals_function(list, other, (void*)equalsfn));
|
||||||
|
list->remove_last(list, (void**)&x);
|
||||||
|
ck_assert(list->equals_function(list, other, (void*)equalsfn));
|
||||||
|
other->remove_first(other, (void**)&x);
|
||||||
|
ck_assert(!list->equals_function(list, other, (void*)equalsfn));
|
||||||
|
list->remove_first(list, (void**)&x);
|
||||||
|
ck_assert(list->equals_function(list, other, (void*)equalsfn));
|
||||||
|
while (list->remove_first(list, (void**)&x) == SUCCESS);
|
||||||
|
while (other->remove_first(other, (void**)&x) == SUCCESS);
|
||||||
|
ck_assert(list->equals_function(list, other, (void*)equalsfn));
|
||||||
|
other->destroy(other);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
Suite *linked_list_suite_create()
|
Suite *linked_list_suite_create()
|
||||||
{
|
{
|
||||||
Suite *s;
|
Suite *s;
|
||||||
@@ -386,5 +471,11 @@ Suite *linked_list_suite_create()
|
|||||||
tcase_add_test(tc, test_clone_offset);
|
tcase_add_test(tc, test_clone_offset);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("equals");
|
||||||
|
tcase_add_checked_fixture(tc, setup_list, teardown_list);
|
||||||
|
tcase_add_test(tc, test_equals_offset);
|
||||||
|
tcase_add_test(tc, test_equals_function);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user