2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
22 #include <NGStreams/NGStreamExceptions.h>
23 #include <NGStreams/NGStream.h>
24 #include <NGStreams/NGFilterStream.h>
27 @implementation NGStream
31 - (void)setLastException:(NSException *)_exception {
34 - (NSException *)lastException {
38 - (unsigned)readBytes:(void *)_buf count:(unsigned)_len {
39 [self subclassResponsibility:_cmd];
42 - (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len {
43 [self subclassResponsibility:_cmd];
54 - (NGStreamMode)mode {
55 [self subclassResponsibility:_cmd];
58 - (BOOL)isRootStream {
59 [self subclassResponsibility:_cmd];
63 // methods method which write exactly _len bytes
65 - (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len {
66 return NGSafeReadBytesFromStream(self, _buf, _len);
69 - (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len {
70 return NGSafeWriteBytesToStream(self, _buf, _len);
76 NSLog(@"WARNING: called mark on a stream which doesn't support marking !");
80 [NGStreamException raiseWithStream:self reason:@"marking not supported"];
83 - (BOOL)markSupported {
87 /* convenience methods */
90 return NGReadByteFromStream(self);
95 - (NSString *)modeDescription {
96 NSString *result = @"unknown";
98 switch ([self mode]) {
99 case NGStreamMode_undefined: result = @"undefined"; break;
100 case NGStreamMode_readOnly: result = @"r"; break;
101 case NGStreamMode_writeOnly: result = @"w"; break;
102 case NGStreamMode_readWrite: result = @"rw"; break;
104 [NGUnknownStreamModeException raiseWithStream:self];
110 - (NSString *)description {
111 return [NSString stringWithFormat:
112 @"<%@[0x%p] mode=%@>",
113 NSStringFromClass([self class]), self,
114 [self modeDescription]];
119 @implementation NGStream(DataMethods)
121 - (NSData *)readDataOfLength:(unsigned int)_length {
125 if (_length == 0) return [NSData data];
127 readCount = [self readBytes:buf count:_length];
128 if (readCount == NGStreamError)
131 return [NSData dataWithBytes:buf length:readCount];
134 - (NSData *)safeReadDataOfLength:(unsigned int)_length {
137 if (_length == 0) return [NSData data];
138 if (![self safeReadBytes:buf count:_length])
140 return [NSData dataWithBytes:buf length:_length];
143 - (unsigned int)writeData:(NSData *)_data {
144 return [self writeBytes:[_data bytes] count:[_data length]];
146 - (BOOL)safeWriteData:(NSData *)_data {
147 return [self safeWriteBytes:[_data bytes] count:[_data length]];
150 @end /* NGStream(DataMethods) */
152 // concrete implementations as functions
154 int NGReadByteFromStream(id<NGInputStream> _stream) {
155 volatile int result = -1;
160 l = [_stream readBytes:&c count:sizeof(unsigned char)];
161 if (l == NGStreamError) {
162 NSException *e = [(id)_stream lastException];
163 if ([e isKindOfClass:[NGEndOfStreamException class]])
172 if ([localException isKindOfClass:[NGEndOfStreamException class]])
175 [localException raise];
182 BOOL NGSafeReadBytesFromStream(id<NGInputStream> _in, void *_buf, unsigned _len){
183 volatile int toBeRead;
184 volatile int readResult;
185 volatile NGIOReadMethodType readBytes;
188 readBytes = (NGIOReadMethodType)
189 [(NSObject *)_in methodForSelector:@selector(readBytes:count:)];
195 *(&readResult) = (unsigned)readBytes(_in, @selector(readBytes:count:),
198 if (readResult == NGStreamError) {
199 /* TODO: improve exception handling ... */
200 [[(id)_in lastException] raise];
202 else if (readResult == toBeRead) {
203 // all bytes were read successfully, return
207 if (readResult < 1) {
208 [NSException raise:NSInternalInconsistencyException
209 format:@"readBytes:count: returned a value < 1"];
212 toBeRead -= readResult;
217 if ([localException isKindOfClass:[NGEndOfStreamException class]]) {
218 [[[NGEndOfStreamException alloc]
219 initWithStream:(id)_in
220 readCount:(_len - toBeRead)
222 data:[NSData dataWithBytes:_buf
223 length:(_len - toBeRead)]]
227 [localException raise];
234 BOOL NGSafeWriteBytesToStream(id<NGOutputStream> _o,const void *_b,unsigned _l) {
235 int toBeWritten = _l;
237 void *pos = (void *)_b;
238 NGIOWriteMethodType writeBytes;
240 writeBytes = (NGIOWriteMethodType)
241 [(NSObject *)_o methodForSelector:@selector(writeBytes:count:)];
245 (int)writeBytes(_o, @selector(writeBytes:count:), pos, toBeWritten);
247 if (writeResult == NGStreamError) {
248 /* remember number of written bytes ??? */
251 else if (writeResult == toBeWritten) {
252 // all bytes were written successfully, return
256 if (writeResult < 1) {
257 [NSException raise:NSInternalInconsistencyException
258 format:@"writeBytes:count: returned a value<1 in %@", _o];
261 toBeWritten -= writeResult;