Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -19,11 +19,11 @@ } of_list_object_t; /** * The OFList class provides easy to use double-linked lists. */ -@interface OFList: OFObject +@interface OFList: OFObject { of_list_object_t *first; of_list_object_t *last; BOOL retain_and_release; } Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -10,10 +10,11 @@ */ #import "config.h" #import "OFList.h" +#import "OFExceptions.h" @implementation OFList + list { return [[[OFList alloc] init] autorelease]; @@ -195,6 +196,45 @@ if (iter != NULL || iter2 != NULL) return NO; return YES; } + +- (id)copy +{ + OFList *new; + of_list_object_t *iter, *o, *prev; + + if (retain_and_release) + new = [[OFList alloc] init]; + else + new = [[OFList alloc] initWithoutRetainAndRelease]; + + o = NULL; + prev = NULL; + + @try { + for (iter = first; iter != NULL; iter = iter->next) { + o = [new allocWithSize: sizeof(of_list_object_t)]; + o->object = iter->object; + o->next = NULL; + o->prev = prev; + + if (new->first == NULL) + new->first = o; + if (prev != NULL) + prev->next = o; + if (retain_and_release) + [o->object retain]; + + prev = o; + } + } @catch (OFException *e) { + [new release]; + @throw e; + } + + new->last = o; + + return new; +} @end Index: tests/OFList/OFList.m ================================================================== --- tests/OFList/OFList.m +++ tests/OFList/OFList.m @@ -21,11 +21,11 @@ #define ZD "%zd" #else #define ZD "%u" #endif -#define NUM_TESTS 14 +#define NUM_TESTS 23 #define SUCCESS \ { \ printf("\r\033[1;%dmTests successful: " ZD "/%d\033[0m", \ (i == NUM_TESTS - 1 ? 32 : 33), i + 1, NUM_TESTS); \ fflush(stdout); \ @@ -53,12 +53,12 @@ int main() { size_t i, j; - OFList *list, *list2; - of_list_object_t *iter; + OFList *list, *list2, *list3; + of_list_object_t *iter, *iter2; list = [OFList list]; [list append: strings[0]]; [list append: strings[1]]; @@ -97,12 +97,28 @@ CHECK([list2 isEqual: list]); [list2 remove: [list2 last]]; CHECK(![list2 isEqual: list]); - [list2 append: @"foo"]; + /* + * Only mutableCopy is guaranteed to return a real copy instead of just + * increasing the reference counter. + */ + [list2 append: [@"foo" mutableCopy]]; CHECK(![list2 isEqual: list]); + list3 = [list2 copy]; + CHECK([list2 isEqual: list3]); + + for (iter = [list2 first], iter2 = [list3 first]; + iter != NULL && iter2 != NULL; + iter = iter->next, iter2 = iter2->next) { + CHECK(iter != iter2) + CHECK(iter->object == iter2->object) + } + CHECK(iter == NULL && iter2 == NULL) + CHECK([[list2 last]->object retainCount] == 3) + puts(""); return 0; }