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