diff --git a/ChangeLog b/ChangeLog index cde4fe5c1..ebd089b4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2013-07-09 Graham Lee + + * Source/GNUmakefile: + * Source/NSInvocationOperation.m: + * Headers/Foundation/Foundation.h: + * Headers/Foundation/NSInvocationOperation.h: + New invocation operation class + 2013-07-09 Richard Frith-Macdonald * Source/GSTLS.m: Fix memory leak (credentials) diff --git a/Headers/Foundation/Foundation.h b/Headers/Foundation/Foundation.h index 092b98813..e21d641a2 100644 --- a/Headers/Foundation/Foundation.h +++ b/Headers/Foundation/Foundation.h @@ -76,6 +76,7 @@ #import #import #import +#import #import #import #import diff --git a/Headers/Foundation/NSInvocationOperation.h b/Headers/Foundation/NSInvocationOperation.h new file mode 100644 index 000000000..786cab116 --- /dev/null +++ b/Headers/Foundation/NSInvocationOperation.h @@ -0,0 +1,63 @@ +/**Interface for NSInvocationOperation for GNUStep + Copyright (C) 2013 Free Software Foundation, Inc. + + Written by: Graham Lee + Date: 2013 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02111 USA. + + */ + +#ifndef __NSInvocationOperation_h_GNUSTEP_BASE_INCLUDE +#define __NSInvocationOperation_h_GNUSTEP_BASE_INCLUDE + +#import +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) + +#if defined(__cplusplus) +extern "C" { +#endif + +@class NSInvocation; +@class NSException; + +@interface NSInvocationOperation : NSOperation +{ + @private + NSInvocation *_invocation; + NSException *_exception; + void *_reserved; +} + +- (id) initWithInvocation: (NSInvocation *)inv; +- (id) initWithTarget: (id)target selector: (SEL)aSelector object: (id)arg; + +- (NSInvocation *) invocation; +- (id) result; + +@end + +extern const NSString * NSInvocationOperationVoidResultException; +extern const NSString * NSInvocationOperationCancelledException; + +#if defined(__cplusplus) +} +#endif + +#endif /* OS_API_VERSION */ +#endif /* __NSInvocationOperation_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Source/GNUmakefile b/Source/GNUmakefile index 6463ef30c..da9079d49 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -223,6 +223,7 @@ NSHTTPCookieStorage.m \ NSIndexPath.m \ NSIndexSet.m \ NSInvocation.m \ +NSInvocationOperation.m \ NSJSONSerialization.m \ NSKeyedArchiver.m \ NSKeyedUnarchiver.m \ @@ -388,6 +389,7 @@ NSHTTPCookieStorage.h \ NSIndexPath.h \ NSIndexSet.h \ NSInvocation.h \ +NSInvocationOperation.h \ NSJSONSerialization.h \ NSKeyedArchiver.h \ NSKeyValueCoding.h \ diff --git a/Source/NSInvocationOperation.m b/Source/NSInvocationOperation.m new file mode 100644 index 000000000..d850ee6ef --- /dev/null +++ b/Source/NSInvocationOperation.m @@ -0,0 +1,133 @@ +/**Implementation for NSInvocationOperation for GNUStep + Copyright (C) 2013 Free Software Foundation, Inc. + + Written by: Graham Lee + Date: 2013 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02111 USA. + + NSInvocationOperation class reference + $Date$ $Revision$ + */ + +#import "common.h" + +#import +#import +#import +#import +#import + +@implementation NSInvocationOperation + +- (id) initWithInvocation: (NSInvocation *)inv +{ + if (((self = [super init])) != nil) + { + [inv retainArguments]; + _invocation = [inv retain]; + } + return self; +} + +- (id) initWithTarget: (id)target selector: (SEL)aSelector object: (id)arg +{ + NSMethodSignature *methodSignature; + NSInvocation *inv; + + methodSignature = [target methodSignatureForSelector: aSelector]; + inv = [NSInvocation invocationWithMethodSignature: methodSignature]; + [inv setTarget: target]; + [inv setSelector: aSelector]; + if ([methodSignature numberOfArguments] > 2) + [inv setArgument: &arg atIndex: 2]; + return [self initWithInvocation: inv]; +} + +- (void) main +{ + if (![self isCancelled]) + { + NS_DURING + [_invocation invoke]; + NS_HANDLER + _exception = [localException copy]; + NS_ENDHANDLER + } +} + +- (NSInvocation *) invocation +{ + return [[_invocation retain] autorelease]; +} + +- (id) result +{ + id result = nil; + + if (![self isFinished]) + { + return nil; + } + if (nil != _exception) + { + [_exception raise]; + } + else if ([self isCancelled]) + { + [NSException raise: (id)NSInvocationOperationCancelledException + format: @"*** %s: operation was cancelled", __PRETTY_FUNCTION__]; + } + else + { + const char *returnType = [[_invocation methodSignature] methodReturnType]; + + if (0 == strncmp(@encode(void), returnType, 1)) + { + [NSException raise: (id)NSInvocationOperationVoidResultException + format: @"*** %s: void result", __PRETTY_FUNCTION__]; + } + else if (0 == strncmp(@encode(id), returnType, 1)) + { + [_invocation getReturnValue: &result]; + } + else + { + unsigned char *buffer = malloc([[_invocation methodSignature] + methodReturnLength]); + + [_invocation getReturnValue: buffer]; + result = [NSValue valueWithBytes: buffer objCType: returnType]; + } + } + return result; +} + +- (void) dealloc +{ + [_invocation release]; + [_exception release]; + [super dealloc]; +} + +@end + +const NSString * NSInvocationOperationVoidResultException + = @"NSInvocationOperationVoidResultException"; +const NSString * NSInvocationOperationCancelledException + = @"NSInvcationOperationCancelledException";