mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Patch by eric@skatter.usask.ca
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3638 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
bcd0eaabda
commit
b3b94f787b
4 changed files with 210 additions and 80 deletions
13
ChangeLog
13
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue