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++;
o = va_arg(ap, id); switch (type)
{
case stObject:
{
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,42 +1638,42 @@
{ {
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];
if ([r isKindOfClass: [NSCompoundPredicate class]] if ([r isKindOfClass: [NSCompoundPredicate class]]
&& [(NSCompoundPredicate *)r compoundPredicateType] && [(NSCompoundPredicate *)r compoundPredicateType]
== NSAndPredicateType) == NSAndPredicateType)
{ {
// merge // merge
if ([l isKindOfClass:[NSCompoundPredicate class]] if ([l isKindOfClass:[NSCompoundPredicate class]]
&& [(NSCompoundPredicate *)l compoundPredicateType] && [(NSCompoundPredicate *)l compoundPredicateType]
== NSAndPredicateType) == NSAndPredicateType)
{ {
[(NSMutableArray *)[(NSCompoundPredicate *)l subpredicates] [(NSMutableArray *)[(NSCompoundPredicate *)l subpredicates]
addObjectsFromArray: [(NSCompoundPredicate *)r subpredicates]]; addObjectsFromArray: [(NSCompoundPredicate *)r subpredicates]];
} }
else else
{ {
[(NSMutableArray *)[(NSCompoundPredicate *)r subpredicates] [(NSMutableArray *)[(NSCompoundPredicate *)r subpredicates]
insertObject: l atIndex: 0]; insertObject: l atIndex: 0];
l = r; l = r;
} }
} }
else if ([l isKindOfClass: [NSCompoundPredicate class]] else if ([l isKindOfClass: [NSCompoundPredicate class]]
&& [(NSCompoundPredicate *)l compoundPredicateType] && [(NSCompoundPredicate *)l compoundPredicateType]
== NSAndPredicateType) == NSAndPredicateType)
{ {
// add to l // add to l
[(NSMutableArray *)[(NSCompoundPredicate *)l subpredicates] [(NSMutableArray *)[(NSCompoundPredicate *)l subpredicates]
addObject: r]; addObject: r];
} }
else else
{ {
l = [NSCompoundPredicate andPredicateWithSubpredicates: l = [NSCompoundPredicate andPredicateWithSubpredicates:
[NSArray arrayWithObjects: l, r, nil]]; [NSArray arrayWithObjects: l, r, nil]];
} }
} }
return l; return l;
@ -1810,9 +1921,10 @@
- (NSExpression *) parseSimpleExpression - (NSExpression *) parseSimpleExpression
{ {
static NSCharacterSet *_identifier; static NSCharacterSet *_identifier;
NSString *ident; unsigned location;
double dbl; NSString *ident;
double dbl;
if ([self scanDouble: &dbl]) if ([self scanDouble: &dbl])
{ {
@ -1864,22 +1976,22 @@
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]];
} }
if ([self scanPredicateKeyword: @"SELF"]) if ([self scanPredicateKeyword: @"SELF"])
{ {
@ -1898,14 +2010,110 @@
return [NSExpression expressionForVariable: [var keyPath]]; return [NSExpression expressionForVariable: [var keyPath]];
} }
if ([self scanPredicateKeyword: @"%K"]) location = [self scanLocation];
{
return [NSExpression expressionForKeyPath: [self nextArg]];
}
if ([self scanPredicateKeyword: @"%@"]) if ([self scanString: @"%" intoString: NULL])
{ {
return [NSExpression expressionForConstantValue: [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;
}
}
[self setScanLocation: location];
} }
// FIXME: Missing other formats such as %d // FIXME: Missing other formats such as %d
@ -1936,7 +2144,7 @@
// prefix with keypath // prefix with keypath
return [NSExpression expressionForKeyPath: return [NSExpression expressionForKeyPath:
[NSString stringWithFormat: @"@%@", [e keyPath]]]; [NSString stringWithFormat: @"@%@", [e keyPath]]];
} }
// skip # as prefix (reserved words) // skip # as prefix (reserved words)
@ -2001,23 +2209,23 @@
if ([self scanPredicateKeyword: @"FIRST"]) if ([self scanPredicateKeyword: @"FIRST"])
{ {
left = [NSExpression expressionForFunction: @"_first" left = [NSExpression expressionForFunction: @"_first"
arguments: [NSArray arrayWithObject: [self parseExpression]]]; arguments: [NSArray arrayWithObject: [self parseExpression]]];
} }
else if ([self scanPredicateKeyword: @"LAST"]) else if ([self scanPredicateKeyword: @"LAST"])
{ {
left = [NSExpression expressionForFunction: @"_last" left = [NSExpression expressionForFunction: @"_last"
arguments: [NSArray arrayWithObject: [self parseExpression]]]; arguments: [NSArray arrayWithObject: [self parseExpression]]];
} }
else if ([self scanPredicateKeyword: @"SIZE"]) else if ([self scanPredicateKeyword: @"SIZE"])
{ {
left = [NSExpression expressionForFunction: @"count" left = [NSExpression expressionForFunction: @"count"
arguments: [NSArray arrayWithObject: [self parseExpression]]]; arguments: [NSArray arrayWithObject: [self parseExpression]]];
} }
else else
{ {
left = [NSExpression expressionForFunction: @"_index" left = [NSExpression expressionForFunction: @"_index"
arguments: [NSArray arrayWithObjects: left, arguments: [NSArray arrayWithObjects: left,
[self parseExpression], nil]]; [self parseExpression], nil]];
} }
if (![self scanString: @"]" intoString: NULL]) if (![self scanString: @"]" intoString: NULL])
{ {
@ -2070,7 +2278,7 @@
{ {
right = [self parseFunctionalExpression]; right = [self parseFunctionalExpression];
left = [NSExpression expressionForFunction: @"_pow" left = [NSExpression expressionForFunction: @"_pow"
arguments: [NSArray arrayWithObjects: left, right, nil]]; arguments: [NSArray arrayWithObjects: left, right, nil]];
} }
else else
{ {
@ -2091,13 +2299,13 @@
{ {
right = [self parsePowerExpression]; right = [self parsePowerExpression];
left = [NSExpression expressionForFunction: @"_mul" left = [NSExpression expressionForFunction: @"_mul"
arguments: [NSArray arrayWithObjects: left, right, nil]]; arguments: [NSArray arrayWithObjects: left, right, nil]];
} }
else if ([self scanString: @"/" intoString: NULL]) else if ([self scanString: @"/" intoString: NULL])
{ {
right = [self parsePowerExpression]; right = [self parsePowerExpression];
left = [NSExpression expressionForFunction: @"_div" left = [NSExpression expressionForFunction: @"_div"
arguments: [NSArray arrayWithObjects: left, right, nil]]; arguments: [NSArray arrayWithObjects: left, right, nil]];
} }
else else
{ {
@ -2118,13 +2326,13 @@
{ {
right = [self parseMultiplicationExpression]; right = [self parseMultiplicationExpression];
left = [NSExpression expressionForFunction: @"_add" left = [NSExpression expressionForFunction: @"_add"
arguments: [NSArray arrayWithObjects: left, right, nil]]; arguments: [NSArray arrayWithObjects: left, right, nil]];
} }
else if ([self scanString: @"-" intoString: NULL]) else if ([self scanString: @"-" intoString: NULL])
{ {
right = [self parseMultiplicationExpression]; right = [self parseMultiplicationExpression];
left = [NSExpression expressionForFunction: @"_sub" left = [NSExpression expressionForFunction: @"_sub"
arguments: [NSArray arrayWithObjects: left, right, nil]]; arguments: [NSArray arrayWithObjects: left, right, nil]];
} }
else else
{ {