From c3fb857b06bc6ef7a1be19113d5d38c98b4f7331 Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 1 Dec 1999 19:36:20 +0000 Subject: [PATCH] Checks for illegal comparator return values. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@5349 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 7 +++++ Source/NSArray.m | 60 +++++++++++++++++++++++++++++++++---------- Source/NSDictionary.m | 55 +++++++++++++++++++++++++++++---------- Source/NSGArray.m | 57 ++++++++++++++++++++++++++++++---------- Source/NSString.m | 22 +++++++++++----- 5 files changed, 155 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7b49c0e7c..235809b1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Dec 1 19:36:00 1999 Richard Frith-Macdonald + + * Source/NSArray.m: When sorting, treat illegal return values from the + comparator the same way as OPENSTEP does, but log a warning. + * Source/NSGArray.m: ditto + * Source/NSDictionary.m ditto + Fri Nov 26 19:46:00 1999 Richard Frith-Macdonald * Headers/Foundation/NSString.h: Tidied and fixed return types for diff --git a/Source/NSArray.m b/Source/NSArray.m index 256d45265..aa2bd800e 100644 --- a/Source/NSArray.m +++ b/Source/NSArray.m @@ -1144,18 +1144,23 @@ static NSString *indentStrings[] = { } - (void) sortUsingFunction: (int(*)(id,id,void*))compare - context: (void*)context + context: (void*)context { /* Shell sort algorithm taken from SortingInAction - a NeXT example */ #define STRIDE_FACTOR 3 // good value for stride factor is not well-understood // 3 is a fairly good choice (Sedgewick) - unsigned c,d, stride; - BOOL found; - int count = [self count]; + unsigned c,d, stride; + BOOL found; + int count = [self count]; +#ifdef GSWARN + BOOL badComparison = NO; +#endif stride = 1; while (stride <= count) - stride = stride * STRIDE_FACTOR + 1; + { + stride = stride * STRIDE_FACTOR + 1; + } while(stride > (STRIDE_FACTOR - 1)) { @@ -1165,27 +1170,54 @@ static NSString *indentStrings[] = { { found = NO; if (stride > c) - break; - d = c - stride; - while (!found) { - // move to left until correct place - id a = [self objectAtIndex: d + stride]; - id b = [self objectAtIndex: d]; - if ((*compare)(a, b, context) == NSOrderedAscending) + break; + } + d = c - stride; + while (!found) /* move to left until correct place */ + { + id a = [self objectAtIndex: d + stride]; + id b = [self objectAtIndex: d]; + NSComparisonResult r; + + r = (*compare)(a, b, context); + if (r < 0) { +#ifdef GSWARN + if (r != NSOrderedAscending) + { + badComparison = YES; + } +#endif IF_NO_GC(RETAIN(a)); [self replaceObjectAtIndex: d + stride withObject: b]; [self replaceObjectAtIndex: d withObject: a]; RELEASE(a); if (stride > d) - break; + { + break; + } d -= stride; // jump by stride factor } - else found = YES; + else + { +#ifdef GSWARN + if (r != NSOrderedDescending && r != NSOrderedSame) + { + badComparison = YES; + } +#endif + found = YES; + } } } } +#ifdef GSWARN + if (badComparison == YES) + { + NSWarnMLog(@"Detected bad return value from comparison", 0); + } +#endif } @end diff --git a/Source/NSDictionary.m b/Source/NSDictionary.m index 5992f09b1..e039b22f9 100644 --- a/Source/NSDictionary.m +++ b/Source/NSDictionary.m @@ -32,6 +32,7 @@ #include #include #include +#include @interface NSDictionaryNonCore : NSDictionary @end @@ -696,16 +697,21 @@ static NSString *indentStrings[] = { * 3 is a fairly good choice (Sedgewick) */ #define STRIDE_FACTOR 3 - unsigned c,d, stride; + unsigned c,d, stride; BOOL found; NSComparisonResult (*comp)(id, SEL, id); - int count = numKeys; + int count = numKeys; +#ifdef GSWARN + BOOL badComparison = NO; +#endif stride = 1; while (stride <= count) - stride = stride * STRIDE_FACTOR + 1; + { + stride = stride * STRIDE_FACTOR + 1; + } lastClass = 0; - while(stride > (STRIDE_FACTOR - 1)) + while (stride > (STRIDE_FACTOR - 1)) { // loop to sort for each value of stride stride = stride / STRIDE_FACTOR; @@ -713,14 +719,16 @@ static NSString *indentStrings[] = { { found = NO; if (stride > c) - break; - d = c - stride; - while (!found) { - // move to left until correct place - id a = keys[d + stride]; - id b = keys[d]; - Class x; + break; + } + d = c - stride; + while (!found) // move to left until correct place + { + id a = keys[d + stride]; + id b = keys[d]; + Class x; + NSComparisonResult r; x = fastClass(a); if (x != lastClass) @@ -729,21 +737,42 @@ static NSString *indentStrings[] = { comp = (NSComparisonResult (*)(id, SEL, id)) [a methodForSelector: @selector(compare:)]; } - if ((*comp)(a, @selector(compare:), b) == NSOrderedAscending) + r = (*comp)(a, @selector(compare:), b); + if (r < 0) { +#ifdef GSWARN + if (r != NSOrderedAscending) + { + badComparison = YES; + } +#endif keys[d + stride] = b; keys[d] = a; if (stride > d) - break; + { + break; + } d -= stride; // jump by stride factor } else { +#ifdef GSWARN + if (r != NSOrderedDescending && r != NSOrderedSame) + { + badComparison = YES; + } +#endif found = YES; } } } } +#ifdef GSWARN + if (badComparison == YES) + { + NSWarnMLog(@"Detected bad return value from comparison", 0); + } +#endif } for (i = 0; i < numKeys; i++) diff --git a/Source/NSGArray.m b/Source/NSGArray.m index 8da6c5ce9..89345e325 100644 --- a/Source/NSGArray.m +++ b/Source/NSGArray.m @@ -530,13 +530,18 @@ static SEL eqSel = @selector(isEqual:); /* Shell sort algorithm taken from SortingInAction - a NeXT example */ #define STRIDE_FACTOR 3 // good value for stride factor is not well-understood // 3 is a fairly good choice (Sedgewick) - unsigned c,d, stride; - BOOL found; - int count = _count; + unsigned c,d, stride; + BOOL found; + int count = _count; +#ifdef GSWARN + BOOL badComparison = NO; +#endif stride = 1; while (stride <= count) - stride = stride * STRIDE_FACTOR + 1; + { + stride = stride * STRIDE_FACTOR + 1; + } while (stride > (STRIDE_FACTOR - 1)) { @@ -546,26 +551,52 @@ static SEL eqSel = @selector(isEqual:); { found = NO; if (stride > c) - break; - d = c - stride; - while (!found) { - // move to left until correct place - id a = _contents_array[d + stride]; - id b = _contents_array[d]; - if ((*compare)(a, b, context) == NSOrderedAscending) + break; + } + d = c - stride; + while (!found) /* move to left until correct place */ + { + id a = _contents_array[d + stride]; + id b = _contents_array[d]; + NSComparisonResult r; + + r = (*compare)(a, b, context); + if (r < 0) { +#ifdef GSWARN + if (r != NSOrderedAscending) + { + badComparison = YES; + } +#endif _contents_array[d+stride] = b; _contents_array[d] = a; if (stride > d) - break; + { + break; + } d -= stride; // jump by stride factor } else - found = YES; + { +#ifdef GSWARN + if (r != NSOrderedDescending && r != NSOrderedSame) + { + badComparison = YES; + } +#endif + found = YES; + } } } } +#ifdef GSWARN + if (badComparison == YES) + { + NSWarnMLog(@"Detected bad return value from comparison", 0); + } +#endif } - (NSEnumerator*) objectEnumerator diff --git a/Source/NSString.m b/Source/NSString.m index 0ad01bc9a..5c7572a72 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -2476,20 +2476,30 @@ handle_printf_atsign (FILE *stream, // Creating Temporary Strings ++ (NSMutableString*) string +{ + return AUTORELEASE([[NSMutableString_c_concrete_class allocWithZone: + NSDefaultMallocZone()] initWithCapacity: 0]); +} + + (NSMutableString*) stringWithCapacity: (unsigned)capacity { - return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] - initWithCapacity: capacity]); + return AUTORELEASE([[NSMutableString_c_concrete_class allocWithZone: + NSDefaultMallocZone()] initWithCapacity: capacity]); } /* Inefficient. */ + (NSString*) stringWithCharacters: (const unichar*)characters length: (unsigned)length { - id n; - n = [[self allocWithZone: NSDefaultMallocZone()] - initWithCharacters: characters length: length]; - return AUTORELEASE(n); + return AUTORELEASE([[NSMutableString_c_concrete_class allocWithZone: + NSDefaultMallocZone()] initWithCharacters: characters length: length]); +} + ++ (id) stringWithContentsOfFile: (NSString *)path +{ + return AUTORELEASE([[NSMutableString_c_concrete_class allocWithZone: + NSDefaultMallocZone()] initWithContentsOfFile: path]); } + (NSString*) stringWithCString: (const char*)byteString