4 Copyright (C) 1996 Free Software Foundation, Inc.
6 Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
9 This file is part of the GNUstep Database Library.
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
21 You should have received a copy of the GNU Library General Public
22 License along with this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 // $Id: EOFault.m 1 2004-08-20 10:38:46Z znek $
30 #include "EOFaultHandler.h"
33 #if NeXT_RUNTIME || APPLE_RUNTIME
34 # include <objc/objc-class.h>
42 # define object_is_instance(object) \
43 ((object!=nil)&&CLS_ISCLASS(((my_objc_object)object)->isa))
45 # warning TODO: implement for NeXT/Apple runtime!
46 # define object_is_instance(object) (object!=nil?YES:NO)
54 @implementation EOFault
56 + (void)makeObjectIntoFault:(id)_object withHandler:(EOFaultHandler *)_handler {
57 [_handler setTargetClass:[_object class] extraData:((id *)_object)[1]];
59 ((EOFault *)_object)->isa = self;
60 ((EOFault *)_object)->faultResolver = [_handler retain];
63 + (EOFaultHandler *)handlerForFault:(id)_fault {
64 if (![self isFault:_fault])
67 return ((EOFault *)_fault)->faultResolver;
70 /* Fault class methods */
72 + (void)clearFault:(id)fault {
73 EOFault *aFault = (EOFault*)fault;
77 if (aFault->isa != self)
80 /* get fault instance reference count + 1 set in creation methods */
81 refs = aFault->faultResolver->faultReferences;
83 /* make clear instance */
84 aFault->isa = [aFault->faultResolver targetClass];
85 aFault->faultResolver = [aFault->faultResolver autorelease];
86 aFault->faultResolver = [aFault->faultResolver extraData];
89 set references to real instance so that
90 re-implemented retain/release mechanism take control
96 + (BOOL)isFault:(id)fault {
97 static Class EOFaultClass = Nil;
100 if (fault == nil) return NO;
101 if (EOFaultClass == Nil) EOFaultClass = [EOFault class];
103 for (clazz = ((EOFault *)fault)->isa; clazz; clazz = clazz->super_class) {
104 if (clazz == EOFaultClass)
110 return NO; // no class faults
116 + (Class)targetClassForFault:(id)_fault {
117 EOFault *aFault = (EOFault*)_fault;
119 // Check that argument is fault
120 if (aFault->isa != self)
123 return [aFault->faultResolver targetClass];
126 // Fault Instance methods
128 - (Class)superclass {
130 return (object_is_instance(self))
131 ? [[self->faultResolver classForFault:self] superclass]
132 : class_get_super_class((Class)self);
134 # warning TODO: add complete implementation for NeXT/Apple runtime!
135 return [[self->faultResolver classForFault:self] superclass];
143 return [self->faultResolver classForFault:self];
146 - (BOOL)isKindOfClass:(Class)_class; {
147 return [self->faultResolver isKindOfClass:_class forFault:self];
149 - (BOOL)isMemberOfClass:(Class)_class {
150 return [self->faultResolver isMemberOfClass:_class forFault:self];
153 - (BOOL)conformsToProtocol:(Protocol *)_protocol {
154 return [self->faultResolver conformsToProtocol:_protocol forFault:self];
157 + (BOOL)respondsToSelector:(SEL)_selector {
159 return class_get_instance_method(self, _selector) != NULL;
161 # warning TODO: add complete implementation for Apple/NeXT runtime!
166 - (BOOL)respondsToSelector:(SEL)_selector {
168 return (object_is_instance(self))
169 ? [self->faultResolver respondsToSelector:_selector forFault:self]
170 : class_get_class_method(self->isa, _selector) != METHOD_NULL;
172 # warning TODO: add complete implementation for Apple/NeXT runtime!
173 return [self->faultResolver respondsToSelector:_selector forFault:self];
177 // ******************** retain counting ********************
183 self->faultResolver->faultReferences++;
187 + (oneway void)release {
189 - (oneway void)release {
190 if (faultResolver->faultReferences <= 0)
193 faultResolver->faultReferences--;
196 + (unsigned)retainCount {
199 - (unsigned)retainCount {
201 return faultResolver->faultReferences+1;
208 [NSAutoreleasePool addObject:self];
213 return NSZoneFromPointer(self);
219 - (BOOL)isGarbageCollectable {
224 NSLog(@"WARNING: tried to deallocate EOFault class ..");
227 [self->isa clearFault:self];
233 - (NSString *)description {
234 return [self->faultResolver descriptionForObject:self];
236 - (NSString *)descriptionWithIndent:(unsigned)level {
237 return [self description];
239 - (NSString *)stringRepresentation {
240 return [self description];
242 - (NSString *)eoShallowDescription {
243 return [self description];
246 - (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
249 return [self description];
252 /* Forwarding stuff */
256 Must be here as initialize is called for each root class
257 without asking if it responds to it !
261 static inline void _resolveFault(EOFault *self) {
262 EOFaultHandler *handler;
265 if (!object_is_instance(self)) {
266 [NSException raise:@"NSInvalidArgumentException"
267 format:@"used EOFault class in forward"];
270 handler = self->faultResolver;
271 [handler completeInitializationOfObject:self];
273 if (self->isa == [EOFault class]) {
274 [NSException raise:@"NSInvalidArgumentException"
276 @"fault error: %@ was not cleared during fault fetching",
277 [handler descriptionForObject:self]];
288 - (void)setObject:(id)object forKey:(id)key {
290 [self setObject:object forKey:key];
292 - (id)objectForKey:(id)key {
294 return [self objectForKey:key];
296 - (void)removeObjectForKey:(id)key {
298 [self removeObjectForKey:key];
301 - (void)takeValuesFromDictionary:(NSDictionary *)dictionary {
303 [self takeValuesFromDictionary:dictionary];
305 - (NSDictionary *)valuesForKeys:(NSArray *)keys {
307 return [self valuesForKeys:keys];
309 - (BOOL)takeValue:(id)object forKey:(id)key {
311 return [self takeValue:object forKey:key];
313 - (id)valueForKey:(id)key {
315 return [self valueForKey:key];
318 - (BOOL)kvcIsPreferredInKeyPath {
325 - (NSMethodSignature *)methodSignatureForSelector:(SEL)_sel {
326 return [self->faultResolver methodSignatureForSelector:_sel forFault:self];
329 - (void)forwardInvocation:(NSInvocation *)_invocation {
330 if ([self->faultResolver shouldPerformInvocation:_invocation]) {
332 [_invocation invoke];
338 @implementation EOFault(RealForwarding)
340 #if NeXT_Foundation_LIBRARY
342 - (void)forwardInvocation:(NSInvocation *)_inv {
345 [_inv setTarget:self];
351 - (retval_t)forward:(SEL)sel:(arglist_t)args {
352 #if 1 && !defined(__APPLE__)
355 forward = class_get_instance_method(objc_lookup_class("NSObject"), _cmd);
356 return ((retval_t (*)(id, SEL, SEL, arglist_t))forward->method_imp)
357 (self, _cmd, sel, args);
359 struct objc_method *m;
363 if ((m = class_get_instance_method(self->isa, sel)) == NULL) {
366 r = [NSString stringWithFormat:
367 @"fault error: resolved fault does not responds to selector %s",
369 [NSException raise:@"NSInvalidArgumentException" reason:r userInfo:nil];
371 return objc_msg_sendv(self, sel, args);
376 @end /* EOFault(RealForwarding) */