2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo 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 OGo 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 OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "NSObject+QPEval.h"
26 @interface NSObject(QPEvalPrivates)
28 - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx;
29 - (NSArray *)evaluateQueryPathComponents:(NSArray *)_pcs;
31 - (void)takeValue:(id)_value forQueryPath:(NSString *)_qp;
32 - (id)valueForQueryPath:(NSString *)_qp;
33 - (NSException *)setQueryPathValue:(id)_value;
36 @end /* NSObject(QPEval) */
39 @implementation NSString(QP)
41 - (NSArray *)queryPathComponents {
45 if ([self rangeOfString:@"/"].length == 0)
46 return [NSArray arrayWithObject:self];
47 if ([self isEqualToString:@"/"])
48 return [NSArray arrayWithObject:self];
50 pc = [NSMutableArray arrayWithCapacity:8];
54 /* add root, if absolute path */
55 if ([self characterAtIndex:0] == '/') {
60 for (s = i; i < len; i++) {
61 if ([self characterAtIndex:i] == '/') {
66 p = [self substringWithRange:NSMakeRange(s, plen)];
68 s = (i + 1); /* next component begins at idx right after '/' .. */
70 else if ([self characterAtIndex:i] == '{') {
73 for (j = (i + 1); j < len; j++) {
74 if ([self characterAtIndex:j] == '}') {
75 /* continue after closing brace .. */
85 p = [self substringWithRange:NSMakeRange(s, (i - s))];
92 @end /* NSString(QP) */
94 @implementation NSObject(QPEval)
96 /* special expressions */
98 - (id)queryPathRootObjectInContext:(id)_ctx {
102 /* query path evaluation */
104 - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx {
110 if ((len = [_pc length]) == 0)
115 c = [_pc characterAtIndex:0];
117 id root = [self queryPathRootObjectInContext:_ctx];
118 result = root ? [NSArray arrayWithObject:root] : nil;
121 result = [NSArray arrayWithObject:self];
126 NSLog(@"0x%08X<%@> eval QP '%@': %@", self, NSStringFromClass([self class]),
132 - (NSArray *)queryPathCursorArray {
133 return [NSArray arrayWithObject:self];
135 - (NSArray *)evaluateQueryPathComponents:(NSArray *)_pcs {
138 NSAutoreleasePool *pool;
140 NSMutableDictionary *ctx;
142 pool = [[NSAutoreleasePool alloc] init];
144 ctx = [NSMutableDictionary dictionaryWithCapacity:16];
146 NSLog(@"eval PCs: %@", _pcs);
148 array = [self queryPathCursorArray];
150 pcs = [_pcs objectEnumerator];
151 while ((array != nil) && (pc = [pcs nextObject])) {
152 if ((array = [array evaluateQueryPathComponent:pc inContext:ctx]) == nil)
156 array = [array retain];
159 return [array autorelease];
162 - (NSArray *)evaluateQueryPath:(NSString *)_path {
163 if ([_path rangeOfString:@"/"].length == 0)
164 return [self evaluateQueryPathComponents:[NSArray arrayWithObject:_path]];
166 if ([_path isEqualToString:@"/"]) {
167 static NSArray *rootElem = nil;
169 rootElem = [NSArray arrayWithObject:@"/"];
170 return [self evaluateQueryPathComponents:rootElem];
173 return [self evaluateQueryPathComponents:[_path queryPathComponents]];
178 - (NSException *)setQueryPathValue:(id)_value {
182 return [NSException exceptionWithName:@"QueryPathEvalException"
183 reason:@"cannot set query-path value on object"
186 - (id)queryPathValue {
190 - (void)takeValue:(id)_value forQueryPath:(NSString *)_qp {
191 [[[self evaluateQueryPath:_qp] setQueryPathValue:_value] raise];
193 - (id)valueForQueryPath:(NSString *)_qp {
194 return [[self evaluateQueryPath:_qp] queryPathValue];
197 @end /* NSObject(QPEval) */
199 @implementation NSArray(QPEval)
201 - (NSArray *)queryPathCursorArray {
204 - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx {
205 unsigned i, j, count;
209 if ((count = [self count]) == 0)
210 return [NSArray array];
212 objs = calloc(count + 1, sizeof(id));
213 for (i = 0, j = 0; i < count; i++) {
216 obj = [self objectAtIndex:i];
217 obj = [obj evaluateQueryPathComponent:_pc inContext:_ctx];
224 array = [NSArray arrayWithObjects:objs count:j];
225 if (objs) free(objs);
229 @end /* NSArray(QPEval) */
231 @implementation NSSet(QPEval)
233 - (NSArray *)evaluateQueryPathComponent:(NSString *)_pc inContext:(id)_ctx {
234 return [[self allObjects] evaluateQueryPathComponent:_pc inContext:(id)_ctx];
236 - (NSArray *)evaluateQueryPathComponents:(NSArray *)_pcs {
237 return [[self allObjects] evaluateQueryPathComponents:_pcs];
240 @end /* NSSet(QPEval) */