Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

More work-in-progress

git-svn-id: http://svn.textmate.org/trunk/Tools/CommitWindowProject@5535 dfb7d73b-c2ec-0310-8fea-fb051d288c6d
  • Loading branch information...
commit 9b54e3f5ee8d10c3199c66805aea2638fa8103a6 1 parent 3d04322
Chris Thomas authored
Showing with 181 additions and 0 deletions.
  1. +34 −0 NSTask+CXAdditions.h
  2. +147 −0 NSTask+CXAdditions.m
View
34 NSTask+CXAdditions.h
@@ -0,0 +1,34 @@
+//
+// NSTask+CXAdditions.h
+//
+// Created by Chris Thomas on 2006-10-20.
+// Copyright 2006 Chris Thomas. All rights reserved.
+//
+
+
+@interface NSTask (CXAdditions)
+
+// For the three methods below:
+// Argument index 0 is an absolute path to the executable.
+// Each file/data/string output is allocated and returned to the caller unless the caller passes NULL.
+// input may be NULL, an NSString object, or an NSData object.
+
+// Return a task (not yet launched) and optionally allocate stdout/stdin/stderr streams for communication with it
++ (NSTask *) taskWithArguments:(NSArray *)arguments
+ input:(NSFileHandle **)outWriteHandle
+ output:(NSFileHandle **)outReadHandle
+ error:(NSFileHandle **)outErrorHandle;
+
+// Atomically execute the task and return output as data
++ (int) executeTaskWithArguments:(NSArray *)args
+ input:(id)inputDataOrString
+ outputData:(NSData **)outputData
+ errorString:(NSString **)errorString;
+
+// Atomically execute the task and return output as string
++ (int) executeTaskWithArguments:(NSArray *)args
+ input:(id)inputDataOrString
+ outputString:(NSString **)outputString
+ errorString:(NSString **)errorString;
+
+@end
View
147 NSTask+CXAdditions.m
@@ -0,0 +1,147 @@
+//
+// NSTask+CXAdditions.m
+//
+// Created by Chris Thomas on 2006-10-20.
+// Copyright 2006 Chris Thomas. All rights reserved.
+//
+
+#import "NSTask+CXAdditions.h"
+
+@interface NSFileHandle (CXAdditions)
+- (NSData *) reallyReadDataToEndOfFile;
+@end
+
+@implementation NSFileHandle (CXAdditions)
+
+// This method exists mainly for ease of debugging. readDataToEndOfFile should actually do the job.
+- (NSData *) reallyReadDataToEndOfFile
+{
+ NSMutableData * outData = [[[NSMutableData alloc] init] autorelease];
+ NSData * currentData;
+
+ currentData = [self availableData];
+ while( currentData != nil && [currentData length] > 0 )
+ {
+ [outData appendData:currentData];
+ currentData = [self availableData];
+ }
+
+ return outData;
+}
+@end
+
+@implementation NSTask (CXAdditions)
+
+// Return a task (not yet launched) and optionally allocate stdout/stdin/stderr streams for communication with it
++ (NSTask *) taskWithArguments:(NSArray *)args
+ input:(NSFileHandle **)outWriteHandle
+ output:(NSFileHandle **)outReadHandle
+ error:(NSFileHandle **)outErrorHandle
+{
+ NSTask *task = [[[NSTask alloc] init] autorelease];
+
+ [task setLaunchPath:[args objectAtIndex:0]];
+ [task setArguments:[args subarrayWithRange:NSMakeRange(1, [args count] - 1)]];
+
+ if( outReadHandle != NULL )
+ {
+ NSPipe * readPipe = [NSPipe pipe];
+ NSFileHandle * readHandle = [readPipe fileHandleForReading];
+
+ [task setStandardOutput:readPipe];
+ *outReadHandle = readHandle;
+ }
+
+ if( outWriteHandle != NULL )
+ {
+ NSPipe * writePipe = [NSPipe pipe];
+ NSFileHandle * writeHandle = [writePipe fileHandleForWriting];
+
+ [task setStandardInput:writePipe];
+ *outWriteHandle = writeHandle;
+ }
+
+ if( outErrorHandle != NULL )
+ {
+ NSPipe * errorPipe = [NSPipe pipe];
+ NSFileHandle * errorHandle = [errorPipe fileHandleForReading];
+
+ [task setStandardError:errorPipe];
+ *outErrorHandle = errorHandle;
+ }
+
+ return task;
+}
+
+// Atomically execute the task and return output as data
++ (int) executeTaskWithArguments:(NSArray *)args
+ input:(id)inputDataOrString
+ outputData:(NSData **)outputData
+ errorString:(NSString **)errorString;
+{
+
+ NSFileHandle * outputFile = nil;
+ NSFileHandle * inputFile = nil;
+ NSFileHandle * errorFile = nil;
+ NSTask * task;
+
+ task = [NSTask taskWithArguments:args
+ input:(inputDataOrString == nil) ? NULL : &inputFile
+ output:(outputData == NULL) ? NULL : &outputFile
+ error:(errorString == NULL) ? NULL : &errorFile];
+
+ if( inputDataOrString != nil )
+ {
+ // Convert string to UTF8 data
+ if( [inputDataOrString isKindOfClass:[NSString class]] )
+ {
+ inputDataOrString = [inputDataOrString dataUsingEncoding:NSUTF8StringEncoding];
+ }
+
+ [inputFile writeData:inputDataOrString];
+ [inputFile closeFile];
+ }
+ [task launch];
+
+ // output data
+ if( outputData != NULL )
+ {
+ *outputData = [outputFile reallyReadDataToEndOfFile];
+ }
+
+ // convert error data to string
+ if( errorString != NULL )
+ {
+ NSData * errorData = [errorFile reallyReadDataToEndOfFile];
+
+ *errorString = [[[NSString alloc] initWithData:errorData
+ encoding:NSUTF8StringEncoding] autorelease];
+ }
+
+ [task waitUntilExit];
+ return [task terminationStatus];
+}
+
++ (int) executeTaskWithArguments:(NSArray *)args
+ input:(id)inputDataOrString
+ outputString:(NSString **)outputString
+ errorString:(NSString **)errorString;
+{
+ NSData * outputData;
+ int terminationStatus;
+
+ terminationStatus = [self executeTaskWithArguments:args
+ input:inputDataOrString
+ outputData:(outputString == NULL) ? NULL : &outputData
+ errorString:errorString];
+
+ if( outputString != nil )
+ {
+ *outputString = [[[NSString alloc] initWithData:outputData
+ encoding:NSUTF8StringEncoding] autorelease];
+ }
+
+ return terminationStatus;
+}
+
+@end
Please sign in to comment.
Something went wrong with that request. Please try again.