libs-gsweb/GSWeb.framework/NSObject+IVarAccess+PerformSel.m
mguesdon 6a4d7eeb1d 2001-03-11 Manuel Guesdon <mguesdon@orange-concept.com>
* GSWeb.framework/GSWWOCompatibility.h/.m: added
        * GSWeb.framework/GNUmakefile: added GSWWOCompatibility.h/.m
        * GSWeb.framework/GSWApplication.h/m: added WOApplicationMain, handle WO/GSWeb names
        * GSWeb.framework/GSWContext.m: handle WO/GSWeb names, added traces
        * GSWeb.framework/GSWConstants.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDynamicURLString.m: handle WO/GSWeb names
        * GSWeb.framework/GSWProjectBundle.m/.h: handle WO/GSWeb names, suppress warnings
        * GSWeb.framework/GSWSession.m: handle WO/GSWeb names
        * GSWeb.framework/GSWRequest.m: handle WO/GSWeb names
        * GSWeb.framework/GSWTemplateParser.m: handle WO/GSWeb names,
                added tag counts to help errors hunt
        * GSWeb.framework/GSWBundle.m: handle WO/GSWeb names, added traces
        * GSWeb.framework/GSWResourceManager.m: handle WO/GSWeb names
        * GSWeb.framework/GSWURLValuedElementData.m: handle WO/GSWeb names
        * GSWeb.framework/GSWComponentRequestHandler.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDirectAction.m: handle WO/GSWeb names
        * GSWeb.framework/GSWForm.m/.h: handle WO/GSWeb names
        * GSWeb.framework/GSWHyperlink.m/.h: handle WO/GSWeb names
        * GSWeb.framework/GSWResourceRequestHandler.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDirectActionRequestHandler.m: handle WO/GSWeb names
        * GSWeb.framework/GSWActiveImage.m/.h: handle WO/GSWeb names
        * GSWeb.framework/GSWBindingNameAssociation.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWBrowser.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWComponent.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWHTMLURLValuedElement.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWImageButton.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWInput.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWPopUpButton.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWString.h/.m: handle WO/GSWeb names
        * GSWeb.framework/GSWAssociation.m: handle WO/GSWeb names
        * GSWeb.framework/GSWCheckBox.m: handle WO/GSWeb names
        * GSWeb.framework/GSWCheckBoxList.m: handle WO/GSWeb names
        * GSWeb.framework/GSWComponentDefinition.m: handle WO/GSWeb names
        * GSWeb.framework/GSWRadioButton.m: handle WO/GSWeb names
        * GSWeb.framework/GSWRadioButtonList.m: handle WO/GSWeb names
        * GSWeb.framework/GSWText.m: handle WO/GSWeb names
        * GSWeb.framework/GSWTextField.m: handle WO/GSWeb names
        * GSWeb.framework/GSWDeployedBundle.m: warnings
        * GSWeb.framework/GSWeb.h: added include GSWeb/GSWSessionTimeOut.h, GSWWOCompatibility.h
        * GSWeb.framework/GSWAdaptor.m: traces
        * GSWeb.framework/GSWDefaultAdaptor.m: handle WO/GSWeb names, added traces
        * GSWeb.framework/GSWDefaultAdaptorThread.m/.h: handle WO/GSWeb names
        * GSWeb.framework/NSNonBlockingFileHandle.m: added traces
        * GSWeb.framework/GSWTemplateParserANTLR.m: handle WO/GSWeb names
        * GSWeb.framework/GSWTemplateParserXML.m: handle WO/GSWeb names
                added tag count to help errors hunt
                remove "Tag gsweb invalid" message
                handle unicode strings in node content traces
                remove html and body tags if they are not present in the template
        * GSWeb.framework/GSWTemplateParseXML.h: added ivar _isHTMLTag, _isBodyTag
        * GSWeb.framework/GSWSessionTimeOutManager.m: dealloc sessionOrderedTimeOuts instead
                of deallocating 2 times sessionTimeOuts
        * GSWExtensions.framework/French.lproj/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
                tag mismatch, Encode french characters
        * GSWExtensions.framework/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
                tag mismatch
        * GSWHTMLBareString.m: handle unicode strings in description
        * GSWExtensions.framework/French.lproj/GSWExceptionPage.gswc/GSWExceptionPage.html:
                Encode french characters, Tag Mismatch
        * GSWExtensions.framework/French.lproj/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.html:
                Encode french characters
        * GSWExtensions.framework/French.lproj/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.html:
                Encode french characters
        * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.html:
                Tag Mismatch
        * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.gswd:
                added convertHTMLEntities for strings
        * GSWeb.framework/GSWRepetition.m: added traces, fix "count" property bug, standardize ivars
        * GSWeb.framework/NSObject+IVarAccess+PerformSel.m: added traces, handle underscored ivars search


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@9332 72102866-910b-0410-8b05-ffd578937521
2001-03-11 17:15:44 +00:00

854 lines
24 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/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;
//====================================================================
@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 GDL2
//--------------------------------------------------------------------
- (id)getIVarNamed:(NSString *)name_
{
id value;
NSLog(@"%@", name_);
NS_DURING
value = [self valueForKey:name_];
NS_HANDLER
{
if([self respondsToSelector:@selector(objectForKey:)] == YES)
value = [self objectForKey:name_];
else
[localException raise];
}
NS_ENDHANDLER;
return value;
}
//--------------------------------------------------------------------
- (void)setIVarNamed:(NSString *)name_
withValue:(id)value_
{
NS_DURING
[self takeValue:value_ forKey:name_];
NS_HANDLER
{
if([self respondsToSelector:@selector(setObject:forKey:)] == YES)
[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;
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];
TmpLockBeforeDate(objectClassLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
_classCache=[NSMutableDictionary dictionary];
if (!objectIVarAccessCache_Get)
objectIVarAccessCache_Get=[NSMutableDictionary new];
[objectIVarAccessCache_Get setObject:_classCache
forKey:_class];
TmpUnlock(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
{
_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];
TmpLockBeforeDate(objectClassLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
[_classCache setObject:_ivarAccess
forKey:name_];
TmpUnlock(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;
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];
TmpLockBeforeDate(objectClassLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
_classCache=[NSMutableDictionary dictionary];
if (!objectIVarAccessCache_Set)
objectIVarAccessCache_Set=[NSMutableDictionary new];
[objectIVarAccessCache_Set setObject:_classCache
forKey:_class];
TmpUnlock(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
{
_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];
TmpLockBeforeDate(objectClassLock,[NSDate dateWithTimeIntervalSinceNow:GSLOCK_DELAY_S]);
[_classCache setObject:_ivarAccess
forKey:name_];
TmpUnlock(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