Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -8,11 +8,10 @@ OFAutoreleasePool.m \ OFExceptions.m \ OFHashes.m \ OFFile.m \ OFList.m \ - OFListObject.m \ OFNumber.m \ OFObject.m \ OFString.m \ OFTCPSocket.m \ OFXMLFactory.m \ Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -8,52 +8,83 @@ * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ #import "OFObject.h" -#import "OFListObject.h" + +typedef struct __of_list_object +{ + id object; + struct __of_list_object *next; + struct __of_list_object *prev; +} of_list_object_t; /** * The OFList class provides easy to use double-linked lists. */ @interface OFList: OFObject { - OFListObject *first; - OFListObject *last; -} - -- init; - -/** - * Frees the OFList and all OFListObjects, but not the data they contian. - */ -- free; - -/** - * Frees the list and the data included in all OFListObjects it contains. - */ -- freeIncludingData; - -/** - * \returns The first OFListObject in the OFList - */ -- (OFListObject*)first; - -/** - * \returns The last OFListObject in the OFList - */ -- (OFListObject*)last; - -/** - * Adds a new OFListObject to the OFList. - * - * \param obj An OFListObject - */ -- add: (OFListObject*)obj; - -/** - * Creates a new OFListObject and adds it to the OFList. - * - * \param obj A data object for the OFListObject which will be added - */ -- addNew: (id)obj; + of_list_object_t *first; + of_list_object_t *last; +} + +/** + * \return The first object in the list + */ +- (of_list_object_t*)first; + +/** + * \return The last object in the list + */ +- (of_list_object_t*)last; + +/** + * Appends an object to the list. + * + * \param obj The object to append + * \return An of_list_object_t, needed to identify the object inside the list. + * For example, if you want to remove an object from the list, you need + * its of_list_object_t. + */ +- (of_list_object_t*)append: (id)obj; + +/** + * Prepends an object to the list. + * + * \param obj The object to prepend + * \return An of_list_object_t, needed to identify the object inside the list. + * For example, if you want to remove an object from the list, you need + * its of_list_object_t. + */ +- (of_list_object_t*)prepend: (id)obj; + +/** + * Inserts an object before another object. + * \param obj The object to insert + * \param listobj The of_list_object_t of the object before which it should be + * inserted + * \return An of_list_object_t, needed to identify the object inside the list. + * For example, if you want to remove an object from the list, you need + * its of_list_object_t. + */ +- (of_list_object_t*)insert: (id)obj + before: (of_list_object_t*)listobj; + +/** + * Inserts an object after another object. + * \param obj The object to insert + * \param listobj The of_list_object_t of the object after which it should be + * inserted + * \return An of_list_object_t, needed to identify the object inside the list. + * For example, if you want to remove an object from the list, you need + * its of_list_object_t. + */ +- (of_list_object_t*)insert: (id)obj + after: (of_list_object_t*)listobj; + +/** + * Removes an object from the list. + * + * \param listobj The list object returned by append / prepend + */ +- remove: (of_list_object_t*)listobj; @end Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -15,66 +15,128 @@ @implementation OFList - init { if ((self = [super init])) { - first = nil; - last = nil; + first = NULL; + last = NULL; } + return self; } - free { - OFListObject *iter, *next; + of_list_object_t *iter; - for (iter = first; iter != nil; iter = next) { - next = [iter next]; - [iter free]; - } + for (iter = first; iter != NULL; iter = iter->next) + [iter->object release]; return [super free]; } -- freeIncludingData -{ - OFListObject *iter, *next; - - for (iter = first; iter != nil; iter = next) { - next = [iter next]; - [iter freeIncludingData]; - } - - first = last = nil; - return [super free]; -} - -- (OFListObject*)first +- (of_list_object_t*)first { return first; } -- (OFListObject*)last +- (of_list_object_t*)last { return last; } -- add: (OFListObject*)obj -{ - if (!first || !last) { - first = last = obj; - return self; - } - - [obj setPrev: last]; - [last setNext: obj]; - - last = obj; - - return self; -} - -- addNew: (id)obj -{ - return [self add: [OFListObject newWithData: obj]]; +- (of_list_object_t*)append: (id)obj +{ + of_list_object_t *o = [self getMemWithSize: sizeof(of_list_object_t)]; + + o->object = obj; + o->next = NULL; + o->prev = last; + + if (last != NULL) + last->next = o; + + last = o; + if (first == NULL) + first = o; + + [obj retain]; + return o; +} + +- (of_list_object_t*)prepend: (id)obj +{ + of_list_object_t *o = [self getMemWithSize: sizeof(of_list_object_t)]; + + o->object = obj; + o->next = first; + o->prev = NULL; + + if (first != NULL) + first->prev = o; + + first = o; + if (last == NULL) + last = o; + + [obj retain]; + return o; +} + +- (of_list_object_t*)insert: (id)obj + before: (of_list_object_t*)listobj +{ + of_list_object_t *o = [self getMemWithSize: sizeof(of_list_object_t)]; + + o->object = obj; + o->next = listobj; + o->prev = listobj->prev; + + if (listobj->prev != NULL) + listobj->prev->next = o; + + listobj->prev = o; + + if (listobj == first) + first = o; + + [obj retain]; + return o; +} + +- (of_list_object_t*)insert: (id)obj + after: (of_list_object_t*)listobj +{ + of_list_object_t *o = [self getMemWithSize: sizeof(of_list_object_t)]; + + o->object = obj; + o->next = listobj->next; + o->prev = listobj; + + if (listobj->next != NULL) + listobj->next->prev = o; + + listobj->next = o; + + if (listobj == last) + last = o; + + [obj retain]; + return o; +} + +- remove: (of_list_object_t*)listobj +{ + if (listobj->prev != NULL) + listobj->prev->next = listobj->next; + if (listobj->next != NULL) + listobj->next->prev = listobj->prev; + + if (first == listobj) + first = listobj->next; + if (last == listobj) + last = listobj->prev; + + [self freeMem: listobj]; + return self; } @end DELETED src/OFListObject.h Index: src/OFListObject.h ================================================================== --- src/OFListObject.h +++ src/OFListObject.h @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2008 - 2009 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of libobjfw. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE included in - * the packaging of this file. - */ - -#import "OFObject.h" - -/** - * The OFListObject class is a class for objects to be stored in an OFObject. - */ -@interface OFListObject: OFObject -{ - id data; - OFListObject *next; - OFListObject *prev; -} - -/** - * \param obj The data object the OFListObject should contain - * \return A new OFListObject. - */ -+ newWithData: (id)obj; - -/** - * Initializes an already allocated OFListObjeect. - * - * \param obj The data object the OFListObject should contain - * \return An initialized OFListObject. - */ -- initWithData: (id)obj; - -/** - * Free the OFListObject and the data it contains. - */ -- freeIncludingData; - -/** - * \return The data object included in the OFListObject - */ -- (id)data; - -/** - * \return The next OFListObject in the OFList - */ -- (OFListObject*)next; - -/** - * \return The previous OFListObject in the OFList - */ -- (OFListObject*)prev; - -/** - * Sets the next OFListObject in the OFList. - * - * \param obj An OFListObject - */ -- setNext: (OFListObject*)obj; - -/** - * Sets the previous OFListObject in the OFList. - * - * \param obj An OFListObject - */ -- setPrev: (OFListObject*)obj; -@end DELETED src/OFListObject.m Index: src/OFListObject.m ================================================================== --- src/OFListObject.m +++ src/OFListObject.m @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2008 - 2009 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of libobjfw. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE included in - * the packaging of this file. - */ - -#import "config.h" - -#import - -#import "OFListObject.h" - -@implementation OFListObject -+ newWithData: (id)obj -{ - return [[self alloc] initWithData: obj]; -} - -- initWithData: (id)obj -{ - if ((self = [super init])) { - next = nil; - prev = nil; - data = obj; - } - - return self; -} - -- freeIncludingData -{ - if (data != nil) - [data free]; - - return [super free]; -} - -- (id)data -{ - return data; -} - -- (OFListObject*)next -{ - return next; -} - -- (OFListObject*)prev -{ - return prev; -} - -- setNext: (OFListObject*)obj -{ - next = obj; - - return self; -} - -- setPrev: (OFListObject*)obj -{ - prev = obj; - - return self; -} -@end Index: tests/OFList/OFList.m ================================================================== --- tests/OFList/OFList.m +++ tests/OFList/OFList.m @@ -22,11 +22,11 @@ #define ZD "%zd" #else #define ZD "%u" #endif -#define NUM_TESTS 5 +#define NUM_TESTS 10 #define SUCCESS \ { \ printf("\r\033[1;%dmTests successful: " ZD "/%d\033[0m", \ (i == NUM_TESTS - 1 ? 32 : 33), i + 1, NUM_TESTS); \ fflush(stdout); \ @@ -36,15 +36,17 @@ printf("\r\033[K\033[1;31mTest " ZD "/%d failed!\033[m\n", \ i + 1, NUM_TESTS); \ return 1; \ } #define CHECK(cond) \ +{ \ if (cond) \ SUCCESS \ else \ FAIL \ - i++; + i++; \ +} const char *strings[] = { "First String Object", "Second String Object", "Third String Object" @@ -51,30 +53,43 @@ }; int main() { - size_t i; - OFList *list; - OFListObject *iter; + size_t i, j; + OFList *list; + of_list_object_t *iter; list = [OFList new]; - [list addNew: [OFString newFromCString: strings[0]]]; - [list addNew: [OFString newFromCString: strings[1]]]; - [list addNew: [OFString newFromCString: strings[2]]]; + [list append: [OFString newFromCString: strings[0]]]; + [list append: [OFString newFromCString: strings[1]]]; + [list append: [OFString newFromCString: strings[2]]]; - for (iter = [list first], i = 0; iter != nil; iter = [iter next], i++) - if (!strcmp([[iter data] cString], strings[i])) + for (iter = [list first], i = 0; iter != NULL; iter = iter->next, i++) + if (!strcmp([iter->object cString], strings[i])) SUCCESS else FAIL - CHECK(!strcmp([[[list first] data] cString], strings[0])) - CHECK(!strcmp([[[list last] data] cString], strings[2])) + CHECK(!strcmp([[list first]->object cString], strings[0])) + CHECK(!strcmp([[list last]->object cString], strings[2])) + + [list remove: [list last]]; + CHECK(!strcmp([[list last]->object cString], strings[1])) + + [list remove: [list first]]; + CHECK(!strcmp([[list first]->object cString], + [[list last]->object cString])) + + [list insert: [OFString newFromCString: strings[0]] + before: [list last]]; + [list insert: [OFString newFromCString: strings[2]] + after: [list first]->next]; + + for (iter = [list first], j = 0; iter != NULL; iter = iter->next, j++) + CHECK(!strcmp([iter->object cString], strings[j])) puts(""); - [list freeIncludingData]; - return 0; }