Index: src/OFMutableSet.h ================================================================== --- src/OFMutableSet.h +++ src/OFMutableSet.h @@ -18,10 +18,14 @@ /** * \brief An mutable unordered set of unique objects. */ @interface OFMutableSet: OFSet +{ + unsigned long mutations; +} + /** * \brief Adds the specified object to the set. * * \param object The object to add to the set */ Index: src/OFMutableSet.m ================================================================== --- src/OFMutableSet.m +++ src/OFMutableSet.m @@ -19,19 +19,63 @@ #define OF_MUTABLE_SET_M #import "OFMutableSet.h" #import "OFDictionary.h" #import "OFNull.h" +#import "OFAutoreleasePool.h" @implementation OFMutableSet - (void)addObject: (id)object { [dictionary _setObject: [OFNull null] forKey: object copyKey: NO]; + + mutations++; } - (void)removeObject: (id)object { [dictionary removeObjectForKey: object]; + + mutations++; +} + +- (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state + objects: (id*)objects + count: (int)count +{ + OFAutoreleasePool *pool = state->extra.pointers[0]; + OFEnumerator *enumerator = state->extra.pointers[1]; + int i; + + state->itemsPtr = objects; + state->mutationsPtr = &mutations; + + if (state->state == -1) + return 0; + + if (state->state == 0) { + pool = [[OFAutoreleasePool alloc] init]; + enumerator = [dictionary keyEnumerator]; + + state->extra.pointers[0] = pool; + state->extra.pointers[1] = enumerator; + + state->state = 1; + } + + for (i = 0; i < count; i++) { + id object = [enumerator nextObject]; + + if (object == nil) { + [pool release]; + state->state = -1; + return i; + } + + objects[i] = object; + } + + return count; } @end Index: tests/OFSet.m ================================================================== --- tests/OFSet.m +++ tests/OFSet.m @@ -15,12 +15,14 @@ */ #include "config.h" #import "OFSet.h" -#import "OFAutoreleasePool.h" #import "OFArray.h" +#import "OFAutoreleasePool.h" + +#import "OFEnumerationMutationException.h" #import "TestsAppDelegate.h" static OFString *module = @"OFSet"; @@ -104,10 +106,21 @@ if (i != 4) ok = NO; TEST(@"Fast enumeration", ok) + + ok = NO; + @try { + for (OFString *s in mutableSet) + [mutableSet removeObject: s]; + } @catch (OFEnumerationMutationException *e) { + ok = YES; + [e dealloc]; + } + + TEST(@"Detection of mutation during Fast Enumeration", ok); #endif [pool drain]; } @end