mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 00:11:26 +00:00
([Invocation -initWithReturnType:]): Use new ivar names. Use calloc
instead of malloc. ([Invocation -encodeWithCoder:]): New method. ([Invocation -initWithCoder:]): New method. ([Invocation -classForConnectedCoder:]): New method. ([Invocation -returnType]): Use new ivar name. ([Invocation -setReturnValue:]): New method. ([Invocation -objectReturnValue]): Method implemented. ([Invocation -intReturnValue]): Method implemented. ([Invocation -returnValueIsTrue]): Method implementation finished. ([Invocation -dealloc]): Use new ivar name. Release return type if necessary. ([ArgframeInvocation -_retainArguments]): New method. ([ArgframeInvocation -_initArgframeFrom:withType:retainArgs:]): Method overhauled. ([ArgframeInvocation -initWithArgframe:type:]): Use new method. ([ArgframeInvocation -encodeWithCoder:]): New method. ([ArgframeInvocation -initWithCoder:]): New method. ([ArgframeInvocation -argumentTypeAtIndex:]): Use new ivar name. ([ArgframeInvocation -retainArguments]): New method. ([ArgframeInvocation -argumentsRetained]): New method. ([ArgframeInvocation -_deallocArgframe]): New method. ([ArgframeInvocation -dealloc]): Use new method. Release args if necessary. ([MethodInvocation -_initTargetAndSelPointers]): New method. ([MethodInvocation -initWithArgframe:selector:]): Use new method. ([MethodInvocation -initWithCoder:]): New method. ([MethodInvocation -initWithTarget:selector:...]): Retain args if necessary. ([MethodInvocation -invoke]): Use new ivars. ([MethodInvocation -invokeWithTarget:]): Use -setTarget:. ([MethodInvocation -selector]): Use new ivar. ([MethodInvocation -setSelector:]): Likewise. ([MethodInvocation -target]): Likewise. ([MethodInvocation -setTarget:]): Likewise. ([ObjectMethodInvocation -_initArgObjectPointer]): New method. ([ObjectMethodInvocation -initWithArgframe:selector:]): Use new method. ([ObjectMethodInvocation -initWithCoder:]): New method. ([ObjectMethodInvocation -invokeWithObject:]): New method. (VoidFunctionInvocation): New class implementation. (ObjectFunctionInvocation): New class implementation. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@998 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
49f9e1b864
commit
645c3c3c96
1 changed files with 432 additions and 64 deletions
|
@ -1,5 +1,5 @@
|
|||
/* Implementation for Objective-C Invocation object
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
@ -23,6 +23,10 @@
|
|||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Invocation.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <objects/NSString.h>
|
||||
#include <objects/Connection.h>
|
||||
#include <objects/ConnectedCoder.h>
|
||||
|
||||
/* Deal with strrchr: */
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
|
@ -41,30 +45,20 @@
|
|||
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
|
||||
|
||||
/*
|
||||
Put something like this in Collecting:
|
||||
- withObjectsAtArgumentIndex: (unsigned)index
|
||||
invoke: (Invocation*)invocation;
|
||||
- putObjectsAtArgumentIndex: (unsigned)index
|
||||
andInvoke: (Invocation*)invocation;
|
||||
- invoke: (Invocation*)invocation
|
||||
withObjectsAtArgumentIndex: (unsigned)index
|
||||
*/
|
||||
|
||||
@implementation Invocation
|
||||
|
||||
- initWithReturnType: (const char *)enc
|
||||
{
|
||||
int l = strlen(enc);
|
||||
OBJC_MALLOC(encoding, char, l + 1);
|
||||
memcpy(encoding, enc, l);
|
||||
encoding[l] = '\0';
|
||||
enc = objc_skip_type_qualifiers (encoding);
|
||||
OBJC_MALLOC(return_type, char, l + 1);
|
||||
memcpy(return_type, enc, l);
|
||||
return_type[l] = '\0';
|
||||
enc = objc_skip_type_qualifiers (return_type);
|
||||
if (*enc != 'v')
|
||||
{
|
||||
/* Work around bug in objc_sizeof_type; it doesn't handle void type */
|
||||
return_size = objc_sizeof_type (enc);
|
||||
return_value = (*objc_malloc) (return_size);
|
||||
return_value = (*objc_calloc) (1, return_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -73,6 +67,50 @@
|
|||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[super encodeWithCoder: coder];
|
||||
[coder encodeValueOfCType: @encode(char*)
|
||||
at: &return_type
|
||||
withName: @"Invocation return type"];
|
||||
[coder encodeValueOfCType: @encode(unsigned)
|
||||
at: &return_size
|
||||
withName: @"Invocation return size"];
|
||||
if (return_size)
|
||||
[coder encodeValueOfObjCType: return_type
|
||||
at: return_value
|
||||
withName: @"Invocation return value"];
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
[coder decodeValueOfCType: @encode(char*)
|
||||
at: &return_type
|
||||
withName: NULL];
|
||||
[coder decodeValueOfCType: @encode(unsigned)
|
||||
at: &return_size
|
||||
withName: NULL];
|
||||
if (return_size)
|
||||
{
|
||||
return_value = (*objc_malloc) (return_size);
|
||||
[coder decodeValueOfObjCType: return_type
|
||||
at: return_value
|
||||
withName: NULL];
|
||||
}
|
||||
else
|
||||
return_value = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (Class) classForConnectedCoder: coder
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy,
|
||||
i.e. as our own class, not a Proxy class. */
|
||||
return [self class];
|
||||
}
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
|
@ -85,7 +123,7 @@
|
|||
|
||||
- (const char *) returnType
|
||||
{
|
||||
return encoding;
|
||||
return return_type;
|
||||
}
|
||||
|
||||
- (unsigned) returnSize
|
||||
|
@ -101,15 +139,71 @@
|
|||
a return value yet. */
|
||||
}
|
||||
|
||||
- (void) setReturnValue: (void*)addr
|
||||
{
|
||||
if (return_value)
|
||||
memcpy (return_value, addr, return_size);
|
||||
/* xxx retain, if necessary. */
|
||||
}
|
||||
|
||||
- objectReturnValue
|
||||
{
|
||||
switch (*return_type)
|
||||
{
|
||||
#define CASE_RETURN(C,T,S) \
|
||||
case C: return [NSNumber numberWith ## S: *(T*)return_value]
|
||||
CASE_RETURN (_C_LNG, long, Long);
|
||||
CASE_RETURN (_C_ULNG, unsigned long, UnsignedLong);
|
||||
CASE_RETURN (_C_INT, int, Int);
|
||||
CASE_RETURN (_C_UINT, unsigned int, UnsignedInt);
|
||||
CASE_RETURN (_C_SHT, short, Short);
|
||||
CASE_RETURN (_C_USHT, unsigned short, UnsignedShort);
|
||||
CASE_RETURN (_C_CHR, char, Char);
|
||||
CASE_RETURN (_C_UCHR, unsigned char, UnsignedChar);
|
||||
CASE_RETURN (_C_FLT, float, Float);
|
||||
CASE_RETURN (_C_DBL, double, Double);
|
||||
#undef CASE_RETURN
|
||||
case _C_PTR:
|
||||
return [NSNumber numberWithUnsignedLong: (long) *(void**)return_value];
|
||||
case _C_CHARPTR:
|
||||
return [NSString stringWithCString: *(char**)return_value];
|
||||
case _C_ID:
|
||||
return *(id*)return_value;
|
||||
case 'v':
|
||||
return nil;
|
||||
default:
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
return 0;
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (int) intReturnValue
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
switch (*return_type)
|
||||
{
|
||||
#define CASE_RETURN(_C,_T) case _C: return (int) *(_T*)return_value
|
||||
CASE_RETURN (_C_LNG, long);
|
||||
CASE_RETURN (_C_ULNG, unsigned long);
|
||||
CASE_RETURN (_C_INT, int);
|
||||
CASE_RETURN (_C_UINT, unsigned int);
|
||||
CASE_RETURN (_C_SHT, short);
|
||||
CASE_RETURN (_C_USHT, unsigned short);
|
||||
CASE_RETURN (_C_CHR, char);
|
||||
CASE_RETURN (_C_UCHR, unsigned char);
|
||||
CASE_RETURN (_C_CHARPTR, char*);
|
||||
CASE_RETURN (_C_FLT, float);
|
||||
CASE_RETURN (_C_DBL, double);
|
||||
CASE_RETURN (_C_PTR, void*);
|
||||
#undef CASE_RETURN
|
||||
case _C_ID:
|
||||
return [*(id*)return_value intValue];
|
||||
case 'v':
|
||||
return 0;
|
||||
default:
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -121,27 +215,29 @@
|
|||
return (*(char*)return_value != 0);
|
||||
case sizeof(short):
|
||||
return (*(short*)return_value != 0);
|
||||
case sizeof(long):
|
||||
return (*(long*)return_value != 0);
|
||||
case sizeof(int):
|
||||
return (*(int*)return_value != 0);
|
||||
}
|
||||
[self notImplemented: _cmd];
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < return_size; i++)
|
||||
if (*((char*)return_value + i) != 0)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
OBJC_FREE(encoding);
|
||||
if (*return_type == _C_ID)
|
||||
[*(id*)return_value release];
|
||||
OBJC_FREE(return_type);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#if 0
|
||||
@implementation CurriedInvocation
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
static int
|
||||
types_get_size_of_stack_arguments(const char *types)
|
||||
{
|
||||
|
@ -185,20 +281,32 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
|
||||
@implementation ArgframeInvocation
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- initWithArgframe: (arglist_t)frame type: (const char *)type
|
||||
- (void) _retainArguments
|
||||
{
|
||||
const char *tmptype;
|
||||
|
||||
tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument (argframe, &tmptype)))
|
||||
{
|
||||
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||
if (*tmptype == _C_ID)
|
||||
[*(id*)datum retain];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _initArgframeFrom: (arglist_t)frame
|
||||
withType: (const char*)type
|
||||
retainArgs: (BOOL)f
|
||||
{
|
||||
int stack_argsize, reg_argsize;
|
||||
|
||||
/* xxx we could just use the return part. Does this matter? */
|
||||
[super initWithReturnType:type];
|
||||
void *datum;
|
||||
|
||||
/* allocate the argframe */
|
||||
stack_argsize = types_get_size_of_stack_arguments(type);
|
||||
stack_argsize = types_get_size_of_stack_arguments (type);
|
||||
reg_argsize = types_get_size_of_register_arguments(type);
|
||||
argframe = (arglist_t) (*objc_calloc)(1 ,sizeof(char*) + reg_argsize);
|
||||
argframe = (arglist_t) (*objc_calloc) (1 ,sizeof(char*) + reg_argsize);
|
||||
if (stack_argsize)
|
||||
argframe->arg_ptr = (*objc_calloc)(1, stack_argsize);
|
||||
argframe->arg_ptr = (*objc_calloc) (1, stack_argsize);
|
||||
else
|
||||
argframe->arg_ptr = 0;
|
||||
|
||||
|
@ -209,8 +317,50 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
(char*)frame + sizeof(char*),
|
||||
reg_argsize);
|
||||
memcpy(argframe->arg_ptr, frame->arg_ptr, stack_argsize);
|
||||
if (f)
|
||||
[self _retainArguments];
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- initWithArgframe: (arglist_t)frame type: (const char *)type
|
||||
{
|
||||
/* xxx we are just using the return part. Does this matter? */
|
||||
[super initWithReturnType: type];
|
||||
[self _initArgframeFrom: frame withType: type retainArgs: NO];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
[super encodeWithCoder: coder];
|
||||
tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument(argframe, &tmptype)))
|
||||
{
|
||||
[coder encodeValueOfObjCType: tmptype
|
||||
at: datum
|
||||
withName: @"Invocation Argframe argument"];
|
||||
}
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
self = [super initWithCoder: coder];
|
||||
[self _initArgframeFrom: NULL withType: return_type retainArgs: NO];
|
||||
tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument(argframe, &tmptype)))
|
||||
{
|
||||
[coder decodeValueOfObjCType: tmptype
|
||||
at: datum
|
||||
withName: NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -220,13 +370,28 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void) retainArguments
|
||||
{
|
||||
if (!args_retained)
|
||||
{
|
||||
if (argframe)
|
||||
[self _retainArguments];
|
||||
args_retained = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) argumentsRetained
|
||||
{
|
||||
return args_retained;
|
||||
}
|
||||
|
||||
- (const char *) argumentTypeAtIndex: (unsigned)i
|
||||
{
|
||||
const char *tmptype = encoding;
|
||||
const char *tmptype = return_type;
|
||||
|
||||
do
|
||||
{
|
||||
tmptype = objc_skip_argspec(objc_skip_typespec(tmptype));
|
||||
tmptype = objc_skip_argspec (tmptype);
|
||||
}
|
||||
while (i--);
|
||||
return tmptype;
|
||||
|
@ -239,19 +404,20 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
|
||||
- (void) getArgument: (void*)addr atIndex: (unsigned)i
|
||||
{
|
||||
const char *tmptype = encoding;
|
||||
const char *tmptype = return_type;
|
||||
void *datum;
|
||||
|
||||
do
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
while (i--);
|
||||
while (i-- && datum);
|
||||
/* xxx Give error msg for null datum */
|
||||
memcpy (addr, datum, objc_sizeof_type(tmptype));
|
||||
}
|
||||
|
||||
- (void) setArgumentAtIndex: (unsigned)i
|
||||
toValueAt: (const void*)addr
|
||||
{
|
||||
const char *tmptype = encoding;
|
||||
const char *tmptype = return_type;
|
||||
void *datum;
|
||||
|
||||
do
|
||||
|
@ -260,23 +426,72 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
memcpy (datum, addr, objc_sizeof_type(tmptype));
|
||||
}
|
||||
|
||||
- (void) _deallocArgframe
|
||||
{
|
||||
if (argframe)
|
||||
{
|
||||
if (argframe->arg_ptr)
|
||||
(*objc_free) (argframe->arg_ptr);
|
||||
(*objc_free) (argframe);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
void *datum;
|
||||
const char *tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument(argframe, &tmptype)))
|
||||
{
|
||||
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||
if (*tmptype == _C_ID)
|
||||
[*(id*)datum release];
|
||||
}
|
||||
[self _deallocArgframe];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#if 0
|
||||
- resetArgframeWithReturnType: (const char*)encoding
|
||||
{
|
||||
[self _deallocArgframe];
|
||||
[self _allocArgframe];
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@implementation MethodInvocation
|
||||
|
||||
- (void) _initTargetAndSelPointers
|
||||
{
|
||||
const char *tmptype = return_type;
|
||||
target_pointer = (id*) my_method_get_next_argument (argframe, &tmptype);
|
||||
sel_pointer = (SEL*) my_method_get_next_argument (argframe, &tmptype);
|
||||
}
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithArgframe: (arglist_t)frame selector: (SEL)sel
|
||||
{
|
||||
const char *sel_type;
|
||||
|
||||
if (! (sel_type = sel_get_type (sel)) )
|
||||
sel_type = sel_get_type ( sel_get_any_typed_uid (sel_get_name (sel)));
|
||||
[self initWithArgframe: frame type: sel_type];
|
||||
[self _initTargetAndSelPointers];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
[self _initTargetAndSelPointers];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithSelector: (SEL)s
|
||||
{
|
||||
[self initWithArgframe: NULL selector: s];
|
||||
[self setArgumentAtIndex: 1 toValueAt: &s];
|
||||
*sel_pointer = s;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -287,9 +502,11 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
void *arg_datum;
|
||||
va_list ap;
|
||||
|
||||
[self initWithSelector:s];
|
||||
tmptype = encoding;
|
||||
[self initWithArgframe: NULL selector: s];
|
||||
tmptype = return_type;
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
if (args_retained)
|
||||
[target retain];
|
||||
*((id*)datum) = target;
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
*((SEL*)datum) = s;
|
||||
|
@ -300,7 +517,13 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
#define CASE_TYPE(_C,_T) case _C: *(_T*)datum = va_arg (ap, _T); break
|
||||
switch (*tmptype)
|
||||
{
|
||||
CASE_TYPE(_C_ID, id);
|
||||
case _C_ID:
|
||||
*(id*)datum = va_arg (ap, id);
|
||||
if (args_retained)
|
||||
[*(id*)datum retain];
|
||||
break;
|
||||
|
||||
CASE_TYPE(_C_SEL, SEL);
|
||||
CASE_TYPE(_C_LNG, long);
|
||||
CASE_TYPE(_C_ULNG, unsigned long);
|
||||
CASE_TYPE(_C_INT, int);
|
||||
|
@ -309,7 +532,10 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
CASE_TYPE(_C_USHT, unsigned short);
|
||||
CASE_TYPE(_C_CHR, char);
|
||||
CASE_TYPE(_C_UCHR, unsigned char);
|
||||
CASE_TYPE(_C_FLT, float);
|
||||
CASE_TYPE(_C_DBL, double);
|
||||
CASE_TYPE(_C_CHARPTR, char*);
|
||||
CASE_TYPE(_C_PTR, void*);
|
||||
default:
|
||||
[self notImplemented: _cmd];
|
||||
// memcpy (datum, va_arg (ap, void*), objc_sizeof_type(tmptype));
|
||||
|
@ -327,35 +553,53 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
id target;
|
||||
id cl;
|
||||
SEL sel;
|
||||
char *tmp_type = return_type;
|
||||
|
||||
/* xxx This could be more efficient by using my_method_get_next_argument
|
||||
instead of -target and -selector. Or, even better, caching the
|
||||
memory offsets of the target and selector in the argframe. */
|
||||
|
||||
target = [self target];
|
||||
target = *target_pointer;
|
||||
if (target == nil)
|
||||
return;
|
||||
|
||||
cl = object_get_class (target);
|
||||
sel = [self selector];
|
||||
sel = *sel_pointer;
|
||||
/* xxx Perhaps we could speed things up by making this an ivar,
|
||||
and caching it. */
|
||||
imp = get_imp (cl, sel);
|
||||
assert(imp);
|
||||
ret = __builtin_apply((void(*)(void))imp,
|
||||
argframe,
|
||||
types_get_size_of_stack_arguments(encoding));
|
||||
if (return_value)
|
||||
types_get_size_of_stack_arguments(return_type));
|
||||
if (return_size)
|
||||
{
|
||||
if (*encoding == 'd')
|
||||
if (*return_type == _C_DBL)
|
||||
/* DBL's are stored in a different place relative to RET. */
|
||||
memcpy(return_value, (char*)ret + 2*sizeof(void*), return_size);
|
||||
else if (*return_type == _C_ID)
|
||||
{
|
||||
if (*(id*)return_value != *(id*)ret)
|
||||
{
|
||||
if (return_retained)
|
||||
{
|
||||
if (*(id*)return_value)
|
||||
[*(id*)return_value release];
|
||||
[*(id*)ret retain];
|
||||
}
|
||||
*(id*)return_value = *(id*)ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(return_value, ret, return_size);
|
||||
{
|
||||
memcpy(return_value, ret, return_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) invokeWithTarget: t
|
||||
{
|
||||
/* xxx Could be more efficient. */
|
||||
[self setArgumentAtIndex:0 toValueAt:&t];
|
||||
[self setTarget: t];
|
||||
[self invoke];
|
||||
}
|
||||
|
||||
|
@ -366,35 +610,90 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
|
||||
- (SEL) selector
|
||||
{
|
||||
SEL s;
|
||||
[self getArgument:&s atIndex:1];
|
||||
return s;
|
||||
return *sel_pointer;
|
||||
}
|
||||
|
||||
- (void) setSelector: (SEL)s
|
||||
{
|
||||
[self setArgumentAtIndex:1 toValueAt:&s];
|
||||
if (sel_types_match(sel_get_type([self selector]), sel_get_type(s)))
|
||||
[self setArgumentAtIndex:1 toValueAt:&s];
|
||||
*sel_pointer = s;
|
||||
else
|
||||
{
|
||||
/* We need to reallocate the argframe */
|
||||
[self notImplemented:_cmd];
|
||||
/* We will need to reallocate the argframe */
|
||||
}
|
||||
}
|
||||
|
||||
- target
|
||||
{
|
||||
id t;
|
||||
[self getArgument:&t atIndex:0];
|
||||
return t;
|
||||
return *target_pointer;
|
||||
}
|
||||
|
||||
- (void) setTarget: t
|
||||
{
|
||||
[self setArgumentAtIndex:0 toValueAt:&t];
|
||||
if (*target_pointer != t)
|
||||
{
|
||||
if (args_retained)
|
||||
{
|
||||
[*target_pointer release];
|
||||
[t retain];
|
||||
}
|
||||
*target_pointer = t;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ObjectMethodInvocation
|
||||
|
||||
- (void) _initArgObjectPointer
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
tmptype = return_type;
|
||||
my_method_get_next_argument (argframe, &tmptype);
|
||||
my_method_get_next_argument (argframe, &tmptype);
|
||||
do
|
||||
{
|
||||
datum = my_method_get_next_argument (argframe, &tmptype);
|
||||
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||
}
|
||||
while (datum && tmptype && *tmptype != _C_ID);
|
||||
if (*tmptype != _C_ID)
|
||||
[self error: "This method does not have an object argument."];
|
||||
arg_object_pointer = (id*) datum;
|
||||
}
|
||||
|
||||
- initWithArgframe: (arglist_t)frame selector: (SEL)sel
|
||||
{
|
||||
[super initWithArgframe: frame selector: sel];
|
||||
[self _initArgObjectPointer];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
[self _initArgObjectPointer];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) invokeWithObject: anObject
|
||||
{
|
||||
if (*arg_object_pointer != anObject)
|
||||
{
|
||||
if (args_retained)
|
||||
{
|
||||
[*arg_object_pointer release];
|
||||
[anObject retain];
|
||||
}
|
||||
*arg_object_pointer = anObject;
|
||||
}
|
||||
[self invoke];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation VoidFunctionInvocation
|
||||
|
@ -409,19 +708,88 @@ my_method_get_next_argument (arglist_t argframe,
|
|||
}
|
||||
#endif
|
||||
|
||||
- initWithFunction: (void(*)())f
|
||||
- initWithVoidFunction: (void(*)())f
|
||||
{
|
||||
[super initWithReturnType: "v"];
|
||||
function = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Encode ourself as a proxies across Connection's; we can't encode
|
||||
a function across the wire. */
|
||||
- classForConnectedCoder: coder
|
||||
{
|
||||
return [[coder connection] proxyClass];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
}
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
(*function) ();
|
||||
}
|
||||
|
||||
- (void) invokeWithObject
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ObjectFunctionInvocation
|
||||
|
||||
- initWithObjectFunction: (id(*)(id))f
|
||||
{
|
||||
[super initWithReturnType: "@"];
|
||||
function = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Encode ourself as a proxies across Connection's; we can't encode
|
||||
a function across the wire. */
|
||||
- classForConnectedCoder: coder
|
||||
{
|
||||
return [[coder connection] proxyClass];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
}
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
[self invokeWithObject: nil];
|
||||
}
|
||||
|
||||
- (void) invokeWithObject: anObject
|
||||
{
|
||||
id r;
|
||||
|
||||
r = (*function) (anObject);
|
||||
if (*(id*)return_value != r)
|
||||
{
|
||||
if (args_retained)
|
||||
{
|
||||
[*(id*)return_value release];
|
||||
[r retain];
|
||||
}
|
||||
*(id*)return_value = r;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* Many other kinds of Invocations are possible:
|
||||
SchemeInvocation, TclInvocation */
|
||||
|
||||
#if 0
|
||||
@implementation CurriedInvocation
|
||||
@end
|
||||
|
||||
What is this nonsense?
|
||||
@interface StreamInvocation
|
||||
@interface LogInvocation
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue