]> err.no Git - sope/blob - sope-core/NGExtensions/EOExt.subproj/EOQualifier+CtxEval.m
bumped Xcode projects to version 4.7. Added a new Xcode project for the STXSaxDriver.
[sope] / sope-core / NGExtensions / EOExt.subproj / EOQualifier+CtxEval.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21
22 #include "EOQualifier+CtxEval.h"
23 #import <EOControl/EOKeyValueCoding.h>
24 #import <EOControl/EONull.h>
25 #include "common.h"
26
27 #if LIB_FOUNDATION_LIBRARY
28 #  import <objc/objc-api.h>
29 #  import <objc/objc.h>
30 #  import <extensions/objc-runtime.h>
31 #elif GNUSTEP_BASE_LIBRARY
32 #  import <objc/objc-api.h>
33 #else
34 #  import <objc/objc.h>
35 #  define sel_get_name sel_getName
36 #endif
37
38 static inline int countSelArgs(SEL _sel) {
39   register const char *selName;
40
41   if ((selName = sel_get_name(_sel))) {
42     register int count;
43     
44     for (count = 0; *selName; selName++) {
45       if (*selName == ':')
46         count++;
47     }
48     return count + 2;
49   }
50   else
51     return -1;
52 }
53
54 @implementation EOQualifier(ContextEvaluation)
55
56 - (BOOL)evaluateWithObject:(id)_object context:(id)_context {
57   [self doesNotRecognizeSelector:_cmd]; /* subclass */
58   return NO;
59 }
60
61 @end /* EOQualifier(ContextEvaluation) */
62
63 @implementation NSArray(ContextEvaluation)
64
65 - (NSArray *)filteredArrayUsingQualifier:(EOQualifier *)_qualifier
66   context:(id)_context
67 {
68   NSMutableArray *a = nil;
69   unsigned i, count;
70
71   for (i = 0, count = [self count]; i < count; i++) {
72     id o;
73
74     o = [self objectAtIndex:i];
75     
76     if ([_qualifier evaluateWithObject:o context:_context]) {
77       if (a == nil) a = [NSMutableArray arrayWithCapacity:count];
78       [a addObject:o];
79     }
80   }
81   return a ? [[a copy] autorelease] : [NSArray array];
82 }
83
84 @end /* NSArray(ContextEvaluation) */
85
86 @implementation EOAndQualifier(ContextEvaluation)
87
88 - (BOOL)evaluateWithObject:(id)_object context:(id)_context {
89   unsigned i;
90   IMP objAtIdx;
91   NSArray *qs;
92
93   qs       = [self qualifiers];
94   objAtIdx = [qs methodForSelector:@selector(objectAtIndex:)];
95   
96   for (i = 0; i < [qs count]; i++) {
97     EOQualifier *q;
98
99     q = objAtIdx(qs, @selector(objectAtIndex:), i);
100
101     if (![q evaluateWithObject:_object context:_context])
102       return NO;
103   }
104   return YES;
105 }
106
107 @end /* EOAndQualifier(ContextEvaluation) */
108
109 @implementation EOOrQualifier(ContextEvaluation)
110
111 - (BOOL)evaluateWithObject:(id)_object context:(id)_context {
112   unsigned i;
113   IMP objAtIdx;
114   NSArray *qs;
115
116   qs       = [self qualifiers];
117   objAtIdx = [qs methodForSelector:@selector(objectAtIndex:)];
118   
119   for (i = 0; i < [qs count]; i++) {
120     EOQualifier *q;
121     
122     q = objAtIdx(qs, @selector(objectAtIndex:), i);
123     
124     if ([q evaluateWithObject:_object context:_context])
125       return YES;
126   }
127   return NO;
128 }
129
130 @end /* EOOrQualifier(ContextEvaluation) */
131
132 @implementation EONotQualifier(ContextEvaluation)
133
134 - (BOOL)evaluateWithObject:(id)_object context:(id)_context {
135   return
136     [[self qualifier] evaluateWithObject:_object context:_context]
137     ? NO : YES;
138 }
139
140 @end /* EONotQualifier(ContextEvaluation) */
141
142 @implementation EOKeyValueQualifier(ContextEvaluation)
143
144 - (BOOL)evaluateWithObject:(id)_object context:(id)_context {
145   static EONull *null = nil;
146   id lv, rv;
147   union {
148     IMP  m;
149     BOOL (*unary)(id, SEL);
150     BOOL (*binary)(id, SEL, id);
151     BOOL (*ctx)(id, SEL, id, id);
152   } m;
153   SEL op;
154   
155   op = [self selector];
156   lv = [_object valueForKeyPath:[self key]];
157   rv = [self value];
158
159   if (null == nil) null = [EONull null];
160   if (lv == nil) lv = null;
161   if (rv == nil) rv = null;
162   
163   if ((m.m = [lv methodForSelector:op]) == NULL) {
164     /* no such operator method ! */
165     [lv doesNotRecognizeSelector:op];
166     return NO;
167   }
168   switch (countSelArgs(op)) {
169     case 0:
170     case 1:
171       NSLog(@"%s: called with invalid selector %@", __PRETTY_FUNCTION__,
172             NSStringFromSelector(op));
173       return NO;
174       
175     case 2:
176       return m.unary(lv, op);
177     case 3:
178       return m.binary(lv, op, rv);
179     default:
180       return m.ctx(lv, op, rv, _context);
181   }
182 }
183
184 @end /* EOKeyValueQualifier(ContextEvaluation) */
185
186 @implementation EOKeyComparisonQualifier(ContextEvaluation)
187
188 - (BOOL)evaluateWithObject:(id)_object context:(id)_context {
189   static EONull *null = nil;
190   id lv, rv;
191   union {
192     IMP  m;
193     BOOL (*unary)(id, SEL);
194     BOOL (*binary)(id, SEL, id);
195     BOOL (*ctx)(id, SEL, id, id);
196   } m;
197   SEL op;
198   
199   lv = [_object valueForKeyPath:[self leftKey]];
200   rv = [_object valueForKeyPath:[self rightKey]];
201   if (null == nil) null = [EONull null];
202   if (lv == nil) lv = null;
203   if (rv == nil) rv = null;
204
205   op = [self selector];
206   
207   if ((m.m = (void *)[lv methodForSelector:op]) == NULL) {
208     /* no such operator method ! */
209     [lv doesNotRecognizeSelector:op];
210     return NO;
211   }
212   switch (countSelArgs(op)) {
213     case 0:
214     case 1:
215       NSLog(@"%s: called with invalid selector %@", __PRETTY_FUNCTION__,
216             NSStringFromSelector(op));
217       return NO;
218       
219     case 2:
220       return m.unary(lv, op);
221     case 3:
222       return m.binary(lv, op, rv);
223     default:
224       return m.ctx(lv, op, rv, _context);
225   }
226 }
227
228 @end /* EOKeyComparisonQualifier(ContextEvaluation) */
229
230 @implementation NSObject(ImplementedQualifierComparisons2)
231
232 - (BOOL)isEqualTo:(id)_object inContext:(id)_context {
233   return [self isEqualTo:_object];
234 }
235 - (BOOL)isNotEqualTo:(id)_object inContext:(id)_context {
236   return [self isNotEqualTo:_object];
237 }
238
239 - (BOOL)isLessThan:(id)_object inContext:(id)_context {
240   return [self isLessThan:_object];
241 }
242 - (BOOL)isGreaterThan:(id)_object inContext:(id)_context {
243   return [self isGreaterThan:_object];
244 }
245 - (BOOL)isLessThanOrEqualTo:(id)_object inContext:(id)_context {
246   return [self isLessThanOrEqualTo:_object];
247 }
248 - (BOOL)isGreaterThanOrEqualTo:(id)_object inContext:(id)_context {
249   return [self isGreaterThanOrEqualTo:_object];
250 }
251
252 - (BOOL)doesContain:(id)_object inContext:(id)_context {
253   return [self doesContain:_object];
254 }
255
256 - (BOOL)isLike:(NSString *)_object inContext:(id)_context {
257   return [self isLike:_object];
258 }
259 - (BOOL)isCaseInsensitiveLike:(NSString *)_object inContext:(id)_context {
260   return [self isCaseInsensitiveLike:_object];
261 }
262
263 @end