Optimised NSScanner

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4882 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-09-13 05:24:42 +00:00
parent 93f37dfa37
commit 92a427d24f
2 changed files with 215 additions and 144 deletions

View file

@ -1,3 +1,8 @@
Mon Sep 13 6:45:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Miscellaneous minor bugfixes plyus,
* Source/NSScanner.m: optimised (well, mostly).
Sun Sep 12 20:22:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSDictionary.m: optimise by avoiding objc method lookup

View file

@ -22,8 +22,11 @@
*/
#include <config.h>
#include <base/fast.x>
#include <Foundation/NSScanner.h>
#include <Foundation/NSException.h>
#include <Foundation/NSGString.h>
#include <Foundation/NSUserDefaults.h>
#include <float.h>
#include <limits.h>
#include <math.h>
@ -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];
}
@ -77,13 +119,16 @@
intoString: (NSString **)value;
{
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,7 +198,9 @@
BOOL got_digits = NO;
/* Check for sign */
switch ([string characterAtIndex: scanLocation])
if (scanLocation < len)
{
switch (charAtIndex(scanLocation))
{
case '+':
scanLocation++;
@ -163,11 +210,12 @@
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,7 +277,7 @@
/* Process digits */
while (scanLocation < len)
{
unichar digit = [string characterAtIndex: scanLocation];
unichar digit = charAtIndex(scanLocation);
switch (digit)
{
case '0': digitValue = 0; break;
@ -259,7 +310,8 @@
break;
if (!overflow)
{
if ((num > numLimit) || ((num == numLimit) && (digitValue > digitLimit)))
if ((num > numLimit)
|| ((num == numLimit) && (digitValue > digitLimit)))
overflow = YES;
else
num = num * radix + digitValue;
@ -302,14 +354,14 @@
/* 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])
switch (charAtIndex(scanLocation))
{
case 'x':
case 'X':
@ -367,7 +419,9 @@
}
/* Check for sign */
switch ([string characterAtIndex: scanLocation])
if (scanLocation < len)
{
switch (charAtIndex(scanLocation))
{
case '+':
scanLocation++;
@ -377,11 +431,12 @@
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,7 +486,7 @@
*/
- (BOOL) scanDouble: (double *)value
{
unichar decimal;
unichar decimal = '.';
unichar c = 0;
double num = 0.0;
long int exponent = 0;
@ -448,14 +503,21 @@
}
/*
* 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)
{
switch (charAtIndex(scanLocation))
{
case '+':
scanLocation++;
@ -465,11 +527,12 @@
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. */
@ -600,13 +663,16 @@
{
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++;
}
@ -768,7 +834,7 @@
*/
- (void) setLocale: (NSDictionary *)localeDictionary
{
locale = RETAIN(localeDictionary);
ASSIGN(locale, localeDictionary);
}
/*