From 0138c510654e1e9372a16b6fb1e4eeea0b872997 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 21 Sep 2012 10:27:05 +0000 Subject: [PATCH] Memory management nad documentation fixes. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35584 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 11 +++ Headers/Foundation/NSArray.h | 127 +++++++++++++++++++++++++---------- Source/NSArray.m | 47 +------------ Source/NSDate.m | 4 +- Source/NSDictionary.m | 95 +++++++++++++------------- Tools/AGSParser.h | 8 +-- Tools/AGSParser.m | 56 +++++++-------- 7 files changed, 189 insertions(+), 159 deletions(-) diff --git a/ChangeLog b/ChangeLog index 859c7552b..5208c824f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-09-21 Richard Frith-Macdonald + + * Source/NSArray.m: + * Source/NSDate.m: + * Source/NSDictionary.m: + * Headers/Foundation/NSArray.h: + Comment/documentation fixups to avoid warnings etc. + * Tools/AGSParser.h: + * Tools/AGSParser.m: + Fix memory management error causing reference to deallocated object. + 2012-09-20 Niels Grewe * Source/GSTimSort.m: A few more timsort bugfixes. diff --git a/Headers/Foundation/NSArray.h b/Headers/Foundation/NSArray.h index debb49e2d..22575ac1d 100644 --- a/Headers/Foundation/NSArray.h +++ b/Headers/Foundation/NSArray.h @@ -39,7 +39,26 @@ extern "C" { @class NSURL; @class NSIndexSet; -@interface NSArray : NSObject +#if OS_API_VERSION(100600, GS_API_LATEST) +enum +{ + NSBinarySearchingFirstEqual = (1UL << 8), /** Specifies that the binary + * search should find the first object equal in the array. + */ + NSBinarySearchingLastEqual = (1UL << 9), /** Specifies that the binary + * search should find the last object equal in the array. + */ + NSBinarySearchingInsertionIndex = (1UL << 10), /** Specifies that the binary + * search should find the index at which an equal object should be inserted + * in order to keep the array sorted + */ +}; + +typedef NSUInteger NSBinarySearchingOptions; +#endif + +@interface NSArray : NSObject + + (id) array; + (id) arrayWithArray: (NSArray*)array; @@ -54,7 +73,11 @@ extern "C" { - (NSArray*) arrayByAddingObject: (id)anObject; - (NSArray*) arrayByAddingObjectsFromArray: (NSArray*)anotherArray; - (BOOL) containsObject: anObject; -- (NSUInteger) count; // Primitive + +/** + * Returns the number of elements contained in the receiver. + */ +- (NSUInteger) count; - (void) getObjects: (__unsafe_unretained id[])aBuffer; - (void) getObjects: (__unsafe_unretained id[])aBuffer range: (NSRange)aRange; - (NSUInteger) indexOfObject: (id)anObject; @@ -71,10 +94,24 @@ extern "C" { - (id) initWithContentsOfURL: (NSURL*)aURL; #endif - (id) initWithObjects: firstObject, ...; -- (id) initWithObjects: (const id[])objects count: (NSUInteger)count; // Primitive +/** + * This should initialize the array with count (may be zero) objects.
+ * Retains each object placed in the array.
+ * Calls -init (which does nothing but maintain MacOS-X compatibility), + * and needs to be re-implemented in subclasses in order to have all + * other initialisers work. + */ +- (id) initWithObjects: (const id[])objects + count: (NSUInteger)count; - (id) lastObject; -- (id) objectAtIndex: (NSUInteger)index; // Primitive + +/** + * Returns the object at the specified index. + * Raises an exception of the index is beyond the array. + */ +- (id) objectAtIndex: (NSUInteger)index; + #if OS_API_VERSION(100400, GS_API_LATEST) - (NSArray *) objectsAtIndexes: (NSIndexSet *)indexes; #endif @@ -213,35 +250,19 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*); options: (NSEnumerationOptions)opts passingTest: (GSPredicateBlock)predicate; -/** - * Returns a sorted array using the block to determine the order of objects. +/** Returns a sorted array using the comparator to determine the + * order of objects. */ -- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr; +- (NSArray *) sortedArrayUsingComparator: (NSComparator)comparator; -/** - * Returns a sorted array using the block to determine the order of objects. +/** Returns a sorted array using the block to determine the order of objects. * * The opts argument is a bitfield. Setting the NSSortConcurrent flag * specifies that it is thread-safe. The NSSortStable bit specifies that * it should keep equal objects in the same order. */ -- (NSArray *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr; - -enum -{ - NSBinarySearchingFirstEqual = (1UL << 8), /** Specifies that the binary - * search should find the first object equal in the array. - */ - NSBinarySearchingLastEqual = (1UL << 9), /** Specifies that the binary - * search should find the last object equal in the array. - */ - NSBinarySearchingInsertionIndex = (1UL << 10), /** Specifies that the binary - * search should find the index at which an equal object should be inserted - * in order to keep the array sorted - */ -}; - -typedef NSUInteger NSBinarySearchingOptions; +- (NSArray *) sortedArrayWithOptions: (NSSortOptions)options + usingComparator: (NSComparator)comparator; /** * Performs a binary search of the array within the specified range for the @@ -249,10 +270,10 @@ typedef NSUInteger NSBinarySearchingOptions; * If NSBinarySearchingInsertionIndex is specified, searches for the index * at which such an object should be inserted. */ -- (NSUInteger)indexOfObject:(id)obj - inSortedRange:(NSRange)r - options:(NSBinarySearchingOptions)opts - usingComparator:(NSComparator)cmp; +- (NSUInteger) indexOfObject: (id)key + inSortedRange: (NSRange)range + options: (NSBinarySearchingOptions)options + usingComparator: (NSComparator)comparator; #endif /** * Accessor for subscripting. This is called by the compiler when you write @@ -266,30 +287,66 @@ typedef NSUInteger NSBinarySearchingOptions; + (id) arrayWithCapacity: (NSUInteger)numItems; -- (void) addObject: (id)anObject; // Primitive +/** + * Adds anObject at the end of the array, thus increasing the size of + * the array. The object is retained upon addition. + */ +- (void) addObject: (id)anObject; - (void) addObjectsFromArray: (NSArray*)otherArray; #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) - (void) exchangeObjectAtIndex: (NSUInteger)i1 withObjectAtIndex: (NSUInteger)i2; #endif -- (id) initWithCapacity: (NSUInteger)numItems; // Primitive -- (void) insertObject: (id)anObject atIndex: (NSUInteger)index; // Primitive + +/** + * Initialise the array with the specified capacity ... this + * should ensure that the array can have numItems added efficiently.
+ * Calls -init (which does nothing but maintain MacOS-X compatibility), + * and needs to be re-implemented in subclasses in order to have all + * other initialisers work. + */ +- (id) initWithCapacity: (NSUInteger)numItems; + +/** + * Inserts an object into the receiver at the specified location.
+ * Raises an exception if given an array index which is too large.
+ * The size of the array increases by one.
+ * The object is retained by the array. + */ +- (void) insertObject: (id)anObject atIndex: (NSUInteger)index; #if OS_API_VERSION(100400, GS_API_LATEST) - (void) insertObjects: (NSArray *)objects atIndexes: (NSIndexSet *)indexes; #endif -- (void) removeObjectAtIndex: (NSUInteger)index; // Primitive + +/** + * Removes an object from the receiver at the specified location.
+ * The size of the array decreases by one.
+ * Raises an exception if given an array index which is too large.
+ */ +- (void) removeObjectAtIndex: (NSUInteger)index; + - (void) removeObjectsAtIndexes: (NSIndexSet *)indexes; + +/** + * Places an object into the receiver at the specified location.
+ * Raises an exception if given an array index which is too large.
+ * The object is retained by the array. + */ - (void) replaceObjectAtIndex: (NSUInteger)index - withObject: (id)anObject; // Primitive + withObject: (id)anObject; + #if OS_API_VERSION(100400, GS_API_LATEST) - (void) replaceObjectsAtIndexes: (NSIndexSet *)indexes withObjects: (NSArray *)objects; #endif + - (void) replaceObjectsInRange: (NSRange)aRange withObjectsFromArray: (NSArray*)anArray; + - (void) replaceObjectsInRange: (NSRange)aRange withObjectsFromArray: (NSArray*)anArray range: (NSRange)anotherRange; + - (void) setArray: (NSArray *)otherArray; - (void) removeAllObjects; diff --git a/Source/NSArray.m b/Source/NSArray.m index 40f261cf0..72dd29d84 100644 --- a/Source/NSArray.m +++ b/Source/NSArray.m @@ -381,9 +381,6 @@ static SEL rlSel; return [copy initWithArray: self copyItems: YES]; } -/** - * Returns the number of elements contained in the receiver. - */ - (NSUInteger) count { [self subclassResponsibility: _cmd]; @@ -874,13 +871,6 @@ static SEL rlSel; return self; } -/** - * This should initialize the array with count (may be zero) objects.
- * Retains each object placed in the array.
- * Calls -init (which does nothing but maintain MacOS-X compatibility), - * and needs to be re-implemented in subclasses in order to have all - * other initialisers work. - */ - (id) initWithObjects: (const id[])objects count: (NSUInteger)count { self = [self init]; @@ -912,19 +902,15 @@ static SEL rlSel; return [copy initWithArray: self copyItems: NO]; } -/** - * Returns the object at the specified index. - * Raises an exception of the index is beyond the array. - */ - (id) objectAtIndex: (NSUInteger)index { [self subclassResponsibility: _cmd]; return nil; } -- (id) objectAtIndexedSubscript: (size_t)index +- (id) objectAtIndexedSubscript: (size_t)anIndex { - return [self objectAtIndex: (NSUInteger)index]; + return [self objectAtIndex: (NSUInteger)anIndex]; } - (NSArray *) objectsAtIndexes: (NSIndexSet *)indexes @@ -1983,23 +1969,12 @@ compare(id elem1, id elem2, void* context) return NSMutableArrayClass; } -/** - * Initialise the array with the specified capacity ... this - * should ensure that the array can have numItems added efficiently.
- * Calls -init (which does nothing but maintain MacOS-X compatibility), - * and needs to be re-implemented in subclasses in order to have all - * other initialisers work. - */ - (id) initWithCapacity: (NSUInteger)numItems { self = [self init]; return self; } -/** - * Adds anObject at the end of the array, thus increasing the size of - * the array. The object is retained upon addition. - */ - (void) addObject: (id)anObject { [self subclassResponsibility: _cmd]; @@ -2020,17 +1995,12 @@ compare(id elem1, id elem2, void* context) RELEASE(tmp); } -/** - * Places an object into the receiver at the specified location.
- * Raises an exception if given an array index which is too large.
- * The object is retained by the array. - */ - (void) replaceObjectAtIndex: (NSUInteger)index withObject: (id)anObject { [self subclassResponsibility: _cmd]; } -- (void)setObject: (id)anObject atIndexedSubscript: (size_t)anIndex +- (void) setObject: (id)anObject atIndexedSubscript: (size_t)anIndex { [self replaceObjectAtIndex: (NSUInteger)anIndex withObject: anObject]; } @@ -2083,12 +2053,6 @@ compare(id elem1, id elem2, void* context) withObjectsFromArray: [anArray subarrayWithRange: anotherRange]]; } -/** - * Inserts an object into the receiver at the specified location.
- * Raises an exception if given an array index which is too large.
- * The size of the array increases by one.
- * The object is retained by the array. - */ - (void) insertObject: anObject atIndex: (NSUInteger)index { [self subclassResponsibility: _cmd]; @@ -2113,11 +2077,6 @@ compare(id elem1, id elem2, void* context) } } -/** - * Removes an object from the receiver at the specified location.
- * The size of the array decreases by one.
- * Raises an exception if given an array index which is too large.
- */ - (void) removeObjectAtIndex: (NSUInteger)index { [self subclassResponsibility: _cmd]; diff --git a/Source/NSDate.m b/Source/NSDate.m index ca37ec027..42f88f0bb 100644 --- a/Source/NSDate.m +++ b/Source/NSDate.m @@ -1132,10 +1132,10 @@ otherTime(NSDate* other) return self; } -- (id) dateByAddingTimeInterval: (NSTimeInterval)seconds +- (id) dateByAddingTimeInterval: (NSTimeInterval)ti { return [[self class] dateWithTimeIntervalSinceReferenceDate: - otherTime(self) + seconds]; + otherTime(self) + ti]; } /** diff --git a/Source/NSDictionary.m b/Source/NSDictionary.m index 582a336f1..01a445b5f 100644 --- a/Source/NSDictionary.m +++ b/Source/NSDictionary.m @@ -1006,60 +1006,61 @@ compareIt(id o1, id o2, void* context) } } -- (NSSet*)keysOfEntriesWithOptions: (NSEnumerationOptions)opts - passingTest: (GSKeysAndObjectsPredicateBlock)aPredicate; +- (NSSet*) keysOfEntriesWithOptions: (NSEnumerationOptions)opts + passingTest: (GSKeysAndObjectsPredicateBlock)aPredicate { /* * See -enumerateKeysAndObjectsWithOptions:usingBlock: for note about * NSEnumerationOptions. */ - id enumerator = [self keyEnumerator]; - SEL objectForKeySelector = @selector(objectForKey:); - IMP objectForKey = [self methodForSelector: objectForKeySelector]; - BLOCK_SCOPE BOOL shouldStop = NO; - NSMutableSet *buildSet = [NSMutableSet new]; - SEL addObjectSelector = @selector(addObject:); - IMP addObject = [buildSet methodForSelector: addObjectSelector]; - NSSet *resultSet = nil; - id obj = nil; - BLOCK_SCOPE NSLock *setLock = nil; + id enumerator = [self keyEnumerator]; + SEL objectForKeySelector = @selector(objectForKey:); + IMP objectForKey = [self methodForSelector: objectForKeySelector]; + BLOCK_SCOPE BOOL shouldStop = NO; + NSMutableSet *buildSet = [NSMutableSet new]; + SEL addObjectSelector = @selector(addObject:); + IMP addObject = [buildSet methodForSelector: addObjectSelector]; + NSSet *resultSet = nil; + id obj = nil; + BLOCK_SCOPE NSLock *setLock = nil; - if (opts & NSEnumerationConcurrent) - { - setLock = [NSLock new]; - } - GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts) - FOR_IN(id, key, enumerator) - obj = (*objectForKey)(self, objectForKeySelector, key); -# if (__has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)) - dispatch_group_async(enumQueueGroup, enumQueue, ^(void){if (shouldStop) - { - return; - } - if (aPredicate(key, obj, &shouldStop)) - { - [setLock lock]; - addObject(buildSet, addObjectSelector, key); - [setLock unlock]; - } - }); -# else - if (CALL_BLOCK(aPredicate, key, obj, &shouldStop)) - { - addObject(buildSet, addObjectSelector, key); - } -# endif + if (opts & NSEnumerationConcurrent) + { + setLock = [NSLock new]; + } + GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts) + FOR_IN(id, key, enumerator) + obj = (*objectForKey)(self, objectForKeySelector, key); +#if (__has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)) + dispatch_group_async(enumQueueGroup, enumQueue, ^(void){ + if (shouldStop) + { + return; + } + if (aPredicate(key, obj, &shouldStop)) + { + [setLock lock]; + addObject(buildSet, addObjectSelector, key); + [setLock unlock]; + } + }); +#else + if (CALL_BLOCK(aPredicate, key, obj, &shouldStop)) + { + addObject(buildSet, addObjectSelector, key); + } +#endif - if (YES == shouldStop) - { - break; - } - END_FOR_IN(enumerator) - GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts) - [setLock release]; - resultSet = [NSSet setWithSet: buildSet]; - [buildSet release]; - return resultSet; + if (YES == shouldStop) + { + break; + } + END_FOR_IN(enumerator) + GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts) + [setLock release]; + resultSet = [NSSet setWithSet: buildSet]; + [buildSet release]; + return resultSet; } - (NSSet*) keysOfEntriesPassingTest: (GSKeysAndObjectsPredicateBlock)aPredicate diff --git a/Tools/AGSParser.h b/Tools/AGSParser.h index 0bfff85dc..951aef9ee 100644 --- a/Tools/AGSParser.h +++ b/Tools/AGSParser.h @@ -44,10 +44,10 @@ /* * The following items are used for logging/debug purposes. */ - NSString *fileName; /** Not retained - file being parsed. */ - NSString *unitName; /** Not retained - unit being parsed. */ - NSString *itemName; /** Not retained - item being parsed. */ - NSArray *lines; /** Not retained - line number mapping. */ + NSString *fileName; /** The file being parsed. */ + NSString *unitName; /** The unit being parsed. */ + NSString *itemName; /** The item being parsed. */ + NSArray *lines; /** The line number mapping. */ /* * The next few ivars represent the data currently being parsed. diff --git a/Tools/AGSParser.m b/Tools/AGSParser.m index 8ce4de516..ce9b9b82a 100644 --- a/Tools/AGSParser.m +++ b/Tools/AGSParser.m @@ -147,6 +147,8 @@ DESTROY(spaces); DESTROY(spacenl); DESTROY(source); + DESTROY(itemName); + DESTROY(unitName); [super dealloc]; } @@ -1922,7 +1924,7 @@ fail: inHeader = YES; } commentsRead = NO; - fileName = name; + ASSIGNCOPY(fileName, name); if (declared == nil) { ASSIGN(declared, [fileName lastPathComponent]); @@ -1977,8 +1979,8 @@ fail: [source addObject: path]; } } - unitName = nil; - itemName = nil; + DESTROY(unitName); + DESTROY(itemName); DESTROY(comment); [self setupBuffer]; @@ -2153,7 +2155,7 @@ fail: [self log: @"implementation with bad name"]; goto fail; } - unitName = name; + ASSIGNCOPY(unitName, name); /* * After the class name, we may have a category name or @@ -2171,7 +2173,7 @@ fail: goto fail; } name = [name stringByAppendingFormat: @"(%@)", category]; - unitName = name; + ASSIGN(unitName, name); } else if (buffer[pos] == ':') { @@ -2240,13 +2242,13 @@ fail: // [self log: @"Found implementation %@", dict]; - unitName = nil; + DESTROY(unitName); DESTROY(comment); [arp drain]; return dict; fail: - unitName = nil; + DESTROY(unitName); DESTROY(comment); [arp drain]; return nil; @@ -2279,7 +2281,7 @@ fail: [self log: @"interface with bad name"]; goto fail; } - unitName = name; + ASSIGNCOPY(unitName, name); [dict setObject: @"class" forKey: @"Type"]; [self setStandards: dict]; @@ -2302,7 +2304,7 @@ fail: [dict setObject: category forKey: @"Category"]; [dict setObject: name forKey: @"BaseClass"]; name = [name stringByAppendingFormat: @"(%@)", category]; - unitName = name; + ASSIGN(unitName, name); [dict setObject: @"category" forKey: @"Type"]; if ([category length] >= 7 && [category compare: @"Private" @@ -2396,13 +2398,13 @@ fail: // [self log: @"Found interface %@", dict]; - unitName = nil; + DESTROY(unitName); DESTROY(comment); [arp drain]; return dict; fail: - unitName = nil; + DESTROY(unitName); DESTROY(comment); [arp drain]; return nil; @@ -2896,7 +2898,7 @@ fail: { [self setStandards: method]; } - itemName = mname; + ASSIGNCOPY(itemName, mname); if (term == ';') { @@ -2946,13 +2948,13 @@ fail: [self appendComment: c to: method]; } - itemName = nil; + DESTROY(itemName); [arp drain]; IF_NO_GC([method autorelease];) return method; fail: - itemName = nil; + DESTROY(itemName); DESTROY(comment); [arp drain]; RELEASE(method); @@ -3062,10 +3064,10 @@ fail: { if ([a0 isEqual: a1] == NO) { - itemName = token; + ASSIGNCOPY(itemName, token); [self log: @"method args in interface %@ don't match " @"those in implementation %@", a0, a1]; - itemName = nil; + DESTROY(itemName); [exist setObject: a1 forKey: @"Args"]; } } @@ -3076,10 +3078,10 @@ fail: { if ([a0 isEqual: a1] == NO) { - itemName = token; + ASSIGNCOPY(itemName, token); [self log: @"method types in interface %@ don't match " @"those in implementation %@", a0, a1]; - itemName = nil; + DESTROY(itemName); [exist setObject: a1 forKey: @"Types"]; } } @@ -3601,7 +3603,8 @@ fail: [dict setObject: name forKey: @"Name"]; [self setStandards: dict]; - unitName = [NSString stringWithFormat: @"(%@)", name]; + DESTROY(unitName); + unitName = [[NSString alloc] initWithFormat: @"(%@)", name]; /* * Protocols may themselves conform to protocols. @@ -3655,14 +3658,14 @@ fail: // [self log: @"Found protocol %@", dict]; - unitName = nil; + DESTROY(unitName); DESTROY(comment); [arp drain]; IF_NO_GC([dict autorelease];) return dict; fail: - unitName = nil; + DESTROY(unitName); DESTROY(comment); [arp drain]; RELEASE(dict); @@ -3854,10 +3857,10 @@ fail: haveSource = NO; DESTROY(declared); DESTROY(comment); - fileName = nil; - unitName = nil; - itemName = nil; - lines = nil; + DESTROY(fileName); + DESTROY(unitName); + DESTROY(itemName); + DESTROY(lines); buffer = 0; length = 0; pos = 0; @@ -4108,9 +4111,8 @@ fail: [data setLength: length*sizeof(unichar)]; buffer = [data mutableBytes]; pos = 0; - lines = [[NSArray alloc] initWithArray: a]; + ASSIGN(lines, [NSArray arrayWithArray: a]); [arp drain]; - IF_NO_GC([lines autorelease];) IF_NO_GC([data autorelease];) }