Index: src/OFArray.h ================================================================== --- src/OFArray.h +++ src/OFArray.h @@ -27,10 +27,11 @@ #ifdef OF_HAVE_BLOCKS typedef void (^of_array_enumeration_block_t)(id object, size_t index, BOOL *stop); typedef BOOL (^of_array_filter_block_t)(id odject, size_t index); typedef id (^of_array_map_block_t)(id object, size_t index); +typedef id (^of_array_reduce_block_t)(id object1, id object2); #endif /** * \brief A class for storing objects in an array. */ @@ -280,10 +281,28 @@ * \param block A block which determines if the object should be in the new * array * \return A new, autoreleased OFArray */ - (OFArray*)filteredArrayUsingBlock: (of_array_filter_block_t)block; + +/** + * \brief Reduces the array to a single object using the specified block. + * + * If the array is empty, it will return nil. + * + * If there is only one object in the array, that object will be returned and + * the block will not be invoked. + * + * If there are at least two objects, the block is invoked for each object + * except the first, where object1 is always to what the array has already been + * reduced and object2 what should be added to object1. + * + * \param block A block which reduces two objects into one, which is called for + * all objects except the first + * \return The array reduced to a single object + */ +- (id)reduceUsingBlock: (of_array_reduce_block_t)block; #endif @end @interface OFArrayEnumerator: OFEnumerator { Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -652,10 +652,47 @@ [self freeMemory: tmp]; } return ret; } + +- (id)reduceUsingBlock: (of_array_reduce_block_t)block +{ + OFAutoreleasePool *pool; + id *cArray; + size_t i, count = [array count]; + id current; + + if (count == 0) + return nil; + if (count == 1) + return [[[self firstObject] retain] autorelease]; + + cArray = [array cArray]; + + pool = [[OFAutoreleasePool alloc] init]; + current = cArray[0]; + + for (i = 1; i < count; i++) { + id old = current; + @try { + current = [block(current, cArray[i]) retain]; + [pool releaseObjects]; + } @finally { + [old release]; + } + } + + @try { + [pool release]; + } @catch (id e) { + [current release]; + @throw e; + } + + return [current autorelease]; +} #endif - (void)dealloc { id *cArray = [array cArray];