Home | History | Annotate | Download | only in OCMock
      1 //---------------------------------------------------------------------------------------
      2 //  $Id$
      3 //  Copyright (c) 2006-2009 by Mulle Kybernetik. See License file for details.
      4 //---------------------------------------------------------------------------------------
      5 
      6 #import "NSInvocation+OCMAdditions.h"
      7 
      8 
      9 @implementation NSInvocation(OCMAdditions)
     10 
     11 - (id)getArgumentAtIndexAsObject:(int)argIndex
     12 {
     13 	const char* argType;
     14 	
     15 	argType = [[self methodSignature] getArgumentTypeAtIndex:argIndex];
     16 	while(strchr("rnNoORV", argType[0]) != NULL)
     17 		argType += 1;
     18 	
     19 	if((strlen(argType) > 1) && (strchr("{^", argType[0]) == NULL) && (strcmp("@?", argType) != 0))
     20 		[NSException raise:NSInvalidArgumentException format:@"Cannot handle argument type '%s'.", argType];
     21 	
     22 	switch (argType[0]) 
     23 	{
     24 		case '#':
     25 		case '@': 
     26 		{
     27 			id value;
     28 			[self getArgument:&value atIndex:argIndex];
     29 			return value;
     30 		}
     31 		case ':':
     32  		{
     33  			SEL s = (SEL)0;
     34  			[self getArgument:&s atIndex:argIndex];
     35  			id value = NSStringFromSelector(s);
     36  			return value;
     37  		}
     38 		case 'i': 
     39 		{
     40 			int value;
     41 			[self getArgument:&value atIndex:argIndex];
     42 			return [NSNumber numberWithInt:value];
     43 		}	
     44 		case 's':
     45 		{
     46 			short value;
     47 			[self getArgument:&value atIndex:argIndex];
     48 			return [NSNumber numberWithShort:value];
     49 		}	
     50 		case 'l':
     51 		{
     52 			long value;
     53 			[self getArgument:&value atIndex:argIndex];
     54 			return [NSNumber numberWithLong:value];
     55 		}	
     56 		case 'q':
     57 		{
     58 			long long value;
     59 			[self getArgument:&value atIndex:argIndex];
     60 			return [NSNumber numberWithLongLong:value];
     61 		}	
     62 		case 'c':
     63 		{
     64 			char value;
     65 			[self getArgument:&value atIndex:argIndex];
     66 			return [NSNumber numberWithChar:value];
     67 		}	
     68 		case 'C':
     69 		{
     70 			unsigned char value;
     71 			[self getArgument:&value atIndex:argIndex];
     72 			return [NSNumber numberWithUnsignedChar:value];
     73 		}	
     74 		case 'I':
     75 		{
     76 			unsigned int value;
     77 			[self getArgument:&value atIndex:argIndex];
     78 			return [NSNumber numberWithUnsignedInt:value];
     79 		}	
     80 		case 'S':
     81 		{
     82 			unsigned short value;
     83 			[self getArgument:&value atIndex:argIndex];
     84 			return [NSNumber numberWithUnsignedShort:value];
     85 		}	
     86 		case 'L':
     87 		{
     88 			unsigned long value;
     89 			[self getArgument:&value atIndex:argIndex];
     90 			return [NSNumber numberWithUnsignedLong:value];
     91 		}	
     92 		case 'Q':
     93 		{
     94 			unsigned long long value;
     95 			[self getArgument:&value atIndex:argIndex];
     96 			return [NSNumber numberWithUnsignedLongLong:value];
     97 		}	
     98 		case 'f':
     99 		{
    100 			float value;
    101 			[self getArgument:&value atIndex:argIndex];
    102 			return [NSNumber numberWithFloat:value];
    103 		}	
    104 		case 'd':
    105 		{
    106 			double value;
    107 			[self getArgument:&value atIndex:argIndex];
    108 			return [NSNumber numberWithDouble:value];
    109 		}	
    110 		case 'B':
    111 		{
    112 			bool value;
    113 			[self getArgument:&value atIndex:argIndex];
    114 			return [NSNumber numberWithBool:value];
    115 		}
    116 		case '^':
    117         {
    118             void *value = NULL;
    119             [self getArgument:&value atIndex:argIndex];
    120             return [NSValue valueWithPointer:value];
    121         }
    122 		case '{': // structure
    123 		{
    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];
    128 		}       
    129 			
    130 	}
    131 	[NSException raise:NSInvalidArgumentException format:@"Argument type '%s' not supported", argType];
    132 	return nil;
    133 }
    134 
    135 - (NSString *)invocationDescription
    136 {
    137 	NSMethodSignature *methodSignature = [self methodSignature];
    138 	NSUInteger numberOfArgs = [methodSignature numberOfArguments];
    139 	
    140 	if (numberOfArgs == 2)
    141 		return NSStringFromSelector([self selector]);
    142 	
    143 	NSArray *selectorParts = [NSStringFromSelector([self selector]) componentsSeparatedByString:@":"];
    144 	NSMutableString *description = [[NSMutableString alloc] init];
    145 	unsigned int i;
    146 	for(i = 2; i < numberOfArgs; i++)
    147 	{
    148 		[description appendFormat:@"%@%@:", (i > 2 ? @" " : @""), [selectorParts objectAtIndex:(i - 2)]];
    149 		[description appendString:[self argumentDescriptionAtIndex:i]];
    150 	}
    151 	
    152 	return [description autorelease];
    153 }
    154 
    155 - (NSString *)argumentDescriptionAtIndex:(int)argIndex
    156 {
    157 	const char *argType = [[self methodSignature] getArgumentTypeAtIndex:argIndex];
    158 	if(strchr("rnNoORV", argType[0]) != NULL)
    159 		argType += 1;
    160 
    161 	switch(*argType)
    162 	{
    163 		case '@':	return [self objectDescriptionAtIndex:argIndex];
    164 		case 'c':	return [self charDescriptionAtIndex:argIndex];
    165 		case 'C':	return [self unsignedCharDescriptionAtIndex:argIndex];
    166 		case 'i':	return [self intDescriptionAtIndex:argIndex];
    167 		case 'I':	return [self unsignedIntDescriptionAtIndex:argIndex];
    168 		case 's':	return [self shortDescriptionAtIndex:argIndex];
    169 		case 'S':	return [self unsignedShortDescriptionAtIndex:argIndex];
    170 		case 'l':	return [self longDescriptionAtIndex:argIndex];
    171 		case 'L':	return [self unsignedLongDescriptionAtIndex:argIndex];
    172 		case 'q':	return [self longLongDescriptionAtIndex:argIndex];
    173 		case 'Q':	return [self unsignedLongLongDescriptionAtIndex:argIndex];
    174 		case 'd':	return [self doubleDescriptionAtIndex:argIndex];
    175 		case 'f':	return [self floatDescriptionAtIndex:argIndex];
    176 		// Why does this throw EXC_BAD_ACCESS when appending the string?
    177 		//	case NSObjCStructType: return [self structDescriptionAtIndex:index];
    178 		case '^':	return [self pointerDescriptionAtIndex:argIndex];
    179 		case '*':	return [self cStringDescriptionAtIndex:argIndex];
    180 		case ':':	return [self selectorDescriptionAtIndex:argIndex];
    181 		default:	return [@"<??" stringByAppendingString:@">"];  // avoid confusion with trigraphs...
    182 	}
    183 	
    184 }
    185 
    186 
    187 - (NSString *)objectDescriptionAtIndex:(int)anInt
    188 {
    189 	id object;
    190 	
    191 	[self getArgument:&object atIndex:anInt];
    192 	if (object == nil)
    193 		return @"nil";
    194 	else if(![object isProxy] && [object isKindOfClass:[NSString class]])
    195 		return [NSString stringWithFormat:@"@\"%@\"", [object description]];
    196 	else
    197 		return [object description];
    198 }
    199 
    200 - (NSString *)charDescriptionAtIndex:(int)anInt
    201 {
    202 	unsigned char buffer[128];
    203 	memset(buffer, 0x0, 128);
    204 	
    205 	[self getArgument:&buffer atIndex:anInt];
    206 	
    207 	// If there's only one character in the buffer, and it's 0 or 1, then we have a BOOL
    208 	if (buffer[1] == '\0' && (buffer[0] == 0 || buffer[0] == 1))
    209 		return [NSString stringWithFormat:@"%@", (buffer[0] == 1 ? @"YES" : @"NO")];
    210 	else
    211 		return [NSString stringWithFormat:@"'%c'", *buffer];
    212 }
    213 
    214 - (NSString *)unsignedCharDescriptionAtIndex:(int)anInt
    215 {
    216 	unsigned char buffer[128];
    217 	memset(buffer, 0x0, 128);
    218 	
    219 	[self getArgument:&buffer atIndex:anInt];
    220 	return [NSString stringWithFormat:@"'%c'", *buffer];
    221 }
    222 
    223 - (NSString *)intDescriptionAtIndex:(int)anInt
    224 {
    225 	int intValue;
    226 	
    227 	[self getArgument:&intValue atIndex:anInt];
    228 	return [NSString stringWithFormat:@"%d", intValue];
    229 }
    230 
    231 - (NSString *)unsignedIntDescriptionAtIndex:(int)anInt
    232 {
    233 	unsigned int intValue;
    234 	
    235 	[self getArgument:&intValue atIndex:anInt];
    236 	return [NSString stringWithFormat:@"%d", intValue];
    237 }
    238 
    239 - (NSString *)shortDescriptionAtIndex:(int)anInt
    240 {
    241 	short shortValue;
    242 	
    243 	[self getArgument:&shortValue atIndex:anInt];
    244 	return [NSString stringWithFormat:@"%hi", shortValue];
    245 }
    246 
    247 - (NSString *)unsignedShortDescriptionAtIndex:(int)anInt
    248 {
    249 	unsigned short shortValue;
    250 	
    251 	[self getArgument:&shortValue atIndex:anInt];
    252 	return [NSString stringWithFormat:@"%hu", shortValue];
    253 }
    254 
    255 - (NSString *)longDescriptionAtIndex:(int)anInt
    256 {
    257 	long longValue;
    258 	
    259 	[self getArgument:&longValue atIndex:anInt];
    260 	return [NSString stringWithFormat:@"%ld", longValue];
    261 }
    262 
    263 - (NSString *)unsignedLongDescriptionAtIndex:(int)anInt
    264 {
    265 	unsigned long longValue;
    266 	
    267 	[self getArgument:&longValue atIndex:anInt];
    268 	return [NSString stringWithFormat:@"%lu", longValue];
    269 }
    270 
    271 - (NSString *)longLongDescriptionAtIndex:(int)anInt
    272 {
    273 	long long longLongValue;
    274 	
    275 	[self getArgument:&longLongValue atIndex:anInt];
    276 	return [NSString stringWithFormat:@"%qi", longLongValue];
    277 }
    278 
    279 - (NSString *)unsignedLongLongDescriptionAtIndex:(int)anInt
    280 {
    281 	unsigned long long longLongValue;
    282 	
    283 	[self getArgument:&longLongValue atIndex:anInt];
    284 	return [NSString stringWithFormat:@"%qu", longLongValue];
    285 }
    286 
    287 - (NSString *)doubleDescriptionAtIndex:(int)anInt;
    288 {
    289 	double doubleValue;
    290 	
    291 	[self getArgument:&doubleValue atIndex:anInt];
    292 	return [NSString stringWithFormat:@"%f", doubleValue];
    293 }
    294 
    295 - (NSString *)floatDescriptionAtIndex:(int)anInt
    296 {
    297 	float floatValue;
    298 	
    299 	[self getArgument:&floatValue atIndex:anInt];
    300 	return [NSString stringWithFormat:@"%f", floatValue];
    301 }
    302 
    303 - (NSString *)structDescriptionAtIndex:(int)anInt;
    304 {
    305 	void *buffer;
    306 	
    307 	[self getArgument:&buffer atIndex:anInt];
    308 	return [NSString stringWithFormat:@":(struct)%p", buffer];
    309 }
    310 
    311 - (NSString *)pointerDescriptionAtIndex:(int)anInt
    312 {
    313 	void *buffer;
    314 	
    315 	[self getArgument:&buffer atIndex:anInt];
    316 	return [NSString stringWithFormat:@"%p", buffer];
    317 }
    318 
    319 - (NSString *)cStringDescriptionAtIndex:(int)anInt
    320 {
    321 	char buffer[128];
    322 	
    323 	memset(buffer, 0x0, 128);
    324 	
    325 	[self getArgument:&buffer atIndex:anInt];
    326 	return [NSString stringWithFormat:@"\"%s\"", buffer];
    327 }
    328 
    329 - (NSString *)selectorDescriptionAtIndex:(int)anInt
    330 {
    331 	SEL selectorValue;
    332 	
    333 	[self getArgument:&selectorValue atIndex:anInt];
    334 	return [NSString stringWithFormat:@"@selector(%@)", NSStringFromSelector(selectorValue)];
    335 }
    336 
    337 @end
    338