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"
25 #if APPLE_RUNTIME || NeXT_RUNTIME
26 # include <objc/objc-class.h>
29 #if NeXT_Foundation_LIBRARY || APPLE_FOUNDATION_LIBRARY || \
30 COCOA_Foundation_LIBRARY
33 @implementation NSObject(FoundationCompability)
35 - (id)copyWithZone:(NSZone *)_z {
39 @end /* NSObject(FoundationCompability) */
42 #endif /* NeXT_Foundation_LIBRARY */
44 #if GNUSTEP_BASE_LIBRARY
45 extern BOOL __objc_responds_to(id, SEL);
48 @implementation NSObject(NGObjWebKVC)
50 - (BOOL)kvcIsPreferredInKeyPath {
54 @end /* NSObject(NGObjWebKVC) */
56 @implementation NSDictionary(NGObjWebKVC)
58 - (BOOL)kvcIsPreferredInKeyPath {
62 @end /* NSDictionary(NGObjWebKVC) */
64 @implementation NSObject(Faults)
73 @end /* NSObject(Faults) */
75 // ******************** KVC methods ********************
77 static inline void _getSetSelName(register unsigned char *buf,
78 register const unsigned char *_key,
79 register unsigned _len) {
122 memcpy(&(buf[3]), _key, _len);
125 buf[3] = toupper(buf[3]);
127 buf[_len + 4] = '\0';
129 static inline SEL _getSetSel(register const unsigned char *_key,
130 register unsigned _len) {
132 _getSetSelName(buf, _key, _len);
133 #if APPLE_RUNTIME || NeXT_RUNTIME
134 return sel_getUid(buf);
136 return sel_get_uid(buf);
141 IMP method; // real method or takeValue:ForKey:
142 char (*cmethod) (id, SEL);
143 unsigned char (*ucmethod)(id, SEL);
144 int (*imethod) (id, SEL);
145 unsigned int (*uimethod)(id, SEL);
146 short (*smethod) (id, SEL);
147 unsigned short (*usmethod)(id, SEL);
148 const char * (*strmethod)(id, SEL);
149 float (*fmethod)(id, SEL);
150 double (*dmethod)(id, SEL);
154 IMP method; // real method or takeValue:ForKey:
155 void (*omethod) (id, SEL, id);
156 void (*cmethod) (id, SEL, char);
157 void (*ucmethod) (id, SEL, unsigned char);
158 void (*imethod) (id, SEL, int);
159 void (*uimethod) (id, SEL, unsigned int);
160 void (*smethod) (id, SEL, short);
161 void (*usmethod) (id, SEL, unsigned short);
162 void (*strmethod)(id, SEL, const char *);
163 void (*fmethod) (id, SEL, float);
164 void (*dmethod) (id, SEL, double);
167 BOOL WOSetKVCValueUsingMethod(id object, NSString *_key, id _value) {
168 NSMethodSignature *sig = nil;
175 if (object == nil) return NO;
176 if (_key == nil) return NO;
178 keyLen = [_key cStringLength];
180 buf = malloc(keyLen + 2);
181 [_key getCString:buf];
182 setSel = _getSetSel(buf, keyLen);
183 free(buf); buf = NULL;
185 if (setSel == NULL) // no such selector
188 sig = [object methodSignatureForSelector:setSel];
189 if (sig == nil) // no signature
192 sm.method = [object methodForSelector:setSel];
194 argType = [sig getArgumentTypeAtIndex:2];
199 sm.omethod(object, setSel, _value);
203 sm.cmethod(object, setSel, [(NSValue *)_value charValue]);
206 sm.ucmethod(object, setSel, [_value unsignedCharValue]);
210 sm.smethod(object, setSel, [_value shortValue]);
213 sm.usmethod(object, setSel, [_value unsignedShortValue]);
217 sm.imethod(object, setSel, [_value intValue]);
220 sm.uimethod(object, setSel, [_value unsignedIntValue]);
224 sm.fmethod(object, setSel, [_value floatValue]);
228 sm.dmethod(object, setSel, [_value doubleValue]);
233 s = NGMallocAtomic([_value cStringLength] + 1);
234 [_value getCString:s];
235 sm.strmethod(object, setSel, s);
241 NSLog(@"%s: cannot set type '%c' yet (key=%@, method=%@) ..",
243 *argType, _key, NSStringFromSelector(setSel));
244 [NSException raise:@"WORuntimeException"
245 format:@"cannot set type '%c' yet (key=%@, method=%@)",
246 *argType, _key, NSStringFromSelector(setSel)];
251 else // did not find method
255 IMP WOGetKVCGetMethod(id object, NSString *_key) {
258 if (object == nil) return NULL;
259 if (_key == nil) return NULL;
266 keyLen = [_key cStringLength];
267 buf = malloc(keyLen + 1);
268 [_key getCString:buf]; buf[keyLen] = '\0';
269 getSel = sel_get_uid(buf);
272 if (getSel == NULL) // no such selector
274 #if GNUSTEP_BASE_LIBRARY
275 if (!__objc_responds_to(object, getSel))
279 return [object methodForSelector:getSel];
282 if ((getSel = NSSelectorFromString(_key)) == NULL) // no such selector
285 if ([object respondsToSelector:getSel])
286 return [object methodForSelector:getSel];
292 id WOGetKVCValueUsingMethod(id object, NSString *_key) {
293 NSMethodSignature *sig = nil;
299 if (object == nil) return nil;
300 if (_key == nil) return nil;
303 // TODO: add support for ivars
304 keyLen = [_key cStringLength];
308 buf = malloc(keyLen + 1);
309 [_key getCString:buf];
310 #if APPLE_RUNTIME || NeXT_RUNTIME
311 getSel = sel_getUid(buf);
313 getSel = sel_get_uid(buf);
315 if (getSel == NULL) // no such selector
317 free(buf); buf = NULL;
319 #if GNUSTEP_BASE_LIBRARY
320 if (!__objc_responds_to(object, getSel))
324 gm.method = [object methodForSelector:getSel];
325 if (gm.method == NULL) // no such method
328 sig = [object methodSignatureForSelector:getSel];
329 if (sig == nil) // no signature
333 static Class NSNumberClass = Nil;
336 if (NSNumberClass == Nil)
337 NSNumberClass = [NSNumber class];
339 retType = [sig methodReturnType];
344 value = gm.method(object, getSel);
345 value = AUTORELEASE(RETAIN(value));
349 value = [NSNumberClass numberWithChar:gm.cmethod(object, getSel)];
352 value = [NSNumberClass numberWithUnsignedChar:
353 gm.ucmethod(object, getSel)];
357 value = [NSNumberClass numberWithShort:gm.smethod(object, getSel)];
360 value = [NSNumberClass numberWithUnsignedShort:
361 gm.usmethod(object, getSel)];
365 value = [NSNumberClass numberWithInt:gm.imethod(object, getSel)];
368 value = [NSNumberClass numberWithUnsignedInt:
369 gm.uimethod(object, getSel)];
373 value = [NSNumberClass numberWithFloat:gm.fmethod(object, getSel)];
376 value = [NSNumberClass numberWithDouble:gm.dmethod(object, getSel)];
380 const char *cstr = gm.strmethod(object, getSel);
381 value = cstr ? [NSString stringWithCString:cstr] : nil;
386 NSLog(@"%s: cannot get type '%c' yet (key=%@, method=%@) ..",
388 *retType, _key, NSStringFromSelector(getSel));
389 [NSException raise:@"WORuntimeException"
390 format:@"cannot get type '%c' yet (key=%@, method=%@)",
391 *retType, _key, NSStringFromSelector(getSel)];