Target.m
author Jens Alfke <jens@mooseyard.com>
Wed Sep 02 08:41:25 2009 -0700 (2009-09-02)
changeset 35 5cab3034d3a1
parent 11 e5976864dfe9
permissions -rw-r--r--
10.6 compatibility: Fix some new compiler warnings, and work around apparent regressions in NSTask and -stringByStandardizingPath.
jens@0
     1
//
jens@0
     2
//  Target.m
jens@0
     3
//  MYUtilities
jens@0
     4
//
jens@0
     5
//  Created by Jens Alfke on 2/11/08.
jens@0
     6
//  Copyright 2008 Jens Alfke. All rights reserved.
jens@0
     7
//
jens@0
     8
jens@0
     9
#import "Target.h"
jens@11
    10
#import "Logging.h"
jens@11
    11
#import "Test.h"
jens@0
    12
jens@0
    13
jens@7
    14
@implementation MYTarget
jens@7
    15
jens@7
    16
jens@7
    17
- (id) initWithReceiver: (id)receiver action: (SEL)action
jens@0
    18
{
jens@7
    19
    self = [super init];
jens@7
    20
    if( self ) {
jens@7
    21
        NSMethodSignature *sig = [receiver methodSignatureForSelector: action];
jens@7
    22
        CAssert(sig,@"%@<%p> does not respond to %@",[receiver class],receiver,NSStringFromSelector(action));
jens@7
    23
        CAssert(sig.numberOfArguments==3,
jens@7
    24
               @"-[%@ %@] can't be used as a target because it takes >1 param",
jens@7
    25
               [receiver class],NSStringFromSelector(action));
jens@7
    26
        CAssert(0==strcmp([sig getArgumentTypeAtIndex: 2],"@"),
jens@7
    27
               @"-[%@ %@] can't be used as a target because it takes a non-object param",
jens@7
    28
               [receiver class],NSStringFromSelector(action));
jens@7
    29
        NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sig];
jens@7
    30
        inv.target = receiver;
jens@7
    31
        inv.selector = action;
jens@7
    32
        _invocations = [inv retain];
jens@7
    33
    }
jens@7
    34
    return self;
jens@0
    35
}
jens@0
    36
jens@7
    37
+ (MYTarget*) targetWithReceiver: (id)receiver action: (SEL)action
jens@7
    38
{
jens@7
    39
    return [[[self alloc] initWithReceiver: receiver action: action] autorelease];
jens@7
    40
}
jens@0
    41
jens@7
    42
- (void) dealloc
jens@7
    43
{
jens@7
    44
    [_invocations release];
jens@7
    45
    [super dealloc];
jens@7
    46
}
jens@7
    47
jens@7
    48
jens@7
    49
- (NSArray*) invocations
jens@7
    50
{
jens@7
    51
    NSMutableArray *invocations = $castIf(NSMutableArray,_invocations);
jens@7
    52
    if( ! invocations )
jens@7
    53
        invocations = [NSMutableArray arrayWithObject: _invocations];
jens@7
    54
    return invocations;
jens@7
    55
}
jens@7
    56
jens@7
    57
jens@7
    58
- (NSString*) description
jens@7
    59
{
jens@7
    60
    NSMutableString *desc = [NSMutableString stringWithFormat: @"%@{", self.class];
jens@7
    61
    BOOL first = YES;
jens@7
    62
    for( NSInvocation *inv in self.invocations ) {
jens@7
    63
        if( first )
jens@7
    64
            first = NO;
jens@7
    65
        else
jens@7
    66
            [desc appendString: @", "];
jens@7
    67
        [desc appendFormat: @"-[%@ %s]", [inv.target class], inv.selector];
jens@7
    68
    }
jens@7
    69
    [desc appendString: @"}"];
jens@7
    70
    return desc;
jens@7
    71
}
jens@7
    72
jens@7
    73
jens@7
    74
static BOOL equalInvocations( NSInvocation *a, NSInvocation *b )
jens@7
    75
{
jens@7
    76
    return a.target==b.target && a.selector==b.selector;
jens@7
    77
}
jens@7
    78
jens@7
    79
jens@7
    80
- (BOOL) isEqual: (MYTarget*)t
jens@7
    81
{
jens@7
    82
    if( ! [t isKindOfClass: [self class]] )
jens@7
    83
        return NO;
jens@7
    84
    if( [_invocations isKindOfClass: [NSInvocation class]] && [t->_invocations isKindOfClass: [NSInvocation class]] )
jens@7
    85
        return equalInvocations(_invocations,t->_invocations);
jens@7
    86
    NSArray *myInvocations = self.invocations, *itsInvocations = t.invocations;
jens@26
    87
    NSUInteger n = myInvocations.count;
jens@7
    88
    if( n != itsInvocations.count )
jens@7
    89
        return NO;
jens@26
    90
    for( NSUInteger i=0; i<n; i++ )
jens@7
    91
        if( ! equalInvocations( [myInvocations objectAtIndex: i],
jens@7
    92
                                [itsInvocations objectAtIndex: i] ) )
jens@7
    93
            return NO;
jens@7
    94
    return YES;
jens@7
    95
}
jens@7
    96
jens@7
    97
jens@7
    98
- (void) addTarget: (MYTarget*)target
jens@7
    99
{
jens@7
   100
    setObj(&_invocations,[self invocations]);
jens@7
   101
    [_invocations addObjectsFromArray: target.invocations];
jens@7
   102
}
jens@7
   103
jens@7
   104
jens@7
   105
static id invokeSingleTarget( NSInvocation *invocation, id param )
jens@0
   106
{
jens@1
   107
    id result = nil;
jens@7
   108
    if( invocation && invocation.target ) {
jens@7
   109
        [invocation retain];
jens@1
   110
        @try{
jens@7
   111
            [invocation setArgument: &param atIndex: 2];
jens@7
   112
            [invocation invoke];
jens@1
   113
            
jens@7
   114
            NSMethodSignature *sig = invocation.methodSignature;
jens@1
   115
            NSUInteger returnLength = sig.methodReturnLength;
jens@1
   116
            if( returnLength==0 ) {
jens@1
   117
                result = nil; // void
jens@0
   118
            } else {
jens@1
   119
                const char *returnType = sig.methodReturnType;
jens@1
   120
                if( returnType[0]=='@' ) {
jens@7
   121
                    [invocation getReturnValue: &result];
jens@1
   122
                } else {
jens@1
   123
                    UInt8 returnBuffer[returnLength];
jens@7
   124
                    [invocation getReturnValue: &returnBuffer];
jens@1
   125
                    result = [NSValue valueWithBytes: &returnBuffer objCType: returnType];
jens@1
   126
                }
jens@0
   127
            }
jens@1
   128
        }@finally{
jens@7
   129
            [invocation release];
jens@0
   130
        }
jens@1
   131
    }
jens@1
   132
    return result;
jens@0
   133
}
jens@7
   134
jens@7
   135
jens@7
   136
- (id) invokeWithSender: (id)sender
jens@7
   137
{
jens@7
   138
    id result;
jens@7
   139
    NSMutableArray *invocations = $castIf(NSMutableArray,_invocations);
jens@7
   140
    if( invocations ) {
jens@8
   141
        result = nil;
jens@7
   142
        for( NSInvocation *invocation in invocations )
jens@7
   143
            result = invokeSingleTarget(invocation,sender);
jens@7
   144
    } else {
jens@7
   145
        result = invokeSingleTarget(_invocations,sender);
jens@7
   146
    }
jens@7
   147
    return result;
jens@7
   148
}
jens@7
   149
jens@7
   150
jens@7
   151
@end
jens@11
   152
jens@11
   153
jens@11
   154
/*
jens@11
   155
 Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
jens@11
   156
 
jens@11
   157
 Redistribution and use in source and binary forms, with or without modification, are permitted
jens@11
   158
 provided that the following conditions are met:
jens@11
   159
 
jens@11
   160
 * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@11
   161
 and the following disclaimer.
jens@11
   162
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
jens@11
   163
 and the following disclaimer in the documentation and/or other materials provided with the
jens@11
   164
 distribution.
jens@11
   165
 
jens@11
   166
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@11
   167
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@11
   168
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@11
   169
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@11
   170
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@11
   171
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@11
   172
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@11
   173
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@11
   174
 */