aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-10-16 12:12:43 +0200
committerTobias Brunner <tobias@strongswan.org>2016-03-08 10:21:57 +0100
commit348b0ffbc67aab6c7e386418d14ed85aeac748a9 (patch)
treecce4cc6bb9de97cdee446a7892d14ccf9834aa1b
parent229cdf6bc8f24f9ce445943117c518dc6bb876a4 (diff)
downloadstrongswan-348b0ffbc67aab6c7e386418d14ed85aeac748a9.tar.bz2
strongswan-348b0ffbc67aab6c7e386418d14ed85aeac748a9.tar.xz
linked-list: Add method to compare two lists of objects for equality
-rw-r--r--src/libstrongswan/collections/linked_list.c54
-rw-r--r--src/libstrongswan/collections/linked_list.h23
-rw-r--r--src/libstrongswan/tests/suites/test_linked_list.c91
3 files changed, 166 insertions, 2 deletions
diff --git a/src/libstrongswan/collections/linked_list.c b/src/libstrongswan/collections/linked_list.c
index a176e5a54..b8fe81578 100644
--- a/src/libstrongswan/collections/linked_list.c
+++ b/src/libstrongswan/collections/linked_list.c
@@ -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 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -433,6 +433,56 @@ METHOD(linked_list_t, clone_offset, linked_list_t*,
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,
private_linked_list_t *this)
{
@@ -503,6 +553,8 @@ linked_list_t *linked_list_create()
.invoke_offset = (void*)_invoke_offset,
.invoke_function = (void*)_invoke_function,
.clone_offset = _clone_offset,
+ .equals_offset = _equals_offset,
+ .equals_function = _equals_function,
.destroy = _destroy,
.destroy_offset = _destroy_offset,
.destroy_function = _destroy_function,
diff --git a/src/libstrongswan/collections/linked_list.h b/src/libstrongswan/collections/linked_list.h
index abc33c12a..5edaa07aa 100644
--- a/src/libstrongswan/collections/linked_list.h
+++ b/src/libstrongswan/collections/linked_list.h
@@ -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 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -218,6 +218,27 @@ struct linked_list_t {
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.
*/
void (*destroy) (linked_list_t *this);
diff --git a/src/libstrongswan/tests/suites/test_linked_list.c b/src/libstrongswan/tests/suites/test_linked_list.c
index 922f954e3..7a161817c 100644
--- a/src/libstrongswan/tests/suites/test_linked_list.c
+++ b/src/libstrongswan/tests/suites/test_linked_list.c
@@ -348,6 +348,91 @@ START_TEST(test_clone_offset)
}
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 *s;
@@ -386,5 +471,11 @@ Suite *linked_list_suite_create()
tcase_add_test(tc, test_clone_offset);
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;
}