1/** 2 * @file 3 * @date 17.5.2007 4 * 5 * Implementation of class HBOutputRedirect. 6 */ 7 8#import "HBOutputRedirect.h" 9 10/// Global pointer to HBOutputRedirect object that manages redirects for stdout. 11static HBOutputRedirect *g_stdoutRedirect = nil; 12 13/// Global pointer to HBOutputRedirect object that manages redirects for stderr. 14static HBOutputRedirect *g_stderrRedirect = nil; 15 16static int stdoutwrite(void *inFD, const char *buffer, int size); 17static int stderrwrite(void *inFD, const char *buffer, int size); 18 19@interface HBOutputRedirect () 20 21/// Output stream (@c stdout or @c stderr) redirected by this object. 22@property (nonatomic, readonly) FILE *stream; 23 24/// Pointer to old write function for the stream. 25@property (nonatomic, readonly) int (*oldWriteFunc)(void *, const char *, int); 26 27@end 28 29/** 30 * Function that replaces stdout->_write and forwards stdout to g_stdoutRedirect. 31 */ 32int stdoutwrite(void *inFD, const char *buffer, int size) 33{ 34 @autoreleasepool 35 { 36 NSString *string = [[NSString alloc] initWithBytes:buffer length:size encoding:NSUTF8StringEncoding]; 37 if (string) 38 { 39 [g_stdoutRedirect forwardOutput:string]; 40 } 41 } 42 return size; 43} 44 45int stderrwrite(void *inFD, const char *buffer, int size) 46{ 47 @autoreleasepool 48 { 49 NSString *string = [[NSString alloc] initWithBytes:buffer length:size encoding:NSUTF8StringEncoding]; 50 if (string) 51 { 52 [g_stderrRedirect forwardOutput:string]; 53 } 54 } 55 return size; 56} 57 58@implementation HBOutputRedirect 59 60/** 61 * Returns HBOutputRedirect object used to redirect stdout. 62 */ 63+ (instancetype)stdoutRedirect 64{ 65 if (!g_stdoutRedirect) 66 { 67 g_stdoutRedirect = [[HBOutputRedirect alloc] initWithStream:stdout type:HBRedirectTypeOutput]; 68 } 69 return g_stdoutRedirect; 70} 71 72/** 73 * Returns HBOutputRedirect object used to redirect stderr. 74 */ 75+ (instancetype)stderrRedirect 76{ 77 if (!g_stderrRedirect) 78 { 79 g_stderrRedirect = [[HBOutputRedirect alloc] initWithStream:stderr type:HBRedirectTypeError]; 80 } 81 return g_stderrRedirect; 82} 83 84/** 85 * Private constructor which should not be called from outside. This is used to 86 * initialize the class at @c stdoutRedirect and @c stderrRedirect. 87 * 88 * @param stream Stream that will be redirected (stdout or stderr). 89 * @param type Type that will be called in listeners to redirect the stream. 90 * 91 * @return New HBOutputRedirect object. 92 */ 93- (instancetype)initWithStream:(FILE *)stream type:(HBRedirectType)type 94{ 95 if (self = [self initWithType:type]) 96 { 97 _stream = stream; 98 _oldWriteFunc = NULL; 99 } 100 return self; 101} 102 103/** 104 * Starts redirecting the stream by redirecting its output to function 105 * @c stdoutwrite() or @c stderrwrite(). Old _write function is stored to 106 * @c oldWriteFunc so it can be restored. 107 */ 108- (void)startRedirect 109{ 110 if (!_oldWriteFunc) 111 { 112 _oldWriteFunc = _stream->_write; 113 _stream->_write = _stream == stdout ? stdoutwrite : stderrwrite; 114 } 115} 116 117/** 118 * Stops redirecting of the stream by returning the stream's _write function 119 * to original. 120 */ 121- (void)stopRedirect 122{ 123 if (_oldWriteFunc) 124 { 125 _stream->_write = _oldWriteFunc; 126 _oldWriteFunc = NULL; 127 } 128} 129 130@end 131