* Added $apply and some other collection utils.
* Moved logging code to a separate code segment.
* Fixed uninitialized variable in Target.
5 // Created by Jens Alfke on 2/11/08.
6 // Copyright 2008 Jens Alfke. All rights reserved.
12 @implementation MYTarget
15 - (id) initWithReceiver: (id)receiver action: (SEL)action
19 NSMethodSignature *sig = [receiver methodSignatureForSelector: action];
20 CAssert(sig,@"%@<%p> does not respond to %@",[receiver class],receiver,NSStringFromSelector(action));
21 CAssert(sig.numberOfArguments==3,
22 @"-[%@ %@] can't be used as a target because it takes >1 param",
23 [receiver class],NSStringFromSelector(action));
24 CAssert(0==strcmp([sig getArgumentTypeAtIndex: 2],"@"),
25 @"-[%@ %@] can't be used as a target because it takes a non-object param",
26 [receiver class],NSStringFromSelector(action));
27 NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sig];
28 inv.target = receiver;
29 inv.selector = action;
30 _invocations = [inv retain];
35 + (MYTarget*) targetWithReceiver: (id)receiver action: (SEL)action
37 return [[[self alloc] initWithReceiver: receiver action: action] autorelease];
42 [_invocations release];
47 - (NSArray*) invocations
49 NSMutableArray *invocations = $castIf(NSMutableArray,_invocations);
51 invocations = [NSMutableArray arrayWithObject: _invocations];
56 - (NSString*) description
58 NSMutableString *desc = [NSMutableString stringWithFormat: @"%@{", self.class];
60 for( NSInvocation *inv in self.invocations ) {
64 [desc appendString: @", "];
65 [desc appendFormat: @"-[%@ %s]", [inv.target class], inv.selector];
67 [desc appendString: @"}"];
72 static BOOL equalInvocations( NSInvocation *a, NSInvocation *b )
74 return a.target==b.target && a.selector==b.selector;
78 - (BOOL) isEqual: (MYTarget*)t
80 if( ! [t isKindOfClass: [self class]] )
82 if( [_invocations isKindOfClass: [NSInvocation class]] && [t->_invocations isKindOfClass: [NSInvocation class]] )
83 return equalInvocations(_invocations,t->_invocations);
84 NSArray *myInvocations = self.invocations, *itsInvocations = t.invocations;
85 unsigned n = myInvocations.count;
86 if( n != itsInvocations.count )
88 for( int i=0; i<n; i++ )
89 if( ! equalInvocations( [myInvocations objectAtIndex: i],
90 [itsInvocations objectAtIndex: i] ) )
96 - (void) addTarget: (MYTarget*)target
98 setObj(&_invocations,[self invocations]);
99 [_invocations addObjectsFromArray: target.invocations];
103 static id invokeSingleTarget( NSInvocation *invocation, id param )
106 if( invocation && invocation.target ) {
109 [invocation setArgument: ¶m atIndex: 2];
112 NSMethodSignature *sig = invocation.methodSignature;
113 NSUInteger returnLength = sig.methodReturnLength;
114 if( returnLength==0 ) {
115 result = nil; // void
117 const char *returnType = sig.methodReturnType;
118 if( returnType[0]=='@' ) {
119 [invocation getReturnValue: &result];
121 UInt8 returnBuffer[returnLength];
122 [invocation getReturnValue: &returnBuffer];
123 result = [NSValue valueWithBytes: &returnBuffer objCType: returnType];
127 [invocation release];
134 - (id) invokeWithSender: (id)sender
137 NSMutableArray *invocations = $castIf(NSMutableArray,_invocations);
140 for( NSInvocation *invocation in invocations )
141 result = invokeSingleTarget(invocation,sender);
143 result = invokeSingleTarget(_invocations,sender);