Index: src/OFArray.h ================================================================== --- src/OFArray.h +++ src/OFArray.h @@ -260,10 +260,17 @@ * array */ - (void)makeObjectsPerformSelector: (SEL)selector withObject: (id)object; +/** + * \brief Returns a copy of the array with the order reversed. + * + * \return A copy of the array with the order reversed + */ +- (OFArray*)reversedArray; + #ifdef OF_HAVE_BLOCKS /** * \brief Executes a block for each object. * * \param block The block to execute for each object Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -551,10 +551,21 @@ for (i = 0; i < count; i++) ((void(*)(id, SEL, id))[cArray[i] methodForSelector: selector])(cArray[i], selector, object); } + +- (OFArray*)reversedArray +{ + OFMutableArray *new = [[self mutableCopy] autorelease]; + + [new reverse]; + + [new makeImmutable]; + + return new; +} - (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state objects: (id*)objects count: (int)count_ { Index: src/OFMutableArray.h ================================================================== --- src/OFMutableArray.h +++ src/OFMutableArray.h @@ -118,10 +118,24 @@ * \param block The block which returns a new object for each object */ - (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block; #endif +/** + * \brief Swaps the objects at the specified indices. + * + * \param index1 The index of the first object to swap + * \param index2 The index of the second object to swap + */ +- (void)swapObjectAtIndex: (size_t)index1 + withObjectAtIndex: (size_t)index2; + +/** + * \brief Reverts the order of the objects in the array. + */ +- (void)reverse; + /** * \brief Converts the mutable array to an immutable array. */ - (void)makeImmutable; @end Index: src/OFMutableArray.m ================================================================== --- src/OFMutableArray.m +++ src/OFMutableArray.m @@ -253,10 +253,39 @@ [self replaceObjectAtIndex: index withObject: block(object, index, stop)]; }]; } #endif + +- (void)swapObjectAtIndex: (size_t)index1 + withObjectAtIndex: (size_t)index2 +{ + id object1 = [self objectAtIndex: index1]; + id object2 = [self objectAtIndex: index2]; + + [object1 retain]; + @try { + [self replaceObjectAtIndex: index1 + withObject: object2]; + [self replaceObjectAtIndex: index2 + withObject: object1]; + } @finally { + [object1 release]; + } +} + +- (void)reverse +{ + size_t i, j, count = [self count]; + + if (count == 0 || count == 1) + return; + + for (i = 0, j = count - 1; i < j; i++, j--) + [self swapObjectAtIndex: i + withObjectAtIndex: j]; +} - (void)makeImmutable { } @end Index: src/OFMutableArray_adjacent.m ================================================================== --- src/OFMutableArray_adjacent.m +++ src/OFMutableArray_adjacent.m @@ -198,10 +198,40 @@ [array removeLastItem]; [object release]; mutations++; } + +- (void)swapObjectAtIndex: (size_t)index1 + withObjectAtIndex: (size_t)index2 +{ + id *cArray = [array cArray]; + size_t count = [array count]; + id tmp; + + if (index1 >= count || index2 >= count) + @throw [OFOutOfRangeException exceptionWithClass: isa]; + + tmp = cArray[index1]; + cArray[index1] = cArray[index2]; + cArray[index2] = tmp; +} + +- (void)reverse +{ + id *cArray = [array cArray]; + size_t i, j, count = [array count]; + + if (count == 0 || count == 1) + return; + + for (i = 0, j = count - 1; i < j; i++, j--) { + id tmp = cArray[i]; + cArray[i] = cArray[j]; + cArray[j] = tmp; + } +} - (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state objects: (id*)objects count: (int)count { Index: tests/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -138,10 +138,24 @@ m[1] = [[a[0] mutableCopy] autorelease]; TEST(@"-[removeObjectsInRange:]", R([m[1] removeObjectsInRange: of_range(0, 2)]) && [m[1] count] == 1 && [[m[1] objectAtIndex: 0] isEqual: c_ary[2]]) + m[1] = [[a[0] mutableCopy] autorelease]; + [m[1] addObject: @"qux"]; + [m[1] addObject: @"last"]; + TEST(@"-[reverse]", + R([m[1] reverse]) && [m[1] isEqual: ([OFArray arrayWithObjects: + @"last", @"qux", @"Baz", @"Bar", @"Foo", nil])]) + + m[1] = [[a[0] mutableCopy] autorelease]; + [m[1] addObject: @"qux"]; + [m[1] addObject: @"last"]; + TEST(@"-[reversedArray]", + [[m[1] reversedArray] isEqual: ([OFArray arrayWithObjects: + @"last", @"qux", @"Baz", @"Bar", @"Foo", nil])]) + EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]", OFOutOfRangeException, [a[0] objectAtIndex: [a[0] count]]) EXPECT_EXCEPTION(@"Detect out of range in -[removeNObjects:]", OFOutOfRangeException, [m[0] removeNObjects: [m[0] count] + 1])