2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "EOQualifier.h"
27 //#define USE_DESCRIPTION_FOR_AT 1
29 static int qDebug = 0;
30 static NSMutableDictionary *EOQualifierParserTypeMappings = nil;
33 The literals understood by the value parser.
35 NOTE: Any literal used here can never be used as a key ! So add as little
39 const unsigned char *token;
44 static EOQPTokEntry toks[] = {
45 { (const unsigned char *)"NULL", nil, 0 },
46 { (const unsigned char *)"nil", nil, 1 },
47 { (const unsigned char *)"YES", nil, 0 },
48 { (const unsigned char *)"NO", nil, 0 },
49 { (const unsigned char *)"TRUE", nil, 0 },
50 { (const unsigned char *)"FALSE", nil, 0 },
51 { (const unsigned char *)NULL, nil, 0 }
54 static inline void _setupLiterals(void) {
55 static BOOL didSetup = NO;
58 toks[0].value = [[NSNull null] retain];
59 toks[1].value = toks[0].value;
60 toks[2].value = [[NSNumber numberWithBool:YES] retain];
61 toks[3].value = [[NSNumber numberWithBool:NO] retain];
62 toks[4].value = toks[2].value;
63 toks[5].value = toks[3].value;
67 static Class StringClass = Nil;
68 static Class NumberClass = Nil;
69 static EONull *null = nil;
71 /* parsing functions */
73 static EOQualifier *_parseCompoundQualifier(id _ctx, const char *_buf,
74 unsigned _bufLen, unsigned *_qualLen);
75 static EOQualifier *_testOperator(id _ctx, const char *_buf,
76 unsigned _bufLen, unsigned *_opLen,
78 static EOQualifier *_parseQualifiers(id _ctx, const char *_buf,
79 unsigned _bufLen, unsigned *_qualLen);
80 static EOQualifier *_parseParenthesisQualifier(id _ctx,
81 const char *_buf, unsigned _bufLen,
83 static EOQualifier *_parseNotQualifier(id _ctx, const char *_buf,
84 unsigned _bufLen, unsigned *_qualLen);
85 static EOQualifier *_parseKeyCompQualifier(id _ctx, const char *_buf,
86 unsigned _bufLen, unsigned *_qualLen);
87 static NSString *_parseKey(id _ctx, const char *_buf, unsigned _bufLen,
89 static id _parseValue(id _ctx, const char *_buf, unsigned _bufLen,
91 static inline unsigned _countWhiteSpaces(const char *_buf, unsigned _bufLen);
92 static NSString *_parseOp(const char *_buf, unsigned _bufLen,
95 @interface EOQualifierParserContext : NSObject
97 NSMapTable *qualifierCache;
99 - (NSDictionary *)resultForFunction:(NSString *)_fct atPos:(unsigned)_pos;
100 - (void)setResult:(NSDictionary *)_dict forFunction:(NSString *)_fct
101 atPos:(unsigned)_pos;
102 - (id)getObjectFromStackFor:(char)_c;
106 - (EOQualifier *)keyComparisonQualifierWithLeftKey:(NSString *)_leftKey
107 operatorSelector:(SEL)_sel
108 rightKey:(NSString *)_rightKey;
109 - (EOQualifier *)keyValueQualifierWithKey:(NSString *)_key
110 operatorSelector:(SEL)_sel
112 - (EOQualifier *)andQualifierWithArray:(NSArray *)_qualifiers;
113 - (EOQualifier *)orQualifierWithArray:(NSArray *)_qualifiers;
114 - (EOQualifier *)notQualifierWithQualifier:(EOQualifier *)_qualifier;
118 @interface EOQualifierVAParserContext : EOQualifierParserContext
122 + (id)contextWithVaList:(va_list *)_va;
123 - (id)initWithVaList:(va_list *)_va;
126 @interface EOQualifierEnumeratorParserContext : EOQualifierParserContext
128 NSEnumerator *enumerator;
130 + (id)contextWithEnumerator:(NSEnumerator *)_enumerator;
131 - (id)initWithEnumerator:(NSEnumerator *)_enumerator;
134 @implementation EOQualifierVAParserContext
136 + (id)contextWithVaList:(va_list *)_va {
137 return [[[EOQualifierVAParserContext alloc] initWithVaList:_va] autorelease];
140 - (id)initWithVaList:(va_list *)_va {
141 if ((self = [super init])) {
147 - (id)getObjectFromStackFor:(char)_c {
150 if (StringClass == Nil) StringClass = [NSString class];
151 if (NumberClass == Nil) NumberClass = [NSNumber class];
152 if (null == nil) null = [EONull null];
155 char *str = va_arg(*self->va, char*);
156 obj = [StringClass stringWithCString:str];
158 else if (_c == 'd') {
159 int i= va_arg(*self->va, int);
160 obj = [NumberClass numberWithInt:i];
162 else if (_c == 'f') {
163 double d = va_arg(*self->va, double);
164 obj = [NumberClass numberWithDouble:d];
166 else if (_c == '@') {
167 id o = va_arg(*self->va, id);
168 #if USE_DESCRIPTION_FOR_AT
169 obj = (o == nil) ? (id)null : (id)[o description];
171 obj = (o == nil) ? (id)null : (id)o;
175 [NSException raise:@"NSInvalidArgumentException"
176 format:@"unknown conversation char %c", _c];
181 @end /* EOQualifierVAParserContext */
183 @implementation EOQualifierEnumeratorParserContext
185 + (id)contextWithEnumerator:(NSEnumerator *)_enumerator {
186 return [[[EOQualifierEnumeratorParserContext alloc]
187 initWithEnumerator:_enumerator] autorelease];
190 - (id)initWithEnumerator:(NSEnumerator *)_enumerator {
191 if ((self = [super init])) {
192 ASSIGN(self->enumerator, _enumerator);
198 [self->enumerator release];
202 - (id)getObjectFromStackFor:(char)_c {
203 static Class NumberClass = Nil;
206 if (NumberClass == Nil) NumberClass = [NSNumber class];
208 o = [self->enumerator nextObject];
211 #if USE_DESCRIPTION_FOR_AT
212 return [o description];
218 return [NumberClass numberWithDouble:[o doubleValue]];
221 return [NumberClass numberWithInt:[o intValue]];
224 // return [NSString stringWithCString:[o cString]];
225 return [[o copy] autorelease];
228 [NSException raise:@"NSInvalidArgumentException"
229 format:@"unknown or not allowed conversation char %c", _c];
234 @end /* EOQualifierEnumeratorParserContext */
236 @implementation EOQualifierParserContext
239 if (StringClass == Nil) StringClass = [NSString class];
241 if ((self = [super init])) {
242 self->qualifierCache = NSCreateMapTable(NSObjectMapKeyCallBacks,
243 NSObjectMapValueCallBacks,
250 if (self->qualifierCache) NSFreeMapTable(self->qualifierCache);
254 - (NSDictionary *)resultForFunction:(NSString *)_fct atPos:(unsigned)_pos
256 return NSMapGet(self->qualifierCache,
257 [StringClass stringWithFormat:@"%@_%d", _fct, _pos]);
260 - (void)setResult:(NSDictionary *)_dict forFunction:(NSString *)_fct
263 NSMapInsert(self->qualifierCache,
264 [StringClass stringWithFormat:@"%@_%d", _fct, _pos],
268 - (id)getObjectFromStackFor:(char)_c {
269 [self doesNotRecognizeSelector:_cmd];
275 - (EOQualifier *)keyComparisonQualifierWithLeftKey:(NSString *)_leftKey
276 operatorSelector:(SEL)_sel
277 rightKey:(NSString *)_rightKey
279 static Class clazz = Nil;
280 if (clazz == Nil) clazz = [EOKeyComparisonQualifier class];
282 return [[[clazz alloc]
283 initWithLeftKey:_leftKey
284 operatorSelector:_sel
288 - (EOQualifier *)keyValueQualifierWithKey:(NSString *)_key
289 operatorSelector:(SEL)_sel
292 static Class clazz = Nil;
293 if (clazz == Nil) clazz = [EOKeyValueQualifier class];
295 return [[[clazz alloc]
297 operatorSelector:_sel
301 - (EOQualifier *)andQualifierWithArray:(NSArray *)_qualifiers {
302 static Class clazz = Nil;
303 if (clazz == Nil) clazz = [EOAndQualifier class];
305 return [[[clazz alloc] initWithQualifierArray:_qualifiers] autorelease];
307 - (EOQualifier *)orQualifierWithArray:(NSArray *)_qualifiers {
308 static Class clazz = Nil;
309 if (clazz == Nil) clazz = [EOOrQualifier class];
311 return [[[clazz alloc] initWithQualifierArray:_qualifiers] autorelease];
314 - (EOQualifier *)notQualifierWithQualifier:(EOQualifier *)_qualifier {
315 static Class clazz = Nil;
316 if (clazz == Nil) clazz = [EONotQualifier class];
318 return [[[clazz alloc] initWithQualifier:_qualifier] autorelease];
321 - (EOQualifierVariable *)variableWithKey:(NSString *)_key {
322 static Class clazz = Nil;
323 if (clazz == Nil) clazz = [EOQualifierVariable class];
325 return [clazz variableWithKey:_key];
328 @end /* EOQualifierParserContext */
330 @implementation EOQualifier(Parsing)
332 + (void)registerValueClass:(Class)_valueClass forTypeName:(NSString *)_type {
333 if (EOQualifierParserTypeMappings == nil)
334 EOQualifierParserTypeMappings = [[NSMutableDictionary alloc] init];
337 NSLog(@"ERROR(%s): got passed no type name!", __PRETTY_FUNCTION__);
340 if (_valueClass == nil) {
341 NSLog(@"ERROR(%s): got passed no value-class for type '%@'!",
342 __PRETTY_FUNCTION__, _type);
346 [EOQualifierParserTypeMappings setObject:_valueClass forKey:_type];
349 + (EOQualifier *)qualifierWithQualifierFormat:(NSString *)_qualifierFormat,... {
351 EOQualifier *qualifier;
358 if (StringClass == Nil) StringClass = [NSString class];
360 bufLen = [_qualifierFormat cStringLength];
361 cbuf = malloc(bufLen + 1);
362 [_qualifierFormat getCString:cbuf]; cbuf[bufLen] = '\0';
365 va_start(va, _qualifierFormat);
367 _parseQualifiers([EOQualifierVAParserContext contextWithVaList:&va],
368 buf, bufLen, &length);
371 if (qualifier != nil) { /* check whether the rest of the string is OK */
373 length += _countWhiteSpaces(buf + length, bufLen - length);
375 if (length < bufLen) {
376 NSLog(@"WARNING(%s): unexpected chars at the end of the "
377 @"string(class=%@,len=%i) '%@'",
379 [_qualifierFormat class],
380 [_qualifierFormat length], _qualifierFormat);
381 NSLog(@" buf-length: %i", bufLen);
382 NSLog(@" length: %i", length);
383 NSLog(@" char[length]: '%c' (%i) '%s'", buf[length], buf[length],
387 else if (length > bufLen) {
388 NSLog(@"WARNING(%s): length should never be longer than bufLen ?, "
389 @"internal parsing error !",
390 __PRETTY_FUNCTION__);
397 + (EOQualifier *)qualifierWithQualifierFormat:(NSString *)_qualifierFormat
398 arguments:(NSArray *)_arguments
400 EOQualifier *qual = nil;
402 const char *buf = NULL;
404 EOQualifierEnumeratorParserContext *ctx;
407 if (StringClass == Nil) StringClass = [NSString class];
409 ctx = [EOQualifierEnumeratorParserContext contextWithEnumerator:
410 [_arguments objectEnumerator]];
412 //NSLog(@"qclass: %@", [_qualifierFormat class]);
413 buf = [_qualifierFormat cString];
414 bufLen = [_qualifierFormat cStringLength];
415 qual = _parseQualifiers(ctx, buf, bufLen, &length);
417 if (qual != nil) { /* check whether the rest of the string is OK */
418 if (length < bufLen) {
419 length += _countWhiteSpaces(buf + length, bufLen - length);
421 if (length != bufLen) {
422 NSLog(@"WARNING(%s): unexpected chars at the end of the string '%@'",
423 __PRETTY_FUNCTION__, _qualifierFormat);
430 @end /* EOQualifier(Parsing) */
432 static EOQualifier *_parseSingleQualifier(id _ctx, const char *_buf,
436 EOQualifier *res = nil;
438 if ((res = _parseParenthesisQualifier(_ctx, _buf, _bufLen, _qualLen)) != nil) {
440 NSLog(@"_parseSingleQualifier return <%@> for <%s> ", res, _buf);
444 if ((res = _parseNotQualifier(_ctx, _buf, _bufLen, _qualLen)) != nil) {
446 NSLog(@"_parseSingleQualifier return <%@> for <%s> ", res, _buf);
450 if ((res = _parseKeyCompQualifier(_ctx, _buf, _bufLen, _qualLen)) != nil) {
452 NSLog(@"_parseSingleQualifier return <%@> for <%s> length %d",
453 res, _buf, *_qualLen);
460 static EOQualifier *_parseQualifiers(id _ctx, const char *_buf, unsigned _bufLen,
463 EOQualifier *res = nil;
466 if ((res = _parseCompoundQualifier(_ctx, _buf, _bufLen, _qualLen))) {
468 NSLog(@"_parseQualifiers return <%@> for <%s> ", res, _buf);
472 if ((res = _parseSingleQualifier(_ctx, _buf, _bufLen, _qualLen))) {
474 NSLog(@"_parseQualifiers return <%@> for <%s> ", res, _buf);
479 NSLog(@"_parseQualifiers return nil for <%s> ", _buf);
484 static EOQualifier *_parseParenthesisQualifier(id _ctx, const char *_buf,
489 unsigned qualLen = 0;
490 EOQualifier *qual = nil;
492 pos = _countWhiteSpaces(_buf, _bufLen);
494 if (_bufLen <= pos + 2) /* at least open and close parenthesis */ {
496 NSLog(@"1_parseParenthesisQualifier return nil for <%s> ", _buf);
500 if (_buf[pos] != '(') {
502 NSLog(@"2_parseParenthesisQualifier return nil for <%s> ", _buf);
507 if (!(qual = _parseQualifiers(_ctx, _buf + pos, _bufLen - pos,
510 NSLog(@"3_parseParenthesisQualifier return nil for <%s> ", _buf);
516 if (_bufLen <= pos) {
518 NSLog(@"4_parseParenthesisQualifier return nil for <%s> qual[%@] %@ bufLen %d "
519 @"pos %d", _buf, [qual class], qual, _bufLen, pos);
523 pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
524 if (_buf[pos] != ')') {
526 NSLog(@"5_parseParenthesisQualifier return nil for <%s> [%s] ", _buf, _buf+pos);
531 NSLog(@"6_parseParenthesisQualifier return <%@> for <%s> ", qual, _buf);
533 *_qualLen = pos + 1; /* one step after the parenthesis */
537 static EOQualifier *_parseNotQualifier(id _ctx, const char *_buf,
538 unsigned _bufLen, unsigned *_qualLen)
540 unsigned pos, len = 0;
542 EOQualifier *qual = nil;
544 pos = _countWhiteSpaces(_buf, _bufLen);
546 if (_bufLen - pos < 4) { /* at least 3 chars for 'NOT' */
548 NSLog(@"_parseNotQualifier return nil for <%s> ", _buf);
555 if (!(((c0 == 'n') || (c0 == 'N')) &&
556 ((c1 == 'o') || (c1 == 'O')) &&
557 ((c2 == 't') || (c2 == 'T')))) {
559 NSLog(@"_parseNotQualifier return nil for <%s> ", _buf);
563 qual = _parseSingleQualifier(_ctx, _buf + pos, _bufLen - pos, &len);
566 NSLog(@"_parseNotQualifier return nil for <%s> ", _buf);
570 *_qualLen = pos +len;
572 NSLog(@"_parseNotQualifier return %@ for <%s> ", qual, _buf);
574 return [_ctx notQualifierWithQualifier:qual];
577 static EOQualifier *_parseKeyCompQualifier(id _ctx, const char *_buf,
578 unsigned _bufLen, unsigned *_qualLen)
582 NSString *value = nil;
583 EOQualifier *qual = nil;
584 NSDictionary *dict = nil;
588 BOOL valueIsKey = NO;
590 dict = [_ctx resultForFunction:@"parseKeyCompQualifier" atPos:(unsigned)_buf];
593 NSLog(@"_parseKeyCompQual return <%@> [cached] for <%s> ", dict, _buf);
595 *_qualLen = [[dict objectForKey:@"length"] unsignedIntValue];
596 return [dict objectForKey:@"object"];
598 pos = _countWhiteSpaces(_buf, _bufLen);
600 if ((key = _parseKey(_ctx , _buf + pos, _bufLen - pos, &length)) == nil) {
602 NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf);
607 pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
609 if (!(op = _parseOp(_buf + pos, _bufLen - pos, &length))) {
611 NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf);
614 sel = [EOQualifier operatorSelectorForString:op];
616 NSLog(@"WARNING(%s): possible unknown operator <%@>", __PRETTY_FUNCTION__,
619 NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf);
623 pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
626 value = _parseValue(_ctx, _buf + pos, _bufLen - pos, &length);
628 value = _parseKey(_ctx, _buf + pos, _bufLen - pos, &length);
631 NSLog(@"_parseKeyCompQualifier return nil for <%s> ", _buf);
641 ? [_ctx keyComparisonQualifierWithLeftKey:key
644 : [_ctx keyValueQualifierWithKey:key
649 NSLog(@"_parseKeyCompQualifier return <%@> for <%s> ", qual, _buf);
652 id keys[2], values[2];
653 keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos];
654 keys[1] = @"object"; values[1] = qual;
656 [NSDictionary dictionaryWithObjects:values forKeys:keys count:2]
657 forFunction:@"parseKeyCompQualifier"
658 atPos:(unsigned)_buf];
664 static NSString *_parseOp(const char *_buf, unsigned _bufLen,
673 NSLog(@"_parseOp _bufLen == 0 --> return nil");
676 pos = _countWhiteSpaces(_buf, _bufLen);
677 if (_bufLen - pos > 1) {/* at least an operation and a value */
681 if (((c0 >= '<') && (c0 <= '>')) || (c0 == '!')) {
684 if ((c1 >= '<') && (c1 <= '>')) {
686 result = [StringClass stringWithCString:_buf + pos length:2];
688 NSLog(@"_parseOp return <%@> for <%s> ", result, _buf);
692 result = [StringClass stringWithCString:&c0 length:1];
694 NSLog(@"_parseOp return <%@> for <%s> ", result, _buf);
698 else { /* string designator operator */
699 unsigned opStart = pos;
700 while (pos < _bufLen) {
701 if (_buf[pos] == ' ')
705 if (pos >= _bufLen) {
706 NSLog(@"WARNING(%s): found end of string during operator parsing",
707 __PRETTY_FUNCTION__);
711 NSLog(@"%s: _parseOp return <%@> for <%s> ", __PRETTY_FUNCTION__,
712 [StringClass stringWithCString:_buf + opStart
713 length:pos - opStart], _buf);
717 return [StringClass stringWithCString:_buf + opStart length:pos - opStart];
721 NSLog(@"_parseOp return nil for <%s> ", _buf);
725 static NSString *_parseKey(id _ctx, const char *_buf, unsigned _bufLen,
729 NSDictionary *dict = nil;
731 unsigned startKey = 0;
735 if (qDebug) NSLog(@"%s: _bufLen == 0 --> return nil", __PRETTY_FUNCTION__);
738 dict = [_ctx resultForFunction:@"parseKey" atPos:(unsigned)_buf];
741 NSLog(@"%s: return <%@> [cached] for <%s> ", __PRETTY_FUNCTION__,
744 *_keyLen = [[dict objectForKey:@"length"] unsignedIntValue];
745 return [dict objectForKey:@"object"];
747 pos = _countWhiteSpaces(_buf, _bufLen);
752 if (_bufLen - pos < 2) {
754 NSLog(@"%s: [c==%%,bufLen-pos<2]: _parseValue return nil for <%s> ",
755 __PRETTY_FUNCTION__, _buf);
760 result = [_ctx getObjectFromStackFor:_buf[pos]];
764 /* '{' for namspaces */
765 register BOOL isQuotedKey = NO;
769 else if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
772 NSLog(@"%s: [c!=AZaz{]: _parseKey return nil for <%s> ",
773 __PRETTY_FUNCTION__, _buf);
779 while (pos < _bufLen) {
781 if (isQuotedKey && c == '"')
784 ((c == ' ') || (c == '<') || (c == '>') || (c == '=') || (c == '!') ||
785 c == ')' || c == '(')
791 result = [StringClass stringWithCString:(_buf + startKey + 1)
792 length:(pos - startKey - 2)];
795 result = [StringClass stringWithCString:(_buf + startKey)
796 length:(pos - startKey)];
801 NSLog(@"%s: return <%@> for <%s> ", __PRETTY_FUNCTION__, result, _buf);
804 id keys[2], values[2];
806 keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos];
807 keys[1] = @"object"; values[1] = result;
810 [NSDictionary dictionaryWithObjects:values forKeys:keys count:2]
811 forFunction:@"parseKey"
812 atPos:(unsigned)_buf];
818 static id _parseValue(id _ctx, const char *_buf, unsigned _bufLen,
821 NSString *cast = nil;
822 NSDictionary *dict = nil;
827 if (NumberClass == Nil) NumberClass = [NSNumber class];
828 if (null == nil) null = [[NSNull null] retain];
831 if (qDebug) NSLog(@"_parseValue _bufLen == 0 --> return nil");
835 dict = [_ctx resultForFunction:@"parseValue" atPos:(unsigned)_buf];
838 NSLog(@"_parseKeyCompQualifier return <%@> [cached] for <%s> ",
841 *_keyLen = [[dict objectForKey:@"length"] unsignedIntValue];
842 return [dict objectForKey:@"object"];
845 pos = _countWhiteSpaces(_buf, _bufLen);
848 if (c == '$') { /* found EOQualifierVariable */
849 unsigned startVar = 0;
854 while (pos < _bufLen) {
855 if ((_buf[pos] == ' ') || (_buf[pos] == ')'))
860 varKey = [StringClass stringWithCString:(_buf + startVar)
861 length:pos - startVar];
862 obj = [_ctx variableWithKey:varKey];
865 /* first, check for CAST */
866 BOOL parseComplexCast = NO;
868 if (c == 'c' && _bufLen > 14) {
869 if (strstr(_buf, "cast") == _buf && (isspace(_buf[4]) || _buf[4]=='(')) {
870 /* for example: cast("1970-01-01T00:00:00Z" as 'dateTime') [min 15 #]*/
871 pos += 4; /* skip 'cast' */
872 while (isspace(_buf[pos])) /* skip spaces */
874 if (_buf[pos] != '(') {
875 NSLog(@"WARNING(%s): got unexpected cast string: '%s'",
876 __PRETTY_FUNCTION__, _buf);
879 pos++; /* skip opening bracket '(' */
881 parseComplexCast = YES;
885 else if (c == '(') { /* starting with a cast */
886 /* for example: (NSCalendarDate)"1999-12-12" [min 5 chars] */
887 unsigned startCast = 0;
891 while (pos < _bufLen) {
892 if (_buf[pos] == ')')
897 if (pos >= _bufLen) {
898 NSLog(@"WARNING(%s): found end of string while reading a cast",
899 __PRETTY_FUNCTION__);
903 cast = [StringClass stringWithCString:(_buf + startCast)
904 length:(pos - 1 - startCast)];
906 NSLog(@"%s: got cast %@", __PRETTY_FUNCTION__, cast);
909 /* next, check for FORMAT SPECIFIER */
911 if (_bufLen - pos < 2) {
913 NSLog(@"_parseValue return nil for <%s> ", _buf);
918 obj = [_ctx getObjectFromStackFor:_buf[pos]];
922 /* next, check for A NUMBER */
923 else if (((c >= '0') && (c <= '9')) || (c == '-')) { /* got a number */
924 unsigned startNumber;
928 while (pos < _bufLen) {
930 if (!((c >= '0') && (c <= '9')))
934 obj = [NumberClass numberWithInt:atoi(_buf + startNumber)];
937 /* check for some text literals */
938 if ((obj == nil) && ((_bufLen - pos) > 1)) {
941 for (i = 0; i < 20 && (toks[i].token != NULL) && (obj == nil); i++) {
942 const unsigned char *tok;
943 unsigned char toklen;
947 toklen = strlen((const char *)tok);
948 if ((_bufLen - pos) < toklen)
949 /* remaining string not long enough */
953 ? strncmp(&(_buf[pos]), (const char *)tok, toklen)
954 : strncasecmp(&(_buf[pos]), (const char *)tok, toklen);
958 if (!(_buf[pos + toklen] == '\0' || isspace(_buf[pos + toklen])))
959 /* not at the string end or folloed by a space */
962 /* wow, found the token */
963 pos += toklen; /* skip it */
968 /* next, check for STRING */
970 if ((c == '\'') || (c == '"')) {
972 char string[_bufLen - pos];
976 while (pos < _bufLen) {
980 if ((ch == '\\') && (_bufLen > (pos + 1))) {
981 if (_buf[pos + 1] == c) {
989 if (pos >= _bufLen) {
990 NSLog(@"WARNING(%s): found end of string before end of quoted text",
991 __PRETTY_FUNCTION__);
994 res = [StringClass stringWithCString:string length:cnt];
995 pos++; /* don`t forget quotations */
996 if (qDebug) NSLog(@"_parseValue return <%@> for <%s> ", res, _buf);
1001 /* complete parsing of cast */
1002 if (parseComplexCast && (pos + 6) < _bufLen) {
1003 /* now we need " as 'dateTime'" [min 7 #] */
1006 while (isspace(_buf[pos]) && pos < _bufLen) pos++;
1008 //printf("POS: '%s'\n", &(_buf[pos]));
1010 if (_buf[pos] != 'a' && _buf[pos] != 'A')
1011 NSLog(@"%s: expecting 'AS' of complex cast ...", __PRETTY_FUNCTION__);
1012 else if (_buf[pos + 1] != 's' && _buf[pos + 1] != 'S')
1013 NSLog(@"%s: expecting 'AS' of complex cast ...", __PRETTY_FUNCTION__);
1019 while (isspace(_buf[pos]) && pos < _bufLen) pos++;
1021 /* read cast type */
1022 if (_buf[pos] != '\'') {
1023 NSLog(@"%s: expected type of complex cast ...", __PRETTY_FUNCTION__);
1026 const unsigned char *cs, *ce;
1028 //printf("POS: '%s'\n", &(_buf[pos]));
1030 cs = (const unsigned char *)&(_buf[pos]);
1031 ce = (const unsigned char *)index((const char *)cs, '\'');
1032 cast = [NSString stringWithCString:(const char*)cs length:(ce - cs)];
1034 NSLog(@"%s: parsed complex cast: '%@' to '%@'",
1035 __PRETTY_FUNCTION__, obj, cast);
1040 //printf("POS: '%s'\n", &(_buf[pos]));
1046 if (cast != nil && obj != nil) {
1050 if ((class = [EOQualifierParserTypeMappings objectForKey:cast]) == nil) {
1051 /* no value explicitly mapped to class, try to construct class name... */
1052 NSString *className;
1055 if ((class = NSClassFromString(className)) == Nil) {
1056 /* check some default cast types ... */
1057 className = [cast lowercaseString];
1059 if ([className isEqualToString:@"datetime"])
1060 class = [NSCalendarDate class];
1061 else if ([className isEqualToString:@"datetime.tz"])
1062 class = [NSCalendarDate class];
1066 obj = [[[class alloc] initWithString:[orig description]] autorelease];
1069 NSLog(@"%s: could not init object '%@' of cast class %@(%@) !",
1070 __PRETTY_FUNCTION__, orig, class, cast);
1075 NSLog(@"WARNING(%s): could not map cast '%@' to a class "
1076 @"(returning null) !",
1077 __PRETTY_FUNCTION__, cast);
1083 NSLog(@"%s: return <%@> for <%s> ", __PRETTY_FUNCTION__,
1084 obj?obj:@"<nil>", _buf);
1088 id keys[2], values[2];
1090 keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos];
1091 keys[1] = @"object"; values[1] = obj;
1094 [NSDictionary dictionaryWithObjects:values forKeys:keys count:2]
1095 forFunction:@"parseValue" atPos:(unsigned)_buf];
1101 static EOQualifier *_testOperator(id _ctx, const char *_buf,
1102 unsigned _bufLen, unsigned *_opLen,
1105 EOQualifier *qual = nil;
1106 char c0, c1, c2 = 0;
1107 unsigned pos, len = 0;
1109 pos = _countWhiteSpaces(_buf, _bufLen);
1111 if (_bufLen < 4) {/* at least OR or AND and somethink more */
1113 NSLog(@"_testOperator return nil for <%s> ", _buf);
1120 if (((c0 == 'a') || (c0 == 'A')) &&
1121 ((c1 == 'n') || (c1 == 'N')) &&
1122 ((c2 == 'd') || (c2 == 'D'))) {
1126 else if (((c0 == 'o') || (c0 == 'O')) && ((c1 == 'r') || (c1 == 'R'))) {
1130 pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
1131 qual = _parseSingleQualifier(_ctx, _buf + pos, _bufLen - pos, &len);
1132 *_opLen = pos + len;
1134 NSLog(@"_testOperator return %@ for <%s> ", qual, _buf);
1139 static EOQualifier *_parseCompoundQualifier(id _ctx, const char *_buf,
1140 unsigned _bufLen, unsigned *_qualLen)
1142 EOQualifier *q0, *q1 = nil;
1143 NSMutableArray *array = nil;
1144 unsigned pos, len = 0;
1145 EOQualifier *result;
1150 if ((q0 = _parseSingleQualifier(_ctx, _buf, _bufLen, &len)) == nil) {
1152 NSLog(@"_parseAndOrQualifier return nil for <%s> ", _buf);
1158 if (!(q1 = _testOperator(_ctx, _buf + pos, _bufLen - pos, &len, &isAnd))) {
1160 NSLog(@"_parseAndOrQualifier return nil for <%s> ", _buf);
1164 array = [NSMutableArray arrayWithObjects:q0, q1, nil];
1170 q0 = _testOperator(_ctx, _buf + pos, _bufLen - pos, &len, &newIsAnd);
1175 if (newIsAnd != isAnd) {
1178 a = [[array copy] autorelease];
1181 ? [_ctx andQualifierWithArray:a]
1182 : [_ctx orQualifierWithArray:a];
1184 [array removeAllObjects];
1185 [array addObject:q1];
1188 [array addObject:q0];
1195 ? [_ctx andQualifierWithArray:array]
1196 : [_ctx orQualifierWithArray:array];
1199 NSLog(@"_parseAndOrQualifier return <%@> for <%s> ", result, _buf);
1204 static inline unsigned _countWhiteSpaces(const char *_buf, unsigned _bufLen) {
1209 NSLog(@"_parseString _bufLen == 0 --> return nil");
1213 while (_buf[cnt] == ' ' || _buf[cnt] == '\t' ||
1214 _buf[cnt] == '\n' || _buf[cnt] == '\r') {