2002-08-20 15:32:13 +00:00
|
|
|
|
/** Implementation of NSObject for GNUStep
|
1996-01-26 19:18:08 +00:00
|
|
|
|
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +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
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
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.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1995-01-26 17:55:52 +00:00
|
|
|
|
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.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1995-01-26 17:55:52 +00:00
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
|
License along with this library; if not, write to the Free
|
2005-05-22 03:32:16 +00:00
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
|
|
<title>NSObject class reference</title>
|
|
|
|
|
$Date$ $Revision$
|
2005-02-22 11:22:44 +00:00
|
|
|
|
*/
|
1995-01-26 17:55:52 +00:00
|
|
|
|
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "config.h"
|
2003-07-31 23:49:32 +00:00
|
|
|
|
#include "GNUstepBase/preface.h"
|
1995-03-12 15:40:22 +00:00
|
|
|
|
#include <stdarg.h>
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "Foundation/NSObject.h"
|
1995-03-23 03:31:30 +00:00
|
|
|
|
#include <objc/Protocol.h>
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "Foundation/NSMethodSignature.h"
|
|
|
|
|
#include "Foundation/NSInvocation.h"
|
|
|
|
|
#include "Foundation/NSAutoreleasePool.h"
|
|
|
|
|
#include "Foundation/NSString.h"
|
|
|
|
|
#include "Foundation/NSArray.h"
|
|
|
|
|
#include "Foundation/NSException.h"
|
|
|
|
|
#include "Foundation/NSPortCoder.h"
|
|
|
|
|
#include "Foundation/NSDistantObject.h"
|
|
|
|
|
#include "Foundation/NSZone.h"
|
|
|
|
|
#include "Foundation/NSDebug.h"
|
|
|
|
|
#include "Foundation/NSThread.h"
|
|
|
|
|
#include "Foundation/NSNotification.h"
|
|
|
|
|
#include "Foundation/NSObjCRuntime.h"
|
|
|
|
|
#include "Foundation/NSMapTable.h"
|
1995-04-05 01:54:16 +00:00
|
|
|
|
#include <limits.h>
|
2003-07-31 23:49:32 +00:00
|
|
|
|
#include "GNUstepBase/GSLocale.h"
|
2002-12-05 04:24:43 +00:00
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
2003-10-16 18:31:38 +00:00
|
|
|
|
#ifdef HAVE_SIGNAL_H
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_SYS_SIGNAL_H
|
|
|
|
|
#include <sys/signal.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
#include "GSPrivate.h"
|
2002-01-30 13:05:35 +00:00
|
|
|
|
|
|
|
|
|
|
2001-08-03 20:43:40 +00:00
|
|
|
|
#ifndef NeXT_RUNTIME
|
1999-06-24 19:30:29 +00:00
|
|
|
|
extern BOOL __objc_responds_to(id, SEL);
|
2001-08-03 20:43:40 +00:00
|
|
|
|
#endif
|
1999-06-24 19:30:29 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
|
|
|
|
|
#include <gc.h>
|
|
|
|
|
#include <gc_typed.h>
|
|
|
|
|
|
2002-05-28 05:23:36 +00:00
|
|
|
|
#endif
|
1998-11-12 10:58:17 +00:00
|
|
|
|
|
2001-06-06 15:18:28 +00:00
|
|
|
|
static Class NSConstantStringClass;
|
2000-10-09 04:41:18 +00:00
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
@class NSDataMalloc;
|
|
|
|
|
@class NSMutableDataMalloc;
|
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
/*
|
|
|
|
|
* allocationLock is needed when running multi-threaded for retain/release
|
|
|
|
|
* to work reliably.
|
|
|
|
|
* We also use it for protecting the map table of zombie information.
|
|
|
|
|
*/
|
|
|
|
|
static objc_mutex_t allocationLock = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL NSZombieEnabled = NO;
|
|
|
|
|
BOOL NSDeallocateZombies = NO;
|
|
|
|
|
|
|
|
|
|
@class NSZombie;
|
|
|
|
|
static Class zombieClass;
|
|
|
|
|
static NSMapTable zombieMap;
|
|
|
|
|
|
|
|
|
|
static void GSMakeZombie(NSObject *o)
|
|
|
|
|
{
|
|
|
|
|
Class c = ((id)o)->class_pointer;
|
|
|
|
|
|
|
|
|
|
((id)o)->class_pointer = zombieClass;
|
|
|
|
|
if (NSDeallocateZombies == NO)
|
|
|
|
|
{
|
2002-04-05 16:26:47 +00:00
|
|
|
|
if (allocationLock != 0)
|
2002-03-27 09:55:57 +00:00
|
|
|
|
{
|
|
|
|
|
objc_mutex_lock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
NSMapInsert(zombieMap, (void*)o, (void*)c);
|
2002-04-05 16:26:47 +00:00
|
|
|
|
if (allocationLock != 0)
|
2002-03-27 09:55:57 +00:00
|
|
|
|
{
|
|
|
|
|
objc_mutex_unlock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void GSLogZombie(id o, SEL sel)
|
|
|
|
|
{
|
|
|
|
|
Class c = 0;
|
|
|
|
|
|
|
|
|
|
if (NSDeallocateZombies == NO)
|
|
|
|
|
{
|
2002-04-05 16:26:47 +00:00
|
|
|
|
if (allocationLock != 0)
|
2002-03-27 09:55:57 +00:00
|
|
|
|
{
|
|
|
|
|
objc_mutex_lock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
c = NSMapGet(zombieMap, (void*)o);
|
2002-04-05 16:26:47 +00:00
|
|
|
|
if (allocationLock != 0)
|
2002-03-27 09:55:57 +00:00
|
|
|
|
{
|
|
|
|
|
objc_mutex_unlock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (c == 0)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Deallocated object (0x%x) sent %@",
|
|
|
|
|
o, NSStringFromSelector(sel));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Deallocated %@ (0x%x) sent %@",
|
|
|
|
|
NSStringFromClass(c), o, NSStringFromSelector(sel));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-31 14:23:23 +00:00
|
|
|
|
|
1998-08-04 09:22:51 +00:00
|
|
|
|
/*
|
|
|
|
|
* Reference count and memory management
|
|
|
|
|
*
|
|
|
|
|
* If REFCNT_LOCAL is defined, reference counts for object are stored
|
|
|
|
|
* with the object, otherwise they are stored in a global map table
|
|
|
|
|
* that has to be protected by mutexes in a multithreraded environment.
|
|
|
|
|
* You therefore want REFCNT_LOCAL defined for best performance.
|
|
|
|
|
*
|
|
|
|
|
* If CACHE_ZONE is defined, the zone in which an object has been
|
|
|
|
|
* allocated is stored with the object - this makes lookup of the
|
|
|
|
|
* correct zone to free memory very fast.
|
|
|
|
|
*/
|
|
|
|
|
|
2002-02-02 07:10:51 +00:00
|
|
|
|
|
2002-01-03 20:39:12 +00:00
|
|
|
|
#if GS_WITH_GC == 0 && !defined(NeXT_RUNTIME)
|
2002-02-02 07:10:51 +00:00
|
|
|
|
#define REFCNT_LOCAL 1
|
|
|
|
|
#define CACHE_ZONE 1
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1998-08-04 09:22:51 +00:00
|
|
|
|
|
2001-12-28 03:40:03 +00:00
|
|
|
|
#ifdef ALIGN
|
|
|
|
|
#undef ALIGN
|
|
|
|
|
#endif
|
|
|
|
|
#define ALIGN __alignof__(double)
|
|
|
|
|
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Define a structure to hold information that is held locally
|
|
|
|
|
* (before the start) in each object.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
typedef struct obj_layout_unpadded {
|
|
|
|
|
#if defined(REFCNT_LOCAL)
|
|
|
|
|
unsigned retained;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(CACHE_ZONE)
|
|
|
|
|
NSZone *zone;
|
|
|
|
|
#endif
|
|
|
|
|
} unp;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
#define UNP sizeof(unp)
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now do the REAL version - using the other version to determine
|
|
|
|
|
* what padding (if any) is required to get the alignment of the
|
|
|
|
|
* structure correct.
|
|
|
|
|
*/
|
1998-08-04 09:22:51 +00:00
|
|
|
|
struct obj_layout {
|
|
|
|
|
#if defined(REFCNT_LOCAL)
|
|
|
|
|
unsigned retained;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(CACHE_ZONE)
|
|
|
|
|
NSZone *zone;
|
|
|
|
|
#endif
|
1998-10-15 05:03:16 +00:00
|
|
|
|
char padding[ALIGN - ((UNP % ALIGN) ? (UNP % ALIGN) : ALIGN)];
|
1998-08-04 09:22:51 +00:00
|
|
|
|
};
|
|
|
|
|
typedef struct obj_layout *obj;
|
|
|
|
|
|
|
|
|
|
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#if !defined(REFCNT_LOCAL)
|
1998-08-04 09:22:51 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
/*
|
|
|
|
|
* Set up map table for non-local reference counts.
|
|
|
|
|
*/
|
1999-01-28 17:21:03 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#define GSI_MAP_EQUAL(M, X, Y) (X.obj == Y.obj)
|
|
|
|
|
#define GSI_MAP_HASH(M, X) (X.uint >> 2)
|
|
|
|
|
#define GSI_MAP_RETAIN_KEY(M, X)
|
|
|
|
|
#define GSI_MAP_RELEASE_KEY(M, X)
|
|
|
|
|
#define GSI_MAP_RETAIN_VAL(M, X)
|
|
|
|
|
#define GSI_MAP_RELEASE_VAL(M, X)
|
|
|
|
|
#define GSI_MAP_KTYPES GSUNION_OBJ|GSUNION_INT
|
|
|
|
|
#define GSI_MAP_VTYPES GSUNION_INT
|
|
|
|
|
#define GSI_MAP_NOCLEAN 1
|
1999-01-28 17:21:03 +00:00
|
|
|
|
|
2003-07-31 23:49:32 +00:00
|
|
|
|
#include "GNUstepBase/GSIMap.h"
|
1999-01-28 17:21:03 +00:00
|
|
|
|
|
2002-06-12 04:29:59 +00:00
|
|
|
|
static GSIMapTable_t retain_counts = {0};
|
1999-12-10 00:59:40 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#endif /* !defined(REFCNT_LOCAL) */
|
1999-05-21 18:14:48 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
/**
|
|
|
|
|
* Examines the extra reference count for the object and, if non-zero
|
|
|
|
|
* decrements it, otherwise leaves it unchanged.<br />
|
|
|
|
|
* Returns a flag to say whether the count was zero
|
|
|
|
|
* (and hence whether the extra refrence count was decremented).<br />
|
|
|
|
|
* This function is used by the [NSObject-release] method.
|
|
|
|
|
*/
|
|
|
|
|
inline BOOL
|
1998-08-04 09:22:51 +00:00
|
|
|
|
NSDecrementExtraRefCountWasZero(id anObject)
|
|
|
|
|
{
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
return NO;
|
|
|
|
|
#else /* GS_WITH_GC */
|
|
|
|
|
#if defined(REFCNT_LOCAL)
|
2002-03-27 09:55:57 +00:00
|
|
|
|
if (allocationLock != 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_lock(allocationLock);
|
2002-06-01 05:08:10 +00:00
|
|
|
|
if (((obj)anObject)[-1].retained == 0)
|
1999-12-10 00:59:40 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_unlock(allocationLock);
|
1999-12-10 00:59:40 +00:00
|
|
|
|
return YES;
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-06-01 05:08:10 +00:00
|
|
|
|
((obj)anObject)[-1].retained--;
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_unlock(allocationLock);
|
1999-12-10 00:59:40 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-06-01 05:08:10 +00:00
|
|
|
|
if (((obj)anObject)[-1].retained == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-06-01 05:08:10 +00:00
|
|
|
|
((obj)anObject)[-1].retained--;
|
1999-12-13 12:14:01 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#else
|
2002-01-30 13:05:35 +00:00
|
|
|
|
GSIMapNode node;
|
1996-02-22 23:12:19 +00:00
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
if (allocationLock != 0)
|
1996-07-15 18:41:44 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_lock(allocationLock);
|
2002-01-30 13:05:35 +00:00
|
|
|
|
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
|
|
|
|
if (node == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_unlock(allocationLock);
|
1999-12-13 12:14:01 +00:00
|
|
|
|
return YES;
|
|
|
|
|
}
|
2002-06-01 05:08:10 +00:00
|
|
|
|
if (node->value.uint == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-01-30 13:05:35 +00:00
|
|
|
|
GSIMapRemoveKey((GSIMapTable)&retain_counts, (GSIMapKey)anObject);
|
2002-06-01 05:08:10 +00:00
|
|
|
|
objc_mutex_unlock(allocationLock);
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
(node->value.uint)--;
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_unlock(allocationLock);
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-01-30 13:05:35 +00:00
|
|
|
|
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
|
|
|
|
if (node == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2002-06-12 04:29:59 +00:00
|
|
|
|
if ((node->value.uint) == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-01-30 13:05:35 +00:00
|
|
|
|
GSIMapRemoveKey((GSIMapTable)&retain_counts, (GSIMapKey)anObject);
|
2002-06-01 05:08:10 +00:00
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
--(node->value.uint);
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
1996-07-15 18:41:44 +00:00
|
|
|
|
}
|
2002-06-05 12:39:28 +00:00
|
|
|
|
return NO;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the extra reference count of anObject (a value in the range
|
|
|
|
|
* from 0 to the maximum unsigned integer value minus one).<br />
|
|
|
|
|
* The retain count for an object is this value plus one.
|
|
|
|
|
*/
|
|
|
|
|
inline unsigned
|
|
|
|
|
NSExtraRefCount(id anObject)
|
1997-09-01 21:59:51 +00:00
|
|
|
|
{
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
return UINT_MAX - 1;
|
|
|
|
|
#else /* GS_WITH_GC */
|
|
|
|
|
#if defined(REFCNT_LOCAL)
|
|
|
|
|
return ((obj)anObject)[-1].retained;
|
|
|
|
|
#else
|
2002-01-30 13:05:35 +00:00
|
|
|
|
GSIMapNode node;
|
|
|
|
|
unsigned ret;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
if (allocationLock != 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_lock(allocationLock);
|
2002-01-30 13:05:35 +00:00
|
|
|
|
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
|
|
|
|
if (node == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
2002-01-30 13:05:35 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = node->value.uint;
|
|
|
|
|
}
|
2002-03-27 09:55:57 +00:00
|
|
|
|
objc_mutex_unlock(allocationLock);
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-01-30 13:05:35 +00:00
|
|
|
|
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
|
|
|
|
if (node == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
2002-01-30 13:05:35 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = node->value.uint;
|
|
|
|
|
}
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
2002-06-02 09:05:11 +00:00
|
|
|
|
return ret;
|
2002-06-05 12:39:28 +00:00
|
|
|
|
#endif
|
|
|
|
|
#endif
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
/**
|
|
|
|
|
* Increments the extra reference count for anObject.<br />
|
|
|
|
|
* The GNUstep version raises an exception if the reference count
|
|
|
|
|
* would be incremented to too large a value.<br />
|
|
|
|
|
* This is used by the [NSObject-retain] method.
|
|
|
|
|
*/
|
|
|
|
|
inline void
|
|
|
|
|
NSIncrementExtraRefCount(id anObject)
|
|
|
|
|
{
|
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
return;
|
|
|
|
|
#else /* GS_WITH_GC */
|
|
|
|
|
#if defined(REFCNT_LOCAL)
|
|
|
|
|
if (allocationLock != 0)
|
|
|
|
|
{
|
|
|
|
|
objc_mutex_lock(allocationLock);
|
|
|
|
|
if (((obj)anObject)[-1].retained == UINT_MAX - 1)
|
|
|
|
|
{
|
|
|
|
|
objc_mutex_unlock (allocationLock);
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"NSIncrementExtraRefCount() asked to increment too far"];
|
|
|
|
|
}
|
|
|
|
|
((obj)anObject)[-1].retained++;
|
|
|
|
|
objc_mutex_unlock (allocationLock);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (((obj)anObject)[-1].retained == UINT_MAX - 1)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"NSIncrementExtraRefCount() asked to increment too far"];
|
|
|
|
|
}
|
|
|
|
|
((obj)anObject)[-1].retained++;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
#else
|
|
|
|
|
GSIMapNode node;
|
1998-08-04 09:22:51 +00:00
|
|
|
|
|
2002-06-05 12:39:28 +00:00
|
|
|
|
if (allocationLock != 0)
|
|
|
|
|
{
|
|
|
|
|
objc_mutex_lock(allocationLock);
|
|
|
|
|
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
|
|
|
|
if (node != 0)
|
|
|
|
|
{
|
|
|
|
|
if ((node->value.uint) == UINT_MAX - 1)
|
|
|
|
|
{
|
|
|
|
|
objc_mutex_unlock(allocationLock);
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format:
|
|
|
|
|
@"NSIncrementExtraRefCount() asked to increment too far"];
|
|
|
|
|
}
|
|
|
|
|
(node->value.uint)++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GSIMapAddPair(&retain_counts, (GSIMapKey)anObject, (GSIMapVal)1);
|
|
|
|
|
}
|
|
|
|
|
objc_mutex_unlock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
|
|
|
|
if (node != 0)
|
|
|
|
|
{
|
|
|
|
|
if ((node->value.uint) == UINT_MAX - 1)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format:
|
|
|
|
|
@"NSIncrementExtraRefCount() asked to increment too far"];
|
|
|
|
|
}
|
|
|
|
|
(node->value.uint)++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GSIMapAddPair(&retain_counts, (GSIMapKey)anObject, (GSIMapVal)1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
}
|
1999-01-28 17:21:03 +00:00
|
|
|
|
|
1998-08-04 09:22:51 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now do conditional compilation of memory allocation functions
|
|
|
|
|
* depending on what information (if any) we are storing before
|
|
|
|
|
* the start of each object.
|
|
|
|
|
*/
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
|
|
|
|
|
inline NSZone *
|
2000-10-31 16:17:33 +00:00
|
|
|
|
GSObjCZone(NSObject *object)
|
1999-01-28 17:21:03 +00:00
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
GSFinalize(void* object, void* data)
|
|
|
|
|
{
|
|
|
|
|
[(id)object gcFinalize];
|
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
GSDebugAllocationRemove(((id)object)->class_pointer, (id)object);
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1999-09-28 10:25:42 +00:00
|
|
|
|
((id)object)->class_pointer = (void*)0xdeadface;
|
1999-01-28 17:21:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline NSObject *
|
1999-09-28 10:25:42 +00:00
|
|
|
|
NSAllocateObject(Class aClass, unsigned extraBytes, NSZone *zone)
|
1999-01-28 17:21:03 +00:00
|
|
|
|
{
|
2002-05-03 10:10:38 +00:00
|
|
|
|
id new;
|
|
|
|
|
int size;
|
1999-09-28 10:25:42 +00:00
|
|
|
|
|
1999-09-29 14:13:52 +00:00
|
|
|
|
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
|
2002-05-03 10:10:38 +00:00
|
|
|
|
size = aClass->instance_size + extraBytes;
|
1999-09-29 14:13:52 +00:00
|
|
|
|
if (zone == GSAtomicMallocZone())
|
|
|
|
|
{
|
|
|
|
|
new = NSZoneMalloc(zone, size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
GC_descr gc_type = (GC_descr)aClass->gc_object_type;
|
1999-09-29 14:13:52 +00:00
|
|
|
|
|
|
|
|
|
if (gc_type == 0)
|
|
|
|
|
{
|
|
|
|
|
new = NSZoneMalloc(zone, size);
|
2000-10-31 16:17:33 +00:00
|
|
|
|
NSLog(@"No garbage collection information for '%s'",
|
2002-02-21 13:31:13 +00:00
|
|
|
|
GSNameFromClass(aClass));
|
1999-09-29 14:13:52 +00:00
|
|
|
|
}
|
2000-07-04 10:17:03 +00:00
|
|
|
|
else if ([aClass requiresTypedMemory])
|
1999-09-29 14:13:52 +00:00
|
|
|
|
{
|
|
|
|
|
new = GC_CALLOC_EXPLICTLY_TYPED(1, size, gc_type);
|
|
|
|
|
}
|
2000-07-04 10:17:03 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
new = NSZoneMalloc(zone, size);
|
|
|
|
|
}
|
1999-09-29 14:13:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-01-28 17:21:03 +00:00
|
|
|
|
if (new != nil)
|
|
|
|
|
{
|
1999-09-28 10:25:42 +00:00
|
|
|
|
memset(new, 0, size);
|
1999-01-28 17:21:03 +00:00
|
|
|
|
new->class_pointer = aClass;
|
1999-09-28 10:25:42 +00:00
|
|
|
|
if (__objc_responds_to(new, @selector(gcFinalize)))
|
|
|
|
|
{
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#ifndef NDEBUG
|
1999-09-28 10:25:42 +00:00
|
|
|
|
/*
|
|
|
|
|
* We only do allocation counting for objects that can be
|
|
|
|
|
* finalised - for other objects we have no way of decrementing
|
|
|
|
|
* the count when the object is collected.
|
|
|
|
|
*/
|
2001-04-19 16:10:23 +00:00
|
|
|
|
GSDebugAllocationAdd(aClass, new);
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1999-09-28 10:25:42 +00:00
|
|
|
|
GC_REGISTER_FINALIZER (new, GSFinalize, NULL, NULL, NULL);
|
|
|
|
|
}
|
1999-01-28 17:21:03 +00:00
|
|
|
|
}
|
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void
|
|
|
|
|
NSDeallocateObject(NSObject *anObject)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* GS_WITH_GC */
|
|
|
|
|
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
#if defined(CACHE_ZONE)
|
|
|
|
|
|
|
|
|
|
inline NSZone *
|
2000-10-31 16:17:33 +00:00
|
|
|
|
GSObjCZone(NSObject *object)
|
1998-10-15 05:03:16 +00:00
|
|
|
|
{
|
2001-06-06 15:18:28 +00:00
|
|
|
|
if (GSObjCClass(object) == NSConstantStringClass)
|
1999-01-28 17:21:03 +00:00
|
|
|
|
return NSDefaultMallocZone();
|
|
|
|
|
return ((obj)object)[-1].zone;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* defined(CACHE_ZONE) */
|
|
|
|
|
|
|
|
|
|
inline NSZone *
|
2000-10-31 16:17:33 +00:00
|
|
|
|
GSObjCZone(NSObject *object)
|
1998-10-15 05:03:16 +00:00
|
|
|
|
{
|
2001-06-06 15:18:28 +00:00
|
|
|
|
if (GSObjCClass(object) == NSConstantStringClass)
|
1999-01-28 17:21:03 +00:00
|
|
|
|
return NSDefaultMallocZone();
|
|
|
|
|
return NSZoneFromPointer(&((obj)object)[-1]);
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* defined(CACHE_ZONE) */
|
|
|
|
|
|
1998-11-12 08:02:48 +00:00
|
|
|
|
inline NSObject *
|
|
|
|
|
NSAllocateObject (Class aClass, unsigned extraBytes, NSZone *zone)
|
1998-08-04 09:22:51 +00:00
|
|
|
|
{
|
1999-06-24 19:30:29 +00:00
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
extern void GSDebugAllocationAdd(Class c, id o);
|
1999-06-24 19:30:29 +00:00
|
|
|
|
#endif
|
2002-05-03 10:10:38 +00:00
|
|
|
|
id new;
|
|
|
|
|
int size;
|
|
|
|
|
|
|
|
|
|
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
|
|
|
|
|
size = aClass->instance_size + extraBytes + sizeof(struct obj_layout);
|
|
|
|
|
if (zone == 0)
|
1998-08-04 09:22:51 +00:00
|
|
|
|
{
|
2002-05-03 10:10:38 +00:00
|
|
|
|
zone = NSDefaultMallocZone();
|
1998-08-04 09:22:51 +00:00
|
|
|
|
}
|
2002-05-03 10:10:38 +00:00
|
|
|
|
new = NSZoneMalloc(zone, size);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
if (new != nil)
|
|
|
|
|
{
|
|
|
|
|
memset (new, 0, size);
|
|
|
|
|
#if defined(CACHE_ZONE)
|
|
|
|
|
((obj)new)->zone = zone;
|
|
|
|
|
#endif
|
|
|
|
|
new = (id)&((obj)new)[1];
|
|
|
|
|
new->class_pointer = aClass;
|
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
GSDebugAllocationAdd(aClass, new);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#endif
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
1998-08-04 09:22:51 +00:00
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-12 08:02:48 +00:00
|
|
|
|
inline void
|
|
|
|
|
NSDeallocateObject(NSObject *anObject)
|
1998-08-04 09:22:51 +00:00
|
|
|
|
{
|
1999-06-24 19:30:29 +00:00
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
extern void GSDebugAllocationRemove(Class c, id o);
|
1999-06-24 19:30:29 +00:00
|
|
|
|
#endif
|
1998-08-04 09:22:51 +00:00
|
|
|
|
if ((anObject!=nil) && CLS_ISCLASS(((id)anObject)->class_pointer))
|
|
|
|
|
{
|
|
|
|
|
obj o = &((obj)anObject)[-1];
|
2000-10-31 16:17:33 +00:00
|
|
|
|
NSZone *z = GSObjCZone(anObject);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
GSDebugAllocationRemove(((id)anObject)->class_pointer, (id)anObject);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#endif
|
2002-03-27 09:55:57 +00:00
|
|
|
|
if (NSZombieEnabled == YES)
|
|
|
|
|
{
|
|
|
|
|
GSMakeZombie(anObject);
|
|
|
|
|
if (NSDeallocateZombies == YES)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(z, o);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
((id)anObject)->class_pointer = (void*) 0xdeadface;
|
|
|
|
|
NSZoneFree(z, o);
|
|
|
|
|
}
|
1998-08-04 09:22:51 +00:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
inline NSZone *
|
2000-10-31 16:17:33 +00:00
|
|
|
|
GSObjCZone(NSObject *object)
|
1998-10-15 05:03:16 +00:00
|
|
|
|
{
|
2001-06-06 15:18:28 +00:00
|
|
|
|
if (GSObjCClass(object) == NSConstantStringClass)
|
2000-10-09 04:41:18 +00:00
|
|
|
|
return NSDefaultMallocZone();
|
|
|
|
|
return NSZoneFromPointer(object);
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-12 08:02:48 +00:00
|
|
|
|
inline NSObject *
|
|
|
|
|
NSAllocateObject (Class aClass, unsigned extraBytes, NSZone *zone)
|
1998-08-04 09:22:51 +00:00
|
|
|
|
{
|
2002-05-03 10:10:38 +00:00
|
|
|
|
id new;
|
|
|
|
|
int size;
|
|
|
|
|
|
|
|
|
|
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
|
|
|
|
|
size = aClass->instance_size + extraBytes;
|
|
|
|
|
new = NSZoneMalloc (zone, size);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
if (new != nil)
|
|
|
|
|
{
|
|
|
|
|
memset (new, 0, size);
|
|
|
|
|
new->class_pointer = aClass;
|
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
GSDebugAllocationAdd(aClass, new);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#endif
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
1998-08-04 09:22:51 +00:00
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-12 08:02:48 +00:00
|
|
|
|
inline void
|
|
|
|
|
NSDeallocateObject(NSObject *anObject)
|
1998-08-04 09:22:51 +00:00
|
|
|
|
{
|
|
|
|
|
if ((anObject!=nil) && CLS_ISCLASS(((id)anObject)->class_pointer))
|
|
|
|
|
{
|
|
|
|
|
NSZone *z = [anObject zone];
|
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2001-04-19 16:10:23 +00:00
|
|
|
|
GSDebugAllocationRemove(((id)anObject)->class_pointer, (id)anObject);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#endif
|
2002-03-27 09:55:57 +00:00
|
|
|
|
if (NSZombieEnabled == YES)
|
|
|
|
|
{
|
|
|
|
|
GSMakeZombie(anObject);
|
|
|
|
|
if (NSDeallocateZombies == YES)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(z, anObject);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
((id)anObject)->class_pointer = (void*) 0xdeadface;
|
|
|
|
|
NSZoneFree(z, anObject);
|
|
|
|
|
}
|
1998-08-04 09:22:51 +00:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
|
|
|
|
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif /* GS_WITH_GC */
|
|
|
|
|
|
1998-08-04 09:22:51 +00:00
|
|
|
|
BOOL
|
|
|
|
|
NSShouldRetainWithZone (NSObject *anObject, NSZone *requestedZone)
|
|
|
|
|
{
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
return YES;
|
|
|
|
|
#else
|
|
|
|
|
return (!requestedZone || requestedZone == NSDefaultMallocZone()
|
2002-03-27 09:55:57 +00:00
|
|
|
|
|| GSObjCZone(anObject) == requestedZone);
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1998-08-04 09:22:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The Class responsible for handling autorelease's. This does not
|
|
|
|
|
need mutex protection, since it is simply a pointer that gets read
|
|
|
|
|
and set. */
|
|
|
|
|
static id autorelease_class = nil;
|
2000-10-30 18:00:27 +00:00
|
|
|
|
static SEL autorelease_sel;
|
|
|
|
|
static IMP autorelease_imp;
|
1998-08-04 09:22:51 +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.
|
|
|
|
|
This does not need mutex protection. */
|
|
|
|
|
static BOOL double_release_check_enabled = NO;
|
|
|
|
|
|
1999-12-13 12:14:01 +00:00
|
|
|
|
|
2003-07-04 11:18:51 +00:00
|
|
|
|
|
|
|
|
|
struct objc_method_description_list {
|
2003-08-15 13:20:50 +00:00
|
|
|
|
int count;
|
|
|
|
|
struct objc_method_description list[1];
|
2003-07-04 11:18:51 +00:00
|
|
|
|
};
|
2003-08-15 13:20:50 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
@defs(Protocol)
|
|
|
|
|
} *pcl;
|
2003-07-04 11:18:51 +00:00
|
|
|
|
|
2003-08-15 13:20:50 +00:00
|
|
|
|
struct objc_method_description *
|
|
|
|
|
GSDescriptionForInstanceMethod(pcl self, SEL aSel)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2003-08-15 13:20:50 +00:00
|
|
|
|
struct objc_protocol_list *p_list;
|
2003-08-24 23:07:41 +00:00
|
|
|
|
const char *name = GSNameFromSelector(aSel);
|
2003-07-04 11:18:51 +00:00
|
|
|
|
struct objc_method_description *result;
|
|
|
|
|
|
2003-08-15 13:20:50 +00:00
|
|
|
|
if (self->instance_methods != 0)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-15 13:20:50 +00:00
|
|
|
|
for (i = 0; i < self->instance_methods->count; i++)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-15 13:20:50 +00:00
|
|
|
|
if (!strcmp ((char*)self->instance_methods->list[i].name, name))
|
|
|
|
|
return &(self->instance_methods->list[i]);
|
2003-07-04 11:18:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-08-15 13:20:50 +00:00
|
|
|
|
for (p_list = self->protocol_list; p_list != 0; p_list = p_list->next)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-15 13:20:50 +00:00
|
|
|
|
for (i = 0; i < p_list->count; i++)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-22 10:31:16 +00:00
|
|
|
|
result = GSDescriptionForInstanceMethod((pcl)p_list->list[i], aSel);
|
2003-08-15 13:20:50 +00:00
|
|
|
|
if (result)
|
|
|
|
|
{
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2003-07-04 11:18:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-15 13:20:50 +00:00
|
|
|
|
struct objc_method_description *
|
|
|
|
|
GSDescriptionForClassMethod(pcl self, SEL aSel)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2003-08-15 13:20:50 +00:00
|
|
|
|
struct objc_protocol_list *p_list;
|
2003-08-24 23:07:41 +00:00
|
|
|
|
const char *name = GSNameFromSelector(aSel);
|
2003-07-04 11:18:51 +00:00
|
|
|
|
struct objc_method_description *result;
|
|
|
|
|
|
2003-08-15 13:20:50 +00:00
|
|
|
|
if (self->class_methods != 0)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-15 13:20:50 +00:00
|
|
|
|
for (i = 0; i < self->class_methods->count; i++)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-15 13:20:50 +00:00
|
|
|
|
if (!strcmp ((char*)self->class_methods->list[i].name, name))
|
|
|
|
|
return &(self->class_methods->list[i]);
|
2003-07-04 11:18:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-08-15 13:20:50 +00:00
|
|
|
|
for (p_list = self->protocol_list; p_list != 0; p_list = p_list->next)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-15 13:20:50 +00:00
|
|
|
|
for (i = 0; i < p_list->count; i++)
|
2003-07-04 11:18:51 +00:00
|
|
|
|
{
|
2003-08-22 10:31:16 +00:00
|
|
|
|
result = GSDescriptionForClassMethod((pcl)p_list->list[i], aSel);
|
2003-08-15 13:20:50 +00:00
|
|
|
|
if (result)
|
|
|
|
|
{
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2003-07-04 11:18:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-15 13:20:50 +00:00
|
|
|
|
@implementation Protocol (Fixup)
|
|
|
|
|
|
|
|
|
|
- (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel
|
|
|
|
|
{
|
|
|
|
|
return GSDescriptionForInstanceMethod((pcl)self, aSel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel;
|
|
|
|
|
{
|
|
|
|
|
return GSDescriptionForClassMethod((pcl)self, aSel);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-04 11:18:51 +00:00
|
|
|
|
@end
|
1996-07-15 18:41:44 +00:00
|
|
|
|
|
2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>NSObject</code> is the root class (a root class is
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* a class with no superclass) of the GNUstep base library
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* class hierarchy, so all classes normally inherit from
|
|
|
|
|
* <code>NSObject</code>. There is an exception though:
|
|
|
|
|
* <code>NSProxy</code> (which is used for remote messaging)
|
|
|
|
|
* does not inherit from <code>NSObject</code>.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* Unless you are really sure of what you are doing, all
|
|
|
|
|
* your own classes should inherit (directly or indirectly)
|
|
|
|
|
* from <code>NSObject</code> (or in special cases from
|
|
|
|
|
* <code>NSProxy</code>). <code>NSObject</code> provides
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* the basic common functionality shared by all GNUstep
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* classes and objects.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* The essential methods which must be implemented by all
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* classes for their instances to be usable within GNUstep
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* are declared in a separate protocol, which is the
|
|
|
|
|
* <code>NSObject</code> protocol. Both
|
|
|
|
|
* <code>NSObject</code> and <code>NSProxy</code> conform to
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* this protocol, which means all objects in a GNUstep
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* application will conform to this protocol (btw, if you
|
|
|
|
|
* don't find a method of <code>NSObject</code> you are
|
|
|
|
|
* looking for in this documentation, make sure you also
|
|
|
|
|
* look into the documentation for the <code>NSObject</code>
|
|
|
|
|
* protocol).
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* Theoretically, in special cases you might need to
|
|
|
|
|
* implement a new root class. If you do, you need to make
|
|
|
|
|
* sure that your root class conforms (at least) to the
|
|
|
|
|
* <code>NSObject</code> protocol, otherwise it will not
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* interact correctly with the GNUstep framework. Said
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* that, I must note that I have never seen a case in which
|
|
|
|
|
* a new root class is needed.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>NSObject</code> is a root class, which implies that
|
|
|
|
|
* instance methods of <code>NSObject</code> are treated in
|
|
|
|
|
* a special way by the Objective-C runtime. This is an
|
|
|
|
|
* exception to the normal way messaging works with class
|
|
|
|
|
* and instance methods: if the Objective-C runtime can't
|
|
|
|
|
* find a class method for a class object, as a last resort
|
|
|
|
|
* it looks for an instance method of the root class with
|
|
|
|
|
* the same name, and executes it if it finds it. This
|
|
|
|
|
* means that instance methods of the root class (such as
|
|
|
|
|
* <code>NSObject</code>) can be performed by class objects
|
|
|
|
|
* which inherit from that root class ! This can only
|
|
|
|
|
* happen if the class doesn't have a class method with the
|
|
|
|
|
* same name, otherwise that method - of course - takes the
|
|
|
|
|
* precedence. Because of this exception,
|
|
|
|
|
* <code>NSObject</code>'s instance methods are written in
|
|
|
|
|
* such a way that they work both on <code>NSObject</code>'s
|
|
|
|
|
* instances and on class objects.
|
|
|
|
|
* </p>
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
@implementation NSObject
|
|
|
|
|
|
2002-09-12 09:09:54 +00:00
|
|
|
|
+ (void) _becomeMultiThreaded: (NSNotification *)aNotification
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
if (allocationLock == 0)
|
1999-12-13 12:14:01 +00:00
|
|
|
|
{
|
2002-03-27 09:55:57 +00:00
|
|
|
|
allocationLock = objc_mutex_allocate();
|
1999-12-13 12:14:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-04 10:17:03 +00:00
|
|
|
|
#if GS_WITH_GC
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* A utility method used when garbage collection is enabled. Can be ignored.
|
|
|
|
|
*/
|
2000-07-04 10:17:03 +00:00
|
|
|
|
+ (BOOL) requiresTypedMemory
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* This message is sent to a class once just before it is used for the first
|
|
|
|
|
* time. If class has a superclass, its implementation of +initialize is
|
|
|
|
|
* called first. You can implement +initialize in your own class if you need
|
|
|
|
|
* to. NSObject's implementation handles essential root object and base
|
|
|
|
|
* library initialization.
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (self == [NSObject class])
|
|
|
|
|
{
|
2002-11-09 16:40:00 +00:00
|
|
|
|
extern void GSBuildStrings(void); // See externs.m
|
2001-04-23 08:55:58 +00:00
|
|
|
|
|
2000-10-11 18:49:32 +00:00
|
|
|
|
#ifdef __MINGW__
|
|
|
|
|
// See libgnustep-base-entry.m
|
2002-11-09 16:40:00 +00:00
|
|
|
|
extern void gnustep_base_socket_init(void);
|
2000-10-11 18:49:32 +00:00
|
|
|
|
gnustep_base_socket_init();
|
2005-02-22 11:22:44 +00:00
|
|
|
|
#else
|
2003-10-16 18:31:38 +00:00
|
|
|
|
|
|
|
|
|
#ifdef SIGPIPE
|
|
|
|
|
/*
|
|
|
|
|
* If SIGPIPE is not handled or ignored, we will abort on any attempt
|
|
|
|
|
* to write to a pipe/socket that has been closed by the other end!
|
|
|
|
|
* We therefore need to ignore the signal if nothing else is already
|
|
|
|
|
* handling it.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef HAVE_SIGACTION
|
|
|
|
|
{
|
|
|
|
|
struct sigaction act;
|
|
|
|
|
|
2003-12-01 06:55:40 +00:00
|
|
|
|
if (sigaction(SIGPIPE, 0, &act) == 0)
|
2003-10-16 18:31:38 +00:00
|
|
|
|
{
|
2003-12-01 06:55:40 +00:00
|
|
|
|
if (act.sa_handler == SIG_DFL)
|
2003-10-16 18:31:38 +00:00
|
|
|
|
{
|
2003-12-01 06:55:40 +00:00
|
|
|
|
// Not ignored or handled ... so we ignore it.
|
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
|
if (sigaction(SIGPIPE, &act, 0) != 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Unable to ignore SIGPIPE\n");
|
|
|
|
|
}
|
2003-10-16 18:31:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Unable to retrieve information about SIGPIPE\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
{
|
|
|
|
|
void (*handler)(int);
|
|
|
|
|
|
|
|
|
|
handler = signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
if (handler != SIG_DFL)
|
|
|
|
|
{
|
|
|
|
|
signal(SIGPIPE, handler);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2000-10-11 18:49:32 +00:00
|
|
|
|
#endif
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1999-11-04 20:08:14 +00:00
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
|
// Manipulate the FPU to add the exception mask. (Fixes SIGFPE
|
|
|
|
|
// problems on *BSD)
|
|
|
|
|
|
2001-05-02 20:49:48 +00:00
|
|
|
|
{
|
|
|
|
|
volatile short cw;
|
1999-11-04 20:08:14 +00:00
|
|
|
|
|
2001-05-02 20:49:48 +00:00
|
|
|
|
__asm__ volatile ("fstcw (%0)" : : "g" (&cw));
|
|
|
|
|
cw |= 1; /* Mask 'invalid' exception */
|
|
|
|
|
__asm__ volatile ("fldcw (%0)" : : "g" (&cw));
|
|
|
|
|
}
|
1999-11-04 20:08:14 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2003-10-16 18:31:38 +00:00
|
|
|
|
|
2002-12-05 04:24:43 +00:00
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
|
GSSetLocaleC(LC_ALL, ""); // Set up locale from environment.
|
|
|
|
|
#endif
|
2001-05-03 15:32:31 +00:00
|
|
|
|
|
1997-09-13 17:52:31 +00:00
|
|
|
|
// Create the global lock
|
2002-06-12 04:29:59 +00:00
|
|
|
|
gnustep_global_lock = [NSRecursiveLock new];
|
2002-03-27 09:55:57 +00:00
|
|
|
|
|
|
|
|
|
// Zombie management stuff.
|
|
|
|
|
zombieMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
|
|
|
|
NSNonOwnedPointerMapValueCallBacks, 0);
|
2002-05-28 19:52:27 +00:00
|
|
|
|
zombieClass = [NSZombie class];
|
2002-03-27 09:55:57 +00:00
|
|
|
|
NSZombieEnabled = GSEnvironmentFlag("NSZombieEnabled", NO);
|
|
|
|
|
NSDeallocateZombies = GSEnvironmentFlag("NSDeallocateZombies", NO);
|
|
|
|
|
|
1999-09-28 19:35:09 +00:00
|
|
|
|
autorelease_class = [NSAutoreleasePool class];
|
2000-10-30 18:00:27 +00:00
|
|
|
|
autorelease_sel = @selector(addObject:);
|
1999-09-28 19:35:09 +00:00
|
|
|
|
autorelease_imp = [autorelease_class methodForSelector: autorelease_sel];
|
|
|
|
|
#if GS_WITH_GC == 0
|
|
|
|
|
#if !defined(REFCNT_LOCAL)
|
2002-02-02 07:10:51 +00:00
|
|
|
|
GSIMapInitWithZoneAndCapacity(&retain_counts,
|
|
|
|
|
NSDefaultMallocZone(), 1024);
|
1998-08-04 09:22:51 +00:00
|
|
|
|
#endif
|
1999-09-28 19:35:09 +00:00
|
|
|
|
#endif
|
2001-06-06 15:18:28 +00:00
|
|
|
|
NSConstantStringClass = [NSString constantStringClass];
|
2000-07-03 11:47:17 +00:00
|
|
|
|
GSBuildStrings();
|
1999-12-13 12:14:01 +00:00
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
addObserver: self
|
|
|
|
|
selector: @selector(_becomeMultiThreaded:)
|
|
|
|
|
name: NSWillBecomeMultiThreadedNotification
|
|
|
|
|
object: nil];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* Allocates a new instance of the receiver from the default
|
|
|
|
|
* zone, by invoking +allocWithZone: with
|
|
|
|
|
* <code>NSDefaultMallocZone()</code> as the zone argument.<br />
|
|
|
|
|
* Returns the created instance.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
+ (id) alloc
|
|
|
|
|
{
|
1997-01-06 21:34:06 +00:00
|
|
|
|
return [self allocWithZone: NSDefaultMallocZone()];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* This is the basic method to create a new instance. It
|
|
|
|
|
* allocates a new instance of the receiver from the specified
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* memory zone.
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <p>
|
|
|
|
|
* Memory for an instance of the receiver is allocated; a
|
|
|
|
|
* pointer to this newly created instance is returned. All
|
|
|
|
|
* instance variables are set to 0 except the
|
|
|
|
|
* <code>isa</code> pointer which is set to point to the
|
|
|
|
|
* object class. No initialization of the instance is
|
|
|
|
|
* performed: it is your responsibility to initialize the
|
|
|
|
|
* instance by calling an appropriate <code>init</code>
|
|
|
|
|
* method. If you are not using the garbage collector, it is
|
|
|
|
|
* also your responsibility to make sure the returned
|
|
|
|
|
* instance is destroyed when you finish using it, by calling
|
|
|
|
|
* the <code>release</code> method to destroy the instance
|
|
|
|
|
* directly, or by using <code>autorelease</code> and
|
|
|
|
|
* autorelease pools.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* You do not normally need to override this method in
|
|
|
|
|
* subclasses, unless you are implementing a class which for
|
|
|
|
|
* some reasons silently allocates instances of another class
|
|
|
|
|
* (this is typically needed to implement class clusters and
|
|
|
|
|
* similar design schemes).
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* If you have turned on debugging of object allocation (by
|
|
|
|
|
* calling the <code>GSDebugAllocationActive</code>
|
|
|
|
|
* function), this method will also update the various
|
|
|
|
|
* debugging counts and monitors of allocated objects, which
|
|
|
|
|
* you can access using the <code>GSDebugAllocation...</code>
|
|
|
|
|
* functions.
|
|
|
|
|
* </p>
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
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
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the receiver.
|
|
|
|
|
*/
|
1998-07-15 12:48:14 +00:00
|
|
|
|
+ (id) copyWithZone: (NSZone*)z
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1998-07-15 12:48:14 +00:00
|
|
|
|
return self;
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <p>
|
|
|
|
|
* This method is a short-hand for alloc followed by init, that is,
|
|
|
|
|
* </p>
|
|
|
|
|
* <p><code>
|
|
|
|
|
* NSObject *object = [NSObject new];
|
|
|
|
|
* </code></p>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* is exactly the same as
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <p><code>
|
|
|
|
|
* NSObject *object = [[NSObject alloc] init];
|
|
|
|
|
* </code></p>
|
|
|
|
|
* <p>
|
|
|
|
|
* This is a general convention: all <code>new...</code>
|
|
|
|
|
* methods are supposed to return a newly allocated and
|
|
|
|
|
* initialized instance, as would be generated by an
|
|
|
|
|
* <code>alloc</code> method followed by a corresponding
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* <code>init...</code> method. Please note that if you are
|
|
|
|
|
* not using a garbage collector, this means that instances
|
|
|
|
|
* generated by the <code>new...</code> methods are not
|
|
|
|
|
* autoreleased, that is, you are responsible for releasing
|
|
|
|
|
* (autoreleasing) the instances yourself. So when you use
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <code>new</code> you typically do something like:
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>
|
|
|
|
|
* NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);
|
|
|
|
|
* </code>
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
2002-08-20 15:07:58 +00:00
|
|
|
|
* You do not normally need to override <code>new</code> in
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* subclasses, because if you override <code>init</code> (and
|
|
|
|
|
* optionally <code>allocWithZone:</code> if you really
|
|
|
|
|
* need), <code>new</code> will automatically use your
|
|
|
|
|
* subclass methods.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* You might need instead to define new <code>new...</code>
|
|
|
|
|
* methods specific to your subclass to match any
|
|
|
|
|
* <code>init...</code> specific to your subclass. For
|
|
|
|
|
* example, if your subclass defines an instance method
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>initWithName:</code>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* </p>
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <p>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* it might be handy for you to have a class method
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>newWithName:</code>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* </p>
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <p>
|
|
|
|
|
* which combines <code>alloc</code> and
|
|
|
|
|
* <code>initWithName:</code>. You would implement it as follows:
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* <code>
|
|
|
|
|
* + (id) newWithName: (NSString *)aName
|
|
|
|
|
* {
|
|
|
|
|
* return [[self alloc] initWithName: aName];
|
|
|
|
|
* }
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* </code>
|
|
|
|
|
* </p>
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1998-07-15 12:48:14 +00:00
|
|
|
|
+ (id) new
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1998-07-15 12:48:14 +00:00
|
|
|
|
return [[self alloc] init];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-09 04:57:04 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the class of which the receiver is an instance.<br />
|
|
|
|
|
* The default implementation returns the private <code>isa</code>
|
|
|
|
|
* instance variable of NSObject, which is used to store a pointer
|
|
|
|
|
* to the objects class.<br />
|
|
|
|
|
* NB. When NSZombie is enabled (see NSDebug.h) this pointer is
|
|
|
|
|
* changed upon object deallocation.
|
|
|
|
|
*/
|
|
|
|
|
- (Class) class
|
|
|
|
|
{
|
|
|
|
|
return object_get_class(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the name of the class of the receiving object by using
|
|
|
|
|
* the NSStringFromClass() function.<br />
|
|
|
|
|
* This is a MacOS-X addition for apple scripting, which is also
|
|
|
|
|
* generally useful.
|
|
|
|
|
*/
|
|
|
|
|
- (NSString*) className
|
|
|
|
|
{
|
|
|
|
|
return NSStringFromClass([self class]);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Creates and returns a copy of the reciever by calling -copyWithZone:
|
|
|
|
|
* passing NSDefaultMallocZone()
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (id) copy
|
|
|
|
|
{
|
2002-06-01 08:55:19 +00:00
|
|
|
|
return [(id)self copyWithZone: NSDefaultMallocZone()];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2002-08-07 15:30:03 +00:00
|
|
|
|
* Deallocates the receiver by calling NSDeallocateObject() with self
|
|
|
|
|
* as the argument.<br />
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* <p>
|
|
|
|
|
* You should normally call the superclass implementation of this method
|
|
|
|
|
* when you override it in a subclass, or the memory occupied by your
|
|
|
|
|
* object will not be released.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>NSObject</code>'s implementation of this method
|
|
|
|
|
* destroys the receiver, by returning the memory allocated
|
|
|
|
|
* to the receiver to the system. After this method has been
|
|
|
|
|
* called on an instance, you must not refer the instance in
|
|
|
|
|
* any way, because it does not exist any longer. If you do,
|
|
|
|
|
* it is a bug and your program might even crash with a
|
|
|
|
|
* segmentation fault.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* If you have turned on the debugging facilities for
|
|
|
|
|
* instance allocation, <code>NSObject</code>'s
|
|
|
|
|
* implementation of this method will also update the various
|
|
|
|
|
* counts and monitors of allocated instances (see the
|
|
|
|
|
* <code>GSDebugAllocation...</code> functions for more
|
|
|
|
|
* info).
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* Normally you are supposed to manage the memory taken by
|
|
|
|
|
* objects by using the high level interface provided by the
|
|
|
|
|
* <code>retain</code>, <code>release</code> and
|
|
|
|
|
* <code>autorelease</code> methods (or better by the
|
|
|
|
|
* corresponding macros <code>RETAIN</code>,
|
|
|
|
|
* <code>RELEASE</code> and <code>AUTORELEASE</code>), and by
|
|
|
|
|
* autorelease pools and such; whenever the
|
|
|
|
|
* release/autorelease mechanism determines that an object is
|
|
|
|
|
* no longer needed (which happens when its retain count
|
|
|
|
|
* reaches 0), it will call the <code>dealloc</code> method
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* to actually deallocate the object. This means that normally,
|
|
|
|
|
* you should not need to call <code>dealloc</code> directly as
|
|
|
|
|
* the gnustep base library automatically calls it for you when
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* the retain count of an object reaches 0.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* Because the <code>dealloc</code> method will be called
|
|
|
|
|
* when an instance is being destroyed, if instances of your
|
|
|
|
|
* subclass use objects or resources (as it happens for most
|
|
|
|
|
* useful classes), you must override <code>dealloc</code> in
|
|
|
|
|
* subclasses to release all objects and resources which are
|
|
|
|
|
* used by the instance, otherwise these objects and
|
|
|
|
|
* resources would be leaked. In the subclass
|
|
|
|
|
* implementation, you should first release all your subclass
|
|
|
|
|
* specific objects and resources, and then invoke super's
|
|
|
|
|
* implementation (which will do the same, and so on up in
|
|
|
|
|
* the class hierarchy to <code>NSObject</code>'s
|
|
|
|
|
* implementation, which finally destroys the object). Here
|
|
|
|
|
* is an example of the implementation of
|
|
|
|
|
* <code>dealloc</code> for a subclass whose instances have a
|
|
|
|
|
* single instance variable <code>name</code> which needs to
|
|
|
|
|
* be released when an instance is deallocated:
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>
|
|
|
|
|
* - (void) dealloc
|
|
|
|
|
* {
|
|
|
|
|
* RELEASE (name);
|
|
|
|
|
* [super dealloc];
|
|
|
|
|
* }
|
|
|
|
|
* </code>
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* <code>dealloc</code> might contain code to release not
|
|
|
|
|
* only objects, but also other resources, such as open
|
|
|
|
|
* files, network connections, raw memory allocated in other
|
|
|
|
|
* ways, etc.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* If you have allocated the memory using a non-standard mechanism, you
|
|
|
|
|
* will not call the superclass (NSObject) implementation of the method
|
|
|
|
|
* as you will need to handle the deallocation specially.<br />
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* In some circumstances, an object may wish to prevent itself from
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* being deallocated, it can do this simply be refraining from calling
|
|
|
|
|
* the superclass implementation.
|
|
|
|
|
* </p>
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
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
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* This method is an anachronism. Do not use it.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) free
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1996-03-26 19:35:47 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
2000-06-30 11:59:59 +00:00
|
|
|
|
format: @"Use `dealloc' instead of `free' for %@.", self];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialises the receiver ... the NSObject implementation simply returns self.
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (id) init
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Creates and rturns a mutable copy of the receiver by calling
|
|
|
|
|
* -mutableCopyWithZone: passing NSDefaultMallocZone().
|
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (id) mutableCopy
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2002-06-01 08:55:19 +00:00
|
|
|
|
return [(id)self mutableCopyWithZone: NSDefaultMallocZone()];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* Returns the super class from which the receiver was derived.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-04-01 20:21:53 +00:00
|
|
|
|
+ (Class) superclass
|
|
|
|
|
{
|
2003-08-24 23:07:41 +00:00
|
|
|
|
return GSObjCSuper(self);
|
1995-04-01 20:21:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* Returns the super class from which the receivers class was derived.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (Class) superclass
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2003-09-10 08:34:24 +00:00
|
|
|
|
return GSObjCSuper(GSObjCClass(self));
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a flag to say if instances of the receiver class will
|
|
|
|
|
* respond to the specified selector. This ignores situations
|
|
|
|
|
* where a subclass implements -forwardInvocation: to respond to
|
|
|
|
|
* selectors not normally handled ... in these cases the subclass
|
|
|
|
|
* may override this method to handle it.
|
2003-02-18 11:43:57 +00:00
|
|
|
|
* <br />If given a null selector, raises NSInvalidArgumentException when
|
|
|
|
|
* in MacOS-X compatibility more, or returns NO otherwise.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
+ (BOOL) instancesRespondToSelector: (SEL)aSelector
|
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSelector == 0)
|
2003-02-18 11:43:57 +00:00
|
|
|
|
{
|
|
|
|
|
if (GSUserDefaultsFlag(GSMacOSXCompatible))
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given",
|
|
|
|
|
NSStringFromSelector(_cmd)];
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1998-11-27 13:27:58 +00:00
|
|
|
|
return __objc_responds_to((id)&self, aSelector);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a flag to say whether the receiving class conforms to aProtocol
|
|
|
|
|
*/
|
1995-03-27 17:25:42 +00:00
|
|
|
|
+ (BOOL) conformsToProtocol: (Protocol*)aProtocol
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
struct objc_protocol_list* proto_list;
|
|
|
|
|
|
2001-12-18 20:04:50 +00:00
|
|
|
|
for (proto_list = ((struct objc_class*)self)->protocols;
|
1996-05-31 16:12:24 +00:00
|
|
|
|
proto_list; proto_list = proto_list->next)
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int i;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2001-12-18 20:04:50 +00:00
|
|
|
|
for (i = 0; i < proto_list->count; i++)
|
2003-01-03 20:14:47 +00:00
|
|
|
|
{
|
|
|
|
|
/* xxx We should add conformsToProtocol to Protocol class. */
|
|
|
|
|
if ([proto_list->list[i] conformsTo: aProtocol])
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if ([self superclass])
|
2001-12-18 20:04:50 +00:00
|
|
|
|
{
|
|
|
|
|
return [[self superclass] conformsToProtocol: aProtocol];
|
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
else
|
2001-12-18 20:04:50 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a flag to say whether the class of the receiver conforms
|
|
|
|
|
* to aProtocol.
|
|
|
|
|
*/
|
1995-03-27 17:25:42 +00:00
|
|
|
|
- (BOOL) conformsToProtocol: (Protocol*)aProtocol
|
|
|
|
|
{
|
2002-06-01 08:55:19 +00:00
|
|
|
|
return [[self class] conformsToProtocol: aProtocol];
|
1995-03-27 17:25:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 17:02:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a pointer to the C function implementing the method used
|
|
|
|
|
* to respond to messages with aSelector by instances of the receiving
|
|
|
|
|
* class.
|
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
|
|
|
|
*/
|
1998-11-02 10:17:28 +00:00
|
|
|
|
+ (IMP) instanceMethodForSelector: (SEL)aSelector
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSelector == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
1998-10-26 12:14:12 +00:00
|
|
|
|
/*
|
|
|
|
|
* Since 'self' is an class, get_imp() will get the instance method.
|
|
|
|
|
*/
|
|
|
|
|
return get_imp((Class)self, aSelector);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
1998-10-26 12:14:12 +00:00
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a pointer to the C function implementing the method used
|
|
|
|
|
* to respond to messages with aSelector.
|
2002-08-27 17:02:05 +00:00
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (IMP) methodForSelector: (SEL)aSelector
|
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSelector == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
1998-10-26 12:14:12 +00:00
|
|
|
|
/*
|
2000-10-31 16:17:33 +00:00
|
|
|
|
* If 'self' is an instance, GSObjCClass() will get the class,
|
1998-10-26 12:14:12 +00:00
|
|
|
|
* and get_imp() will get the instance method.
|
2000-10-31 16:17:33 +00:00
|
|
|
|
* If 'self' is a class, GSObjCClass() will get the meta-class,
|
1998-10-26 12:14:12 +00:00
|
|
|
|
* and get_imp() will get the class method.
|
|
|
|
|
*/
|
2000-10-31 16:17:33 +00:00
|
|
|
|
return get_imp(GSObjCClass(self), aSelector);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a pointer to the C function implementing the method used
|
|
|
|
|
* to respond to messages with aSelector whihc are sent to instances
|
|
|
|
|
* of the receiving class.
|
2002-08-27 17:02:05 +00:00
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1998-07-29 09:36:16 +00:00
|
|
|
|
+ (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector
|
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
struct objc_method *mth;
|
|
|
|
|
|
|
|
|
|
if (aSelector == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
2004-08-20 17:53:16 +00:00
|
|
|
|
mth = GSGetMethod(self, aSelector, YES, YES);
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types]
|
|
|
|
|
: nil;
|
1998-07-29 09:36:16 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the method signature describing how the receiver would handle
|
|
|
|
|
* a message with aSelector.
|
2002-08-27 17:02:05 +00:00
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
|
|
|
|
|
{
|
2003-07-04 09:33:53 +00:00
|
|
|
|
const char *types;
|
|
|
|
|
struct objc_method *mth;
|
|
|
|
|
Class c;
|
2001-01-03 11:22:59 +00:00
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (aSelector == 0)
|
2002-08-27 17:02:05 +00:00
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
2004-08-20 17:53:16 +00:00
|
|
|
|
c = (GSObjCIsInstance(self) ? GSObjCClass(self) : (Class)self);
|
|
|
|
|
mth = GSGetMethod(c, aSelector, GSObjCIsInstance(self), YES);
|
2003-07-04 09:33:53 +00:00
|
|
|
|
|
2001-03-07 21:21:10 +00:00
|
|
|
|
if (mth == 0)
|
2001-04-10 03:27:01 +00:00
|
|
|
|
{
|
2003-07-04 09:33:53 +00:00
|
|
|
|
return nil; // Method not implemented
|
2001-04-10 03:27:01 +00:00
|
|
|
|
}
|
2003-06-20 18:53:34 +00:00
|
|
|
|
types = mth->method_types;
|
2003-07-04 09:33:53 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there are protocols that this class conforms to,
|
|
|
|
|
* the method may be listed in a protocol with more
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* detailed type information than in the class itself
|
2003-07-04 09:33:53 +00:00
|
|
|
|
* and we must therefore use the information from the
|
|
|
|
|
* protocol.
|
|
|
|
|
* This is because protocols also carry information
|
|
|
|
|
* used by the Distributed Objects system, which the
|
|
|
|
|
* runtime does not maintain in classes.
|
|
|
|
|
*/
|
|
|
|
|
if (c->protocols != 0)
|
|
|
|
|
{
|
|
|
|
|
struct objc_protocol_list *protocols = c->protocols;
|
|
|
|
|
BOOL found = NO;
|
|
|
|
|
|
|
|
|
|
while (found == NO && protocols != 0)
|
|
|
|
|
{
|
|
|
|
|
unsigned i = 0;
|
|
|
|
|
|
|
|
|
|
while (found == NO && i < protocols->count)
|
|
|
|
|
{
|
|
|
|
|
Protocol *p;
|
|
|
|
|
struct objc_method_description *pmth;
|
|
|
|
|
|
|
|
|
|
p = protocols->list[i++];
|
|
|
|
|
if (c == (Class)self)
|
|
|
|
|
{
|
|
|
|
|
pmth = [p descriptionForClassMethod: aSelector];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pmth = [p descriptionForInstanceMethod: aSelector];
|
|
|
|
|
}
|
|
|
|
|
if (pmth != 0)
|
|
|
|
|
{
|
|
|
|
|
types = pmth->types;
|
|
|
|
|
found = YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
protocols = protocols->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (types == 0)
|
2000-07-04 10:17:03 +00:00
|
|
|
|
{
|
2001-03-07 21:21:10 +00:00
|
|
|
|
return nil;
|
2000-07-04 10:17:03 +00:00
|
|
|
|
}
|
|
|
|
|
return [NSMethodSignature signatureWithObjCTypes: types];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a string describing the receiver. The default implementation
|
2002-08-20 10:22:05 +00:00
|
|
|
|
* gives the class and memory location of the receiver.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (NSString*) description
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1999-12-13 12:14:01 +00:00
|
|
|
|
return [NSString stringWithFormat: @"<%s: %lx>",
|
2003-08-24 23:07:41 +00:00
|
|
|
|
GSClassNameFromObject(self), (unsigned long)self];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a string describing the receiving class. The default implementation
|
|
|
|
|
* gives the name of the class by calling NSStringFromClass().
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
+ (NSString*) description
|
|
|
|
|
{
|
2002-06-01 08:55:19 +00:00
|
|
|
|
return NSStringFromClass(self);
|
1998-12-18 17:05:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sets up the ObjC runtime so that the receiver is used wherever code
|
|
|
|
|
* calls for aClassObject to be used.
|
|
|
|
|
*/
|
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);
|
1998-10-07 11:26:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* We may have replaced a class in the cache, or may have replaced one
|
|
|
|
|
* which had cached methods, so we must rebuild the cache.
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Raises an invalid argument exception providing infomration about
|
|
|
|
|
* the receivers inability to handle aSelector.
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (void) doesNotRecognizeSelector: (SEL)aSelector
|
|
|
|
|
{
|
1996-09-17 14:33:30 +00:00
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
2002-06-01 08:55:19 +00:00
|
|
|
|
format: @"%s(%s) does not recognize %s",
|
2005-02-22 11:22:44 +00:00
|
|
|
|
GSClassNameFromObject(self),
|
2002-01-31 15:41:47 +00:00
|
|
|
|
GSObjCIsInstance(self) ? "instance" : "class",
|
2003-08-24 23:07:41 +00:00
|
|
|
|
aSelector ? GSNameFromSelector(aSelector) : "(null)"];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
- (retval_t) forward: (SEL)aSel : (arglist_t)argFrame
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
1998-05-21 13:41:55 +00:00
|
|
|
|
NSInvocation *inv;
|
|
|
|
|
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSel == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
2000-10-24 11:58:25 +00:00
|
|
|
|
inv = AUTORELEASE([[NSInvocation alloc] initWithArgframe: argFrame
|
2002-06-01 08:55:19 +00:00
|
|
|
|
selector: aSel]);
|
|
|
|
|
[self forwardInvocation: inv];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
return [inv returnFrame: argFrame];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* This method is called automatically to handle a message sent to
|
|
|
|
|
* the receiver for which the receivers class has no method.<br />
|
2005-07-01 17:31:07 +00:00
|
|
|
|
* The default implemnentation calls -doesNotRecognizeSelector:
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (void) forwardInvocation: (NSInvocation*)anInvocation
|
|
|
|
|
{
|
2002-06-01 08:55:19 +00:00
|
|
|
|
[self doesNotRecognizeSelector: [anInvocation selector]];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Called after the receiver has been created by decoding some sort
|
|
|
|
|
* of archive. Returns self. Subclasses may override this to perform
|
|
|
|
|
* some special initialisation upon being decoded.
|
|
|
|
|
*/
|
1995-01-26 17:55:52 +00:00
|
|
|
|
- (id) awakeAfterUsingCoder: (NSCoder*)aDecoder
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
// FIXME - should this be added (as in OS X) now that we have NSKeyedArchiver?
|
|
|
|
|
// - (Class) classForKeyedArchiver
|
|
|
|
|
// {
|
|
|
|
|
// return [self classForArchiver];
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Override to substitute class when an instance is being archived by an
|
|
|
|
|
* [NSArchiver]. Default implementation returns -classForCoder.
|
|
|
|
|
*/
|
1998-10-11 06:26:40 +00:00
|
|
|
|
- (Class) classForArchiver
|
|
|
|
|
{
|
|
|
|
|
return [self classForCoder];
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Override to substitute class when an instance is being serialized by an
|
|
|
|
|
* [NSCoder]. Default implementation returns <code>[self class]</code> (no
|
|
|
|
|
* substitution).
|
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
- (Class) classForCoder
|
|
|
|
|
{
|
|
|
|
|
return [self class];
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Override to substitute class when an instance is being serialized by an
|
|
|
|
|
* [NSPortCoder]. Default implementation returns -classForCoder .
|
|
|
|
|
*/
|
1998-10-11 06:26:40 +00:00
|
|
|
|
- (Class) classForPortCoder
|
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self classForCoder];
|
1998-10-11 06:26:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
// FIXME - should this be added (as in OS X) now that we have NSKeyedArchiver?
|
|
|
|
|
// - (id) replacedmentObjectForKeyedArchiver: (NSKeyedArchiver *)keyedArchiver
|
|
|
|
|
// {
|
|
|
|
|
// return [self replacementObjectForCoder: (NSArchiver *)keyedArchiver];
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Override to substitute another object for this instance when being archived
|
|
|
|
|
* by given [NSArchiver]. Default implementation returns
|
|
|
|
|
* -replacementObjectForCoder:.
|
|
|
|
|
*/
|
1998-10-22 10:02:39 +00:00
|
|
|
|
- (id) replacementObjectForArchiver: (NSArchiver*)anArchiver
|
1998-10-11 06:26:40 +00:00
|
|
|
|
{
|
|
|
|
|
return [self replacementObjectForCoder: (NSCoder*)anArchiver];
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Override to substitute another object for this instance when being
|
|
|
|
|
* serialized by given [NSCoder]. Default implementation returns
|
|
|
|
|
* <code>self</code>.
|
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (id) replacementObjectForCoder: (NSCoder*)anEncoder
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-21 07:31:31 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the actual object to be encoded for sending over the
|
|
|
|
|
* network on a Distributed Objects connection.<br />
|
|
|
|
|
* The default implementation returns self if the receiver is being
|
|
|
|
|
* sent <em>bycopy</em> and returns a proxy otherwise.<br />
|
|
|
|
|
* Subclasses may override this method to change this behavior,
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* eg. to ensure that they are always copied.
|
2002-08-21 07:31:31 +00:00
|
|
|
|
*/
|
1998-10-11 06:26:40 +00:00
|
|
|
|
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder
|
|
|
|
|
{
|
2000-06-26 11:12:13 +00:00
|
|
|
|
static Class proxyClass = 0;
|
|
|
|
|
static IMP proxyImp = 0;
|
|
|
|
|
|
|
|
|
|
if (proxyImp == 0)
|
|
|
|
|
{
|
|
|
|
|
proxyClass = [NSDistantObject class];
|
2000-06-28 09:35:12 +00:00
|
|
|
|
/*
|
|
|
|
|
* use get_imp() because NSDistantObject doesn't implement
|
|
|
|
|
* methodForSelector:
|
|
|
|
|
*/
|
2000-10-31 16:17:33 +00:00
|
|
|
|
proxyImp = get_imp(GSObjCClass((id)proxyClass),
|
2000-06-28 09:35:12 +00:00
|
|
|
|
@selector(proxyWithLocal:connection:));
|
2000-06-26 11:12:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([aCoder isBycopy])
|
|
|
|
|
{
|
|
|
|
|
return self;
|
1998-10-11 06:26:40 +00:00
|
|
|
|
}
|
2000-06-26 11:12:13 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return (*proxyImp)(proxyClass, @selector(proxyWithLocal:connection:),
|
|
|
|
|
self, [aCoder connection]);
|
1998-10-11 06:26:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1996-01-26 19:18:08 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
/* NSObject protocol */
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Adds the receiver to the current autorelease pool, so that it will be
|
|
|
|
|
* sent a -release message when the pool is destroyed.<br />
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* Returns the receiver.<br />
|
|
|
|
|
* In GNUstep, the [NSObject+enableDoubleReleaseCheck:] method may be used
|
|
|
|
|
* to turn on checking for ratain/release errors in this method.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1999-12-13 12:14:01 +00:00
|
|
|
|
- (id) autorelease
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#if GS_WITH_GC == 0
|
1995-08-04 20:52:07 +00:00
|
|
|
|
if (double_release_check_enabled)
|
|
|
|
|
{
|
|
|
|
|
unsigned release_count;
|
1997-10-28 14:34:49 +00:00
|
|
|
|
unsigned retain_count = [self retainCount];
|
1995-08-04 20:52:07 +00:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
1998-10-25 07:56:22 +00:00
|
|
|
|
(*autorelease_imp)(autorelease_class, autorelease_sel, self);
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Dummy method returning the receiver.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (id) autorelease
|
1995-04-05 01:54:16 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the receiver.
|
|
|
|
|
*/
|
1998-09-28 20:38:02 +00:00
|
|
|
|
+ (Class) class
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the hash of the receiver. Subclasses should ensure that their
|
|
|
|
|
* implementations of this method obey the rule that if the -isEqual: method
|
|
|
|
|
* returns YES for two instances of the class, the -hash method returns the
|
2004-08-11 05:24:55 +00:00
|
|
|
|
* same value for both instances.<br />
|
|
|
|
|
* The default implementation returns a value based on the address
|
|
|
|
|
* of the instance.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (unsigned) hash
|
|
|
|
|
{
|
2004-08-11 05:24:55 +00:00
|
|
|
|
/*
|
|
|
|
|
* Ideally we would shift left to lose any zero bits produced by the
|
|
|
|
|
* alignment of the object in memory ... but that depends on the
|
|
|
|
|
* processor architecture and the memory allocatiion implementation.
|
|
|
|
|
* In the absence of detailed information, pick a reasonable value
|
|
|
|
|
* assuming the object will be aligned to an eight byte boundary.
|
|
|
|
|
*/
|
|
|
|
|
return (unsigned)self >> 3;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Tests anObject and the receiver for equality. The default implementation
|
|
|
|
|
* considers two objects to be equal only if they are the same object
|
|
|
|
|
* (ie occupy the same memory location).<br />
|
|
|
|
|
* If a subclass overrides this method, it should also override the -hash
|
|
|
|
|
* method so that if two objects are equal they both have the same hash.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (BOOL) isEqual: (id)anObject
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
return (self == anObject);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if aClass is the NSObject class
|
|
|
|
|
*/
|
1998-06-24 17:22:34 +00:00
|
|
|
|
+ (BOOL) isKindOfClass: (Class)aClass
|
|
|
|
|
{
|
1999-07-28 14:49:41 +00:00
|
|
|
|
if (aClass == [NSObject class])
|
|
|
|
|
return YES;
|
1998-06-24 17:22:34 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if the class of the receiver is either the same as aClass
|
|
|
|
|
* or is derived from (a subclass of) aClass.
|
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL) isKindOfClass: (Class)aClass
|
|
|
|
|
{
|
2000-10-31 16:17:33 +00:00
|
|
|
|
Class class = GSObjCClass(self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
2000-10-31 16:17:33 +00:00
|
|
|
|
return GSObjCIsKindOf(class, aClass);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if aClass is the same as the receiving class.
|
|
|
|
|
*/
|
1998-06-24 17:22:34 +00:00
|
|
|
|
+ (BOOL) isMemberOfClass: (Class)aClass
|
|
|
|
|
{
|
2000-10-31 16:17:33 +00:00
|
|
|
|
return (self == aClass) ? YES : NO;
|
1998-06-24 17:22:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if the class of the receiver is aClass
|
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL) isMemberOfClass: (Class)aClass
|
|
|
|
|
{
|
2000-10-31 16:17:33 +00:00
|
|
|
|
return (GSObjCClass(self) == aClass) ? YES : NO;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2002-08-14 07:36:25 +00:00
|
|
|
|
* Returns a flag to differentiate between 'true' objects, and objects
|
2002-06-01 08:55:19 +00:00
|
|
|
|
* which are proxies for other objects (ie they forward messages to the
|
|
|
|
|
* other objects).<br />
|
|
|
|
|
* The default implementation returns NO.
|
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL) isProxy
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 14:24:54 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if the receiver is aClass or a subclass of aClass.
|
|
|
|
|
*/
|
|
|
|
|
+ (BOOL) isSubclassOfClass: (Class)aClass
|
|
|
|
|
{
|
|
|
|
|
return GSObjCIsKindOf(self, aClass);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Causes the receiver to execute the method implementation corresponding
|
|
|
|
|
* to aSelector and returns the result.<br />
|
|
|
|
|
* The method must be one which takes no arguments and returns an object.
|
2002-08-27 17:02:05 +00:00
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) performSelector: (SEL)aSelector
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1998-10-26 12:14:12 +00:00
|
|
|
|
IMP msg;
|
|
|
|
|
|
|
|
|
|
if (aSelector == 0)
|
2002-08-27 17:02:05 +00:00
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-10-31 16:17:33 +00:00
|
|
|
|
msg = get_imp(GSObjCClass(self), aSelector);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (!msg)
|
1996-03-26 20:59:42 +00:00
|
|
|
|
{
|
1998-10-26 12:14:12 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
2003-08-24 23:07:41 +00:00
|
|
|
|
format: @"invalid selector passed to %s",
|
|
|
|
|
GSNameFromSelector(_cmd)];
|
1996-03-26 20:59:42 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (*msg)(self, aSelector);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Causes the receiver to execute the method implementation corresponding
|
|
|
|
|
* to aSelector and returns the result.<br />
|
|
|
|
|
* The method must be one which takes one argument and returns an object.
|
2002-08-27 17:02:05 +00:00
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) performSelector: (SEL)aSelector withObject: (id) anObject
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1998-10-26 12:14:12 +00:00
|
|
|
|
IMP msg;
|
|
|
|
|
|
|
|
|
|
if (aSelector == 0)
|
2002-08-27 17:02:05 +00:00
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-10-31 16:17:33 +00:00
|
|
|
|
msg = get_imp(GSObjCClass(self), aSelector);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (!msg)
|
1996-03-26 20:59:42 +00:00
|
|
|
|
{
|
1998-10-26 12:14:12 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
2005-02-22 11:22:44 +00:00
|
|
|
|
format: @"invalid selector passed to %s",
|
2003-08-24 23:07:41 +00:00
|
|
|
|
GSNameFromSelector(_cmd)];
|
1996-03-26 20:59:42 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
1998-10-26 12:14:12 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (*msg)(self, aSelector, anObject);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Causes the receiver to execute the method implementation corresponding
|
|
|
|
|
* to aSelector and returns the result.<br />
|
|
|
|
|
* The method must be one which takes two arguments and returns an object.
|
2002-08-27 17:02:05 +00:00
|
|
|
|
* <br />Raises NSInvalidArgumentException if given a null selector.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) performSelector: (SEL)aSelector
|
|
|
|
|
withObject: (id) object1
|
|
|
|
|
withObject: (id) object2
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1998-10-26 12:14:12 +00:00
|
|
|
|
IMP msg;
|
|
|
|
|
|
|
|
|
|
if (aSelector == 0)
|
2002-08-27 17:02:05 +00:00
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-10-31 16:17:33 +00:00
|
|
|
|
msg = get_imp(GSObjCClass(self), aSelector);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (!msg)
|
1996-03-26 20:59:42 +00:00
|
|
|
|
{
|
1998-10-26 12:14:12 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
2003-08-24 23:07:41 +00:00
|
|
|
|
format: @"invalid selector passed to %s", GSNameFromSelector(_cmd)];
|
1996-03-26 20:59:42 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
1998-10-26 12:14:12 +00:00
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return (*msg)(self, aSelector, object1, object2);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 05:08:10 +00:00
|
|
|
|
/**
|
2002-08-07 15:30:03 +00:00
|
|
|
|
* Decrements the retain count for the receiver if greater than zeron,
|
|
|
|
|
* otherwise calls the dealloc method instead.<br />
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* The default implementation calls the NSDecrementExtraRefCountWasZero()
|
|
|
|
|
* function to test the extra reference count for the receiver (and
|
|
|
|
|
* decrement it if non-zero) - if the extra reference count is zero then
|
|
|
|
|
* the retain count is one, and the dealloc method is called.<br />
|
|
|
|
|
* In GNUstep, the [NSObject+enableDoubleReleaseCheck:] method may be used
|
2002-08-07 15:30:03 +00:00
|
|
|
|
* to turn on checking for ratain/release errors in this method.
|
2002-06-01 05:08:10 +00:00
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (oneway void) release
|
|
|
|
|
{
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#if GS_WITH_GC == 0
|
1995-08-04 20:52:07 +00:00
|
|
|
|
if (double_release_check_enabled)
|
|
|
|
|
{
|
|
|
|
|
unsigned release_count;
|
1997-10-28 14:34:49 +00:00
|
|
|
|
unsigned retain_count = [self retainCount];
|
1995-08-04 20:52:07 +00:00
|
|
|
|
release_count = [autorelease_class autoreleaseCountForObject:self];
|
1997-10-28 14:34:49 +00:00
|
|
|
|
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))
|
1999-12-15 17:31:01 +00:00
|
|
|
|
{
|
2002-08-07 15:30:03 +00:00
|
|
|
|
[self dealloc];
|
1999-12-15 17:31:01 +00:00
|
|
|
|
}
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 05:08:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* The class implementation of the release method is a dummy method
|
|
|
|
|
* having no effect. It is present so that class objects can be stored
|
|
|
|
|
* in containers (such as NSArray) which will send them retain and
|
|
|
|
|
* release messages.
|
|
|
|
|
*/
|
1995-04-05 01:54:16 +00:00
|
|
|
|
+ (oneway void) release
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a flag to say if the receiver will
|
|
|
|
|
* respond to the specified selector. This ignores situations
|
|
|
|
|
* where a subclass implements -forwardInvocation: to respond to
|
|
|
|
|
* selectors not normally handled ... in these cases the subclass
|
|
|
|
|
* may override this method to handle it.
|
2003-02-18 11:43:57 +00:00
|
|
|
|
* <br />If given a null selector, raises NSInvalidArgumentException when
|
|
|
|
|
* in MacOS-X compatibility more, or returns NO otherwise.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (BOOL) respondsToSelector: (SEL)aSelector
|
|
|
|
|
{
|
2002-06-29 16:01:33 +00:00
|
|
|
|
if (aSelector == 0)
|
2003-02-18 11:43:57 +00:00
|
|
|
|
{
|
|
|
|
|
if (GSUserDefaultsFlag(GSMacOSXCompatible))
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given",
|
|
|
|
|
NSStringFromSelector(_cmd)];
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2003-10-16 14:56:35 +00:00
|
|
|
|
|
1998-11-27 13:27:58 +00:00
|
|
|
|
return __objc_responds_to(self, aSelector);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 05:08:10 +00:00
|
|
|
|
/**
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* Increments the reference count and returns the receiver.<br />
|
|
|
|
|
* The default implementation does this by calling NSIncrementExtraRefCount()
|
2002-06-01 05:08:10 +00:00
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) retain
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#if GS_WITH_GC == 0
|
1995-03-24 20:09:36 +00:00
|
|
|
|
NSIncrementExtraRefCount(self);
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 05:08:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* The class implementation of the retain method is a dummy method
|
|
|
|
|
* having no effect. It is present so that class objects can be stored
|
|
|
|
|
* in containers (such as NSArray) which will send them retain and
|
|
|
|
|
* release messages.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (id) retain
|
1995-04-05 01:54:16 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 05:08:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the reference count for the receiver. Each instance has an
|
|
|
|
|
* implicit reference count of 1, and has an 'extra refrence count'
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* returned by the NSExtraRefCount() function, so the value returned by
|
|
|
|
|
* this method is always greater than zero.<br />
|
|
|
|
|
* By convention, objects which should (or can) never be deallocated
|
|
|
|
|
* return the maximum unsigned integer value.
|
2002-06-01 05:08:10 +00:00
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
- (unsigned) retainCount
|
|
|
|
|
{
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
return UINT_MAX;
|
|
|
|
|
#else
|
1999-05-21 18:14:48 +00:00
|
|
|
|
return NSExtraRefCount(self) + 1;
|
1999-01-28 17:21:03 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 05:08:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* The class implementation of the retainCount method always returns
|
|
|
|
|
* the maximum unsigned integer value, as classes can not be deallocated
|
|
|
|
|
* the retain count mechanism is a dummy system for them.
|
|
|
|
|
*/
|
1995-04-05 01:54:16 +00:00
|
|
|
|
+ (unsigned) retainCount
|
|
|
|
|
{
|
|
|
|
|
return UINT_MAX;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the reciever.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) self
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the memory allocation zone in which the receiver is located.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (NSZone*) zone
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2000-10-31 16:17:33 +00:00
|
|
|
|
return GSObjCZone(self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Called to encode the instance variables of the receiver to aCoder.<br />
|
|
|
|
|
* Subclasses should call the superclass method at the start of their
|
|
|
|
|
* own implementation.
|
|
|
|
|
*/
|
1995-04-09 01:53:53 +00:00
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Called to intialise instance variables of the receiver from aDecoder.<br />
|
|
|
|
|
* Subclasses should call the superclass method at the start of their
|
|
|
|
|
* own implementation.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* Returns the version number of the receiving class. This will default to
|
|
|
|
|
* a number assigned by the Objective C compiler if [NSObject -setVersion] has
|
|
|
|
|
* not been called.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (int) version
|
1998-09-28 20:38:02 +00:00
|
|
|
|
{
|
|
|
|
|
return class_get_version(self);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* Sets the version number of the receiving class. Should be nonnegative.
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (id) setVersion: (int)aVersion
|
1998-09-28 20:38:02 +00:00
|
|
|
|
{
|
1998-10-09 13:54:54 +00:00
|
|
|
|
if (aVersion < 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%s +setVersion: may not set a negative version",
|
2003-08-24 23:07:41 +00:00
|
|
|
|
GSClassNameFromObject(self)];
|
1998-09-28 20:38:02 +00:00
|
|
|
|
class_set_version(self, aVersion);
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1994-11-08 16:44:01 +00:00
|
|
|
|
@end
|
|
|
|
|
|
1996-07-15 18:41:44 +00:00
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Methods for compatibility with the NEXTSTEP (pre-OpenStep) 'Object' class.
|
|
|
|
|
*/
|
1995-03-12 15:40:22 +00:00
|
|
|
|
@implementation NSObject (NEXTSTEP)
|
|
|
|
|
|
|
|
|
|
/* NEXTSTEP Object class compatibility */
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Logs a message. <em>Deprecated.</em> Use NSLog() in new code.
|
|
|
|
|
*/
|
2002-06-01 08:55:19 +00:00
|
|
|
|
- (id) 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"
|
2003-08-24 23:07:41 +00:00
|
|
|
|
char fmt[(strlen((char*)FMT)+strlen((char*)GSClassNameFromObject(self))
|
1995-03-12 15:40:22 +00:00
|
|
|
|
+((aString!=NULL)?strlen((char*)aString):0)+8)];
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
2003-08-24 23:07:41 +00:00
|
|
|
|
sprintf(fmt, FMT, GSClassNameFromObject(self),
|
2000-10-31 16:17:33 +00:00
|
|
|
|
GSObjCIsInstance(self)?"instance":"class",
|
1995-03-12 15:40:22 +00:00
|
|
|
|
(aString!=NULL)?aString:"");
|
|
|
|
|
va_start(ap, aString);
|
1996-09-07 21:07:27 +00:00
|
|
|
|
/* xxx What should `code' argument be? Current 0. */
|
|
|
|
|
objc_verror (self, 0, fmt, ap);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
va_end(ap);
|
|
|
|
|
return nil;
|
|
|
|
|
#undef FMT
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/*
|
1996-02-24 16:38:43 +00:00
|
|
|
|
- (const char *) name
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
2003-08-24 23:07:41 +00:00
|
|
|
|
return GSClassNameFromObject(self);
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-01-26 17:55:52 +00:00
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (BOOL) isKindOf: (Class)aClassObject
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self isKindOfClass: aClassObject];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (BOOL) isMemberOf: (Class)aClassObject
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self isMemberOfClass: aClassObject];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (BOOL) instancesRespondTo: (SEL)aSel
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self instancesRespondToSelector: aSel];
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (BOOL) respondsTo: (SEL)aSel
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self respondsToSelector: aSel];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (BOOL) conformsTo: (Protocol*)aProtocol
|
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self conformsToProtocol: aProtocol];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-03-27 17:25:42 +00:00
|
|
|
|
- (BOOL) conformsTo: (Protocol*)aProtocol
|
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self conformsToProtocol: aProtocol];
|
1995-03-27 17:25:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (retval_t) performv: (SEL)aSel :(arglist_t)argFrame
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSel == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return objc_msg_sendv(self, aSel, argFrame);
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (IMP) instanceMethodFor: (SEL)aSel
|
1995-01-26 17:55:52 +00:00
|
|
|
|
{
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return [self instanceMethodForSelector:aSel];
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-28 09:35:12 +00:00
|
|
|
|
+ (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector
|
1997-09-01 21:59:51 +00:00
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
struct objc_method* mth;
|
|
|
|
|
|
|
|
|
|
if (aSelector == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
2004-08-20 17:53:16 +00:00
|
|
|
|
mth = GSGetMethod(self, aSelector, YES, YES);
|
2000-06-28 09:35:12 +00:00
|
|
|
|
return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types]
|
|
|
|
|
: nil;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (IMP) methodFor: (SEL)aSel
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
return [self methodForSelector: aSel];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
+ (id) poseAs: (Class)aClassObject
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2000-06-30 11:59:59 +00:00
|
|
|
|
[self poseAsClass: aClassObject];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return self;
|
1995-01-26 17:55:52 +00:00
|
|
|
|
}
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) doesNotRecognize: (SEL)aSel
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
1996-03-26 20:59:42 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
2002-01-31 15:41:47 +00:00
|
|
|
|
format: @"%s(%s) does not recognize %s",
|
2005-02-22 11:22:44 +00:00
|
|
|
|
GSClassNameFromObject(self),
|
2002-01-31 15:41:47 +00:00
|
|
|
|
GSObjCIsInstance(self) ? "instance" : "class",
|
2003-08-24 23:07:41 +00:00
|
|
|
|
aSel ? GSNameFromSelector(aSel) : "(null)"];
|
1996-03-26 20:59:42 +00:00
|
|
|
|
return nil;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) perform: (SEL)sel with: (id)anObject
|
1995-03-23 03:31:30 +00:00
|
|
|
|
{
|
1998-09-28 20:38:02 +00:00
|
|
|
|
return [self performSelector:sel withObject:anObject];
|
1995-03-23 03:31:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) perform: (SEL)sel with: (id)anObject with: (id)anotherObject
|
1995-04-03 01:32:58 +00:00
|
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
|
return [self performSelector:sel withObject:anObject
|
1998-09-28 20:38:02 +00:00
|
|
|
|
withObject:anotherObject];
|
|
|
|
|
}
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
@end
|
|
|
|
|
|
1996-07-15 18:41:44 +00:00
|
|
|
|
|
2000-11-27 22:26:08 +00:00
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Some non-standard extensions mainly needed for backwards compatibility
|
|
|
|
|
* and internal utility reasons.
|
|
|
|
|
*/
|
2004-04-16 23:21:26 +00:00
|
|
|
|
@implementation NSObject (GNUstep)
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
|
|
|
|
/* GNU Object class compatibility */
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Called to change the class used for autoreleasing objects.
|
|
|
|
|
*/
|
1995-03-12 19:29:37 +00:00
|
|
|
|
+ (void) setAutoreleaseClass: (Class)aClass
|
|
|
|
|
{
|
|
|
|
|
autorelease_class = aClass;
|
1998-10-25 07:56:22 +00:00
|
|
|
|
autorelease_imp = [self instanceMethodForSelector: autorelease_sel];
|
1995-03-12 19:29:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* returns the class used to autorelease objects.
|
|
|
|
|
*/
|
1995-03-12 19:29:37 +00:00
|
|
|
|
+ (Class) autoreleaseClass
|
|
|
|
|
{
|
|
|
|
|
return autorelease_class;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-01 08:55:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Enables runtime checking of retain/release/autorelease operations.<br />
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* <p>Whenever either -autorelease or -release is called, the contents of any
|
2002-06-01 08:55:19 +00:00
|
|
|
|
* autorelease pools will be checked to see if there are more outstanding
|
|
|
|
|
* release operations than the objects retain count. In which case an
|
|
|
|
|
* exception is raised to say that the object is released too many times.
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* </p>
|
|
|
|
|
* <p><strong>Beware</strong>, since this feature entails examining all active
|
|
|
|
|
* autorelease pools every time an object is released or autoreleased, it
|
|
|
|
|
* can cause a massive performance degradation ... it should only be enabled
|
|
|
|
|
* for debugging.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
2002-10-27 01:38:30 +00:00
|
|
|
|
* When you are having memory allocation problems, it may make more sense
|
|
|
|
|
* to look at the memory allocation debugging functions documented in
|
|
|
|
|
* NSDebug.h, or use the NSZombie features.
|
2002-06-02 09:05:11 +00:00
|
|
|
|
* </p>
|
2002-06-01 08:55:19 +00:00
|
|
|
|
*/
|
1995-08-04 20:52:07 +00:00
|
|
|
|
+ (void) enableDoubleReleaseCheck: (BOOL)enable
|
|
|
|
|
{
|
|
|
|
|
double_release_check_enabled = enable;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* The default (NSObject) implementation of this method simply calls
|
|
|
|
|
* the -description method and discards the locale
|
|
|
|
|
* information.
|
|
|
|
|
*/
|
2002-01-06 11:26:49 +00:00
|
|
|
|
- (NSString*) descriptionWithLocale: (NSDictionary*)aLocale
|
|
|
|
|
{
|
|
|
|
|
return [self description];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (NSString*) descriptionWithLocale: (NSDictionary*)aLocale
|
|
|
|
|
{
|
|
|
|
|
return [self description];
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* The default (NSObject) implementation of this method simply calls
|
|
|
|
|
* the -descriptionWithLocale: method and discards the
|
|
|
|
|
* level information.
|
|
|
|
|
*/
|
2002-01-06 11:26:49 +00:00
|
|
|
|
- (NSString*) descriptionWithLocale: (NSDictionary*)aLocale
|
|
|
|
|
indent: (unsigned)level
|
|
|
|
|
{
|
|
|
|
|
return [self descriptionWithLocale: aLocale];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (NSString*) descriptionWithLocale: (NSDictionary*)aLocale
|
|
|
|
|
indent: (unsigned)level
|
|
|
|
|
{
|
|
|
|
|
return [self descriptionWithLocale: aLocale];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) _dealloc
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
- (BOOL) isMetaClass
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
- (BOOL) isClass
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2003-09-10 08:34:24 +00:00
|
|
|
|
return GSObjCIsClass((Class)self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
- (BOOL) isInstance
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2000-10-31 16:17:33 +00:00
|
|
|
|
return GSObjCIsInstance(self);
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
- (BOOL) isMemberOfClassNamed: (const char*)aClassName
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
return ((aClassName!=NULL)
|
2002-02-21 13:31:13 +00:00
|
|
|
|
&&!strcmp(GSNameFromClass(GSObjCClass(self)), aClassName));
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
+ (struct objc_method_description *) descriptionForInstanceMethod: (SEL)aSel
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSel == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return ((struct objc_method_description *)
|
2004-08-20 17:53:16 +00:00
|
|
|
|
GSGetMethod(self, aSel, YES, YES));
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
- (struct objc_method_description *) descriptionForMethod: (SEL)aSel
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSel == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return ((struct objc_method_description *)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
GSGetMethod((GSObjCIsInstance(self)
|
2004-08-20 17:53:16 +00:00
|
|
|
|
? GSObjCClass(self) : (Class)self),
|
|
|
|
|
aSel,
|
|
|
|
|
GSObjCIsInstance(self),
|
|
|
|
|
YES));
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-14 08:52:39 +00:00
|
|
|
|
/**
|
|
|
|
|
* Transmutes the receiver into an immutable version of the same object
|
|
|
|
|
* and returns the result.<br />
|
|
|
|
|
* If the receiver is not a mutable object or cannot be simply transmuted,
|
|
|
|
|
* then this method either returns the receiver unchanged or,
|
|
|
|
|
* if the force flag is set to YES, returns an autoreleased copy of the
|
|
|
|
|
* receiver.<br />
|
|
|
|
|
* Mutable classes should override this default implementation.<br />
|
|
|
|
|
* This method is used in methods which are declared to return immutable
|
|
|
|
|
* objects (eg. an NSArray), but which create and build mutable ones
|
|
|
|
|
* internally.
|
|
|
|
|
*/
|
|
|
|
|
- (id) makeImmutableCopyOnFail: (BOOL)force
|
|
|
|
|
{
|
|
|
|
|
if (force == YES)
|
|
|
|
|
{
|
|
|
|
|
return AUTORELEASE([self copy]);
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Changes the class of the receiver (the 'isa' pointer) to be aClassObject,
|
|
|
|
|
* but only if the receiver is an instance of a subclass of aClassObject
|
|
|
|
|
* which has not added extra instance variables.<br />
|
|
|
|
|
* Returns zero on failure, or the old class on success.
|
|
|
|
|
*/
|
2000-03-17 13:13:08 +00:00
|
|
|
|
- (Class) transmuteClassTo: (Class)aClassObject
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2000-10-31 16:17:33 +00:00
|
|
|
|
if (GSObjCIsInstance(self) == YES)
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (class_is_class(aClassObject))
|
|
|
|
|
if (class_get_instance_size(aClassObject)==class_get_instance_size(isa))
|
2002-10-14 08:52:39 +00:00
|
|
|
|
if ([self isKindOfClass: aClassObject])
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
Class old_isa = isa;
|
|
|
|
|
isa = aClassObject;
|
|
|
|
|
return old_isa;
|
|
|
|
|
}
|
2002-10-14 08:52:39 +00:00
|
|
|
|
return 0;
|
1995-03-12 15:40:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-17 13:13:08 +00:00
|
|
|
|
+ (int) streamVersion: (TypedStream*)aStream
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2001-08-28 18:45:17 +00:00
|
|
|
|
#ifndef NeXT_RUNTIME
|
1995-03-12 15:40:22 +00:00
|
|
|
|
if (aStream->mode == OBJC_READONLY)
|
|
|
|
|
return objc_get_stream_class_version (aStream, self);
|
|
|
|
|
else
|
2001-08-28 18:45:17 +00:00
|
|
|
|
#endif
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return class_get_version (self);
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
//NOTE: original comments included the following excerpt, however it is
|
|
|
|
|
// probably not relevant now since the implementations are stubbed out.
|
|
|
|
|
// 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.
|
1995-03-12 15:40:22 +00:00
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Originally used to read the instance variables declared in this
|
|
|
|
|
* particular part of the object from a stream. Currently stubbed out.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) read: (TypedStream*)aStream
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
|
// [super read: aStream];
|
1995-03-12 15:40:22 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Originally used to write the instance variables declared in this
|
|
|
|
|
* particular part of the object to a stream. Currently stubbed out.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) write: (TypedStream*)aStream
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
// [super write: aStream];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Originally used before [NSCoder] and related classes existed. Currently
|
|
|
|
|
* stubbed out.
|
|
|
|
|
*/
|
2000-06-30 11:59:59 +00:00
|
|
|
|
- (id) awake
|
1995-03-12 15:40:22 +00:00
|
|
|
|
{
|
|
|
|
|
// [super awake];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
1998-11-12 10:58:17 +00:00
|
|
|
|
|
2000-02-24 22:16:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Stuff for compatibility with 'Object' derived classes.
|
|
|
|
|
*/
|
|
|
|
|
@interface Object (NSObjectCompat)
|
2002-06-14 08:59:28 +00:00
|
|
|
|
+ (NSString*) description;
|
2000-02-24 22:16:53 +00:00
|
|
|
|
+ (void) release;
|
|
|
|
|
+ (id) retain;
|
2002-06-14 08:59:28 +00:00
|
|
|
|
- (NSString*) className;
|
|
|
|
|
- (NSString*) description;
|
2000-02-24 22:16:53 +00:00
|
|
|
|
- (void) release;
|
2002-06-14 08:59:28 +00:00
|
|
|
|
- (BOOL) respondsToSelector: (SEL)aSel;
|
2000-02-24 22:16:53 +00:00
|
|
|
|
- (id) retain;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation Object (NSObjectCompat)
|
2002-06-14 08:59:28 +00:00
|
|
|
|
+ (NSString*) description
|
|
|
|
|
{
|
|
|
|
|
return NSStringFromClass(self);
|
|
|
|
|
}
|
2000-02-24 22:16:53 +00:00
|
|
|
|
+ (void) release
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
+ (id) retain
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
2002-06-14 08:59:28 +00:00
|
|
|
|
- (NSString*) className
|
|
|
|
|
{
|
|
|
|
|
return NSStringFromClass([self class]);
|
|
|
|
|
}
|
|
|
|
|
- (NSString*) description
|
|
|
|
|
{
|
|
|
|
|
return [NSString stringWithFormat: @"<%s: %lx>",
|
2003-08-24 23:07:41 +00:00
|
|
|
|
GSClassNameFromObject(self), (unsigned long)self];
|
2002-06-14 08:59:28 +00:00
|
|
|
|
}
|
2002-08-19 10:26:07 +00:00
|
|
|
|
- (BOOL) isProxy
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2000-02-24 22:16:53 +00:00
|
|
|
|
- (void) release
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2002-06-14 08:59:28 +00:00
|
|
|
|
- (BOOL) respondsToSelector: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
/* Object implements -respondsTo: */
|
|
|
|
|
return [self respondsTo: aSelector];
|
|
|
|
|
}
|
2000-02-24 22:16:53 +00:00
|
|
|
|
- (id) retain
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
|
|
|
|
|
|
2005-07-01 17:31:07 +00:00
|
|
|
|
@interface NSZombie
|
|
|
|
|
- (retval_t) forward:(SEL)aSel :(arglist_t)argFrame;
|
|
|
|
|
- (void) forwardInvocation: (NSInvocation*)anInvocation;
|
|
|
|
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector;
|
|
|
|
|
@end
|
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
@implementation NSZombie
|
|
|
|
|
- (retval_t) forward:(SEL)aSel :(arglist_t)argFrame
|
|
|
|
|
{
|
2002-08-27 17:02:05 +00:00
|
|
|
|
if (aSel == 0)
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
|
|
|
|
|
|
2002-03-27 09:55:57 +00:00
|
|
|
|
GSLogZombie(self, aSel);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
- (void) forwardInvocation: (NSInvocation*)anInvocation
|
|
|
|
|
{
|
|
|
|
|
unsigned size = [[anInvocation methodSignature] methodReturnLength];
|
|
|
|
|
unsigned char v[size];
|
|
|
|
|
|
|
|
|
|
memset(v, '\0', size);
|
|
|
|
|
GSLogZombie(self, [anInvocation selector]);
|
|
|
|
|
[anInvocation setReturnValue: (void*)v];
|
|
|
|
|
return;
|
|
|
|
|
}
|
2003-07-23 21:42:03 +00:00
|
|
|
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
Class c;
|
|
|
|
|
|
|
|
|
|
if (allocationLock != 0)
|
|
|
|
|
{
|
|
|
|
|
objc_mutex_lock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
c = NSMapGet(zombieMap, (void*)self);
|
|
|
|
|
if (allocationLock != 0)
|
|
|
|
|
{
|
|
|
|
|
objc_mutex_unlock(allocationLock);
|
|
|
|
|
}
|
|
|
|
|
return [c instanceMethodSignatureForSelector: aSelector];
|
|
|
|
|
}
|
2002-03-27 09:55:57 +00:00
|
|
|
|
@end
|
|
|
|
|
|