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 "NGDataStream.h"
23
#include "NGStreamExceptions.h"
26
// TODO: cache -bytes and -length of NSData for immutable data!
28
@implementation NGDataStream
31
return [super version] + 2;
35
return [self streamWithData:[NSMutableData dataWithCapacity:1024]];
37
+ (id)dataStreamWithCapacity:(int)_capacity {
38
return [self streamWithData:[NSMutableData dataWithCapacity:_capacity]];
41
+ (id)streamWithData:(NSData *)_data {
42
return [[[self alloc] initWithData:_data] autorelease];
44
- (id)initWithData:(NSData *)_data mode:(NGStreamMode)_mode {
45
if ((self = [super init])) {
46
self->data = [_data retain];
49
if ([self->data respondsToSelector:@selector(methodForSelector:)] == YES) {
50
self->dataLength = (unsigned int(*)(id, SEL))
51
[self->data methodForSelector:@selector(length)];
52
self->dataBytes = (const void*(*)(id, SEL))
53
[self->data methodForSelector:@selector(bytes)];
56
self->dataLength = NULL;
57
self->dataBytes = NULL;
60
self->streamMode = _mode;
62
/* for read-only streams */
63
if (self->streamMode == NGStreamMode_readOnly) {
64
self->bytes = [self->data bytes];
65
self->length = [self->data length];
70
- (id)initWithData:(NSData *)_data {
73
smode = [data isKindOfClass:[NSMutableData class]]
74
? NGStreamMode_readWrite
75
: NGStreamMode_readOnly;
76
return [self initWithData:_data mode:smode];
81
[self->lastException release];
87
/* NGTextInputStream */
89
- (NSException *)lastException {
90
return self->lastException;
92
- (void)setLastException:(NSException *)_exception {
93
ASSIGN(self->lastException, _exception);
95
- (void)resetLastException {
96
[self->lastException release];
97
self->lastException = nil;
104
- (unsigned)availableBytes {
105
// returns number of available bytes
106
register unsigned currentLength = 0;
108
if (self->bytes == NULL) {
109
currentLength = (self->dataLength == NULL)
110
? [self->data length]
111
: self->dataLength(self->data, @selector(length));
114
currentLength = self->length;
116
return (currentLength == position)
118
: (currentLength - position);
123
- (unsigned)readBytes:(void *)_buf count:(unsigned)_len {
125
// NGStreamNotOpenException when the stream is not open
126
// NGEndOfStreamException when the end of the stream is reached
127
register unsigned currentLength = 0;
129
if (self->bytes == NULL) {
130
currentLength = (self->dataLength == NULL)
131
? [self->data length]
132
: self->dataLength(self->data, @selector(length));
135
currentLength = self->length;
137
if (self->data == nil) {
140
e = [NGStreamNotOpenException exceptionWithStream:self reason:
141
@"tried to read from a data stream "
142
@"which was closed"];
143
[self setLastException:e];
144
return NGStreamError;
147
if (currentLength == position) {
148
[self setLastException:
149
[NGEndOfStreamException exceptionWithStream:self]];
150
return NGStreamError;
154
range.location = position;
156
if ((position + _len) > currentLength)
157
range.length = currentLength - position;
161
[self->data getBytes:_buf range:range];
163
position += range.length;
169
register const unsigned char *p;
170
register unsigned int currentLength = 0;
173
if (self->bytes == NULL) {
174
currentLength = (self->dataLength == NULL)
175
? [self->data length]
176
: self->dataLength(self->data, @selector(length));
179
currentLength = self->length;
181
if (currentLength == position)
184
if (self->bytes == NULL) {
185
p = (self->dataBytes == NULL)
187
: self->dataBytes(self->data, @selector(bytes));
191
result = p[self->position];
196
- (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len {
198
// NGReadOnlyStreamException when the stream is not writeable
199
// NGStreamNotOpenException when the stream is not open
201
if (self->data == nil) {
204
e = [NGStreamNotOpenException exceptionWithStream:self reason:
205
@"tried to write to a data stream "
206
@"which was closed"];
207
[self setLastException:e];
208
return NGStreamError;
210
if (!NGCanWriteInStreamMode(streamMode)) {
213
e = [NGReadOnlyStreamException exceptionWithStream:self];
214
[self setLastException:e];
215
return NGStreamError;
217
[(NSMutableData *)self->data appendBytes:_buf length:_len];
223
ASSIGN(self->lastException, (id)nil);
224
[self->data release]; self->data = nil;
226
streamMode = NGStreamMode_undefined;
230
- (NGStreamMode)mode {
233
- (BOOL)isRootStream {
237
// NGPositionableStream
239
- (BOOL)moveToLocation:(unsigned)_location {
240
position = _location;
243
- (BOOL)moveByOffset:(int)_delta {
250
- (BOOL)wouldBlockInMode:(NGStreamMode)_mode {
255
return [super retain];
258
/* bytebuffer / lookahead API */
260
- (int)la:(unsigned)_la {
261
register unsigned int currentLength, newpos;
262
register const unsigned char *p;
265
if (self->bytes == NULL) {
266
currentLength = (self->dataLength == NULL)
267
? [self->data length]
268
: self->dataLength(self->data, @selector(length));
271
currentLength = self->length;
273
if (currentLength == self->position) // already at EOF
276
newpos = (self->position + _la);
277
if (newpos >= currentLength)
278
return -1; /* a look into EOF */
280
if (self->bytes == NULL) {
281
p = (self->dataBytes == NULL)
283
: self->dataBytes(self->data, @selector(bytes));
292
- (void)consume { // consume one byte
293
register unsigned int currentLength = 0;
295
if (self->bytes == NULL) {
296
currentLength = (self->dataLength == NULL)
297
? [self->data length]
298
: self->dataLength(self->data, @selector(length));
301
currentLength = self->length;
303
if (currentLength == self->position)
306
self->position++; // consume
308
- (void)consume:(unsigned)_cnt { // consume _cnt bytes
309
register unsigned int currentLength = 0;
311
if (self->bytes == NULL) {
312
currentLength = (self->dataLength == NULL)
313
? [self->data length]
314
: self->dataLength(self->data, @selector(length));
317
currentLength = self->length;
319
if (currentLength == self->position)
322
self->position += _cnt; // consume
324
if (self->position > currentLength)
325
self->position = currentLength;
328
@end /* NGDataStream */