Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -18,27 +18,52 @@ #import "OFEnumerator.h" #import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN -typedef struct OFListItem OFListItem; /** - * @struct OFListItem OFList.h ObjFW/OFList.h + * @typedef OFListItem OFList.h ObjFW/OFList.h * * @brief A list item. * - * A struct that contains a pointer to the next list item, the previous list - * item and the object. + * See @ref OFListItemNext, @ref OFListItemPrevious and @ref OFListItemObject. + */ +typedef struct OFListItem *OFListItem; + +#ifdef __cplusplus +extern "C" { +#endif +/*! + * @brief Returns the next list item of the list item. + * + * @param listItem The list item for which the next list item should be returned + * @return The next list item of the list item + */ +OFListItem OFListItemNext(OFListItem _Nonnull listItem); + +/*! + * @brief Returns the previous list item of the list item. + * + * @param listItem The list item for which the previous list item should be + * returned + * @return The previous list item of the list item + */ +OFListItem OFListItemPrevious(OFListItem _Nonnull listItem); + +/*! + * @brief Returns the object of the list item. + * + * @warning The returned object is not retained and autoreleased - this is the + * caller's responsibility! + * + * @param listItem The list item for which the object should be returned + * @return The object of the list item */ -struct OFListItem { - /** A pointer to the next list object in the list */ - OFListItem *_Nullable next; - /** A pointer to the previous list object in the list */ - OFListItem *_Nullable previous; - /** The object for the list object */ - id __unsafe_unretained object; -}; +id OFListItemObject(OFListItem _Nonnull listItem); +#ifdef __cplusplus +} +#endif /** * @class OFList OFList.h ObjFW/OFList.h * * @brief A class which provides easy to use double-linked lists. @@ -47,21 +72,21 @@ OFSerialization> #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # define ObjectType id #endif { - OFListItem *_Nullable _firstListItem; - OFListItem *_Nullable _lastListItem; + OFListItem _Nullable _firstListItem; + OFListItem _Nullable _lastListItem; size_t _count; unsigned long _mutations; OF_RESERVE_IVARS(OFList, 4) } /** * @brief The first list object of the list. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFListItem *firstListItem; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFListItem firstListItem; /** * @brief The first object of the list or `nil`. * * @warning The returned object is *not* retained and autoreleased for @@ -70,11 +95,11 @@ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) ObjectType firstObject; /** * @brief The last list object of the list. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFListItem *lastListItem; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFListItem lastListItem; /** * @brief The last object of the list or `nil`. * * @warning The returned object is *not* retained and autoreleased for @@ -95,21 +120,21 @@ * @param object The object to append * @return An OFListItem, needed to identify the object inside the list. * For example, if you want to remove an object from the list, you need * its OFListItem. */ -- (OFListItem *)appendObject: (ObjectType)object; +- (OFListItem)appendObject: (ObjectType)object; /** * @brief Prepends an object to the list. * * @param object The object to prepend * @return An OFListItem, needed to identify the object inside the list. * For example, if you want to remove an object from the list, you need * its OFListItem. */ -- (OFListItem *)prependObject: (ObjectType)object; +- (OFListItem)prependObject: (ObjectType)object; /** * @brief Inserts an object before another list object. * * @param object The object to insert @@ -117,12 +142,12 @@ * inserted * @return An OFListItem, needed to identify the object inside the list. * For example, if you want to remove an object from the list, you need * its OFListItem. */ -- (OFListItem *)insertObject: (ObjectType)object - beforeListItem: (OFListItem *)listItem; +- (OFListItem)insertObject: (ObjectType)object + beforeListItem: (OFListItem)listItem; /** * @brief Inserts an object after another list object. * * @param object The object to insert @@ -130,19 +155,19 @@ * inserted * @return An OFListItem, needed to identify the object inside the list. * For example, if you want to remove an object from the list, you need * its OFListItem. */ -- (OFListItem *)insertObject: (ObjectType)object - afterListItem: (OFListItem *)listItem; +- (OFListItem)insertObject: (ObjectType)object + afterListItem: (OFListItem)listItem; /** * @brief Removes the object with the specified list object from the list. * * @param listItem The list object returned by append / prepend */ -- (void)removeListItem: (OFListItem *)listItem; +- (void)removeListItem: (OFListItem)listItem; /** * @brief Checks whether the list contains an object equal to the specified * object. * Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -23,23 +23,46 @@ #import "OFXMLElement.h" #import "OFArray.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" + +struct OFListItem { + OFListItem previous, next; + id object; +}; OF_DIRECT_MEMBERS @interface OFListEnumerator: OFEnumerator { OFList *_list; - OFListItem *_Nullable _current; + OFListItem _Nullable _current; unsigned long _mutations; unsigned long *_Nullable _mutationsPtr; } - (instancetype)initWithList: (OFList *)list mutationsPointer: (unsigned long *)mutationsPtr; @end + +OFListItem +OFListItemNext(OFListItem listItem) +{ + return listItem->next; +} + +OFListItem +OFListItemPrevious(OFListItem listItem) +{ + return listItem->previous; +} + +id +OFListItemObject(OFListItem listItem) +{ + return listItem->object; +} @implementation OFList @synthesize firstListItem = _firstListItem, lastListItem = _lastListItem; + (instancetype)list @@ -76,26 +99,25 @@ return self; } - (void)dealloc { - OFListItem *next; + OFListItem next; - for (OFListItem *iter = _firstListItem; iter != NULL; iter = next) { + for (OFListItem iter = _firstListItem; iter != NULL; iter = next) { [iter->object release]; next = iter->next; OFFreeMemory(iter); } [super dealloc]; } -- (OFListItem *)appendObject: (id)object +- (OFListItem)appendObject: (id)object { - OFListItem *listItem; + OFListItem listItem = OFAllocMemory(1, sizeof(*listItem)); - listItem = OFAllocMemory(1, sizeof(OFListItem)); listItem->object = [object retain]; listItem->next = NULL; listItem->previous = _lastListItem; if (_lastListItem != NULL) @@ -110,13 +132,13 @@ _mutations++; return listItem; } -- (OFListItem *)prependObject: (id)object +- (OFListItem)prependObject: (id)object { - OFListItem *listItem = OFAllocMemory(1, sizeof(OFListItem)); + OFListItem listItem = OFAllocMemory(1, sizeof(*listItem)); listItem->object = [object retain]; listItem->next = _firstListItem; listItem->previous = NULL; @@ -131,14 +153,13 @@ _mutations++; return listItem; } -- (OFListItem *)insertObject: (id)object - beforeListItem: (OFListItem *)listItem +- (OFListItem)insertObject: (id)object beforeListItem: (OFListItem)listItem { - OFListItem *newListItem = OFAllocMemory(1, sizeof(OFListItem)); + OFListItem newListItem = OFAllocMemory(1, sizeof(*newListItem)); newListItem->object = [object retain]; newListItem->next = listItem; newListItem->previous = listItem->previous; @@ -154,14 +175,13 @@ _mutations++; return newListItem; } -- (OFListItem *)insertObject: (id)object - afterListItem: (OFListItem *)listItem +- (OFListItem)insertObject: (id)object afterListItem: (OFListItem)listItem { - OFListItem *newListItem = OFAllocMemory(1, sizeof(OFListItem)); + OFListItem newListItem = OFAllocMemory(1, sizeof(*newListItem)); newListItem->object = [object retain]; newListItem->next = listItem->next; newListItem->previous = listItem; @@ -177,11 +197,11 @@ _mutations++; return newListItem; } -- (void)removeListItem: (OFListItem *)listItem +- (void)removeListItem: (OFListItem)listItem { if (listItem->previous != NULL) listItem->previous->next = listItem->next; if (listItem->next != NULL) listItem->next->previous = listItem->previous; @@ -214,11 +234,11 @@ } - (bool)isEqual: (id)object { OFList *list; - OFListItem *iter, *iter2; + OFListItem iter, iter2; if (object == self) return true; if (![object isKindOfClass: [OFList class]]) @@ -244,11 +264,11 @@ - (bool)containsObject: (id)object { if (_count == 0) return false; - for (OFListItem *iter = _firstListItem; iter != NULL; iter = iter->next) + for (OFListItem iter = _firstListItem; iter != NULL; iter = iter->next) if ([iter->object isEqual: object]) return true; return false; } @@ -256,24 +276,24 @@ - (bool)containsObjectIdenticalTo: (id)object { if (_count == 0) return false; - for (OFListItem *iter = _firstListItem; iter != NULL; iter = iter->next) + for (OFListItem iter = _firstListItem; iter != NULL; iter = iter->next) if (iter->object == object) return true; return false; } - (void)removeAllObjects { - OFListItem *next; + OFListItem next; _mutations++; - for (OFListItem *iter = _firstListItem; iter != NULL; iter = next) { + for (OFListItem iter = _firstListItem; iter != NULL; iter = next) { [iter->object release]; next = iter->next; OFFreeMemory(iter); } @@ -281,19 +301,16 @@ } - (id)copy { OFList *copy = [[[self class] alloc] init]; - OFListItem *listItem, *previous; - - listItem = NULL; - previous = NULL; + OFListItem listItem = NULL, previous = NULL; @try { - for (OFListItem *iter = _firstListItem; + for (OFListItem iter = _firstListItem; iter != NULL; iter = iter->next) { - listItem = OFAllocMemory(1, sizeof(OFListItem)); + listItem = OFAllocMemory(1, sizeof(*listItem)); listItem->object = [iter->object retain]; listItem->next = NULL; listItem->previous = previous; if (copy->_firstListItem == NULL) @@ -319,11 +336,11 @@ { unsigned long hash; OFHashInit(&hash); - for (OFListItem *iter = _firstListItem; iter != NULL; iter = iter->next) + for (OFListItem iter = _firstListItem; iter != NULL; iter = iter->next) OFHashAddHash(&hash, [iter->object hash]); OFHashFinalize(&hash); return hash; @@ -336,11 +353,11 @@ if (_count == 0) return @"[]"; ret = [OFMutableString stringWithString: @"[\n"]; - for (OFListItem *iter = _firstListItem; + for (OFListItem iter = _firstListItem; iter != NULL; iter = iter->next) { void *pool = objc_autoreleasePoolPush(); [ret appendString: [iter->object description]]; @@ -361,11 +378,11 @@ { OFXMLElement *element = [OFXMLElement elementWithName: self.className namespace: OFSerializationNS]; - for (OFListItem *iter = _firstListItem; + for (OFListItem iter = _firstListItem; iter != NULL; iter = iter->next) { void *pool = objc_autoreleasePoolPush(); [element addChild: [iter->object XMLElementBySerializing]]; @@ -377,11 +394,11 @@ - (int)countByEnumeratingWithState: (OFFastEnumerationState *)state objects: (id *)objects count: (int)count { - OFListItem *listItem; + OFListItem listItem; memcpy(&listItem, state->extra, sizeof(listItem)); state->itemsPtr = objects; state->mutationsPtr = &_mutations; Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -274,11 +274,11 @@ assert(queue != nil); @try { if (![queue.firstObject handleObject: object]) { - OFListItem *listItem = queue.firstListItem; + OFListItem listItem = queue.firstListItem; /* * The handler might have called -[cancelAsyncRequests] * so that our queue is now empty, in which case we * should do nothing. @@ -288,11 +288,12 @@ * Make sure we keep the target until after we * are done removing the object. The reason for * this is that the target might call * -[cancelAsyncRequests] in its dealloc. */ - [[listItem->object retain] autorelease]; + [[OFListItemObject(listItem) retain] + autorelease]; [queue removeListItem: listItem]; if (queue.count == 0) { [_kernelEventObserver @@ -317,11 +318,11 @@ assert(queue != nil); @try { if (![queue.firstObject handleObject: object]) { - OFListItem *listItem = queue.firstListItem; + OFListItem listItem = queue.firstListItem; /* * The handler might have called -[cancelAsyncRequests] * so that our queue is now empty, in which case we * should do nothing. @@ -331,11 +332,12 @@ * Make sure we keep the target until after we * are done removing the object. The reason for * this is that the target might call * -[cancelAsyncRequests] in its dealloc. */ - [[listItem->object retain] autorelease]; + [[OFListItemObject(listItem) retain] + autorelease]; [queue removeListItem: listItem]; if (queue.count == 0) { [_kernelEventObserver @@ -1418,13 +1420,13 @@ #ifdef OF_HAVE_THREADS [state->_timersQueueMutex lock]; @try { #endif - for (OFListItem *iter = state->_timersQueue.firstListItem; - iter != NULL; iter = iter->next) { - if ([iter->object isEqual: timer]) { + for (OFListItem iter = state->_timersQueue.firstListItem; + iter != NULL; iter = OFListItemNext(iter)) { + if ([OFListItemObject(iter) isEqual: timer]) { [state->_timersQueue removeListItem: iter]; break; } } #ifdef OF_HAVE_THREADS @@ -1575,16 +1577,17 @@ #ifdef OF_HAVE_THREADS [state->_timersQueueMutex lock]; @try { #endif - OFListItem *listItem = + OFListItem listItem = state->_timersQueue.firstListItem; - if (listItem != NULL && [listItem->object - fireDate].timeIntervalSinceNow <= 0) { - timer = [[listItem->object + if (listItem != NULL && + [OFListItemObject(listItem) fireDate] + .timeIntervalSinceNow <= 0) { + timer = [[OFListItemObject(listItem) retain] autorelease]; [state->_timersQueue removeListItem: listItem]; Index: src/OFSortedList.h ================================================================== --- src/OFSortedList.h +++ src/OFSortedList.h @@ -31,27 +31,25 @@ #endif { OF_RESERVE_IVARS(OFSortedList, 4) } -- (OFListItem *)appendObject: (ObjectType)object OF_UNAVAILABLE; -- (OFListItem *)prependObject: (ObjectType)object OF_UNAVAILABLE; -- (OFListItem *)insertObject: (ObjectType)object - beforeListItem: (OFListItem *)listItem - OF_UNAVAILABLE; -- (OFListItem *)insertObject: (ObjectType)object - afterListItem: (OFListItem *)listItem - OF_UNAVAILABLE; +- (OFListItem)appendObject: (ObjectType)object OF_UNAVAILABLE; +- (OFListItem)prependObject: (ObjectType)object OF_UNAVAILABLE; +- (OFListItem)insertObject: (ObjectType)object + beforeListItem: (OFListItem)listItem OF_UNAVAILABLE; +- (OFListItem)insertObject: (ObjectType)object + afterListItem: (OFListItem)listItem OF_UNAVAILABLE; /** * @brief Inserts the object to the list while keeping the list sorted. * * @param object The object to insert * @return The list object for the object just added */ -- (OFListItem *)insertObject: (ObjectType )object; +- (OFListItem)insertObject: (ObjectType )object; #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # undef ObjectType #endif @end OF_ASSUME_NONNULL_END Index: src/OFSortedList.m ================================================================== --- src/OFSortedList.m +++ src/OFSortedList.m @@ -16,39 +16,39 @@ #include "config.h" #import "OFSortedList.h" @implementation OFSortedList -- (OFListItem *)appendObject: (id)object +- (OFListItem)appendObject: (id)object +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (OFListItem)prependObject: (id)object { OF_UNRECOGNIZED_SELECTOR } -- (OFListItem *)prependObject: (id)object +- (OFListItem)insertObject: (id)object beforeListItem: (OFListItem)listItem { OF_UNRECOGNIZED_SELECTOR } -- (OFListItem *)insertObject: (id)object - beforeListItem: (OFListItem *)listItem +- (OFListItem)insertObject: (id)object afterListItem: (OFListItem)listItem { OF_UNRECOGNIZED_SELECTOR } -- (OFListItem *)insertObject: (id)object - afterListItem: (OFListItem *)listItem -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (OFListItem *)insertObject: (id )object -{ - OFListItem *iter; - - for (iter = _lastListItem; iter != NULL; iter = iter->previous) { - if ([object compare: iter->object] != OFOrderedAscending) +- (OFListItem)insertObject: (id )object +{ + OFListItem iter; + + for (iter = _lastListItem; iter != NULL; + iter = OFListItemPrevious(iter)) { + if ([object compare: OFListItemObject(iter)] != + OFOrderedAscending) return [super insertObject: object afterListItem: iter]; } return [super prependObject: object]; } @end Index: src/OFThreadPool.m ================================================================== --- src/OFThreadPool.m +++ src/OFThreadPool.m @@ -160,11 +160,11 @@ for (;;) { OFThreadPoolJob *job; [_queueCondition lock]; @try { - OFListItem *listItem; + OFListItem listItem; if (_terminate) { objc_autoreleasePoolPop(pool); return nil; } @@ -180,11 +180,11 @@ } listItem = _queue.firstListItem; } - job = [[listItem->object retain] autorelease]; + job = [[OFListItemObject(listItem) retain] autorelease]; [_queue removeListItem: listItem]; } @finally { [_queueCondition unlock]; } Index: tests/OFListTests.m ================================================================== --- tests/OFListTests.m +++ tests/OFListTests.m @@ -28,11 +28,11 @@ - (void)listTests { void *pool = objc_autoreleasePoolPush(); OFList *list; OFEnumerator *enumerator; - OFListItem *iter; + OFListItem iter; OFString *obj; size_t i; bool ok; TEST(@"+[list]", (list = [OFList list])) @@ -39,35 +39,38 @@ TEST(@"-[appendObject:]", [list appendObject: strings[0]] && [list appendObject: strings[1]] && [list appendObject: strings[2]]) TEST(@"-[firstListItem]", - [list.firstListItem->object isEqual: strings[0]]) + [OFListItemObject(list.firstListItem) isEqual: strings[0]]) - TEST(@"-[firstListItem]->next", - [list.firstListItem->next->object isEqual: strings[1]]) + TEST(@"OFListItemNext()", + [OFListItemObject(OFListItemNext(list.firstListItem)) + isEqual: strings[1]]) TEST(@"-[lastListItem]", - [list.lastListItem->object isEqual: strings[2]]) + [OFListItemObject(list.lastListItem) isEqual: strings[2]]) - TEST(@"-[lastListItem]->previous", - [list.lastListItem->previous->object isEqual: strings[1]]) + TEST(@"OFListItemPrevious()", + [OFListItemObject(OFListItemPrevious(list.lastListItem)) + isEqual: strings[1]]) TEST(@"-[removeListItem:]", R([list removeListItem: list.lastListItem]) && - [list.lastListItem->object isEqual: strings[1]] && + [list.lastObject isEqual: strings[1]] && R([list removeListItem: list.firstListItem]) && - [list.firstListItem->object isEqual: list.lastListItem->object]) + [list.firstObject isEqual: list.lastObject]) TEST(@"-[insertObject:beforeListItem:]", [list insertObject: strings[0] beforeListItem: list.lastListItem] && - [list.lastListItem->previous->object isEqual: strings[0]]) + [OFListItemObject(OFListItemPrevious(list.lastListItem)) + isEqual: strings[0]]) TEST(@"-[insertObject:afterListItem:]", [list insertObject: strings[2] - afterListItem: list.firstListItem->next] && - [list.lastListItem->object isEqual: strings[2]]) + afterListItem: OFListItemNext(list.firstListItem)] && + [list.lastObject isEqual: strings[2]]) TEST(@"-[count]", list.count == 3) TEST(@"-[containsObject:]", [list containsObject: strings[1]] && @@ -77,13 +80,14 @@ [list containsObjectIdenticalTo: strings[1]] && ![list containsObjectIdenticalTo: [OFString stringWithString: strings[1]]]) TEST(@"-[copy]", (list = [[list copy] autorelease]) && - [list.firstListItem->object isEqual: strings[0]] && - [list.firstListItem->next->object isEqual: strings[1]] && - [list.lastListItem->object isEqual: strings[2]]) + [list.firstObject isEqual: strings[0]] && + [OFListItemObject(OFListItemNext(list.firstListItem)) + isEqual: strings[1]] && + [list.lastObject isEqual: strings[2]]) TEST(@"-[isEqual:]", [list isEqual: [[list copy] autorelease]]) TEST(@"-[description]", [list.description isEqual: @"[\n\tFoo,\n\tBar,\n\tBaz\n]"]) @@ -92,14 +96,14 @@ iter = list.firstListItem; i = 0; ok = true; while ((obj = [enumerator nextObject]) != nil) { - if (![obj isEqual: iter->object]) + if (![obj isEqual: OFListItemObject(iter)]) ok = false; - iter = iter->next; + iter = OFListItemNext(iter); i++; } if (list.count != i) ok = false; @@ -116,14 +120,14 @@ iter = list.firstListItem; i = 0; ok = true; for (OFString *object in list) { - if (![object isEqual: iter->object]) + if (![object isEqual: OFListItemObject(iter)]) ok = false; - iter = iter->next; + iter = OFListItemNext(iter); i++; } if (list.count != i) ok = false;