git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3638 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-02-01 20:58:02 +00:00
parent bcd0eaabda
commit b3b94f787b
4 changed files with 210 additions and 80 deletions

View file

@ -1,3 +1,16 @@
Mon Feb 1 11:25:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Patch supplied by eric@skatter.usask.ca
* Testing/nsscanner.m: Explicitly include NSString.h.
Cleaned up autorelease pool handling.
Fixed some printf arguments that didn't match their formats.
Added tests for scanHexInt:.
* Source/include/NSScanner.h:
Add declarations for scanInt: and scanHexInt: methods.
* Source/NSScanner.m Added scanHexInt: method.
Cleaned up some comments.
Added conditional compile to let scanDouble: accept numbers
like 1.234eFoo (as 1.234). For now, numbers like this are rejected.
Mon Feb 1 11:25:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* src/NSArray.m: ([-initWithContentsOfFile:]) Fixed memory leak.

View file

@ -70,6 +70,8 @@
* Scanning a string
*/
- (BOOL)scanInt:(int *)value;
- (BOOL)scanInt:(int *)value;
- (BOOL)scanHexInt:(unsigned int *)value;
- (BOOL)scanRadixUnsignedInt:(unsigned int *)value;
- (BOOL)scanLongLong:(long long *)value;
- (BOOL)scanFloat:(float *)value;

View file

@ -211,42 +211,16 @@
/*
* Scan an unsigned int of the given radix into value.
* Internal version used by scanRadixUnsignedInt: and scanHexInt:.
*/
- (BOOL)scanRadixUnsignedInt: (unsigned int *)value
- (BOOL)scanUnsignedInt_: (unsigned int *)value radix:(int)radix gotDigits:(BOOL)gotDigits
{
unsigned int num = 0;
unsigned int numLimit, digitLimit, digitValue, radix;
unsigned int numLimit, digitLimit, digitValue;
BOOL overflow = NO;
BOOL got_digits = NO;
unsigned int saveScanLocation = scanLocation;
/* Skip whitespace */
if (![self _skipToNextField])
{
scanLocation = saveScanLocation;
return NO;
}
/* Check radix */
radix = 10;
if ((scanLocation < len) && ([string characterAtIndex:scanLocation] == '0'))
{
radix = 8;
scanLocation++;
got_digits = YES;
if (scanLocation < len)
{
switch ([string characterAtIndex:scanLocation])
{
case 'x':
case 'X':
scanLocation++;
radix = 16;
got_digits = NO;
break;
}
}
}
/* Set limits */
numLimit = UINT_MAX / radix;
digitLimit = UINT_MAX % radix;
@ -292,11 +266,11 @@
num = num * radix + digitValue;
}
scanLocation++;
got_digits = YES;
gotDigits = YES;
}
/* Save result */
if (!got_digits)
if (!gotDigits)
{
scanLocation = saveScanLocation;
return NO;
@ -311,6 +285,67 @@
return YES;
}
/*
* Scan an unsigned int of the given radix into value.
*/
- (BOOL)scanRadixUnsignedInt: (unsigned int *)value
{
int radix;
BOOL gotDigits = NO;
unsigned int saveScanLocation = scanLocation;
/* Skip whitespace */
if (![self _skipToNextField])
{
scanLocation = saveScanLocation;
return NO;
}
/* Check radix */
radix = 10;
if ((scanLocation < len) && ([string characterAtIndex:scanLocation] == '0'))
{
radix = 8;
scanLocation++;
gotDigits = YES;
if (scanLocation < len)
{
switch ([string characterAtIndex:scanLocation])
{
case 'x':
case 'X':
scanLocation++;
radix = 16;
gotDigits = NO;
break;
}
}
}
if ( [self scanUnsignedInt_:value radix:radix gotDigits:gotDigits])
return YES;
scanLocation = saveScanLocation;
return NO;
}
/*
* Scan a hexadecimal unsigned integer into value.
*/
- (BOOL)scanHexInt: (unsigned int *)value
{
unsigned int saveScanLocation = scanLocation;
/* Skip whitespace */
if (![self _skipToNextField])
{
scanLocation = saveScanLocation;
return NO;
}
if ([self scanUnsignedInt_:value radix:16 gotDigits:NO])
return YES;
scanLocation = saveScanLocation;
return NO;
}
/*
* Scan a long long int into value.
* Same as scanInt, except with different variable types and limits.
@ -414,9 +449,9 @@
}
/*
* FIXME: Should get decimal point character from locale. The problem
* is that I can't find anything in the OPENSTEP specification about
* the format of the locale dictionary.
* 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.
*/
decimal = '.';
@ -471,27 +506,35 @@
return NO;
}
/* Check for trailing exponent
Numbers like 1.23eFOO are rejected. */
/* Check for trailing exponent */
if ((scanLocation < len) && ((c == 'e') || (c == 'E')))
{
int exp;
int expval;
int expScanLocation = scanLocation;
scanLocation++;
if (![self _scanInt: &exp])
if ([self _scanInt: &expval])
{
/* 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;
}
}
else
{
#ifdef _ACCEPT_BAD_EXPONENTS_
/* Numbers like 1.23eFOO are accepted (as 1.23). */
scanLocation = expScanLocation;
#else
/* Numbers like 1.23eFOO are rejected. */
scanLocation = saveScanLocation;
return NO;
}
/* Check for exponent overflow */
if (num)
{
if ((exponent > 0) && (exp > (LONG_MAX - exponent)))
exponent = LONG_MAX;
else if ((exponent < 0) && (exp < (LONG_MIN - exponent)))
exponent = LONG_MIN;
else
exponent += exp;
#endif
}
}
if (value)

View file

@ -11,6 +11,7 @@
*
*/
#include <Foundation/NSString.h>
#include <Foundation/NSScanner.h>
#include <Foundation/NSAutoreleasePool.h>
#include <limits.h>
@ -61,8 +62,6 @@ testScanIntGood (int i)
else if (value != i)
printf ("scanInt of `%s' returned value %d.\n", [string cString], value);
testFullScan ("scanInt", string, scanner);
[string release];
[scanner release];
}
/*
@ -82,8 +81,6 @@ testScanIntOverflow (double d)
else if (value != ((d < 0) ? INT_MIN : INT_MAX))
printf ("scanInt of `%s' didn't overflow, returned %d.\n", [string cString], value);
testFullScan ("scanInt", string, scanner);
[string release];
[scanner release];
}
/*
@ -141,7 +138,6 @@ testScanInt (void)
scanLocation = [scanner scanLocation];
if (scanLocation != 4)
printf ("scanInt of `%s' moves scan location to %u.\n", [string cString], scanLocation);
[scanner release];
/*
* Check that non-digits don't move the scan location
@ -153,7 +149,6 @@ testScanInt (void)
scanLocation = [scanner scanLocation];
if (scanLocation != 0)
printf ("scanInt of `%s' moves scan location to %u.\n", [string cString], scanLocation);
[scanner release];
/*
* Check that non-digits don't consume characters to be skipped
@ -165,7 +160,6 @@ testScanInt (void)
scanLocation = [scanner scanLocation];
if (scanLocation != 0)
printf ("scanInt of `%s' moves scan location to %u.\n", [string cString], scanLocation);
[scanner release];
}
/*
@ -195,8 +189,7 @@ testScanRadixUnsignedIntFinish (NSString *string, BOOL expectValue, unsigned int
printf ("scanRadixUnsignedInt of `%s' failed.\n", [string cString]);
}
if (expectedScanLocation != [scanner scanLocation])
printf ("scanRadixUnsignedInt of `%s' moved scan location to %lu (expected %lu)\n", [scanner scanLocation], expectedScanLocation);
[scanner release];
printf ("scanRadixUnsignedInt of `%s' moved scan location to %u (expected %u)\n", [string cString], [scanner scanLocation], expectedScanLocation);
}
/*
@ -216,7 +209,6 @@ testScanRadixUnsignedIntGood (NSString *format, unsigned int i)
}
string = [NSString stringWithFormat:format, i];
testScanRadixUnsignedIntFinish (string, YES, i, [string length]);
[string release];
}
/*
@ -236,8 +228,6 @@ testScanRadixUnsignedIntOverflow (double d)
else if (value != UINT_MAX)
printf ("scanRadixUnsignedInt of `%s' didn't overflow, returned %u (%#x).\n", [string cString], value, value);
testFullScan ("scanRadixUnsignedInt", string, scanner);
[string release];
[scanner release];
}
/*
@ -298,6 +288,89 @@ testScanRadixUnsignedInt (void)
testScanRadixUnsignedIntFinish (@"FOO", NO, 0, 0);
testScanRadixUnsignedIntFinish (@" FOO", NO, 0, 0);
testScanRadixUnsignedIntFinish (@" 0x ", NO, 0, 0);
#endif
}
/*
************************************************************************
* scanHexInt: *
************************************************************************
*/
/*
* Test a valid scanHexInt operation
*/
void
testScanHexIntFinish (NSString *string, BOOL expectValue, unsigned int expectedValue, unsigned int expectedScanLocation)
{
NSScanner *scanner;
unsigned int value;
scanner = [NSScanner scannerWithString:string];
if ([scanner scanHexInt:&value]) {
if (!expectValue)
printf ("scanHexInt of `%s' succeeded.\n", [string cString]);
else if (value != expectedValue)
printf ("scanHexInt of `%s' returned value %u (%#x).\n", [string cString], value, value);
}
else {
if (expectValue)
printf ("scanHexInt of `%s' failed.\n", [string cString]);
}
if (expectedScanLocation != [scanner scanLocation])
printf ("scanHexInt of `%s' moved scan location to %u (expected %u)\n", [string cString], [scanner scanLocation], expectedScanLocation);
}
/*
* Test a valid scanHexInt operation
*/
void
testScanHexIntGood (NSString *format, unsigned int i)
{
NSString *string;
if (format == nil) {
testScanHexIntGood (@"%x", i);
testScanHexIntGood (@"%X", i);
return;
}
string = [NSString stringWithFormat:format, i];
testScanHexIntFinish (string, YES, i, [string length]);
}
/*
* Test scanHexInt operation
*/
void
testScanHexInt (void)
{
unsigned int i;
/*
* Check values within range
*/
i = UINT_MAX-32;
for (;;) {
testScanHexIntGood (nil, i);
if (i == UINT_MAX)
break;
i++;
}
for (i = 0 ; i <= 32 ; i++)
testScanHexIntGood (nil, i);
/*
* Check that non-digits terminate the scan
*/
testScanHexIntFinish (@"1234FOO", YES, 0x1234F, 5);
testScanHexIntFinish (@"01234FOO", YES, 0x1234F, 6);
/*
* Check that non-digits don't move the scan location
*/
testScanHexIntFinish (@"GOO", NO, 0, 0);
testScanHexIntFinish (@" GOO", NO, 0, 0);
testScanHexIntFinish (@" x ", NO, 0, 0);
}
/*
@ -357,8 +430,6 @@ testScanLongLongGood (long long i)
printf ("scanLongLong of `%s' returned value %s.\n", [string cString],
longlongToString (value));
testFullScan ("scanLongLong", string, scanner);
[string release];
[scanner release];
}
/*
@ -379,8 +450,6 @@ testScanLongLongOverflow (const char *sign, unsigned long long check, long long
printf ("scanLongLong of `%s' didn't overflow, returned %s.\n", [string cString],
longlongToString (value));
testFullScan ("scanLongLong", string, scanner);
[string release];
[scanner release];
}
/*
@ -493,7 +562,6 @@ testScanDoubleGood (NSString *string, double expect)
printf ("scanDouble of `%s' returned value %.*e (%g LSB different).\n",
[string cString], DBL_DIG + 2, value, error);
testFullScan ("scanDouble", string, scanner);
[scanner release];
}
static void
@ -501,7 +569,6 @@ testScanDoubleOneDigit (NSString *format, int digit, double expect)
{
NSString *string = [NSString stringWithFormat:format, digit];
testScanDoubleGood (string, expect);
[string release];
}
static void
@ -520,7 +587,6 @@ testScanDoubleShort (NSString *string, double expect, unsigned int length)
scanLocation = [scanner scanLocation];
if (scanLocation != length)
printf ("scanDouble of `%s' moves scan location to %u.\n", [string cString], scanLocation);
[scanner release];
}
void
@ -535,7 +601,6 @@ testScanDoubleBad (NSString *string)
scanLocation = [scanner scanLocation];
if (scanLocation != 0)
printf ("scanDouble of `%s' moves scan location to %u.\n", [string cString], scanLocation);
[scanner release];
}
/*
@ -854,12 +919,19 @@ testScanUpToCharactersFromSet (void)
* TEST DRIVER *
************************************************************************
*/
void
runtest (void (*test)(void))
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
(*test)();
[arp release];
}
int
main (int argc, char **argv)
{
extern char *optarg;
int c;
NSAutoreleasePool *arp = [NSAutoreleasePool new];
while ((c = getopt (argc, argv, "e:")) != EOF) {
switch (c) {
@ -869,16 +941,16 @@ main (int argc, char **argv)
}
}
testScanInt ();
testScanRadixUnsignedInt ();
runtest (testScanInt);
runtest (testScanRadixUnsignedInt);
runtest (testScanHexInt);
#if defined (LONG_LONG_MAX)
testScanLongLong ();
runtest (testScanLongLong);
#endif
testScanDouble ();
testScanString ();
testScanUpToString ();
testScanCharactersFromSet ();
testScanUpToCharactersFromSet ();
[arp release];
runtest (testScanDouble);
runtest (testScanString);
runtest (testScanUpToString);
runtest (testScanCharactersFromSet);
runtest (testScanUpToCharactersFromSet);
return 0;
}