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
22 #include "NSObject+WO.h"
26 #if APPLE_RUNTIME || NeXT_RUNTIME
27 # include <objc/objc-class.h>
30 #if NeXT_Foundation_LIBRARY || APPLE_FOUNDATION_LIBRARY || \
31 COCOA_Foundation_LIBRARY
34 @implementation NSObject(FoundationCompability)
36 - (id)copyWithZone:(NSZone *)_z {
40 @end /* NSObject(FoundationCompability) */
43 #endif /* NeXT_Foundation_LIBRARY */
45 #if GNUSTEP_BASE_LIBRARY
46 extern BOOL __objc_responds_to(id, SEL);
49 @implementation NSObject(NGObjWebKVC)
51 - (BOOL)kvcIsPreferredInKeyPath {
55 @end /* NSObject(NGObjWebKVC) */
57 @implementation NSDictionary(NGObjWebKVC)
59 - (BOOL)kvcIsPreferredInKeyPath {
63 @end /* NSDictionary(NGObjWebKVC) */
65 @implementation NSObject(Faults)
74 @end /* NSObject(Faults) */
76 // ******************** KVC methods ********************
78 static inline void _getSetSelName(register unsigned char *buf,
79 register const unsigned char *_key,
80 register unsigned _len) {
123 memcpy(&(buf[3]), _key, _len);
126 buf[3] = toupper(buf[3]);
128 buf[_len + 4] = '\0';
130 static inline SEL _getSetSel(register const unsigned char *_key,
131 register unsigned _len) {
133 _getSetSelName((unsigned char *)buf, _key, _len);
134 #if APPLE_RUNTIME || NeXT_RUNTIME
135 return sel_getUid(buf);
137 return sel_get_uid(buf);
142 IMP method; // real method or takeValue:ForKey:
143 char (*cmethod) (id, SEL);
144 unsigned char (*ucmethod)(id, SEL);
145 int (*imethod) (id, SEL);
146 unsigned int (*uimethod)(id, SEL);
147 short (*smethod) (id, SEL);
148 unsigned short (*usmethod)(id, SEL);
149 const char * (*strmethod)(id, SEL);
150 float (*fmethod)(id, SEL);
151 double (*dmethod)(id, SEL);
155 IMP method; // real method or takeValue:ForKey:
156 void (*omethod) (id, SEL, id);
157 void (*cmethod) (id, SEL, char);
158 void (*ucmethod) (id, SEL, unsigned char);
159 void (*imethod) (id, SEL, int);
160 void (*uimethod) (id, SEL, unsigned int);
161 void (*smethod) (id, SEL, short);
162 void (*usmethod) (id, SEL, unsigned short);
163 void (*strmethod)(id, SEL, const char *);
164 void (*fmethod) (id, SEL, float);
165 void (*dmethod) (id, SEL, double);
168 BOOL WOSetKVCValueUsingMethod(id object, NSString *_key, id _value) {
169 NSMethodSignature *sig = nil;
176 if (object == nil) return NO;
177 if (_key == nil) return NO;
179 keyLen = [_key cStringLength];
181 buf = malloc(keyLen + 2);
182 [_key getCString:buf];
183 setSel = _getSetSel((unsigned char *)buf, keyLen);
184 free(buf); buf = NULL;
186 if (setSel == NULL) // no such selector
189 sig = [object methodSignatureForSelector:setSel];
190 if (sig == nil) // no signature
193 sm.method = [object methodForSelector:setSel];
195 argType = [sig getArgumentTypeAtIndex:2];
200 sm.omethod(object, setSel, _value);
204 sm.cmethod(object, setSel, [(NSValue *)_value charValue]);
207 sm.ucmethod(object, setSel, [_value unsignedCharValue]);
211 sm.smethod(object, setSel, [_value shortValue]);
214 sm.usmethod(object, setSel, [_value unsignedShortValue]);
218 sm.imethod(object, setSel, [_value intValue]);
221 sm.uimethod(object, setSel, [_value unsignedIntValue]);
225 sm.fmethod(object, setSel, [_value floatValue]);
229 sm.dmethod(object, setSel, [_value doubleValue]);
234 s = NGMallocAtomic([_value cStringLength] + 1);
235 [_value getCString:s];
236 sm.strmethod(object, setSel, s);
242 NSLog(@"%s: cannot set type '%c' yet (key=%@, method=%@) ..",
244 *argType, _key, NSStringFromSelector(setSel));
245 [NSException raise:@"WORuntimeException"
246 format:@"cannot set type '%c' yet (key=%@, method=%@)",
247 *argType, _key, NSStringFromSelector(setSel)];
252 else // did not find method
256 IMP WOGetKVCGetMethod(id object, NSString *_key) {
259 if (object == nil) return NULL;
260 if (_key == nil) return NULL;
267 keyLen = [_key cStringLength];
268 buf = malloc(keyLen + 1);
269 [_key getCString:buf]; buf[keyLen] = '\0';
270 getSel = sel_get_uid(buf);
273 if (getSel == NULL) // no such selector
275 #if GNUSTEP_BASE_LIBRARY
276 if (!__objc_responds_to(object, getSel))
280 return [object methodForSelector:getSel];
283 if ((getSel = NSSelectorFromString(_key)) == NULL) // no such selector
286 if ([object respondsToSelector:getSel])
287 return [object methodForSelector:getSel];
293 id WOGetKVCValueUsingMethod(id object, NSString *_key) {
294 NSMethodSignature *sig = nil;
300 if (object == nil) return nil;
301 if (_key == nil) return nil;
304 // TODO: add support for ivars
305 keyLen = [_key cStringLength];
309 buf = malloc(keyLen + 1);
310 [_key getCString:buf];
311 #if APPLE_RUNTIME || NeXT_RUNTIME
312 getSel = sel_getUid(buf);
314 getSel = sel_get_uid(buf);
316 if (getSel == NULL) // no such selector
318 free(buf); buf = NULL;
320 #if GNUSTEP_BASE_LIBRARY
321 if (!__objc_responds_to(object, getSel))
325 gm.method = [object methodForSelector:getSel];
326 if (gm.method == NULL) // no such method
329 sig = [object methodSignatureForSelector:getSel];
330 if (sig == nil) // no signature
334 static Class NSNumberClass = Nil;
337 if (NSNumberClass == Nil)
338 NSNumberClass = [NSNumber class];
340 retType = [sig methodReturnType];
345 value = gm.method(object, getSel);
346 value = AUTORELEASE(RETAIN(value));
350 value = [NSNumberClass numberWithChar:gm.cmethod(object, getSel)];
353 value = [NSNumberClass numberWithUnsignedChar:
354 gm.ucmethod(object, getSel)];
358 value = [NSNumberClass numberWithShort:gm.smethod(object, getSel)];
361 value = [NSNumberClass numberWithUnsignedShort:
362 gm.usmethod(object, getSel)];
366 value = [NSNumberClass numberWithInt:gm.imethod(object, getSel)];
369 value = [NSNumberClass numberWithUnsignedInt:
370 gm.uimethod(object, getSel)];
374 value = [NSNumberClass numberWithFloat:gm.fmethod(object, getSel)];
377 value = [NSNumberClass numberWithDouble:gm.dmethod(object, getSel)];
381 const char *cstr = gm.strmethod(object, getSel);
382 value = cstr ? [NSString stringWithCString:cstr] : nil;
387 NSLog(@"%s: cannot get type '%c' yet (key=%@, method=%@) ..",
389 *retType, _key, NSStringFromSelector(getSel));
390 [NSException raise:@"WORuntimeException"
391 format:@"cannot get type '%c' yet (key=%@, method=%@)",
392 *retType, _key, NSStringFromSelector(getSel)];