1995-01-26 17:55:52 +00:00
|
|
|
|
/* Implementation of NSObject for GNUStep
|
1996-01-26 19:18:08 +00:00
|
|
|
|
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
1995-01-26 17:55:52 +00:00
|
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1995-01-26 17:55:52 +00:00
|
|
|
|
Date: August 1994
|
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
1995-01-26 17:55:52 +00:00
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
1996-04-17 15:34:35 +00:00
|
|
|
|
#include <gnustep/base/preface.h>
|
1995-03-12 15:40:22 +00:00
|
|
|
|
#include <stdarg.h>
|
1995-04-17 21:13:20 +00:00
|
|
|
|
#include <Foundation/NSObject.h>
|
1995-03-23 03:31:30 +00:00
|
|
|
|
#include <objc/Protocol.h>
|
|
|
|
|
#include <objc/objc-api.h>
|
1995-04-17 21:13:20 +00:00
|
|
|
|
#include <Foundation/NSMethodSignature.h>
|
|
|
|
|
#include <Foundation/NSInvocation.h>
|
|
|
|
|
#include <Foundation/NSAutoreleasePool.h>
|
1995-08-24 22:24:17 +00:00
|
|
|
|
#include <Foundation/NSString.h>
|
1996-02-22 23:12:19 +00:00
|
|
|
|
#include <Foundation/NSMapTable.h>
|
1996-03-26 20:59:42 +00:00
|
|
|
|
#include <Foundation/NSException.h>
|
1995-04-05 01:54:16 +00:00
|
|
|
|
#include <limits.h>
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
|
|
|
|
extern void (*_objc_error)(id object, const char *format, va_list);
|
|
|
|
|
|
1996-05-31 14:23:23 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
/* Reference count management */
|
|
|
|
|
|
|
|
|
|
/* Doesn't handle multi-threaded stuff.
|
|
|
|
|
Doesn't handle exceptions. */
|
|
|
|
|
|
|
|
|
|
/* The hashtable of retain counts on objects */
|
1996-02-22 23:12:19 +00:00
|
|
|
|
static NSMapTable *retain_counts = NULL;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
|
|
|
|
/* The Class responsible for handling autorelease's */
|
1995-03-12 19:29:37 +00:00
|
|
|
|
static id autorelease_class = nil;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
1995-08-04 20:52:07 +00:00
|
|
|
|
/* When this is `YES', every call to release/autorelease, checks to make sure
|
|
|
|
|
isn't being set up to release itself too many times. */
|
|
|
|
|
static BOOL double_release_check_enabled = NO;
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
BOOL NSShouldRetainWithZone(NSObject *anObject, NSZone *requestedZone)
|
|
|
|
|
{
|
|
|
|
|
if (!requestedZone || [anObject zone] == requestedZone)
|
|
|
|
|
return YES;
|
|
|
|
|
else
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
1996-02-22 23:12:19 +00:00
|
|
|
|
void NSIncrementExtraRefCount (id anObject)
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1996-02-22 23:12:19 +00:00
|
|
|
|
unsigned c = (unsigned) NSMapGet (retain_counts, anObject);
|
|
|
|
|
NSMapInsert (retain_counts, anObject, (void*)c+1);
|
|
|
|
|
|
|
|
|
|
/* xxx Make this more efficient like it was before: */
|
|
|
|
|
#if 0
|
1995-03-12 15:40:22 +00:00
|
|
|
|
coll_node_ptr n;
|
|
|
|
|
|
|
|
|
|
n = coll_hash_node_for_key(retain_counts, anObject);
|
|
|
|
|
if (n)
|
|
|
|
|
(n->value.unsigned_int_u)++;
|
|
|
|
|
else
|
|
|
|
|
coll_hash_add(&retain_counts, anObject, (unsigned)1);
|
1996-02-22 23:12:19 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-02-22 23:12:19 +00:00
|
|
|
|
BOOL NSDecrementExtraRefCountWasZero (id anObject)
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1996-02-22 23:12:19 +00:00
|
|
|
|
unsigned c = (unsigned) NSMapGet (retain_counts, anObject);
|
|
|
|
|
|
|
|
|
|
if (!c)
|
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
|
|
c--;
|
|
|
|
|
if (c)
|
|
|
|
|
NSMapInsert (retain_counts, anObject, (void*)c);
|
|
|
|
|
else
|
|
|
|
|
NSMapRemove (retain_counts, anObject);
|
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
|
|
/* xxx Make this more efficient like it was before: */
|
|
|
|
|
#if 0
|
1995-03-12 15:40:22 +00:00
|
|
|
|
coll_node_ptr n;
|
|
|
|
|
|
|
|
|
|
n = coll_hash_node_for_key(retain_counts, anObject);
|
1995-06-28 22:56:42 +00:00
|
|
|
|
if (!n) return wasZero;
|
|
|
|
|
if (n->value.unsigned_int_u) wasZero = NO;
|
|
|
|
|
if (!--n->value.unsigned_int_u)
|
|
|
|
|
coll_hash_remove(retain_counts, anObject);
|
|
|
|
|
return wasZero;
|
1996-02-22 23:12:19 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
|
|
|
|
|
@implementation NSObject
|
|
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (self == [NSObject class])
|
|
|
|
|
{
|
1996-03-22 13:39:01 +00:00
|
|
|
|
retain_counts = NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
1996-02-22 23:12:19 +00:00
|
|
|
|
NSIntMapValueCallBacks, 64);
|
1995-09-27 23:15:24 +00:00
|
|
|
|
autorelease_class = [NSAutoreleasePool class];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) alloc
|
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self allocWithZone:NS_NOZONE];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
|
|
|
|
{
|
1996-01-26 19:18:08 +00:00
|
|
|
|
return NSAllocateObject (self, 0, z);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) new
|
|
|
|
|
{
|
|
|
|
|
return [[self alloc] init];
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- copyWithZone:(NSZone *)zone;
|
|
|
|
|
{
|
1996-01-26 19:18:08 +00:00
|
|
|
|
return NSCopyObject (self, 0, zone);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (id) copy
|
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self copyWithZone: NS_NOZONE];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
1996-01-26 19:18:08 +00:00
|
|
|
|
NSDeallocateObject (self);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-01-26 17:55:52 +00:00
|
|
|
|
- free
|
|
|
|
|
{
|
1996-03-26 19:35:47 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Use `dealloc' instead of `free'."];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (id) init
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- mutableCopyWithZone:(NSZone *)zone
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self copyWithZone:zone];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (id) mutableCopy
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self mutableCopyWithZone: NS_NOZONE];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-01 20:21:53 +00:00
|
|
|
|
+ (Class) superclass
|
|
|
|
|
{
|
1996-01-26 19:18:08 +00:00
|
|
|
|
return class_get_super_class (self);
|
1995-04-01 20:21:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (Class) superclass
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1996-01-26 19:18:08 +00:00
|
|
|
|
return object_get_super_class (self);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (BOOL) instancesRespondToSelector: (SEL)aSelector
|
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (class_get_instance_method(self, aSelector) != METHOD_NULL);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-27 17:25:42 +00:00
|
|
|
|
+ (BOOL) conformsToProtocol: (Protocol*)aProtocol
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
struct objc_protocol_list* proto_list;
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
for (proto_list = ((struct objc_class*)self)->class_pointer->protocols;
|
1996-05-31 15:13:58 +00:00
|
|
|
|
proto_list; proto_list = proto_list_>next)
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1996-05-31 15:13:58 +00:00
|
|
|
|
for (i=0; i < proto_list_>count; i++)
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1995-04-01 17:48:49 +00:00
|
|
|
|
/* xxx We should add conformsToProtocol to Protocol class. */
|
1996-05-31 15:13:58 +00:00
|
|
|
|
if ([proto_list_>list[i] conformsTo: aProtocol])
|
1994-11-08 16:44:01 +00:00
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if ([self superclass])
|
|
|
|
|
return [[self superclass] conformsToProtocol: aProtocol];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
else
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-27 17:25:42 +00:00
|
|
|
|
- (BOOL) conformsToProtocol: (Protocol*)aProtocol
|
|
|
|
|
{
|
|
|
|
|
return [[self class] conformsToProtocol:aProtocol];
|
|
|
|
|
}
|
|
|
|
|
|
1994-11-08 16:44:01 +00:00
|
|
|
|
+ (IMP) instanceMethodForSelector: (SEL)aSelector
|
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return method_get_imp(class_get_instance_method(self, aSelector));
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (IMP) methodForSelector: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
return (method_get_imp(object_is_instance(self)
|
1995-03-12 15:40:22 +00:00
|
|
|
|
?class_get_instance_method(self->isa, aSelector)
|
|
|
|
|
:class_get_class_method(self->isa, aSelector)));
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (NSString*) description
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-08-24 22:24:17 +00:00
|
|
|
|
return [NSString stringWithCString: object_get_class_name(self)];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1994-11-08 16:44:01 +00:00
|
|
|
|
+ (NSString*) description
|
|
|
|
|
{
|
1995-08-24 22:24:17 +00:00
|
|
|
|
return [NSString stringWithCString: class_get_class_name(self)];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
+ (void) poseAsClass: (Class)aClassObject
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
class_pose_as(self, aClassObject);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) doesNotRecognizeSelector: (SEL)aSelector
|
|
|
|
|
{
|
1996-03-26 19:35:47 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"%s does not recognize %s",
|
|
|
|
|
object_get_class_name(self), sel_get_name(aSelector)];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (retval_t) forward:(SEL)aSel :(arglist_t)argFrame
|
|
|
|
|
{
|
1995-03-12 19:29:37 +00:00
|
|
|
|
#if 1
|
|
|
|
|
[self doesNotRecognizeSelector:aSel];
|
|
|
|
|
return NULL;
|
|
|
|
|
#else
|
1994-11-08 16:44:01 +00:00
|
|
|
|
void *retFrame;
|
|
|
|
|
NSMethodSignature *ms = [self methodSignatureForSelector:aSel];
|
|
|
|
|
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:ms
|
|
|
|
|
frame:argFrame];
|
|
|
|
|
/* is this right? */
|
1995-03-12 19:29:37 +00:00
|
|
|
|
retFrame = (void*) alloca([ms methodReturnLength]);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
[self forwardInvocation:inv];
|
|
|
|
|
[inv getReturnValue:retFrame];
|
|
|
|
|
/* where do ms and inv get free'd? */
|
|
|
|
|
return retFrame;
|
1995-03-12 19:29:37 +00:00
|
|
|
|
#endif
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) forwardInvocation: (NSInvocation*)anInvocation
|
|
|
|
|
{
|
|
|
|
|
[self doesNotRecognizeSelector:[anInvocation selector]];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1995-01-26 17:55:52 +00:00
|
|
|
|
- (id) awakeAfterUsingCoder: (NSCoder*)aDecoder
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (Class) classForCoder
|
|
|
|
|
{
|
|
|
|
|
return [self class];
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (id) replacementObjectForCoder: (NSCoder*)anEncoder
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1996-01-26 19:18:08 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
/* NSObject protocol */
|
|
|
|
|
|
|
|
|
|
- autorelease
|
|
|
|
|
{
|
1995-08-04 20:52:07 +00:00
|
|
|
|
if (double_release_check_enabled)
|
|
|
|
|
{
|
|
|
|
|
unsigned release_count;
|
|
|
|
|
unsigned retain_count = [self retainCount];
|
|
|
|
|
release_count = [autorelease_class autoreleaseCountForObject:self];
|
|
|
|
|
if (release_count > retain_count)
|
1996-03-26 19:35:47 +00:00
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"Autorelease would release object too many times.\n"
|
1996-03-26 20:59:42 +00:00
|
|
|
|
@"%d release(s) versus %d retain(s)", release_count, retain_count];
|
1995-08-04 20:52:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
[autorelease_class addObject:self];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-05 01:54:16 +00:00
|
|
|
|
+ autorelease
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (Class) class
|
|
|
|
|
{
|
1995-03-23 03:31:30 +00:00
|
|
|
|
return object_get_class(self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned) hash
|
|
|
|
|
{
|
|
|
|
|
return (unsigned)self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) isEqual: anObject
|
|
|
|
|
{
|
|
|
|
|
return (self == anObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) isKindOfClass: (Class)aClass
|
|
|
|
|
{
|
|
|
|
|
Class class;
|
|
|
|
|
|
|
|
|
|
for (class = self->isa; class!=Nil; class = class_get_super_class(class))
|
|
|
|
|
if (class==aClass)
|
|
|
|
|
return YES;
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) isMemberOfClass: (Class)aClass
|
|
|
|
|
{
|
|
|
|
|
return self->isa==aClass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) isProxy
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- perform: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
IMP msg = objc_msg_lookup(self, aSelector);
|
|
|
|
|
if (!msg)
|
1996-03-26 20:59:42 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"invalid selector passed to %s", sel_get_name(_cmd)];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (*msg)(self, aSelector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- perform: (SEL)aSelector withObject: anObject
|
|
|
|
|
{
|
|
|
|
|
IMP msg = objc_msg_lookup(self, aSelector);
|
|
|
|
|
if (!msg)
|
1996-03-26 20:59:42 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"invalid selector passed to %s", sel_get_name(_cmd)];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (*msg)(self, aSelector, anObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- perform: (SEL)aSelector withObject: object1 withObject: object2
|
|
|
|
|
{
|
|
|
|
|
IMP msg = objc_msg_lookup(self, aSelector);
|
|
|
|
|
if (!msg)
|
1996-03-26 20:59:42 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"invalid selector passed to %s", sel_get_name(_cmd)];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (*msg)(self, aSelector, object1, object2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (oneway void) release
|
|
|
|
|
{
|
1995-08-04 20:52:07 +00:00
|
|
|
|
if (double_release_check_enabled)
|
|
|
|
|
{
|
|
|
|
|
unsigned release_count;
|
|
|
|
|
unsigned retain_count = [self retainCount];
|
|
|
|
|
release_count = [autorelease_class autoreleaseCountForObject:self];
|
|
|
|
|
if (release_count > retain_count)
|
1996-03-26 19:35:47 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Release would release object too many times."];
|
1995-08-04 20:52:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (NSDecrementExtraRefCountWasZero(self))
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-05 01:54:16 +00:00
|
|
|
|
+ (oneway void) release
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL) respondsToSelector: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
return ((object_is_instance(self)
|
|
|
|
|
?class_get_instance_method(self->isa, aSelector)
|
|
|
|
|
:class_get_class_method(self->isa, aSelector))!=METHOD_NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- retain
|
|
|
|
|
{
|
1995-03-24 20:09:36 +00:00
|
|
|
|
NSIncrementExtraRefCount(self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-05 01:54:16 +00:00
|
|
|
|
+ retain
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (unsigned) retainCount
|
|
|
|
|
{
|
1996-02-22 23:12:19 +00:00
|
|
|
|
return (unsigned) NSMapGet (retain_counts, self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-05 01:54:16 +00:00
|
|
|
|
+ (unsigned) retainCount
|
|
|
|
|
{
|
|
|
|
|
return UINT_MAX;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- self
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSZone *)zone
|
|
|
|
|
{
|
1995-03-18 16:58:29 +00:00
|
|
|
|
return NSZoneFromPtr(self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-09 01:53:53 +00:00
|
|
|
|
#if 1 /* waiting until I resolve type conflict with GNU Coding method */
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
1995-03-23 03:31:30 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
1995-04-09 01:53:53 +00:00
|
|
|
|
- initWithCoder: (NSCoder*)aDecoder
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
@implementation NSObject (NEXTSTEP)
|
|
|
|
|
|
|
|
|
|
/* NEXTSTEP Object class compatibility */
|
|
|
|
|
|
|
|
|
|
- error:(const char *)aString, ...
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
#define FMT "error: %s (%s)\n%s\n"
|
|
|
|
|
char fmt[(strlen((char*)FMT)+strlen((char*)object_get_class_name(self))
|
|
|
|
|
+((aString!=NULL)?strlen((char*)aString):0)+8)];
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
sprintf(fmt, FMT, object_get_class_name(self),
|
|
|
|
|
object_is_instance(self)?"instance":"class",
|
|
|
|
|
(aString!=NULL)?aString:"");
|
|
|
|
|
va_start(ap, aString);
|
|
|
|
|
(*_objc_error)(self, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
return nil;
|
|
|
|
|
#undef FMT
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-02-24 16:38:43 +00:00
|
|
|
|
- (const char *) name
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return object_get_class_name(self);
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL)isKindOf:(Class)aClassObject
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self isKindOfClass:aClassObject];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL)isMemberOf:(Class)aClassObject
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self isMemberOfClass:aClassObject];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
+ (BOOL)instancesRespondTo:(SEL)aSel
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self instancesRespondToSelector:aSel];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL)respondsTo:(SEL)aSel
|
|
|
|
|
{
|
|
|
|
|
return [self respondsToSelector:aSel];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (BOOL) conformsTo: (Protocol*)aProtocol
|
|
|
|
|
{
|
|
|
|
|
return [self conformsToProtocol:aProtocol];
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-27 17:25:42 +00:00
|
|
|
|
- (BOOL) conformsTo: (Protocol*)aProtocol
|
|
|
|
|
{
|
|
|
|
|
return [self conformsToProtocol:aProtocol];
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (retval_t)performv:(SEL)aSel :(arglist_t)argFrame
|
|
|
|
|
{
|
|
|
|
|
return objc_msg_sendv(self, aSel, argFrame);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (IMP)instanceMethodFor:(SEL)aSel
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self instanceMethodForSelector:aSel];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (IMP)methodFor:(SEL)aSel
|
|
|
|
|
{
|
|
|
|
|
return [self methodForSelector:aSel];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ poseAs:(Class)aClassObject
|
|
|
|
|
{
|
|
|
|
|
[self poseAsClass:aClassObject];
|
|
|
|
|
return self;
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
|
|
|
|
+ (int)version
|
|
|
|
|
{
|
|
|
|
|
return class_get_version(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ setVersion:(int)aVersion
|
|
|
|
|
{
|
|
|
|
|
class_set_version(self, aVersion);
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- notImplemented:(SEL)aSel
|
|
|
|
|
{
|
1996-03-26 20:59:42 +00:00
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"method %s not implemented", sel_get_name(aSel)];
|
|
|
|
|
return nil;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- doesNotRecognize:(SEL)aSel
|
|
|
|
|
{
|
1996-03-26 20:59:42 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"%s does not recognize %s",
|
|
|
|
|
object_get_class_name(self), sel_get_name(aSel)];
|
|
|
|
|
return nil;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-23 03:31:30 +00:00
|
|
|
|
- perform: (SEL)sel with: anObject
|
|
|
|
|
{
|
|
|
|
|
return [self perform:sel withObject:anObject];
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-03 01:32:58 +00:00
|
|
|
|
- perform: (SEL)sel with: anObject with: anotherObject
|
|
|
|
|
{
|
|
|
|
|
return [self perform:sel withObject:anObject withObject:anotherObject];
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation NSObject (GNU)
|
|
|
|
|
|
|
|
|
|
/* GNU Object class compatibility */
|
|
|
|
|
|
1995-03-12 19:29:37 +00:00
|
|
|
|
+ (void) setAutoreleaseClass: (Class)aClass
|
|
|
|
|
{
|
|
|
|
|
autorelease_class = aClass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (Class) autoreleaseClass
|
|
|
|
|
{
|
|
|
|
|
return autorelease_class;
|
|
|
|
|
}
|
|
|
|
|
|
1995-08-04 20:52:07 +00:00
|
|
|
|
+ (void) enableDoubleReleaseCheck: (BOOL)enable
|
|
|
|
|
{
|
|
|
|
|
double_release_check_enabled = enable;
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (int)compare:anotherObject;
|
|
|
|
|
{
|
|
|
|
|
if ([self isEqual:anotherObject])
|
|
|
|
|
return 0;
|
|
|
|
|
// Ordering objects by their address is pretty useless,
|
|
|
|
|
// so subclasses should override this is some useful way.
|
|
|
|
|
else if (self > anotherObject)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)isMetaClass
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)isClass
|
|
|
|
|
{
|
|
|
|
|
return object_is_class(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)isInstance
|
|
|
|
|
{
|
|
|
|
|
return object_is_instance(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)isMemberOfClassNamed:(const char *)aClassName
|
|
|
|
|
{
|
|
|
|
|
return ((aClassName!=NULL)
|
|
|
|
|
&&!strcmp(class_get_class_name(self->isa), aClassName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel
|
|
|
|
|
{
|
|
|
|
|
return ((struct objc_method_description *)
|
|
|
|
|
class_get_instance_method(self, aSel));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (struct objc_method_description *)descriptionForMethod:(SEL)aSel
|
|
|
|
|
{
|
|
|
|
|
return ((struct objc_method_description *)
|
|
|
|
|
(object_is_instance(self)
|
|
|
|
|
?class_get_instance_method(self->isa, aSel)
|
|
|
|
|
:class_get_class_method(self->isa, aSel)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (Class)transmuteClassTo:(Class)aClassObject
|
|
|
|
|
{
|
|
|
|
|
if (object_is_instance(self))
|
|
|
|
|
if (class_is_class(aClassObject))
|
|
|
|
|
if (class_get_instance_size(aClassObject)==class_get_instance_size(isa))
|
|
|
|
|
if ([self isKindOfClass:aClassObject])
|
|
|
|
|
{
|
|
|
|
|
Class old_isa = isa;
|
|
|
|
|
isa = aClassObject;
|
|
|
|
|
return old_isa;
|
|
|
|
|
}
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- subclassResponsibility:(SEL)aSel
|
|
|
|
|
{
|
1996-03-26 20:59:42 +00:00
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"subclass should override %s", sel_get_name(aSel)];
|
|
|
|
|
return nil;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 19:29:37 +00:00
|
|
|
|
- shouldNotImplement:(SEL)aSel
|
|
|
|
|
{
|
1996-03-26 20:59:42 +00:00
|
|
|
|
[NSException
|
|
|
|
|
raise: NSGenericException
|
|
|
|
|
format: @"%s should not implement %s",
|
|
|
|
|
object_get_class_name(self), sel_get_name(aSel)];
|
|
|
|
|
return nil;
|
1995-03-12 19:29:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
+ (int)streamVersion: (TypedStream*)aStream
|
|
|
|
|
{
|
|
|
|
|
if (aStream->mode == OBJC_READONLY)
|
|
|
|
|
return objc_get_stream_class_version (aStream, self);
|
|
|
|
|
else
|
|
|
|
|
return class_get_version (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These are used to write or read the instance variables
|
|
|
|
|
// declared in this particular part of the object. Subclasses
|
|
|
|
|
// should extend these, by calling [super read/write: aStream]
|
|
|
|
|
// before doing their own archiving. These methods are private, in
|
|
|
|
|
// the sense that they should only be called from subclasses.
|
|
|
|
|
|
|
|
|
|
- read: (TypedStream*)aStream
|
|
|
|
|
{
|
|
|
|
|
// [super read: aStream];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- write: (TypedStream*)aStream
|
|
|
|
|
{
|
|
|
|
|
// [super write: aStream];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- awake
|
|
|
|
|
{
|
|
|
|
|
// [super awake];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|