diff --git a/ChangeLog b/ChangeLog index 9989bd515..9bd09c176 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Sep 13 6:45:00 1999 Richard Frith-Macdonald + + Miscellaneous minor bugfixes plyus, + * Source/NSScanner.m: optimised (well, mostly). + Sun Sep 12 20:22:00 1999 Richard Frith-Macdonald * Source/NSDictionary.m: optimise by avoiding objc method lookup diff --git a/Source/NSScanner.m b/Source/NSScanner.m index e9dc81161..93c580808 100644 --- a/Source/NSScanner.m +++ b/Source/NSScanner.m @@ -22,8 +22,11 @@ */ #include +#include #include #include +#include +#include #include #include #include @@ -31,6 +34,30 @@ @implementation NSScanner +static Class NSString_class; +static Class NSGString_class; +static NSCharacterSet *defaultSkipSet; +static SEL memSel = @selector(characterIsMember:); + +/* + * Hack for direct access to internals of an NSGString object. + */ +typedef struct { + @defs(NSGString) +} *stringAccess; +#define charAtIndex(I) ((stringAccess)string)->_contents_chars[I] + ++ (void) initialize +{ + if (self == [NSScanner class]) + { + defaultSkipSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; + RETAIN(defaultSkipSet); + NSString_class = [NSString class]; + NSGString_class = [NSGString class]; + } +} + /* * Create and return a scanner that scans aString. */ @@ -39,10 +66,13 @@ return AUTORELEASE([[self alloc] initWithString: aString]); } -+ (id) localizedScannerWithString: (NSString*)locale ++ (id) localizedScannerWithString: (NSString*)aString { - [self notImplemented: _cmd]; - return Nil; + NSScanner *scanner = [self scannerWithString: aString]; + NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; + + scanner->locale = RETAIN([defs dictionaryRepresentation]); + return scanner; } /* @@ -52,9 +82,21 @@ - (id) initWithString: (NSString *)aString { [super init]; - string = [aString copyWithZone: [self zone]]; + /* + * Ensure that we have an NSGString so we can access its internals directly. + */ + if (fastClass(aString) == NSGString_class) + string = RETAIN(aString); + else if ([aString isKindOfClass: NSString_class]) + string = [[NSGString_class alloc] initWithString: aString]; + else + { + [self dealloc]; + [NSException raise: NSInvalidArgumentException + format: @"Scanner initialised with something not a string"]; + } len = [string length]; - charactersToBeSkipped = RETAIN([NSCharacterSet whitespaceAndNewlineCharacterSet]); + charactersToBeSkipped = RETAIN(defaultSkipSet); return self; } @@ -64,7 +106,7 @@ - (void) dealloc { RELEASE(string); - RELEASE(locale); + TEST_RELEASE(locale); RELEASE(charactersToBeSkipped); [super dealloc]; } @@ -74,16 +116,19 @@ * For internal use only. */ - (BOOL) _scanCharactersFromSet: (NSCharacterSet *)set - intoString: (NSString **)value; + intoString: (NSString **)value; { - unsigned int start; + unsigned int start; + BOOL (*memImp)(NSCharacterSet*, SEL, unichar); if (scanLocation >= len) return NO; + memImp = (BOOL (*)(NSCharacterSet*, SEL, unichar)) + [set methodForSelector: memSel]; start = scanLocation; while (scanLocation < len) { - if (![set characterIsMember: [string characterAtIndex: scanLocation]]) + if ((*memImp)(set, memSel, charAtIndex(scanLocation)) == NO) break; scanLocation++; } @@ -153,21 +198,24 @@ BOOL got_digits = NO; /* Check for sign */ - switch ([string characterAtIndex: scanLocation]) + if (scanLocation < len) { - case '+': - scanLocation++; - break; - case '-': - negative = YES; - scanLocation++; - break; + switch (charAtIndex(scanLocation)) + { + case '+': + scanLocation++; + break; + case '-': + negative = YES; + scanLocation++; + break; + } } /* Process digits */ while (scanLocation < len) { - unichar digit = [string characterAtIndex: scanLocation]; + unichar digit = charAtIndex(scanLocation); if ((digit < '0') || (digit > '9')) break; if (!overflow) { @@ -185,7 +233,8 @@ return NO; if (value) { - if (overflow || (num > (negative ? (unsigned int)INT_MIN : (unsigned int)INT_MAX))) + if (overflow + || (num > (negative ? (unsigned int)INT_MIN : (unsigned int)INT_MAX))) *value = negative ? INT_MIN: INT_MAX; else if (negative) *value = -num; @@ -212,7 +261,9 @@ * Scan an unsigned int of the given radix into value. * Internal version used by scanRadixUnsignedInt: and scanHexInt: . */ -- (BOOL) scanUnsignedInt_: (unsigned int *)value radix: (int)radix gotDigits: (BOOL)gotDigits +- (BOOL) scanUnsignedInt_: (unsigned int *)value + radix: (int)radix + gotDigits: (BOOL)gotDigits { unsigned int num = 0; unsigned int numLimit, digitLimit, digitValue; @@ -226,44 +277,45 @@ /* Process digits */ while (scanLocation < len) { - unichar digit = [string characterAtIndex: scanLocation]; + unichar digit = charAtIndex(scanLocation); switch (digit) { - case '0': digitValue = 0; break; - case '1': digitValue = 1; break; - case '2': digitValue = 2; break; - case '3': digitValue = 3; break; - case '4': digitValue = 4; break; - case '5': digitValue = 5; break; - case '6': digitValue = 6; break; - case '7': digitValue = 7; break; - case '8': digitValue = 8; break; - case '9': digitValue = 9; break; - case 'a': digitValue = 0xA; break; - case 'b': digitValue = 0xB; break; - case 'c': digitValue = 0xC; break; - case 'd': digitValue = 0xD; break; - case 'e': digitValue = 0xE; break; - case 'f': digitValue = 0xF; break; - case 'A': digitValue = 0xA; break; - case 'B': digitValue = 0xB; break; - case 'C': digitValue = 0xC; break; - case 'D': digitValue = 0xD; break; - case 'E': digitValue = 0xE; break; - case 'F': digitValue = 0xF; break; - default: - digitValue = radix; - break; + case '0': digitValue = 0; break; + case '1': digitValue = 1; break; + case '2': digitValue = 2; break; + case '3': digitValue = 3; break; + case '4': digitValue = 4; break; + case '5': digitValue = 5; break; + case '6': digitValue = 6; break; + case '7': digitValue = 7; break; + case '8': digitValue = 8; break; + case '9': digitValue = 9; break; + case 'a': digitValue = 0xA; break; + case 'b': digitValue = 0xB; break; + case 'c': digitValue = 0xC; break; + case 'd': digitValue = 0xD; break; + case 'e': digitValue = 0xE; break; + case 'f': digitValue = 0xF; break; + case 'A': digitValue = 0xA; break; + case 'B': digitValue = 0xB; break; + case 'C': digitValue = 0xC; break; + case 'D': digitValue = 0xD; break; + case 'E': digitValue = 0xE; break; + case 'F': digitValue = 0xF; break; + default: + digitValue = radix; + break; } if (digitValue >= radix) break; if (!overflow) { - if ((num > numLimit) || ((num == numLimit) && (digitValue > digitLimit))) - overflow = YES; - else - num = num * radix + digitValue; - } + if ((num > numLimit) + || ((num == numLimit) && (digitValue > digitLimit))) + overflow = YES; + else + num = num * radix + digitValue; + } scanLocation++; gotDigits = YES; } @@ -302,23 +354,23 @@ /* Check radix */ radix = 10; - if ((scanLocation < len) && ([string characterAtIndex: scanLocation] == '0')) + if ((scanLocation < len) && (charAtIndex(scanLocation) == '0')) { - radix = 8; - scanLocation++; - gotDigits = YES; - if (scanLocation < len) - { - switch ([string characterAtIndex: scanLocation]) + radix = 8; + scanLocation++; + gotDigits = YES; + if (scanLocation < len) { - case 'x': - case 'X': - scanLocation++; - radix = 16; - gotDigits = NO; - break; + switch (charAtIndex(scanLocation)) + { + case 'x': + case 'X': + scanLocation++; + radix = 16; + gotDigits = NO; + break; + } } - } } if ( [self scanUnsignedInt_: value radix: radix gotDigits: gotDigits]) return YES; @@ -367,21 +419,24 @@ } /* Check for sign */ - switch ([string characterAtIndex: scanLocation]) + if (scanLocation < len) { - case '+': - scanLocation++; - break; - case '-': - negative = YES; - scanLocation++; - break; + switch (charAtIndex(scanLocation)) + { + case '+': + scanLocation++; + break; + case '-': + negative = YES; + scanLocation++; + break; + } } /* Process digits */ while (scanLocation < len) { - unichar digit = [string characterAtIndex: scanLocation]; + unichar digit = charAtIndex(scanLocation); if ((digit < '0') || (digit > '9')) break; if (!overflow) { @@ -431,14 +486,14 @@ */ - (BOOL) scanDouble: (double *)value { - unichar decimal; - unichar c = 0; - double num = 0.0; - long int exponent = 0; - BOOL negative = NO; - BOOL got_dot = NO; - BOOL got_digit = NO; - unsigned int saveScanLocation = scanLocation; + unichar decimal = '.'; + unichar c = 0; + double num = 0.0; + long int exponent = 0; + BOOL negative = NO; + BOOL got_dot = NO; + BOOL got_digit = NO; + unsigned int saveScanLocation = scanLocation; /* Skip whitespace */ if (![self _skipToNextField]) @@ -448,28 +503,36 @@ } /* - * FIXME: Should get decimal point character from locale. - * The key is NSDecimalSeparator. - * The problem is that I can't find anything in GNUSTEP about locales. + * Get decimal point character from locale if necessary. */ - decimal = '.'; + if (locale != nil) + { + NSString *pointString; + + pointString = [locale objectForKey: NSDecimalSeparator]; + if ([pointString length] > 0) + decimal = [pointString characterAtIndex: 0]; + } /* Check for sign */ - switch ([string characterAtIndex: scanLocation]) + if (scanLocation < len) { - case '+': - scanLocation++; - break; - case '-': - negative = YES; - scanLocation++; - break; + switch (charAtIndex(scanLocation)) + { + case '+': + scanLocation++; + break; + case '-': + negative = YES; + scanLocation++; + break; + } } /* Process number */ while (scanLocation < len) { - c = [string characterAtIndex: scanLocation]; + c = charAtIndex(scanLocation); if ((c >= '0') && (c <= '9')) { /* Ensure that the number being accumulated will not overflow. */ @@ -499,53 +562,53 @@ } scanLocation++; } - if (!got_digit) - { - scanLocation = saveScanLocation; - return NO; - } + if (!got_digit) + { + scanLocation = saveScanLocation; + return NO; + } - /* Check for trailing exponent */ - if ((scanLocation < len) && ((c == 'e') || (c == 'E'))) - { - int expval; + /* Check for trailing exponent */ + if ((scanLocation < len) && ((c == 'e') || (c == 'E'))) + { + int expval; - scanLocation++; - if ([self _scanInt: &expval]) + scanLocation++; + if ([self _scanInt: &expval]) + { + /* Check for exponent overflow */ + if (num) { - /* Check for exponent overflow */ - if (num) - { - if ((exponent > 0) && (expval > (LONG_MAX - exponent))) - exponent = LONG_MAX; - else if ((exponent < 0) && (expval < (LONG_MIN - exponent))) - exponent = LONG_MIN; - else - exponent += expval; - } + if ((exponent > 0) && (expval > (LONG_MAX - exponent))) + exponent = LONG_MAX; + else if ((exponent < 0) && (expval < (LONG_MIN - exponent))) + exponent = LONG_MIN; + else + exponent += expval; } - else - { + } + else + { #ifdef _ACCEPT_BAD_EXPONENTS_ - /* Numbers like 1.23eFOO are accepted (as 1.23). */ - scanLocation = expScanLocation; + /* Numbers like 1.23eFOO are accepted (as 1.23). */ + scanLocation = expScanLocation; #else - /* Numbers like 1.23eFOO are rejected. */ - scanLocation = saveScanLocation; - return NO; + /* Numbers like 1.23eFOO are rejected. */ + scanLocation = saveScanLocation; + return NO; #endif - } - } - if (value) - { - if (num && exponent) - num *= pow(10.0, (double) exponent); - if (negative) - *value = -num; - else - *value = num; - } - return YES; + } + } + if (value) + { + if (num && exponent) + num *= pow(10.0, (double) exponent); + if (negative) + *value = -num; + else + *value = num; + } + return YES; } /* @@ -577,7 +640,7 @@ * containing the scanned characters is returned by reference in value. */ - (BOOL) scanCharactersFromSet: (NSCharacterSet *)aSet - intoString: (NSString **)value; + intoString: (NSString **)value; { unsigned int saveScanLocation = scanLocation; @@ -598,15 +661,18 @@ - (BOOL) scanUpToCharactersFromSet: (NSCharacterSet *)set intoString: (NSString **)value; { - unsigned int saveScanLocation = scanLocation; - unsigned int start; + unsigned int saveScanLocation = scanLocation; + unsigned int start; + BOOL (*memImp)(NSCharacterSet*, SEL, unichar); if (![self _skipToNextField]) return NO; start = scanLocation; + memImp = (BOOL (*)(NSCharacterSet*, SEL, unichar)) + [set methodForSelector: memSel]; while (scanLocation < len) { - if ([set characterIsMember: [string characterAtIndex: scanLocation]]) + if ((*memImp)(set, memSel, charAtIndex(scanLocation)) == YES) break; scanLocation++; } @@ -644,8 +710,8 @@ if (range.location + range.length > len) return NO; range = [string rangeOfString: aString - options: caseSensitive ? 0 : NSCaseInsensitiveSearch - range: range]; + options: caseSensitive ? 0 : NSCaseInsensitiveSearch + range: range]; if (range.length == 0) { scanLocation = saveScanLocation; @@ -675,8 +741,8 @@ range.location = scanLocation; range.length = len - scanLocation; found = [string rangeOfString: aString - options: caseSensitive ? 0 : NSCaseInsensitiveSearch - range: range]; + options: caseSensitive ? 0 : NSCaseInsensitiveSearch + range: range]; if (found.length) range.length = found.location - scanLocation; if (range.length == 0) @@ -768,7 +834,7 @@ */ - (void) setLocale: (NSDictionary *)localeDictionary { - locale = RETAIN(localeDictionary); + ASSIGN(locale, localeDictionary); } /*