diff --git a/Sources/Objectively/List.c b/Sources/Objectively/List.c index fb4d2f3..87743ef 100644 --- a/Sources/Objectively/List.c +++ b/Sources/Objectively/List.c @@ -32,6 +32,26 @@ #pragma mark - Object +/** + * @see Object::copy(const Object *) + * @remarks Elements are not retained, since List does not retain them on + * insertion either. The copy does not inherit `destroy`, and so borrows the + * elements rather than owning them, as `filteredList` and `mappedList` do. + */ +static Object *copy(const Object *self) { + + const List *this = (List *) self; + + List *copy = $(alloc(List), init); + assert(copy); + + for (ListNode *node = this->head; node; node = node->next) { + $(copy, append, node->element); + } + + return (Object *) copy; +} + /** * @see Object::dealloc(Object *) */ @@ -357,6 +377,7 @@ static void _sort(List *self, Comparator comparator) { */ static void initialize(Class *clazz) { + ((ObjectInterface *) clazz->interface)->copy = copy; ((ObjectInterface *) clazz->interface)->dealloc = dealloc; ((ListInterface *) clazz->interface)->append = append; diff --git a/Tests/Objectively/List.c b/Tests/Objectively/List.c index 1d1755a..e121ac2 100644 --- a/Tests/Objectively/List.c +++ b/Tests/Objectively/List.c @@ -25,6 +25,46 @@ #include "Objectively.h" +START_TEST(copyList) { + + int one = 1, two = 2, three = 3, four = 4; + + List *list = $(alloc(List), init); + + $(list, append, &one); + $(list, append, &two); + $(list, append, &three); + + List *copy = (List *) $((Object *) list, copy); + + ck_assert_ptr_ne(list, copy); + ck_assert_int_eq(3, copy->count); + + ListNode *a = list->head, *b = copy->head; + while (a && b) { + ck_assert_ptr_eq(a->element, b->element); + ck_assert_ptr_ne(a, b); + a = a->next; + b = b->next; + } + ck_assert_ptr_eq(NULL, a); + ck_assert_ptr_eq(NULL, b); + + $(copy, append, &four); + + ck_assert_int_eq(4, copy->count); + ck_assert_int_eq(3, list->count); + + release(copy); + + ck_assert_int_eq(3, list->count); + ck_assert_ptr_eq(&one, list->head->element); + ck_assert_ptr_eq(&three, list->tail->element); + + release(list); + +} END_TEST + START_TEST(appendElement) { int one = 1, two = 2, three = 3; @@ -384,6 +424,7 @@ int main(int argc, char **argv) { TCase *tcase = tcase_create("List"); tcase_add_test(tcase, appendElement); tcase_add_test(tcase, containsElement); + tcase_add_test(tcase, copyList); tcase_add_test(tcase, enumerate); tcase_add_test(tcase, filter); tcase_add_test(tcase, filteredList);