Index: src/OFMutableArray.h ================================================================== --- src/OFMutableArray.h +++ src/OFMutableArray.h @@ -9,10 +9,14 @@ * the packaging of this file. */ #import "OFArray.h" +#ifdef OF_HAVE_BLOCKS +typedef id (^of_array_replace_block_t)(id obj, size_t idx, BOOL *stop); +#endif + /** * \brief A class for storing, adding and removing objects in an array. */ @interface OFMutableArray: OFArray { @@ -100,6 +104,15 @@ * \param nobjects The number of objects to remove * \param index The index at which the objects are removed */ - (void)removeNObjects: (size_t)nobjects atIndex: (size_t)index; + +#ifdef OF_HAVE_BLOCKS +/** + * Replaces each object with the object returned by the block. + * + * \param block The block which returns a new object for each object + */ +- (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block; +#endif @end Index: src/OFMutableArray.m ================================================================== --- src/OFMutableArray.m +++ src/OFMutableArray.m @@ -250,7 +250,31 @@ newWithClass: isa]; block(objs[i], i, &stop); } } + +- (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block +{ + OFObject **objs = [array cArray]; + size_t i, count = [array count]; + BOOL stop = NO; + unsigned long mutations2 = mutations; + + for (i = 0; i < count && !stop; i++) { + if (mutations != mutations2) + @throw [OFEnumerationMutationException + newWithClass: isa]; + + id new = block(objs[i], i, &stop); + + if (new == nil) + @throw [OFInvalidArgumentException newWithClass: isa + selector: _cmd]; + + [new retain]; + [objs[i] release]; + objs[i] = new; + } +} #endif @end Index: src/OFMutableDictionary.h ================================================================== --- src/OFMutableDictionary.h +++ src/OFMutableDictionary.h @@ -9,10 +9,14 @@ * the packaging of this file. */ #import "OFDictionary.h" +#ifdef OF_HAVE_BLOCKS +typedef id (^of_dictionary_replace_block_t)(id key, id obj, BOOL *stop); +#endif + /** * \brief A class for using mutable hash tables. */ @interface OFMutableDictionary: OFDictionary { @@ -33,6 +37,15 @@ * Remove the object with the given key from the dictionary. * * \param key The key whose object should be removed */ - (void)removeObjectForKey: (OFObject*)key; + +#ifdef OF_HAVE_BLOCKS +/** + * Replaces each object with the object returned by the block. + * + * \param block The block which returns a new object for each object + */ +- (void)replaceObjectsUsingBlock: (of_dictionary_replace_block_t)block; +#endif @end Index: src/OFMutableDictionary.m ================================================================== --- src/OFMutableDictionary.m +++ src/OFMutableDictionary.m @@ -280,7 +280,33 @@ if (data[i] != NULL && data[i] != DELETED) block(data[i]->key, data[i]->object, &stop); } } + +- (void)replaceObjectsUsingBlock: (of_dictionary_replace_block_t)block +{ + size_t i; + BOOL stop = NO; + unsigned long mutations2 = mutations; + + for (i = 0; i < size && !stop; i++) { + if (mutations != mutations2) + @throw [OFEnumerationMutationException + newWithClass: isa]; + + if (data[i] != NULL && data[i] != DELETED) { + id new = block(data[i]->key, data[i]->object, &stop); + + if (new == nil) + @throw [OFInvalidArgumentException + newWithClass: isa + selector: _cmd]; + + [new retain]; + [data[i]->object release]; + data[i]->object = new; + } + } +} #endif @end Index: tests/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -220,10 +220,24 @@ } TEST(@"Detection of mutation during enumeration using blocks", ok) } + + TEST(@"-[replaceObjectsUsingBlock:]", + R([m[0] replaceObjectsUsingBlock: + ^ id (id obj, size_t idx, BOOL *stop) { + switch (idx) { + case 0: + return @"foo"; + case 1: + return @"bar"; + } + + return nil; + }]) && [[m[0] objectAtIndex: 0] isEqual: @"foo"] && + [[m[0] objectAtIndex: 1] isEqual: @"bar"]) #endif [pool drain]; } @end Index: tests/OFDictionaryTests.m ================================================================== --- tests/OFDictionaryTests.m +++ tests/OFDictionaryTests.m @@ -91,10 +91,22 @@ } TEST(@"Detection of mutation during Fast Enumeration", ok) [dict removeObjectForKey: @""]; + + TEST(@"-[replaceObjectsUsingBlock:]", + R([dict replaceObjectsUsingBlock: + ^ id (id key, id obj, BOOL *stop) { + if ([key isEqual: keys[0]]) + return @"value_1"; + if ([key isEqual: keys[1]]) + return @"value_2"; + + return nil; + }]) && [[dict objectForKey: keys[0]] isEqual: @"value_1"] && + [[dict objectForKey: keys[1]] isEqual: @"value_2"]) #endif #ifdef OF_HAVE_BLOCKS { __block size_t i = 0;