diff --git a/ChangeLog b/ChangeLog index d60d40648..1ed653368 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-08-19 Richard Frith-Macdonald + + * Source/NSProxy.m: Documented all methods and corrected implementation + of some introspection methods. + 2002-08-16 Richard Frith-Macdonald * Source/Base.gsdoc: Moved to Documentation. diff --git a/Headers/gnustep/base/NSProxy.h b/Headers/gnustep/base/NSProxy.h index e8f6a9014..feb9c4879 100644 --- a/Headers/gnustep/base/NSProxy.h +++ b/Headers/gnustep/base/NSProxy.h @@ -36,19 +36,38 @@ + (id) alloc; + (id) allocWithZone: (NSZone*)z; ++ (id) autorelease; + (Class) class; ++ (NSString*) description; ++ (BOOL) isKindOfClass: (Class)aClass; ++ (BOOL) isMemberOfClass: (Class)aClass; + (void) load; ++ (void) release; + (BOOL) respondsToSelector: (SEL)aSelector; ++ (id) retain; ++ (unsigned int) retainCount; +- (id) autorelease; +- (Class) class; +- (BOOL) conformsToProtocol: (Protocol*)aProtocol; - (void) dealloc; - (NSString*) description; - (void) forwardInvocation: (NSInvocation*)anInvocation; -- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector; - -@end - -@interface Object (IsProxy) +- (unsigned int) hash; +- (id) init; +- (BOOL) isEqual: (id)anObject; +- (BOOL) isKindOfClass: (Class)aClass; +- (BOOL) isMemberOfClass: (Class)aClass; - (BOOL) isProxy; +- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector; +- (void) release; +- (BOOL) respondsToSelector: (SEL)aSelector; +- (id) retain; +- (unsigned int) retainCount; +- (id) self; +- (Class) superclass; +- (NSZone*) zone; + @end #endif /* __NSProxy_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Source/NSObject.m b/Source/NSObject.m index 11ba0838a..bf55e5aae 100644 --- a/Source/NSObject.m +++ b/Source/NSObject.m @@ -1935,6 +1935,10 @@ _fastMallocBuffer(unsigned size) return [NSString stringWithFormat: @"<%s: %lx>", object_get_class_name(self), (unsigned long)self]; } +- (BOOL) isProxy +{ + return NO; +} - (void) release { return; diff --git a/Source/NSProxy.m b/Source/NSProxy.m index 40a6a582a..a0980dd63 100644 --- a/Source/NSProxy.m +++ b/Source/NSProxy.m @@ -38,39 +38,84 @@ extern BOOL __objc_responds_to(id, SEL); #endif +/** + * The NSProxy class provides a basic implementation of a class whose + * instances are used to stand in for other objects.
+ * The class provides the most basic methods of NSObject, and expects + * messages for other methods to be forwarded to the real + * object represented by the proxy. You must subclass NSProxy to + * implement -forwardInvocation: to these real objects. + */ @implementation NSProxy +/** + * Allocates and returns an NSProxy instance in the default zone. + */ + (id) alloc { return [self allocWithZone: NSDefaultMallocZone()]; } +/** + * Allocates and returns an NSProxy instance in the specified zone z. + */ + (id) allocWithZone: (NSZone*)z { NSProxy* ob = (NSProxy*) NSAllocateObject(self, 0, z); return ob; } +/** + * Returns the receiver + */ + (id) autorelease { return self; } +/** + * Returns the receiver + */ + (Class) class { return self; } +/** + * Returns a string describing the receiver. + */ + (NSString*) description { return [NSString stringWithFormat: @"<%s>", object_get_class_name(self)]; } +/** + * Returns NO ... the NSProxy class cannot be an instance of any class. + */ ++ (BOOL) isKindOfClass: (Class)aClass +{ + return NO; +} + +/** + * Returns YES if aClass is identical to the receiver, NO otherwise. + */ ++ (BOOL) isMemberOfClass: (Class)aClass +{ + return(self == aClass); +} + +/** + * A dummy method ... + */ + (void) load { /* Do nothing */ } +/** + * Returns the method signature for the specified selector. + */ + (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector { struct objc_method *mth; @@ -92,11 +137,17 @@ extern BOOL __objc_responds_to(id, SEL); return nil; } +/** + * A dummy method to ensure that the class can safely be held in containers. + */ + (void) release { /* Do nothing */ } +/** + * Returns YES if the receiver responds to aSelector, NO otherwise. + */ + (BOOL) respondsToSelector: (SEL)aSelector { if (__objc_responds_to(self, aSelector)) @@ -105,16 +156,33 @@ extern BOOL __objc_responds_to(id, SEL); return NO; } +/** + * Returns the receiver. + */ + (id) retain { return self; } +/** + * Returns the maximum unsigned integer value. + */ ++ (unsigned int) retainCount +{ + return UINT_MAX; +} + +/** + * Returns the superclass of the receiver + */ + (Class) superclass { return class_get_super_class (self); } +/** + * Adds the receiver to the current autorelease pool and returns self. + */ - (id) autorelease { #if GS_WITH_GC == 0 @@ -123,30 +191,54 @@ extern BOOL __objc_responds_to(id, SEL); return self; } +/** + * Returns the class of the receiver. + */ - (Class) class { return object_get_class(self); } +/** + * Calls the -forwardInvocation: method to determine if the 'real' object + * referred to by the proxy conforms to aProtocol. Returns the result.
+ * NB. The default operation of -forwardInvocation: is to raise an exception. + */ - (BOOL) conformsToProtocol: (Protocol*)aProtocol { - [NSException raise: NSGenericException - format: @"subclass %s should override %s", object_get_class_name(self), - sel_get_name(_cmd)]; - return NO; + NSMethodSignature *sig; + NSInvocation *inv; + BOOL ret; + + sig = [self methodSignatureForSelector: _cmd]; + inv = [NSInvocation invocationWithMethodSignature: sig]; + [inv setSelector: _cmd]; + [inv setArgument: &aProtocol atIndex: 2]; + [self forwardInvocation: inv]; + [inv getReturnValue: &ret]; + return ret; } +/** + * Frees the memory used by the receiver. + */ - (void) dealloc { NSDeallocateObject((NSObject*)self); } +/** + * Returns a text descrioption of the receiver. + */ - (NSString*) description { return [NSString stringWithFormat: @"<%s %lx>", object_get_class_name(self), (unsigned long)self]; } +/** + * Calls the -forwardInvocation: method and returns the result. + */ - (retval_t) forward:(SEL)aSel :(arglist_t)argFrame { NSInvocation *inv; @@ -157,6 +249,9 @@ extern BOOL __objc_responds_to(id, SEL); return [inv returnFrame: argFrame]; } +/** + * Raises an NSInvalidArgumentException + */ - (void) forwardInvocation: (NSInvocation*)anInvocation { [NSException raise: NSInvalidArgumentException @@ -164,11 +259,17 @@ extern BOOL __objc_responds_to(id, SEL); sel_get_name(_cmd)]; } +/** + * Returns the address of the receiver ... so it can be stored in a dictionary. + */ - (unsigned int) hash { return (unsigned int)self; } +/** + * Initialises the receiver and returns the resulting instance. + */ - (id) init { [NSException raise: NSGenericException @@ -177,41 +278,59 @@ extern BOOL __objc_responds_to(id, SEL); return self; } +/** + * Tests for pointer equality with anObject + */ - (BOOL) isEqual: (id)anObject { return (self == anObject); } -+ (BOOL) isKindOfClass: (Class)aClass -{ - return NO; -} - +/** + * Calls the -forwardInvocation: method to determine if the 'real' object + * referred to by the proxy is an instance of the specified class. + * Returns the result.
+ * NB. The default operation of -forwardInvocation: is to raise an exception. + */ - (BOOL) isKindOfClass: (Class)aClass { - Class class = self->isa; + NSMethodSignature *sig; + NSInvocation *inv; + BOOL ret; - while (class != nil) - { - if (class == aClass) - { - return YES; - } - class = class_get_super_class(class); - } - return NO; -} - -+ (BOOL) isMemberOfClass: (Class)aClass -{ - return(self == aClass); + sig = [self methodSignatureForSelector: _cmd]; + inv = [NSInvocation invocationWithMethodSignature: sig]; + [inv setSelector: _cmd]; + [inv setArgument: &aClass atIndex: 2]; + [self forwardInvocation: inv]; + [inv getReturnValue: &ret]; + return ret; } +/** + * Calls the -forwardInvocation: method to determine if the 'real' object + * referred to by the proxy is an instance of the specified class. + * Returns the result.
+ * NB. The default operation of -forwardInvocation: is to raise an exception. + */ - (BOOL) isMemberOfClass: (Class)aClass { - return(self->isa == aClass); + NSMethodSignature *sig; + NSInvocation *inv; + BOOL ret; + + sig = [self methodSignatureForSelector: _cmd]; + inv = [NSInvocation invocationWithMethodSignature: sig]; + [inv setSelector: _cmd]; + [inv setArgument: &aClass atIndex: 2]; + [self forwardInvocation: inv]; + [inv getReturnValue: &ret]; + return ret; } +/** + * Returns YES + */ - (BOOL) isProxy { return YES; @@ -224,7 +343,7 @@ extern BOOL __objc_responds_to(id, SEL); return self; } -/* +/** * If we respond to the method directly, create and return a method * signature. Otherwise raise an exception. */ @@ -296,17 +415,25 @@ extern BOOL __objc_responds_to(id, SEL); return (*msg)(self, aSelector, anObject, anotherObject); } +/** + * Decrement the retain count for the receiver ... deallocate if it would + * become negative. + */ - (void) release { #if GS_WITH_GC == 0 - if (_retain_count-- == 0) + if (_retain_count == 0) { [self dealloc]; } + else + { + _retain_count--; + } #endif } -/* +/** * If we respond to the method directly, return YES, otherwise * forward this request to the object we are acting as a proxy for. */ @@ -336,6 +463,9 @@ extern BOOL __objc_responds_to(id, SEL); } } +/** + * Increment the retain count for the receiver. + */ - (id) retain { #if GS_WITH_GC == 0 @@ -344,26 +474,33 @@ extern BOOL __objc_responds_to(id, SEL); return self; } +/** + * Return the retain count for the receiver. + */ - (unsigned int) retainCount { return _retain_count + 1; } -+ (unsigned) retainCount -{ - return UINT_MAX; -} - +/** + * Returns the receiver. + */ - (id) self { return self; } +/** + * Returns the superclass of the receivers class. + */ - (Class) superclass { return object_get_super_class(self); } +/** + * Returns the zone in which the receiver was allocated. + */ - (NSZone*) zone { return NSZoneFromPointer(self);