Header File: BJGTextIOHandler.h
//
// BJGTextIOHandler.h
// Escape
//
// Created by Brent Gulanowski on 11/27/05.
// Copyright 2005 Bored Astronaut Software. All rights reserved.
//
// An interface to text-based input and output; primarily for handling stdio.#import <Foundation/Foundation.h>
@interface BJGTextIOHandler : NSObject {
NSFileHandle *inputFH;
NSFileHandle *outputFH;
id delegate;
}/* designated initializer */
-(id)initWithInputFile:(NSString *)inFile outputFile:(NSString *)outFile;/* set inFile to nil for stdin, outFile to nil for stdout */
-(void)setInputFile:(NSString *)inFile;
-(void)setOutputFile:(NSString *)outFile;/* if there’s no delegate, nothing happens */
-(id)delegate;
-(void)setDelegate:(id)del;
-(void)write:(NSString *)line;@end
Source code: BJGTextIOHandler.h
Implementation File: BJGTextIOHandler.m
//
// BJGTextIOHandler.m
// Escape
//
// Created by Brent Gulanowski on 11/27/05.
// Copyright 2005 Bored Astronaut Software. All rights reserved.
//#import “BJGTextIOHandler.h”
@interface BJGTextIOHandler (BJGTextIOHandler_private)
-(void)receive;
@end@implementation BJGTextIOHandler
/** inheritance tree overrides **/
#pragma mark NSObject
#if 0 /* remove the guards as necessary */
+(void)initialize {
}
#endif-(id)init {
return [self initWithInputFile:nil outputFile:nil];
}/** new methods **/
#pragma mark BJGTextIOHandler
-(id)initWithInputFile:(NSString *)inFile outputFile:(NSString *)outFile {
[self setInputFile:inFile];
[self setOutputFile:outFile];return self;
}-(void)write:(NSString *)line {
if(line) {
[outputFH writeData:[line dataUsingEncoding:NSUTF8StringEncoding]];
}
}-(void)setInputFile:(NSString *)inFile {
inputFH = [[NSFileHandle fileHandleForReadingAtPath:inFile] retain];
if(nil == inputFH) {
inputFH = [NSFileHandle fileHandleWithStandardInput];
}
}-(void)setOutputFile:(NSString *)outFile {
outputFH = [[NSFileHandle fileHandleForWritingAtPath:outFile] retain];
if(nil == outputFH) {
outputFH = [NSFileHandle fileHandleWithStandardOutput];
}
}-(id)delegate {
return delegate;
}-(void)setDelegate:(id)del {
if(del) {
if(NO == [del respondsToSelector:NSSelectorFromString(@”processInput:”)]) {
NSLog(@”Delegate must implement -processInput: method.”);
delegate = nil;
}
else if (!delegate) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:NSSelectorFromString(@”receive”)
name:NSFileHandleDataAvailableNotification
object:inputFH];
}
}
delegate = del;
if(delegate) {
[inputFH waitForDataInBackgroundAndNotify];
}
else {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}#pragma mark BJGTextIOHandler_private
-(void)receive {NSData *data = [inputFH availableData];
/* should always be true if “-receive” is called */
if(delegate) {
NSString *read;
if(!data || [data length] == 0) {
[delegate processInput:nil];
}
else {
read = [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
/* Workaround to clean up garbage attached to single-character input. Why is this happening? */
if(’\n’ == [read characterAtIndex:[read length] - 3]) {
read = [read substringToIndex:[read length] - 2];
}
read = [read stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[self write:[delegate processInput:read]];
}
}
if(delegate) {
[inputFH waitForDataInBackgroundAndNotify];
}
}@end
Source code: BJGTextIOHandler.m