libs-gsweb/GSWeb.framework/NSObject+IVarAccess+PerformSel.m
David Ayers 048a35991b * GSWeb.framework/GSWUtils.h/m
(IsStyle,IsNumberStyle, ExceptionRaise, ExceptionRaise0,
	ValidationExceptionRaise, ValidationExceptionRaise0,
	ExceptionByAddingUserInfoObjectFrameInfo,
	ExceptionByAddingUserInfoObjectFrameInfo0,
	ExceptionByAddingUserInfoFunctionFrameInfo,
	ExceptionByAddingUserInfoFunctionFrameInfo0, ): Reformat
	defines.
	(GSW_LOCK_LIMIT): New define.
	(ExceptionRaiseFn, ExceptionRaiseFn0,
	ValidationExceptionRaiseFn,
	ValidationExceptionRaiseFn0): Reformat declaration.
	(TmpLock, TmpTryLockBeforeDate, TmpLockBeforeDate, TmpUnlock):
	Remove.
	([NSLock isLocked]): Remove.
	([NSLock tmplock]): Ditto.
	([NSLock tmplockFromFunction:file:line:]): Ditto.
	([NSLock tmptryLock]): Ditto.
	([NSLock tmptryLockFromFunction:file:line:]): Ditto.
	([NSLock tmptryLockBeforeDate:]): Ditto.
	([NSLock tmptryLockBeforeDate:fromFunction:file:line:]):
	Ditto.
	([NSLock tmpunlock]): Ditto.
	([NSLock tmpunlockFromFunction:file:line:]): Ditto.
	([NSLock description]): Ditto.
	([NSRecursiveLock isLocked]): Ditto.
	([NSRecursiveLock tmplock]): Ditto.
	([NSRecursiveLock tmplockFromFunction:file:line:]): Ditto.
	([NSRecursiveLock tmptryLock]): Ditto.
	([NSRecursiveLock tmptryLockFromFunction:file:line:]): Ditto.
	([NSRecursiveLock tmptryLockBeforeDate:]): Ditto.
	([NSRecursiveLock
	tmptryLockBeforeDate:fromFunction:file:line:]):
	Ditto.
	([NSRecursiveLock tmpunlock]): Ditto.
	([NSRecursiveLock tmpunlockFromFunction:file:line:]): Ditto.
	(NSLockException, MessageForMutexLockError)
	(LoggedLock, LoggedLockBeforeDate, LoggedTryLock,
	LoggedTryLockBeforeDate, LoggedUnlock): New macros.
	(loggedLockBeforeDateFromFunctionInFileInLine,
	loggedUnlockFromFunctionInFileInLine): New logging lock
	functions.
	([NSThread description]): New Category.
	(volatileInternalDescription): New static function.
	(GSW_LOCK_LIMIT): New marco.
	* GSWeb.framework/GSWApplication.m
	([GSWApplication isRequestHandlingLocked]): Test lock instead
	of relying on obsolete lock categories.
	([GSWApplication lockRequestHandling]): Use new locking
	macros.
	([GSWApplication unlockRequestHandling]): Ditto.
	([GSWApplication lock]): Ditto.
	([GSWApplication unlock]): Ditto.
	* GSWeb.framework/GSWAssociation.m
	([GSWAssociation setClasse:forHandler:]): Ditto
	([GSWAssociation addLogHandlerClasse:]): Ditto.
	([GSWAssociation removeLogHandlerClasse:]): Ditto.
	([GSWAssociation logValue:forSet:]): Ditto.
	([GSWAssociation
	logSynchronizeForValue:inComponent:componentToParent:]):
	Ditto.
	* GSWeb.framework/GSWBundle.m
	([GSWBundle unlock]): Ditto.
	([GSWBundle lock]): Ditto.
	* GSWeb.framework/GSWDefaultAdaptor.m
	([GSWDefaultAdaptor tryLock]): Ditto.
	([GSWDefaultAdaptor unlock]): Ditto.
	* GSWeb.framework/GSWDeployedBundle.m
	([GSWDeployedBundle lock]): Ditto.
	([GSWDeployedBundle unlock]): Ditto.
	* GSWeb.framework/GSWResourceManager.m
	([GSWResourceManager unlock]): Ditto.
	([GSWResourceManager lock]): Ditto.
	* GSWeb.framework/GSWSessionStore.m
	([GSWSessionStore unlock]): Ditto.
	([GSWSessionStore tryLock]): Ditto.
	([GSWSessionStore lock]): Ditto.
	* GSWeb.framework/GSWSessionTimeOutManager.m
	([GSWSessionTimeOutManager
	tryLockBeforeTimeIntervalSinceNow:]):
	Ditto.
	([GSWSessionTimeOutManager lockBeforeTimeIntervalSinceNow]):
	Ditto.
	([GSWSessionTimeOutManager unlock]): Ditto.
	* GSWeb.framework/GSWStaticResourceRequestHandler.m
	([GSWStaticResourceRequestHandler handleRequest:]): Ditto.
	* GSWeb.framework/GSWStatisticsStore.m
	([GSWStatisticsStore unlock]): Ditto.
	([GSWStatisticsStore lock]): Ditto.
	* GSWeb.framework/NSObject+IVarAccess+PerformSel.m:
	([NSObject getIVarNamed]): Use GSW_LOCK_LIMIT macro.
	Reformat.
	([NSObject setIVarNamed:withValue:]): Ditto.

	* Makefile.postamble: Remove autom4te.cache on distclean.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@18605 72102866-910b-0410-8b05-ffd578937521
2004-02-16 14:37:46 +00:00

959 lines
27 KiB
Objective-C

/* NSObject+IVarAccess+PerformSel.m
Copyright (C) 1999 Free Software Foundation, Inc.
Written by: Manuel Guesdon <mguesdon@sbuilders.com>
Date: Jan 1999
This file is part of the GNUstep Web Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
static char rcsId[] = "$Id$";
#include "GSWeb.h"
NSMutableDictionary* objectIVarAccessCache_Set=nil;
NSMutableDictionary* objectIVarAccessCache_Get=nil;
NSLock* objectClassLock=nil;
//===================================================================================
typedef enum
{
NSObjectIVarsAccessType_Error = -1,
NSObjectIVarsAccessType_None = 0,
NSObjectIVarsAccessType_PerformSelector,
NSObjectIVarsAccessType_Invocation,
NSObjectIVarsAccessType_Direct,
NSObjectIVarsAccessType_Dictionary,
NSObjectIVarsAccessType_DictionaryWithRemoveObject,
NSObjectIVarsAccessType_DictionaryWithoutRemoveObject,
NSObjectIVarsAccessType_EO
} NSObjectIVarsAccessType;
//====================================================================
@interface NSObjectIVarsAccess : NSObject
{
@public
NSObjectIVarsAccessType accessType;
union
{
SEL selector;
NSInvocation* invocation;
struct objc_ivar* ivar;
} infos;
};
+(id)ivarAccess;
@end
//====================================================================
@implementation NSObjectIVarsAccess
//--------------------------------------------------------------------
+(id)ivarAccess
{
return [[self new]autorelease];
};
//--------------------------------------------------------------------
-(void)dealloc
{
if (accessType==NSObjectIVarsAccessType_Invocation)
{
DESTROY(infos.invocation);
};
[super dealloc];
};
@end
//====================================================================
struct objc_ivar* GSGetInstanceVariableStruct(id obj,
NSString* iVarName,
BOOL underscored)
{
const char* name=NULL;
Class class;
struct objc_ivar_list *ivars=NULL;
struct objc_ivar *ivar=NULL;
if (underscored)
iVarName=[NSString stringWithFormat:@"_%@",iVarName];
name=[iVarName cString];
class=[obj class];
while (class && !ivar)
{
ivars = class->ivars;
class = class->super_class;
if (ivars)
{
int i;
for (i=0;!ivar && i<ivars->ivar_count;i++)
{
if (strcmp(ivars->ivar_list[i].ivar_name, name)==0)
ivar = &ivars->ivar_list[i];
};
};
};
return ivar;
};
//--------------------------------------------------------------------
const char* GSGetInstanceVariableType(id obj,
NSString *iVarName,
BOOL underscored)
{
struct objc_ivar *ivar = GSGetInstanceVariableStruct(obj,iVarName,underscored);
if (ivar)
return ivar->ivar_type;
else
return NULL;
};
//====================================================================
@implementation NSObject (IVarsAccess)
//--------------------------------------------------------------------
+(BOOL)isIVarAccessCachingDisabled
{
return NO;
};
//--------------------------------------------------------------------
+(NSString*)getFunctionNameWithTemplate:(NSString*)tpl
forVariable:(NSString*)varName
uppercaseFirstLetter:(BOOL)uppercaseFirstLetter
{
NSString* fn=nil;
if (tpl && [tpl length]>0)
{
NSString* fnMain=nil;
if (uppercaseFirstLetter)
{
NSString* first=[[varName substringToIndex:1] uppercaseString];
NSString* next=[varName substringFromIndex:1];
fnMain=[NSString stringWithFormat:@"%@%@",first,next];
}
else
fnMain=varName;
fn=[NSString stringWithFormat:tpl,fnMain];
}
else
fn=[NSString stringWithString:varName];
return fn;
};
//--------------------------------------------------------------------
-(SEL)getSelectorWithFunctionTemplate:(NSString*)tpl
forVariable:(NSString*)varName
uppercaseFirstLetter:(BOOL)uppercaseFirstLetter
{
NSString* fnName=nil;
SEL selector=NULL;
fnName=[NSObject getFunctionNameWithTemplate:tpl
forVariable:varName
uppercaseFirstLetter:uppercaseFirstLetter];
selector=NSSelectorFromString(fnName);
if (selector && ![self respondsToSelector:selector])
selector=NULL;
return selector;
};
#if HAVE_GDL2
//--------------------------------------------------------------------
- (id)getIVarNamed:(NSString *)name_
{
id value=nil;
SEL sel = @selector(valueForKey:);//NEW NSSelectorFromString(@"valueForKey:");
//MGNEW id (*imp)(id, SEL, id) = (id (*)(id, SEL, id))[NSObject instanceMethodForSelector: sel];
NSDebugMLLog(@"low",@"getIVarNamed %@ in %@ %p (superClass:%@)",
name_,
[self class],
self,
[self superclass]);
//NSLog(@"%@",name_);
//NSLog(@"sel (valueForKey <NSObject>) : %d", (int)sel);
NS_DURING
value = [self valueForKey:name_];//MGNEW
//MGNEW value = (*imp)(self, sel, name_);
NS_HANDLER
{
NSDebugMLLog(@"low",@"getIVarNamed %@ in %@ %p (superClass:%@). valueForKey: exception",
name_,
[self class],
self,
[self superclass]);
if([self respondsToSelector:@selector(objectForKey:)] == YES) {
if (name_) {
value = [self objectForKey:name_];
} else {
value=nil;
}
} else {
LOGException(@"==> %@ (%@) gvfk from string=%p gvfk sel=%p initWithCapacity from string:=%p initWithCapacity sel:=%p NSStringFromSelector(sel)",
localException,
[localException reason],
NSSelectorFromString(@"valueForKey:"),
@selector(valueForKey:),
NSSelectorFromString(@"initWithCapacity:"),
@selector(initWithCapacity:),
NSStringFromSelector(sel));
[localException raise];
}
}
NS_ENDHANDLER;
return value;
}
//--------------------------------------------------------------------
- (void)setIVarNamed:(NSString *)name_
withValue:(id)value_
{
SEL sel = @selector(takeValue:forKey:);//NEW NSSelectorFromString(@"takeValue:forKey:");
//MGNEW id (*imp)(id, SEL, id, id) = (id (*)(id, SEL, id, id))[NSObject instanceMethodForSelector: sel];
//NSLog(@"sel (takeValue:forKey: <NSObject>) : %d", (int)sel);
NS_DURING
//NSLog(@"setIVarNamed : self = %@", NSStringFromClass([self class]));
//NSLog(@"setIVarNamed : name_ = %@ (%@)", name_, NSStringFromClass([name_ class]));
//NSLog(@"setIVarNamed : value_ = %@ (%@)", value_, NSStringFromClass([value_ class]));
[self takeValue:value_ forKey:name_];//MGNEW
//MGNEW (*imp)(self, sel, value_, name_);
NS_HANDLER
{
if (![name_ isEqualToString:@"self"]) {
if([self respondsToSelector:@selector(setObject:forKey:)] == YES) {
if (value_ && name_) {
[self setObject:value_ forKey:name_];
}
} else {
[localException raise];
}
}
}
NS_ENDHANDLER;
}
#else
//--------------------------------------------------------------------
id PDataToId(const char* retType,void* pdata)
{
id value=nil;
switch(*retType)
{
case _C_CLASS:
value=*((id*)pdata);
break;
case _C_ID:
value=*((id*)pdata);
break;
case _C_CHR:
value=[NSNumber numberWithChar:*((char*)pdata)];
break;
case _C_UCHR:
value=[NSNumber numberWithUnsignedChar:*((unsigned char*)pdata)];
break;
case _C_SHT:
value=[NSNumber numberWithShort:*((short*)pdata)];
break;
case _C_USHT:
value=[NSNumber numberWithUnsignedShort:*((unsigned short*)pdata)];
break;
case _C_INT:
value=[NSNumber numberWithInt:*((int*)pdata)];
break;
case _C_UINT:
value=[NSNumber numberWithUnsignedInt:*((unsigned int*)pdata)];
break;
case _C_LNG:
value=[NSNumber numberWithLong:*((long*)pdata)];
break;
case _C_ULNG:
value=[NSNumber numberWithUnsignedLong:*((unsigned long*)pdata)];
break;
case _C_FLT:
value=[NSNumber numberWithFloat:*((float*)pdata)];
break;
case _C_DBL:
value=[NSNumber numberWithFloat:*((double*)pdata)];
break;
case _C_CHARPTR:
value=[NSString stringWithCString:*((char**)pdata)];
break;
case _C_SEL:
case _C_VOID:
case _C_PTR:
case _C_STRUCT_B:
default:
//TODO
break;
};
return value;
};
//--------------------------------------------------------------------
void IdToPData(const char* retType,id _value,void* pdata)
{
switch(*retType)
{
case _C_CLASS:
*((Class*)pdata)=_value;
break;
case _C_ID:
*((id*)pdata)=_value;
break;
case _C_CHR:
*((char*)pdata)=[_value charValue];
break;
case _C_UCHR:
*((unsigned char*)pdata)=[_value unsignedCharValue];
break;
case _C_SHT:
*((short*)pdata)=[_value shortValue];
break;
case _C_USHT:
*((unsigned short*)pdata)=[_value unsignedShortValue];
break;
case _C_INT:
*((int*)pdata)=[_value intValue];
break;
case _C_UINT:
*((unsigned int*)pdata)=[_value unsignedIntValue];
break;
case _C_LNG:
*((long*)pdata)=[_value longValue];
break;
case _C_ULNG:
*((unsigned long*)pdata)=[_value unsignedLongValue];
break;
case _C_FLT:
*((float*)pdata)=[_value floatValue];
break;
case _C_DBL:
*((double*)pdata)=[_value doubleValue];
break;
case _C_CHARPTR:
case _C_SEL:
case _C_VOID:
case _C_PTR:
case _C_STRUCT_B:
default:
//TODO
break;
};
};
//--------------------------------------------------------------------
-(id)getIVarNamed:(NSString*)name_
withCacheObject:(NSObjectIVarsAccess*)ivarAccess_
{
id _value=nil;
switch(ivarAccess_->accessType)
{
case NSObjectIVarsAccessType_Error:
break;
case NSObjectIVarsAccessType_None:
break;
case NSObjectIVarsAccessType_PerformSelector:
NSDebugMLLog(@"low",@"getIVarNamed %@ in %@ %p (superClass:%@)with performSelector",
name_,
[self class],
self,
[self superclass]);
_value=[self performSelector:ivarAccess_->infos.selector];
break;
case NSObjectIVarsAccessType_Invocation:
{
const char* retType=[[ivarAccess_->infos.invocation methodSignature] methodReturnType];
NSAssert([ivarAccess_->infos.invocation selector],@"No Selector in Invocation");
[ivarAccess_->infos.invocation setTarget:self];
[ivarAccess_->infos.invocation invoke];
if (*retType!=_C_VOID)
{
void* pdata=objc_atomic_malloc(objc_sizeof_type(retType));
if (!pdata)
{
NSAssert(pdata,@"No ret value buffer");
//TODO
}
else
{
NSDebugMLLog(@"low",
@"getIVarNamed %@ in %@ %p (superClass:%@) with invocation %@ (retType=%s)",
name_,
[self class],
self,
[self superclass],
ivarAccess_->infos.invocation,
retType);
[ivarAccess_->infos.invocation getReturnValue:pdata];
_value=PDataToId(retType,pdata);
objc_free(pdata);
};
};
};
break;
case NSObjectIVarsAccessType_Direct:
{
const char* IVarType=ivarAccess_->infos.ivar->ivar_type;
unsigned int size=objc_sizeof_type(IVarType);
void* pdata=objc_atomic_malloc(size);
NSDebugMLLog(@"low",@"getIVarNamed %@ in %@ %p (superClass:%@) by variable ",
name_,
[self class],
self,
[self superclass]);
if (pdata)
{
int offset = ivarAccess_->infos.ivar->ivar_offset;
memcpy(pdata,((void*)self)+offset, size);
_value=PDataToId(IVarType,pdata);
objc_free(pdata);
}
else
{
//TODO
NSAssert(NO,@"no pdata");
};
};
break;
case NSObjectIVarsAccessType_Dictionary:
_value=[self objectForKey:name_];
break;
case NSObjectIVarsAccessType_EO:
_value=[self valueForKey:name_];
break;
default:
break;
};
return _value;
};
//--------------------------------------------------------------------
-(id)getIVarNamed:(NSString*)name_
{
id _value=nil;
NSException* _exception=nil;
BOOL _cachindEnabled=YES;
Class _class=Nil;
NSObjectIVarsAccess* _ivarAccess=nil;
NSMutableDictionary* _classCache=nil;
LOGObjectFnStart();
NSDebugMLLog(@"low",@"getIVarNamed %@ in %p %@ (superClass:%@)",
name_,self,[self class],[self superclass]);
_class=[self class];
_classCache=[objectIVarAccessCache_Get objectForKey:_class];
if (!_classCache)
{
_cachindEnabled=![_class isIVarAccessCachingDisabled];
if (_cachindEnabled)
{
if (!objectClassLock)
objectClassLock=[NSLock new];
LoggedLockBeforeDate(objectClassLock, GSW_LOCK_LIMIT);
_classCache=[NSMutableDictionary dictionary];
if (!objectIVarAccessCache_Get)
objectIVarAccessCache_Get=[NSMutableDictionary new];
[objectIVarAccessCache_Get setObject:_classCache
forKey:_class];
LoggedUnlock(objectClassLock);
};
};
if (_cachindEnabled)
_ivarAccess=[_classCache objectForKey:name_];
if (!_ivarAccess)
{
SEL sel=NULL;
_ivarAccess=[NSObjectIVarsAccess ivarAccess];
sel=[self getSelectorWithFunctionTemplate:@"get%@"
forVariable:name_
uppercaseFirstLetter:YES];
if (!sel)
sel=[self getSelectorWithFunctionTemplate:@"%@"
forVariable:name_
uppercaseFirstLetter:NO];
NSDebugMLLog(@"low",@"getIVarNamed %@ in %@ %p sel=%p ",
name_,[self class],self,(void*)sel);
if (sel)
{
NSMethodSignature* _sig = [self methodSignatureForSelector:sel];
if ([_sig numberOfArguments]!=2)
{
_exception =[NSException exceptionWithName: @"NSObject IVar"
format: @"Can't get Variable named "
@"%@ in %@ %p (superClass:%@): "
@"fn args mismatch",
name_,
[self class],
self,
[self superclass]];
}
else
{
const char* retType=[_sig methodReturnType];
NSDebugMLLog(@"low",@"retType=%s",retType);
if (!retType)
{
_exception=[NSException exceptionWithName:@"NSObject IVar"
format:@"Can't get Variable named "
@"%@ in %@ %p (superClass:%@): "
@"fn unknown type",
name_,
[self class],
self,
[self superclass]];
}
else
{
if (*retType==_C_ID)
{
_ivarAccess->accessType
= NSObjectIVarsAccessType_PerformSelector;
_ivarAccess->infos.selector=sel;
}
else
{
NSInvocation* _invocation
= [NSInvocation invocationWithMethodSignature:_sig];
NSDebugMLLog(@"low",
@"_invocation methodSignature "
@"methodReturnType=%s",
[[_invocation methodSignature]
methodReturnType]);
[_invocation setSelector:sel];
_ivarAccess->accessType
= NSObjectIVarsAccessType_Invocation;
_ivarAccess->infos.invocation=_invocation;
NSAssert([_ivarAccess->infos.invocation selector],
@"No Selector in Invocation");
[_ivarAccess->infos.invocation retain];
};
};
};
}
else
{
struct objc_ivar* ivar=GSGetInstanceVariableStruct(self,name_,YES);
if (!ivar)
ivar=GSGetInstanceVariableStruct(self,name_,NO);
if (ivar)
{
_ivarAccess->accessType=NSObjectIVarsAccessType_Direct;
_ivarAccess->infos.ivar=ivar;
}
else
{
NSDebugMLLog(@"low",
@"getIVarNamed %@ in %@ %p (superClass:%@) "
@"with objectForKey ",
name_,
[self class],
self,
[self superclass]);
if ([self respondsToSelector:@selector(objectForKey:)])
{
_ivarAccess->accessType=NSObjectIVarsAccessType_Dictionary;
}
else if ([self respondsToSelector:@selector(valueForKey:)])
{
_ivarAccess->accessType=NSObjectIVarsAccessType_EO;
}
else
{
_exception=[NSException exceptionWithName:@"NSObject IVar"
format:@"Can't get Variable named "
@"%@ in %@ %p (superClass:%@) "
@"with objectForKey",
name_,
[self class],
self,
[self superclass]];
};
};
};
if (_exception)
_ivarAccess->accessType=NSObjectIVarsAccessType_Error;
if (_cachindEnabled)
{
if (!objectClassLock)
objectClassLock=[NSLock new];
LoggedLockBeforeDate(objectClassLock, GSW_LOCK_LIMIT);
[_classCache setObject:_ivarAccess
forKey:name_];
LoggedUnlock(objectClassLock);
};
};
if (_exception)
[_exception raise];
else
_value=[self getIVarNamed:name_
withCacheObject:_ivarAccess];
// LOGObjectFnStop();
return _value;
};
//--------------------------------------------------------------------
-(void)setIVarNamed:(NSString*)name_
withValue:(id)value_
withCacheObject:(NSObjectIVarsAccess*)ivarAccess_
{
LOGObjectFnStart();
switch(ivarAccess_->accessType)
{
case NSObjectIVarsAccessType_Error:
break;
case NSObjectIVarsAccessType_None:
break;
case NSObjectIVarsAccessType_PerformSelector:
NSDebugMLLog(@"low",
@"setIVarNamed %@ in %@ %p (superClass:%@) with performSelector value:%@",
name_,
[self class],
self,
[self superclass],
value_);
[self performSelector:ivarAccess_->infos.selector
withObject:value_];
break;
case NSObjectIVarsAccessType_Invocation:
{
const char* type=[[ivarAccess_->infos.invocation methodSignature] getArgumentTypeAtIndex:2];
void* pdata=objc_atomic_malloc(objc_sizeof_type(type));
IdToPData(type,value_,pdata);
NSAssert([ivarAccess_->infos.invocation selector],@"No Selector in Invocation");
[ivarAccess_->infos.invocation setTarget:self];
[ivarAccess_->infos.invocation setArgument:pdata
atIndex:2];
NSDebugMLLog(@"low",
@"setIVarNamed %@ in %@ %p (superClass:%@) with invocation value:%@",
name_,
[self class],
self,
[self superclass],
value_);
[ivarAccess_->infos.invocation invoke];
objc_free(pdata);
};
break;
case NSObjectIVarsAccessType_Direct:
{
const char* IVarType=ivarAccess_->infos.ivar->ivar_type;
if (IVarType)
{
unsigned int size=objc_sizeof_type(IVarType);
void* pdata=objc_atomic_malloc(size);
int offset = ivarAccess_->infos.ivar->ivar_offset;
IdToPData(IVarType,value_,pdata);
memcpy(((void*)self)+offset,pdata, size);
objc_free(pdata);
}
else
{
ExceptionRaise(@"NSObject IVar",
@"Can't set Variable named %@ in %@ %p (superClass:%@)",
name_,
[self class],
self,
[self superclass]);
};
};
break;
case NSObjectIVarsAccessType_DictionaryWithRemoveObject:
case NSObjectIVarsAccessType_DictionaryWithoutRemoveObject:
if (value_ || ivarAccess_->accessType==NSObjectIVarsAccessType_DictionaryWithoutRemoveObject)
{
NSDebugMLLog(@"low",
@"setIVarNamed %@ in %@ %p (superClass:%@) with setObjectForKey:",
name_,
[self class],
self,
[self superclass]);
// keyvalue coding
[self setObject:value_
forKey:name_];
}
else
{
NSDebugMLLog(@"low",
@"setIVarNamed %@ in %@ %p (superClass:%@) with removeObjectForKey:",
name_,
[self class],
self,
[self superclass]);
// keyvalue coding
[self removeObjectForKey:name_];
};
break;
case NSObjectIVarsAccessType_EO:
NSDebugMLLog(@"low",
@"setIVarNamed %@ in %@ %p (superClass:%@) with takeValue:forKey:",
name_,
[self class],
self,
[self superclass]);
// keyvalue coding
[self takeValue:value_
forKey:name_];
break;
default:
break;
};
LOGObjectFnStop();
};
//--------------------------------------------------------------------
-(void)setIVarNamed:(NSString*)name_
withValue:(id)value_
{
NSException* _exception=nil;
BOOL _cachindEnabled=YES;
Class _class=[self class];
NSObjectIVarsAccess* _ivarAccess=nil;
NSMutableDictionary* _classCache
= [objectIVarAccessCache_Set objectForKey:_class];
// LOGObjectFnStart();
NSDebugMLLog(@"low",
@"LOG setIVarNamed:%@ withValue:%@ in %p %@ (superClass:%@)",
name_,value_,self,[self class],[self superclass]);
if (!_classCache)
{
_cachindEnabled=![_class isIVarAccessCachingDisabled];
if (_cachindEnabled)
{
if (!objectClassLock)
objectClassLock=[NSLock new];
LoggedLockBeforeDate(objectClassLock, GSW_LOCK_LIMIT);
_classCache=[NSMutableDictionary dictionary];
if (!objectIVarAccessCache_Set)
objectIVarAccessCache_Set=[NSMutableDictionary new];
[objectIVarAccessCache_Set setObject:_classCache
forKey:_class];
LoggedUnlock(objectClassLock);
};
};
if (_cachindEnabled)
_ivarAccess=[_classCache objectForKey:name_];
if (!_ivarAccess)
{
SEL sel=NULL;
NSDebugMLLog(@"low",@"Not ivarAccess for name:%@",name_);
_ivarAccess=[NSObjectIVarsAccess ivarAccess];
// NSDebugMLLog(@"low",@"LOG setIVarNamed:%@ withValue:%@ in %@",name_,value_,[self class]);
sel=[self getSelectorWithFunctionTemplate:@"set%@:"
forVariable:name_
uppercaseFirstLetter:YES];
NSDebugMLLog(@"low",
@"sel=%ld (for %@ in %@)",
sel,name_,[self class]);
if (sel)
{
NSMethodSignature* _sig = [self methodSignatureForSelector:sel];
if ([_sig numberOfArguments]!=3)
{
_exception=[NSException exceptionWithName:@"NSObject IVar"
format:@"Can't set Variable named %@ "
@"in %@ %p (superClass:%@) "
@"(fn Bad number of Arguments)",
name_,
[self class],
self,
[self superclass]];
}
else
{
const char* type=[_sig getArgumentTypeAtIndex:2];
if (!type)
{
_exception
=[NSException exceptionWithName:@"NSObject IVar"
format:@"Can't set Variable named %@ "
@"in %@ %p (superClass:%@) "
@"(fn get argument type)",
name_,
[self class],
self,
[self superclass]];
}
else
{
if (*type==_C_ID)
{
_ivarAccess->accessType
= NSObjectIVarsAccessType_PerformSelector;
_ivarAccess->infos.selector=sel;
NSDebugMLLog(@"low",
@"perform selector (IVar named :%@)",
name_);
}
else
{
NSInvocation* _invocation
= [NSInvocation invocationWithMethodSignature:_sig];
[_invocation setSelector:sel];
_ivarAccess->accessType
= NSObjectIVarsAccessType_Invocation;
_ivarAccess->infos.invocation=_invocation;
NSAssert([_ivarAccess->infos.invocation selector],
@"No Selector in Invocation");
[_ivarAccess->infos.invocation retain];
NSDebugMLLog(@"low",
@"invocation (IVar named :%@)",
name_);
};
};
};
}
else
{
struct objc_ivar* ivar=GSGetInstanceVariableStruct(self,name_,YES);
if (!ivar)
ivar=GSGetInstanceVariableStruct(self,name_,NO);
if (ivar)
{
_ivarAccess->accessType=NSObjectIVarsAccessType_Direct;
_ivarAccess->infos.ivar=ivar;
NSDebugMLLog(@"low",
@"direct (IVar named :%@)",
name_);
}
else
{
BOOL _respondsToSetObject=NO;
BOOL _respondsToRemoveObject=NO;
NSDebugMLLog(@"low",
@"setIVarNamed %@ in %@ %p (superClass:%@) "
@"with dictionary ",
name_,
[self class],
self,
[self superclass]);
_respondsToSetObject
= [self respondsToSelector:@selector(setObject:forKey:)];
_respondsToRemoveObject
=[self respondsToSelector:@selector(removeObjectForKey:)];
if (_respondsToSetObject)
{
if (_respondsToRemoveObject)
_ivarAccess->accessType
= NSObjectIVarsAccessType_DictionaryWithRemoveObject;
else
_ivarAccess->accessType
= NSObjectIVarsAccessType_DictionaryWithoutRemoveObject;
}
else
{
BOOL _respondsToTakeValue
= [self respondsToSelector:@selector(takeValue:forKey:)];
if (_respondsToTakeValue)
_ivarAccess->accessType=NSObjectIVarsAccessType_EO;
else
{
_exception
= [NSException exceptionWithName:@"NSObject IVar"
format:@"Can't set Variable named %@ "
@"in %@ %p (superClass:%@) value=%@",
name_,
[self class],
self,
[self superclass],
value_];
};
};
};
};
if (_exception)
_ivarAccess->accessType=NSObjectIVarsAccessType_Error;
if (_cachindEnabled)
{
if (!objectClassLock)
objectClassLock=[NSLock new];
LoggedLockBeforeDate(objectClassLock, GSW_LOCK_LIMIT);
[_classCache setObject:_ivarAccess
forKey:name_];
LoggedUnlock(objectClassLock);
};
};
if (_exception)
[_exception raise];
else
[self setIVarNamed:name_
withValue:value_
withCacheObject:_ivarAccess];
// LOGObjectFnStop();
};
#endif
//--------------------------------------------------------------------
#define PERFORM_SELECTOR_WITH_XX_VALUE \
id retValue=nil; \
NSMethodSignature* methodSignature=[NSObject methodSignatureForSelector:_selector]; \
const char* retType=[methodSignature methodReturnType]; \
NSInvocation* invocation= [NSInvocation invocationWithMethodSignature:methodSignature]; \
[invocation setTarget:self]; \
[invocation setSelector:_selector]; \
[invocation setArgument:&_value atIndex:2]; \
[invocation invoke]; \
if (retType && *retType==_C_ID) \
[invocation getReturnValue:&retValue]; \
return retValue;
//--------------------------------------------------------------------
-(id)performSelector:(SEL)_selector
withIntValue:(int)_value
{
PERFORM_SELECTOR_WITH_XX_VALUE
};
//--------------------------------------------------------------------
-(id)performSelector:(SEL)_selector
withFloatValue:(float)_value
{
PERFORM_SELECTOR_WITH_XX_VALUE
};
//--------------------------------------------------------------------
-(id)performSelector:(SEL)_selector
withDoubleValue:(double)_value
{
PERFORM_SELECTOR_WITH_XX_VALUE
};
//--------------------------------------------------------------------
-(id)performSelector:(SEL)_selector
withShortValue:(short)_value
{
PERFORM_SELECTOR_WITH_XX_VALUE
};
//--------------------------------------------------------------------
-(id)performSelector:(SEL)_selector
withUShortValue:(ushort)_value
{
PERFORM_SELECTOR_WITH_XX_VALUE
};
@end