// // NSInvocationAdditions.m // HigherOrderMessaging // // Created by Ofri Wolfus on 24/09/05. // Copyright 2005 Ofri Wolfus. All rights reserved. // #import "NSInvocationAdditions.h" #import "HOMObjCValue-Private.h" #import "HOMUtilities.h" @implementation NSInvocation (HOMAdditions) //Get our return value - (id)returnValue { const char *t = [[self methodSignature] methodReturnType]; id r = nil; if (*t == *@encode(id) || *t == *@encode(Class)) [self getReturnValue:&r]; return r; } /* * The implementation of this method is not really efficient * as an invocation already holds all the arguments and their sizes, * but since digging into NSInvocation's implementation details * is not fun, I'm leaving it as is until someone complains. */ - (Message *)message { id r, m; // Store the current return value [self getReturnValue:&r]; // Message the MessageBuilder class which in turn // returns us a Message instance [self invokeWithTarget:objc_getClass("MessageBuilder")]; // Get the returned message [self getReturnValue:&m]; // Set back the old return value [self setReturnValue:&r]; // And return our message return m; } @end //Default is the slow but supported way BOOL HOMFastInvocationCopy = NO; @implementation NSInvocation (HOMCopying) //Force our invocation to copy - (id)copyWithZone:(NSZone *)zone { /*#ifdef HOMALLOW_FAST_INVOCATION_COPY if (HOMFastInvocationCopy) { NSInvocation *newInvocation = (NSInvocation *)NSCopyObject(self, 0, zone); //Copy the argument frame of the invocation unsigned size = [signature frameLength]; typeof(argumentFrame) newArgumentFrame = malloc(size); newInvocation->argumentFrame = memcpy(newArgumentFrame, argumentFrame, size); //Copy the container //newInvocation->container = [container copyWithZone:zone]; if (container) newInvocation->container = [[NSArray allocWithZone:zone] initWithArray:container copyItems:YES]; //An NSInvocation instance retains its signature on initialization and therefor we have to do it manually here [[newInvocation methodSignature] retain]; return newInvocation; } #endif*/ NSMethodSignature *sig = [self methodSignature]; NSInvocation *result = [NSInvocation invocationWithMethodSignature:sig]; //Set the selector of the new invocation [result setSelector:[self selector]]; //Set the arguments of the new invocation unsigned numberOfArgs = [sig numberOfArguments]; for(int i = 0; i < numberOfArgs; i++) { void *arg = malloc(sizeOfType([sig getArgumentTypeAtIndex:i])); [self getArgument:arg atIndex:i]; [result setArgument:arg atIndex:i]; free(arg); } //Retain the arguments if we retained them if ([self argumentsRetained]) [result retainArguments]; //We expect that an object returned from -copyWithZone: will not be autoreleased so we must retain our new invocation [result retain]; return result; } @end