mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-02-24 04:01:16 +00:00
* 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
854 lines
24 KiB
Objective-C
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
|
|
|