1/* 2 Copyright (C) 2000-2005 SKYRIX Software AG 3 4 This file is part of SOPE. 5 6 SOPE is free software; you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License as published by the 8 Free Software Foundation; either version 2, or (at your option) any 9 later version. 10 11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with SOPE; see the file COPYING. If not, write to the 18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. 20*/ 21 22#include "NGTextStream.h" 23#include "common.h" 24 25@implementation NGTextStream 26 27- (void)dealloc { 28 [self->lastException release]; 29 [super dealloc]; 30} 31 32/* NGTextInputStream */ 33 34- (NSException *)lastException { 35 return nil; 36} 37- (void)setLastException:(NSException *)_exception { 38 ASSIGN(self->lastException, _exception); 39} 40- (void)resetLastException { 41 [self->lastException release]; 42 self->lastException = nil; 43} 44 45- (unichar)readCharacter { 46 [self subclassResponsibility:_cmd]; 47 return 0; 48} 49 50- (BOOL)isOpen { 51 return YES; 52} 53 54/* NGExtendedTextInputStream */ 55 56- (NSString *)readLineAsString { 57 NSMutableString *str; 58 unichar c; 59 60 *(&str) = (id)[NSMutableString string]; 61 62 NS_DURING { 63 while ((c = [self readCharacter]) != '\n') 64 [str appendString:[NSString stringWithCharacters:&c length:1]]; 65 } 66 NS_HANDLER { 67 if ([localException isKindOfClass:[NGEndOfStreamException class]]) { 68 if ([str length] == 0) str = nil; 69 } 70 else 71 [localException raise]; 72 } 73 NS_ENDHANDLER; 74 75 return str; 76} 77 78- (unsigned)readCharacters:(unichar *)_chars count:(unsigned)_count { 79 /* 80 Read up to _count characters, but one at the minimum. 81 */ 82 volatile unsigned pos; 83 84 NS_DURING { 85 for (pos = 0; pos < _count; pos++) 86 _chars[pos] = [self readCharacter]; 87 } 88 NS_HANDLER { 89 if ([localException isKindOfClass:[NGEndOfStreamException class]]) { 90 if (pos == 0) 91 [localException raise]; 92 } 93 else 94 [localException raise]; 95 } 96 NS_ENDHANDLER; 97 98 NSAssert1(pos > 0, @"invalid character count to be returned: %i", pos); 99 return pos; 100} 101 102- (BOOL)safeReadCharacters:(unichar *)_chars count:(unsigned)_count { 103 volatile unsigned pos; 104 105 for (pos = 0; pos < _count; pos++) 106 _chars[pos] = [self readCharacter]; 107 108 return YES; 109} 110 111/* NGTextOutputStream */ 112 113- (BOOL)writeCharacter:(unichar)_character { 114 [self subclassResponsibility:_cmd]; 115 return NO; 116} 117 118- (BOOL)writeString:(NSString *)_string { 119 unsigned length = [_string length], cnt = 0; 120 unichar buffer[length]; 121 void (*writeChar)(id, SEL, unichar); 122 123 writeChar = (void (*)(id,SEL,unichar)) 124 [self methodForSelector:@selector(writeCharacter:)]; 125 126 [_string getCharacters:buffer]; 127 for (cnt = 0; cnt < length; cnt++) 128 writeChar(self, @selector(writeCharacter:), buffer[cnt]); 129 130 return YES; 131} 132 133- (BOOL)flush { 134 return YES; 135} 136 137/* NGExtendedTextOutputStream */ 138 139- (BOOL)writeFormat:(NSString *)_format arguments:(va_list)_ap { 140 NSString *tmp; 141 142 tmp = [[[NSString alloc] initWithFormat:_format arguments:_ap] autorelease]; 143 [self writeString:tmp]; 144 return YES; 145} 146- (BOOL)writeFormat:(NSString *)_format, ... { 147 va_list ap; 148 BOOL res = NO; 149 150 va_start(ap, _format); 151 152#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 153 /* As soon as we add an exception handler on Leopard compilation 154 * breaks. Probably some GCC bug. 155 */ 156 res = [self writeFormat:_format arguments:ap]; 157#else 158 NS_DURING { 159 res = [self writeFormat:_format arguments:ap]; 160 } 161 NS_HANDLER { 162 va_end(ap); 163 [localException raise]; 164 } 165 NS_ENDHANDLER; 166#endif 167 168 va_end(ap); 169 170 return res; 171} 172 173- (BOOL)writeNewline { 174 if (![self writeString:@"\n"]) return NO; 175 return [self flush]; 176} 177 178- (unsigned)writeCharacters:(const unichar *)_chars count:(unsigned)_count { 179 /* 180 Write up to _count characters, but one at the minimum. 181 */ 182 volatile unsigned pos; 183 184 NS_DURING { 185 for (pos = 0; pos < _count; pos++) 186 [self writeCharacter:_chars[pos]]; 187 } 188 NS_HANDLER { 189 if ([localException isKindOfClass:[NGEndOfStreamException class]]) { 190 if (pos == 0) 191 [localException raise]; 192 } 193 else 194 [localException raise]; 195 } 196 NS_ENDHANDLER; 197 198 NSAssert1(pos > 0, @"invalid character count to be returned: %i", pos); 199 return pos; 200} 201 202- (BOOL)safeWriteCharacters:(const unichar *)_chars count:(unsigned)_count { 203 unsigned pos; 204 205 for (pos = 0; pos < _count; pos++) { 206 if (![self writeCharacter:_chars[pos]]) 207 return NO; 208 } 209 210 return YES; 211} 212 213@end /* NGTextStream */ 214