]> git.wincent.com - WOTest.git/blob - NSInvocation+WOTest.m
Fix object-to-pointer comparisons on Leopard
[WOTest.git] / NSInvocation+WOTest.m
1 //
2 //  NSInvocation+WOTest.m
3 //  WOTest
4 //
5 //  Created by Wincent Colaiuta on 30 January 2006.
6 //
7 //  Copyright 2006-2007 Wincent Colaiuta.
8 //  This program is free software: you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License as published by
10 //  the Free Software Foundation, either version 3 of the License, or
11 //  (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 //
21
22 #import "NSInvocation+WOTest.h"
23 #import "WOTest.h"
24
25 @implementation NSInvocation (WOTest)
26
27 - (BOOL)WOTest_isEqualToInvocation:(NSInvocation *)anInvocation
28 {
29     // first do a basic comparison without arguments
30     if (![self WOTest_isEqualToInvocationIgnoringArguments:anInvocation]) return NO;
31     
32     // compare arguments (skip first two: self and _cmd)
33     NSMethodSignature *aSignature = [self methodSignature];
34     NSMethodSignature *otherSignature = [anInvocation methodSignature];
35     for (unsigned i = 2, max = [aSignature numberOfArguments]; i < max; i++)
36     {
37         const char *aType = [aSignature getArgumentTypeAtIndex:i];
38         const char *otherType = [otherSignature getArgumentTypeAtIndex:i];
39         if (strcmp(aType, otherType) != 0) return NO;
40         
41         // compare the two values
42         return [[self WOTest_valueForArgumentAtIndex:i] isEqual:[anInvocation WOTest_valueForArgumentAtIndex:i]];
43     }
44     
45     return YES; // if get this far, all equality tests passed (no arguments)
46 }
47
48 - (BOOL)WOTest_isEqualToInvocationIgnoringArguments:(NSInvocation *)anInvocation
49 {
50     // basic checks: compare against nil and against self
51     if (!anInvocation) return NO;
52     if (anInvocation == self) return YES;
53     
54     // compare selectors
55     if ([self selector] != [anInvocation selector]) return NO;
56     
57     // compare signatures
58     NSMethodSignature *aSignature = [self methodSignature];
59     NSMethodSignature *otherSignature = [anInvocation methodSignature];
60     if (![aSignature isEqual:otherSignature]) return NO;
61         
62     return YES; // if get this far, all equality tests passed (no arguments)
63 }
64
65 - (NSValue *)WOTest_valueForArgumentAtIndex:(unsigned)index
66 {
67     NSMethodSignature *methodSignature = [self methodSignature];
68     NSParameterAssert(index < [methodSignature numberOfArguments]);
69     const char *type = [methodSignature getArgumentTypeAtIndex:index];
70
71     // no way to find out size needed for argument, so allocate enough for all
72     size_t bufferSize = (size_t)[methodSignature frameLength];
73     void *buffer = malloc(bufferSize);
74     NSAssert1((buffer != NULL), @"malloc() failed (size %d)", bufferSize);
75     [self getArgument:&buffer atIndex:index];
76     NSValue *aValue = [NSValue value:&buffer withObjCType:type];
77
78     // following line yields a runtime error:
79     // malloc: ***  Deallocation of a pointer not malloced: 0x26a45c; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
80     //free(buffer); // is NSValue freeing automatically?
81     return aValue;
82 }
83
84 - (void)WOTest_setArgumentValue:(NSValue *)aValue atIndex:(unsigned)index
85 {
86     NSMethodSignature *methodSignature = [self methodSignature];
87     NSParameterAssert(index < [methodSignature numberOfArguments]);
88     NSParameterAssert(aValue != nil);
89     size_t bufferSize = [aValue WOTest_bufferSize];
90     void *buffer = malloc(bufferSize);
91     NSAssert1((buffer != NULL), @"malloc() failed (size %d)", bufferSize);
92     [aValue getValue:buffer];
93     [self setArgument:buffer atIndex:index];
94     free(buffer);
95 }
96
97 @end