Added URLUtils. Rewrote Target.
authorJens Alfke <jens@mooseyard.com>
Fri May 02 12:49:43 2008 -0700 (2008-05-02)
changeset 759addced5e2a
parent 6 2d492d8c2053
child 8 5588347dfcbd
Added URLUtils. Rewrote Target.
CollectionUtils.h
CollectionUtils.m
Target.h
Target.m
URLUtils.h
URLUtils.m
     1.1 --- a/CollectionUtils.h	Fri Apr 18 09:25:10 2008 -0700
     1.2 +++ b/CollectionUtils.h	Fri May 02 12:49:43 2008 -0700
     1.3 @@ -47,6 +47,7 @@
     1.4  
     1.5  @interface NSSet (MYUtils)
     1.6  + (NSSet*) my_unionOfSet: (NSSet*)set1 andSet: (NSSet*)set2;
     1.7 ++ (NSSet*) my_intersectionOfSet: (NSSet*)set1 andSet: (NSSet*)set2;
     1.8  + (NSSet*) my_differenceOfSet: (NSSet*)set1 andSet: (NSSet*)set2;
     1.9  @end
    1.10  
     2.1 --- a/CollectionUtils.m	Fri Apr 18 09:25:10 2008 -0700
     2.2 +++ b/CollectionUtils.m	Fri May 02 12:49:43 2008 -0700
     2.3 @@ -161,7 +161,9 @@
     2.4  
     2.5  
     2.6  
     2.7 +
     2.8  @implementation NSSet (MYUtils)
     2.9 +
    2.10  + (NSSet*) my_unionOfSet: (NSSet*)set1 andSet: (NSSet*)set2
    2.11  {
    2.12      if( set1 == set2 || set2.count==0 )
    2.13 @@ -175,6 +177,19 @@
    2.14      }
    2.15  }
    2.16  
    2.17 ++ (NSSet*) my_intersectionOfSet: (NSSet*)set1 andSet: (NSSet*)set2
    2.18 +{
    2.19 +    if( set1 == set2 || set1.count==0 )
    2.20 +        return set1;
    2.21 +    else if( set2.count==0 )
    2.22 +        return set2;
    2.23 +    else {
    2.24 +        NSMutableSet *result = [set1 mutableCopy];
    2.25 +        [result intersectSet: set2];
    2.26 +        return [result autorelease];
    2.27 +    }
    2.28 +}
    2.29 +
    2.30  + (NSSet*) my_differenceOfSet: (NSSet*)set1 andSet: (NSSet*)set2
    2.31  {
    2.32      if( set1.count==0 || set2.count==0 )
    2.33 @@ -187,6 +202,7 @@
    2.34          return [result autorelease];
    2.35      }
    2.36  }
    2.37 +
    2.38  @end
    2.39  
    2.40  
     3.1 --- a/Target.h	Fri Apr 18 09:25:10 2008 -0700
     3.2 +++ b/Target.h	Fri May 02 12:49:43 2008 -0700
     3.3 @@ -9,9 +9,18 @@
     3.4  #import <Cocoa/Cocoa.h>
     3.5  
     3.6  
     3.7 -#define $target(RCVR,METHOD)    _mktarget((RCVR),@selector(METHOD))
     3.8 +@interface MYTarget : NSObject
     3.9 +{
    3.10 +    id _invocations;    // May be an NSInvocation, or an NSMutableArray of them
    3.11 +}
    3.12  
    3.13 -id $calltarget( NSInvocation *target, id sender );
    3.14 ++ (MYTarget*) targetWithReceiver: (id)receiver action: (SEL)action;
    3.15  
    3.16 +- (void) addTarget: (MYTarget*)target;
    3.17  
    3.18 -NSInvocation* _mktarget( id rcvr, SEL action );
    3.19 +- (id) invokeWithSender: (id)sender;
    3.20 +
    3.21 +@end
    3.22 +
    3.23 +
    3.24 +#define $target(RCVR,METHOD)    [MYTarget targetWithReceiver: (RCVR) action: @selector(METHOD)]
     4.1 --- a/Target.m	Fri Apr 18 09:25:10 2008 -0700
     4.2 +++ b/Target.m	Fri May 02 12:49:43 2008 -0700
     4.3 @@ -9,49 +9,140 @@
     4.4  #import "Target.h"
     4.5  
     4.6  
     4.7 -NSInvocation* _mktarget( id rcvr, SEL action )
     4.8 +@implementation MYTarget
     4.9 +
    4.10 +
    4.11 +- (id) initWithReceiver: (id)receiver action: (SEL)action
    4.12  {
    4.13 -    NSMethodSignature *sig = [rcvr methodSignatureForSelector: action];
    4.14 -    CAssert(sig,@"%@<%p> does not respond to %@",[rcvr class],rcvr,NSStringFromSelector(action));
    4.15 -    CAssert(sig.numberOfArguments==3,
    4.16 -           @"-[%@ %@] can't be used as a target because it takes >1 param",
    4.17 -           [rcvr class],NSStringFromSelector(action));
    4.18 -    CAssert(0==strcmp([sig getArgumentTypeAtIndex: 2],"@"),
    4.19 -           @"-[%@ %@] can't be used as a target because it takes a non-object param",
    4.20 -           [rcvr class],NSStringFromSelector(action));
    4.21 -    NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sig];
    4.22 -    inv.target = rcvr;
    4.23 -    inv.selector = action;
    4.24 -    return inv;
    4.25 +    self = [super init];
    4.26 +    if( self ) {
    4.27 +        NSMethodSignature *sig = [receiver methodSignatureForSelector: action];
    4.28 +        CAssert(sig,@"%@<%p> does not respond to %@",[receiver class],receiver,NSStringFromSelector(action));
    4.29 +        CAssert(sig.numberOfArguments==3,
    4.30 +               @"-[%@ %@] can't be used as a target because it takes >1 param",
    4.31 +               [receiver class],NSStringFromSelector(action));
    4.32 +        CAssert(0==strcmp([sig getArgumentTypeAtIndex: 2],"@"),
    4.33 +               @"-[%@ %@] can't be used as a target because it takes a non-object param",
    4.34 +               [receiver class],NSStringFromSelector(action));
    4.35 +        NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sig];
    4.36 +        inv.target = receiver;
    4.37 +        inv.selector = action;
    4.38 +        _invocations = [inv retain];
    4.39 +    }
    4.40 +    return self;
    4.41  }
    4.42  
    4.43 ++ (MYTarget*) targetWithReceiver: (id)receiver action: (SEL)action
    4.44 +{
    4.45 +    return [[[self alloc] initWithReceiver: receiver action: action] autorelease];
    4.46 +}
    4.47  
    4.48 -id $calltarget( NSInvocation *target, id param )
    4.49 +- (void) dealloc
    4.50 +{
    4.51 +    [_invocations release];
    4.52 +    [super dealloc];
    4.53 +}
    4.54 +
    4.55 +
    4.56 +- (NSArray*) invocations
    4.57 +{
    4.58 +    NSMutableArray *invocations = $castIf(NSMutableArray,_invocations);
    4.59 +    if( ! invocations )
    4.60 +        invocations = [NSMutableArray arrayWithObject: _invocations];
    4.61 +    return invocations;
    4.62 +}
    4.63 +
    4.64 +
    4.65 +- (NSString*) description
    4.66 +{
    4.67 +    NSMutableString *desc = [NSMutableString stringWithFormat: @"%@{", self.class];
    4.68 +    BOOL first = YES;
    4.69 +    for( NSInvocation *inv in self.invocations ) {
    4.70 +        if( first )
    4.71 +            first = NO;
    4.72 +        else
    4.73 +            [desc appendString: @", "];
    4.74 +        [desc appendFormat: @"-[%@ %s]", [inv.target class], inv.selector];
    4.75 +    }
    4.76 +    [desc appendString: @"}"];
    4.77 +    return desc;
    4.78 +}
    4.79 +
    4.80 +
    4.81 +static BOOL equalInvocations( NSInvocation *a, NSInvocation *b )
    4.82 +{
    4.83 +    return a.target==b.target && a.selector==b.selector;
    4.84 +}
    4.85 +
    4.86 +
    4.87 +- (BOOL) isEqual: (MYTarget*)t
    4.88 +{
    4.89 +    if( ! [t isKindOfClass: [self class]] )
    4.90 +        return NO;
    4.91 +    if( [_invocations isKindOfClass: [NSInvocation class]] && [t->_invocations isKindOfClass: [NSInvocation class]] )
    4.92 +        return equalInvocations(_invocations,t->_invocations);
    4.93 +    NSArray *myInvocations = self.invocations, *itsInvocations = t.invocations;
    4.94 +    unsigned n = myInvocations.count;
    4.95 +    if( n != itsInvocations.count )
    4.96 +        return NO;
    4.97 +    for( int i=0; i<n; i++ )
    4.98 +        if( ! equalInvocations( [myInvocations objectAtIndex: i],
    4.99 +                                [itsInvocations objectAtIndex: i] ) )
   4.100 +            return NO;
   4.101 +    return YES;
   4.102 +}
   4.103 +
   4.104 +
   4.105 +- (void) addTarget: (MYTarget*)target
   4.106 +{
   4.107 +    setObj(&_invocations,[self invocations]);
   4.108 +    [_invocations addObjectsFromArray: target.invocations];
   4.109 +}
   4.110 +
   4.111 +
   4.112 +static id invokeSingleTarget( NSInvocation *invocation, id param )
   4.113  {
   4.114      id result = nil;
   4.115 -    if( target && target.target ) {
   4.116 -        [target retain];
   4.117 +    if( invocation && invocation.target ) {
   4.118 +        [invocation retain];
   4.119          @try{
   4.120 -            [target setArgument: &param atIndex: 2];
   4.121 -            [target invoke];
   4.122 +            [invocation setArgument: &param atIndex: 2];
   4.123 +            [invocation invoke];
   4.124              
   4.125 -            NSMethodSignature *sig = target.methodSignature;
   4.126 +            NSMethodSignature *sig = invocation.methodSignature;
   4.127              NSUInteger returnLength = sig.methodReturnLength;
   4.128              if( returnLength==0 ) {
   4.129                  result = nil; // void
   4.130              } else {
   4.131                  const char *returnType = sig.methodReturnType;
   4.132                  if( returnType[0]=='@' ) {
   4.133 -                    [target getReturnValue: &result];
   4.134 +                    [invocation getReturnValue: &result];
   4.135                  } else {
   4.136                      UInt8 returnBuffer[returnLength];
   4.137 -                    [target getReturnValue: &returnBuffer];
   4.138 +                    [invocation getReturnValue: &returnBuffer];
   4.139                      result = [NSValue valueWithBytes: &returnBuffer objCType: returnType];
   4.140                  }
   4.141              }
   4.142          }@finally{
   4.143 -            [target release];
   4.144 +            [invocation release];
   4.145          }
   4.146      }
   4.147      return result;
   4.148  }
   4.149 +
   4.150 +
   4.151 +- (id) invokeWithSender: (id)sender
   4.152 +{
   4.153 +    id result;
   4.154 +    NSMutableArray *invocations = $castIf(NSMutableArray,_invocations);
   4.155 +    if( invocations ) {
   4.156 +        for( NSInvocation *invocation in invocations )
   4.157 +            result = invokeSingleTarget(invocation,sender);
   4.158 +    } else {
   4.159 +        result = invokeSingleTarget(_invocations,sender);
   4.160 +    }
   4.161 +    return result;
   4.162 +}
   4.163 +
   4.164 +
   4.165 +@end
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/URLUtils.h	Fri May 02 12:49:43 2008 -0700
     5.3 @@ -0,0 +1,18 @@
     5.4 +//
     5.5 +//  URLUtils.h
     5.6 +//  Cloudy
     5.7 +//
     5.8 +//  Created by Jens Alfke on 4/28/08.
     5.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
    5.10 +//
    5.11 +
    5.12 +#import <Foundation/Foundation.h>
    5.13 +
    5.14 +
    5.15 +@interface NSHTTPURLResponse (MYUtilities)
    5.16 +
    5.17 +- (NSError*) HTTPError;
    5.18 +
    5.19 +@end
    5.20 +
    5.21 +extern NSString* const MyHTTPErrorDomain;
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/URLUtils.m	Fri May 02 12:49:43 2008 -0700
     6.3 @@ -0,0 +1,32 @@
     6.4 +//
     6.5 +//  URLUtils.m
     6.6 +//  Cloudy
     6.7 +//
     6.8 +//  Created by Jens Alfke on 4/28/08.
     6.9 +//  Copyright 2008 __MyCompanyName__. All rights reserved.
    6.10 +//
    6.11 +
    6.12 +#import "URLUtils.h"
    6.13 +
    6.14 +
    6.15 +@implementation NSHTTPURLResponse (MYUtilities)
    6.16 +
    6.17 +
    6.18 +- (NSError*) HTTPError
    6.19 +{
    6.20 +    // HTTP status >= 300 is considered an error:
    6.21 +    int status = self.statusCode;
    6.22 +    if( status >= 300 ) {
    6.23 +        NSString *reason = NSLocalizedStringFromTable( @"HTTP_ERROR_MESSAGE",@"UKCrashReporter",@"");
    6.24 +        reason = [NSHTTPURLResponse localizedStringForStatusCode: status];
    6.25 +        NSDictionary *info = $dict({NSLocalizedFailureReasonErrorKey,reason});
    6.26 +        return [NSError errorWithDomain: MyHTTPErrorDomain code: status userInfo: info];
    6.27 +    } else
    6.28 +        return nil;
    6.29 +}
    6.30 +
    6.31 +
    6.32 +NSString* const MyHTTPErrorDomain = @"HTTP";
    6.33 +
    6.34 +
    6.35 +@end