Attempt to support parsing of '%' sequences.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25273 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2007-06-20 08:03:51 +00:00
parent ec410c6ec0
commit d5a15722e8
2 changed files with 254 additions and 44 deletions

View file

@ -2,6 +2,8 @@
* Source/NSPredicate.m: Fix bug #20215 ... scanning of greater than * Source/NSPredicate.m: Fix bug #20215 ... scanning of greater than
and less than operators. and less than operators.
Add code to attempt to support parsing of predicates containing
all the '%' format strings ... untested.
2007-06-15 Adam Fedor <fedor@gnu.org> 2007-06-15 Adam Fedor <fedor@gnu.org>

View file

@ -50,6 +50,21 @@
GSClassNameFromObject(self), GSObjCIsInstance(self) ? "instance" : "class",\ GSClassNameFromObject(self), GSObjCIsInstance(self) ? "instance" : "class",\
GSNameFromSelector(_cmd)] GSNameFromSelector(_cmd)]
typedef enum {
stObject,
stChar,
stUnichar,
stString,
stUnistring,
stSShort,
stUShort,
stSInt,
stUInt,
stSQuad,
stUQuad,
stFloat,
} scanType;
@interface GSPredicateScanner : NSScanner @interface GSPredicateScanner : NSScanner
{ {
NSEnumerator *_args; // Not retained. NSEnumerator *_args; // Not retained.
@ -61,7 +76,7 @@
args: (NSArray*)args; args: (NSArray*)args;
- (id) initWithString: (NSString*)format - (id) initWithString: (NSString*)format
vargs: (va_list)vargs; vargs: (va_list)vargs;
- (id) nextArg; - (id) nextArg: (scanType)type;
- (BOOL) scanPredicateKeyword: (NSString *) key; - (BOOL) scanPredicateKeyword: (NSString *) key;
- (NSPredicate *) parse; - (NSPredicate *) parse;
- (NSPredicate *) parsePredicate; - (NSPredicate *) parsePredicate;
@ -1432,13 +1447,13 @@
return self; return self;
} }
- (id) nextArg - (id) nextArg: (scanType)type
{ {
id o; id o;
if (_args != nil) if (_args != nil)
{ {
o = [_args nextObject]; o = [_args nextObject]; // Just assuming type of arg is OK
} }
else else
{ {
@ -1456,7 +1471,103 @@
o = va_arg(ap, id); o = va_arg(ap, id);
} }
_retrieved++; _retrieved++;
switch (type)
{
case stObject:
{
o = va_arg(ap, id); o = va_arg(ap, id);
break;
}
case stChar:
{
signed char v = (signed char)va_arg(ap, int);
o = [NSNumber numberWithChar: v];
break;
}
case stUnichar:
{
uint16_t v = (uint16_t)va_arg(ap, int);
o = [NSNumber numberWithInt: v];
break;
}
case stString:
{
char *v = (char*)va_arg(ap, char*);
o = [NSString stringWithCString: v
encoding: [NSString defaultCStringEncoding]];
break;
}
case stUnistring:
{
unichar *v = (unichar*)va_arg(ap, unichar*);
int l = 0;
if (v != 0)
{
while (v[l] != 0)
{
l++;
}
}
o = [NSString stringWithCharacters: v length: l];
break;
}
case stSShort:
{
short v = (short)va_arg(ap, int);
o = [NSNumber numberWithShort: v];
break;
}
case stUShort:
{
unsigned short v = (unsigned short)va_arg(ap, int);
o = [NSNumber numberWithUnsignedShort: v];
break;
}
case stSInt:
{
int v = va_arg(ap, int);
o = [NSNumber numberWithInt: v];
break;
}
case stUInt:
{
unsigned int v = va_arg(ap, unsigned int);
o = [NSNumber numberWithUnsignedInt: v];
break;
}
case stSQuad:
{
long long v = va_arg(ap, long long);
o = [NSNumber numberWithLongLong: v];
break;
}
case stUQuad:
{
unsigned long long v = va_arg(ap, unsigned long long);
o = [NSNumber numberWithUnsignedLongLong: v];
break;
}
case stFloat:
{
double v = va_arg(ap, double);
o = [NSNumber numberWithDouble: v];
break;
}
default:
[NSException raise: NSGenericException
format: @"Unknown type - '%d'", type];
}
} }
return o; return o;
} }
@ -1527,8 +1638,8 @@
{ {
NSPredicate *l = [self parseOr]; NSPredicate *l = [self parseOr];
while ([self scanPredicateKeyword: @"AND"] || while ([self scanPredicateKeyword: @"AND"]
[self scanPredicateKeyword: @"&&"]) || [self scanPredicateKeyword: @"&&"])
{ {
NSPredicate *r = [self parseOr]; NSPredicate *r = [self parseOr];
@ -1811,6 +1922,7 @@
- (NSExpression *) parseSimpleExpression - (NSExpression *) parseSimpleExpression
{ {
static NSCharacterSet *_identifier; static NSCharacterSet *_identifier;
unsigned location;
NSString *ident; NSString *ident;
double dbl; double dbl;
@ -1864,19 +1976,19 @@
return [NSExpression expressionForConstantValue: a]; return [NSExpression expressionForConstantValue: a];
} }
if ([self scanPredicateKeyword: @"NULL"] || if ([self scanPredicateKeyword: @"NULL"]
[self scanPredicateKeyword: @"NIL"]) || [self scanPredicateKeyword: @"NIL"])
{ {
return [NSExpression expressionForConstantValue: [NSNull null]]; return [NSExpression expressionForConstantValue: [NSNull null]];
} }
if ([self scanPredicateKeyword: @"TRUE"] || if ([self scanPredicateKeyword: @"TRUE"]
[self scanPredicateKeyword: @"YES"]) || [self scanPredicateKeyword: @"YES"])
{ {
return [NSExpression expressionForConstantValue: return [NSExpression expressionForConstantValue:
[NSNumber numberWithBool: YES]]; [NSNumber numberWithBool: YES]];
} }
if ([self scanPredicateKeyword: @"FALSE"] || if ([self scanPredicateKeyword: @"FALSE"]
[self scanPredicateKeyword: @"NO"]) || [self scanPredicateKeyword: @"NO"])
{ {
return [NSExpression expressionForConstantValue: return [NSExpression expressionForConstantValue:
[NSNumber numberWithBool: NO]]; [NSNumber numberWithBool: NO]];
@ -1898,14 +2010,110 @@
return [NSExpression expressionForVariable: [var keyPath]]; return [NSExpression expressionForVariable: [var keyPath]];
} }
if ([self scanPredicateKeyword: @"%K"]) location = [self scanLocation];
if ([self scanString: @"%" intoString: NULL])
{ {
return [NSExpression expressionForKeyPath: [self nextArg]]; if ([self isAtEnd] == NO)
{
unichar c = [[self string] characterAtIndex: [self scanLocation]];
switch (c)
{
case '%': // '%%' is treated as '%'
location = [self scanLocation];
break;
case 'K':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForKeyPath:
[self nextArg: stObject]];
case '@':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stObject]];
case 'c':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stChar]];
case 'C':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stUnichar]];
case 'd':
case 'D':
case 'i':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stSInt]];
case 'o':
case 'O':
case 'u':
case 'U':
case 'x':
case 'X':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stUInt]];
case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stFloat]];
case 'h':
[self scanString: @"h" intoString: NULL];
if ([self isAtEnd] == NO)
{
c = [[self string] characterAtIndex: [self scanLocation]];
if (c == 'i')
{
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stSShort]];
}
if (c == 'u')
{
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stUShort]];
}
}
break;
case 'q':
[self scanString: @"q" intoString: NULL];
if ([self isAtEnd] == NO)
{
c = [[self string] characterAtIndex: [self scanLocation]];
if (c == 'i')
{
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stSQuad]];
}
if (c == 'u' || c == 'x' || c == 'X')
{
[self setScanLocation: [self scanLocation] + 1];
return [NSExpression expressionForConstantValue:
[self nextArg: stUQuad]];
}
}
break;
}
} }
if ([self scanPredicateKeyword: @"%@"]) [self setScanLocation: location];
{
return [NSExpression expressionForConstantValue: [self nextArg]];
} }
// FIXME: Missing other formats such as %d // FIXME: Missing other formats such as %d