Added URLUtils. Rewrote Target.
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: ¶m atIndex: 2];
4.121 - [target invoke];
4.122 + [invocation setArgument: ¶m 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