main
1//
2// Licensed under the terms in License.txt
3//
4// Copyright 2010 Allen Ding. All rights reserved.
5//
6
7#import "NSInvocation+KiwiAdditions.h"
8#import "KWFormatter.h"
9#import "KWObjCUtilities.h"
10#import "NSMethodSignature+KiwiAdditions.h"
11
12@implementation NSInvocation(KiwiAdditions)
13
14#pragma mark -
15#pragma mark Creating NSInvocation Objects
16
17+ (NSInvocation *)invocationWithTarget:(id)anObject selector:(SEL)aSelector {
18 return [self invocationWithTarget:anObject selector:aSelector messageArguments:nil];
19}
20
21+ (NSInvocation *)invocationWithTarget:(id)anObject selector:(SEL)aSelector messageArguments:(const void *)firstBytes, ... {
22 if (anObject == nil) {
23 [NSException raise:NSInvalidArgumentException format:@"%@ - target must not be nil",
24 NSStringFromSelector(_cmd)];
25 }
26
27 NSMethodSignature *signature = [anObject methodSignatureForSelector:aSelector];
28
29 if (signature == nil) {
30 [NSException raise:NSInvalidArgumentException format:@"%@ - target returned nil for -methodSignatureForSelector",
31 NSStringFromSelector(_cmd)];
32 }
33
34 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
35 [invocation setTarget:anObject];
36 [invocation setSelector:aSelector];
37 NSUInteger numberOfMessageArguments = [signature numberOfMessageArguments];
38
39 if (numberOfMessageArguments == 0)
40 return invocation;
41
42 va_list argumentList;
43 va_start(argumentList, firstBytes);
44 const void *bytes = firstBytes;
45
46 for (NSUInteger i = 0; i < numberOfMessageArguments && bytes != nil; ++i) {
47 [invocation setMessageArgument:bytes atIndex:i];
48 bytes = va_arg(argumentList, const void *);
49 }
50
51 va_end(argumentList);
52 return invocation;
53}
54
55#pragma mark -
56#pragma mark Accessing Message Arguments
57
58- (NSData *)messageArgumentDataAtIndex:(NSUInteger)anIndex {
59 NSUInteger length = KWObjCTypeLength([[self methodSignature] messageArgumentTypeAtIndex:anIndex]);
60 void *buffer = malloc(length);
61 [self getMessageArgument:buffer atIndex:anIndex];
62 // NSData takes over ownership of buffer
63 NSData* data = [NSData dataWithBytesNoCopy:buffer length:length];
64 return data;
65}
66
67- (void)getMessageArgument:(void *)buffer atIndex:(NSUInteger)anIndex {
68 [self getArgument:buffer atIndex:anIndex + 2];
69}
70
71- (void)setMessageArgument:(const void *)bytes atIndex:(NSUInteger)anIndex {
72 [self setArgument:(void *)bytes atIndex:anIndex + 2];
73}
74
75- (void)setMessageArguments:(const void *)firstBytes, ... {
76 NSUInteger numberOfMessageArguments = [[self methodSignature] numberOfMessageArguments];
77
78 if (numberOfMessageArguments == 0)
79 return;
80
81 va_list argumentList;
82 va_start(argumentList, firstBytes);
83 const void *bytes = firstBytes;
84
85 for (NSUInteger i = 0; i < numberOfMessageArguments && bytes != nil; ++i) {
86 [self setMessageArgument:bytes atIndex:i];
87 bytes = va_arg(argumentList, const void *);
88 }
89
90 va_end(argumentList);
91}
92
93@end