1 //---------------------------------------------------------------------------------------
3 // Copyright (c) 2006-2009 by Mulle Kybernetik. See License file for details.
4 //---------------------------------------------------------------------------------------
6 #import "NSInvocation+OCMAdditions.h"
9 @implementation NSInvocation(OCMAdditions)
11 - (id)getArgumentAtIndexAsObject:(int)argIndex
15 argType = [[self methodSignature] getArgumentTypeAtIndex:argIndex];
16 while(strchr("rnNoORV", argType[0]) != NULL)
19 if((strlen(argType) > 1) && (strchr("{^", argType[0]) == NULL) && (strcmp("@?", argType) != 0))
20 [NSException raise:NSInvalidArgumentException format:@"Cannot handle argument type '%s'.", argType];
28 [self getArgument:&value atIndex:argIndex];
34 [self getArgument:&s atIndex:argIndex];
35 id value = NSStringFromSelector(s);
41 [self getArgument:&value atIndex:argIndex];
42 return [NSNumber numberWithInt:value];
47 [self getArgument:&value atIndex:argIndex];
48 return [NSNumber numberWithShort:value];
53 [self getArgument:&value atIndex:argIndex];
54 return [NSNumber numberWithLong:value];
59 [self getArgument:&value atIndex:argIndex];
60 return [NSNumber numberWithLongLong:value];
65 [self getArgument:&value atIndex:argIndex];
66 return [NSNumber numberWithChar:value];
71 [self getArgument:&value atIndex:argIndex];
72 return [NSNumber numberWithUnsignedChar:value];
77 [self getArgument:&value atIndex:argIndex];
78 return [NSNumber numberWithUnsignedInt:value];
83 [self getArgument:&value atIndex:argIndex];
84 return [NSNumber numberWithUnsignedShort:value];
89 [self getArgument:&value atIndex:argIndex];
90 return [NSNumber numberWithUnsignedLong:value];
94 unsigned long long value;
95 [self getArgument:&value atIndex:argIndex];
96 return [NSNumber numberWithUnsignedLongLong:value];
101 [self getArgument:&value atIndex:argIndex];
102 return [NSNumber numberWithFloat:value];
107 [self getArgument:&value atIndex:argIndex];
108 return [NSNumber numberWithDouble:value];
113 [self getArgument:&value atIndex:argIndex];
114 return [NSNumber numberWithBool:value];
119 [self getArgument:&value atIndex:argIndex];
120 return [NSValue valueWithPointer:value];
122 case '{': // structure
124 NSUInteger maxArgSize = [[self methodSignature] frameLength];
125 NSMutableData *argumentData = [[[NSMutableData alloc] initWithLength:maxArgSize] autorelease];
126 [self getArgument:[argumentData mutableBytes] atIndex:argIndex];
127 return [NSValue valueWithBytes:[argumentData bytes] objCType:argType];
131 [NSException raise:NSInvalidArgumentException format:@"Argument type '%s' not supported", argType];
135 - (NSString *)invocationDescription
137 NSMethodSignature *methodSignature = [self methodSignature];
138 NSUInteger numberOfArgs = [methodSignature numberOfArguments];
140 if (numberOfArgs == 2)
141 return NSStringFromSelector([self selector]);
143 NSArray *selectorParts = [NSStringFromSelector([self selector]) componentsSeparatedByString:@":"];
144 NSMutableString *description = [[NSMutableString alloc] init];
146 for(i = 2; i < numberOfArgs; i++)
148 [description appendFormat:@"%@%@:", (i > 2 ? @" " : @""), [selectorParts objectAtIndex:(i - 2)]];
149 [description appendString:[self argumentDescriptionAtIndex:i]];
152 return [description autorelease];
155 - (NSString *)argumentDescriptionAtIndex:(int)argIndex
157 const char *argType = [[self methodSignature] getArgumentTypeAtIndex:argIndex];
158 if(strchr("rnNoORV", argType[0]) != NULL)
163 case '@': return [self objectDescriptionAtIndex:argIndex];
164 case 'B': return [self boolDescriptionAtIndex:argIndex];
165 case 'c': return [self charDescriptionAtIndex:argIndex];
166 case 'C': return [self unsignedCharDescriptionAtIndex:argIndex];
167 case 'i': return [self intDescriptionAtIndex:argIndex];
168 case 'I': return [self unsignedIntDescriptionAtIndex:argIndex];
169 case 's': return [self shortDescriptionAtIndex:argIndex];
170 case 'S': return [self unsignedShortDescriptionAtIndex:argIndex];
171 case 'l': return [self longDescriptionAtIndex:argIndex];
172 case 'L': return [self unsignedLongDescriptionAtIndex:argIndex];
173 case 'q': return [self longLongDescriptionAtIndex:argIndex];
174 case 'Q': return [self unsignedLongLongDescriptionAtIndex:argIndex];
175 case 'd': return [self doubleDescriptionAtIndex:argIndex];
176 case 'f': return [self floatDescriptionAtIndex:argIndex];
177 // Why does this throw EXC_BAD_ACCESS when appending the string?
178 // case NSObjCStructType: return [self structDescriptionAtIndex:index];
179 case '^': return [self pointerDescriptionAtIndex:argIndex];
180 case '*': return [self cStringDescriptionAtIndex:argIndex];
181 case ':': return [self selectorDescriptionAtIndex:argIndex];
182 default: return [@"<??" stringByAppendingString:@">"]; // avoid confusion with trigraphs...
188 - (NSString *)objectDescriptionAtIndex:(int)anInt
192 [self getArgument:&object atIndex:anInt];
195 else if(![object isProxy] && [object isKindOfClass:[NSString class]])
196 return [NSString stringWithFormat:@"@\"%@\"", [object description]];
198 return [object description];
201 - (NSString *)boolDescriptionAtIndex:(int)anInt
205 [self getArgument:&value atIndex:anInt];
206 return value ? @"YES" : @"NO";
209 - (NSString *)charDescriptionAtIndex:(int)anInt
211 unsigned char buffer[128];
212 memset(buffer, 0x0, 128);
214 [self getArgument:&buffer atIndex:anInt];
216 // If there's only one character in the buffer, and it's 0 or 1, then we have a BOOL
217 if (buffer[1] == '\0' && (buffer[0] == 0 || buffer[0] == 1))
218 return [NSString stringWithFormat:@"%@", (buffer[0] == 1 ? @"YES" : @"NO")];
220 return [NSString stringWithFormat:@"'%c'", *buffer];
223 - (NSString *)unsignedCharDescriptionAtIndex:(int)anInt
225 unsigned char buffer[128];
226 memset(buffer, 0x0, 128);
228 [self getArgument:&buffer atIndex:anInt];
229 return [NSString stringWithFormat:@"'%c'", *buffer];
232 - (NSString *)intDescriptionAtIndex:(int)anInt
236 [self getArgument:&intValue atIndex:anInt];
237 return [NSString stringWithFormat:@"%d", intValue];
240 - (NSString *)unsignedIntDescriptionAtIndex:(int)anInt
242 unsigned int intValue;
244 [self getArgument:&intValue atIndex:anInt];
245 return [NSString stringWithFormat:@"%d", intValue];
248 - (NSString *)shortDescriptionAtIndex:(int)anInt
252 [self getArgument:&shortValue atIndex:anInt];
253 return [NSString stringWithFormat:@"%hi", shortValue];
256 - (NSString *)unsignedShortDescriptionAtIndex:(int)anInt
258 unsigned short shortValue;
260 [self getArgument:&shortValue atIndex:anInt];
261 return [NSString stringWithFormat:@"%hu", shortValue];
264 - (NSString *)longDescriptionAtIndex:(int)anInt
268 [self getArgument:&longValue atIndex:anInt];
269 return [NSString stringWithFormat:@"%ld", longValue];
272 - (NSString *)unsignedLongDescriptionAtIndex:(int)anInt
274 unsigned long longValue;
276 [self getArgument:&longValue atIndex:anInt];
277 return [NSString stringWithFormat:@"%lu", longValue];
280 - (NSString *)longLongDescriptionAtIndex:(int)anInt
282 long long longLongValue;
284 [self getArgument:&longLongValue atIndex:anInt];
285 return [NSString stringWithFormat:@"%qi", longLongValue];
288 - (NSString *)unsignedLongLongDescriptionAtIndex:(int)anInt
290 unsigned long long longLongValue;
292 [self getArgument:&longLongValue atIndex:anInt];
293 return [NSString stringWithFormat:@"%qu", longLongValue];
296 - (NSString *)doubleDescriptionAtIndex:(int)anInt;
300 [self getArgument:&doubleValue atIndex:anInt];
301 return [NSString stringWithFormat:@"%f", doubleValue];
304 - (NSString *)floatDescriptionAtIndex:(int)anInt
308 [self getArgument:&floatValue atIndex:anInt];
309 return [NSString stringWithFormat:@"%f", floatValue];
312 - (NSString *)structDescriptionAtIndex:(int)anInt;
316 [self getArgument:&buffer atIndex:anInt];
317 return [NSString stringWithFormat:@":(struct)%p", buffer];
320 - (NSString *)pointerDescriptionAtIndex:(int)anInt
324 [self getArgument:&buffer atIndex:anInt];
325 return [NSString stringWithFormat:@"%p", buffer];
328 - (NSString *)cStringDescriptionAtIndex:(int)anInt
332 memset(buffer, 0x0, 128);
334 [self getArgument:&buffer atIndex:anInt];
335 return [NSString stringWithFormat:@"\"%s\"", buffer];
338 - (NSString *)selectorDescriptionAtIndex:(int)anInt
342 [self getArgument:&selectorValue atIndex:anInt];
343 return [NSString stringWithFormat:@"@selector(%@)", NSStringFromSelector(selectorValue)];