mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
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:
parent
ec410c6ec0
commit
d5a15722e8
2 changed files with 254 additions and 44 deletions
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue