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 <NGStreams/NGConcreteStreamFileHandle.h>
23#include <NGStreams/NGStreamProtocols.h>
24#include <NGStreams/NGStreamExceptions.h>
25#include <NGStreams/NGBufferedStream.h>
26#include "common.h"
27
28@interface NGStream(FileHandleReset)
29
30- (void)resetFileHandle;
31
32@end
33
34@implementation NGConcreteStreamFileHandle
35
36- (id)initWithStream:(id<NGStream>)_stream {
37  if ((self = [super init])) {
38    self->stream = [_stream retain];
39  }
40  return self;
41}
42
43- (void)dealloc {
44  if ([stream respondsToSelector:@selector(resetFileHandle)])
45    [(NGStream *)self->stream resetFileHandle];
46  [self->stream release];
47  [super dealloc];
48}
49
50// accessors
51
52- (id<NGStream>)stream {
53  return self->stream;
54}
55
56/* NSFileHandle operations */
57
58- (void)closeFile {
59  [self->stream close];
60}
61
62- (int)fileDescriptor {
63  if ([self->stream respondsToSelector:@selector(fileDescriptor)])
64    return [(id)self->stream fileDescriptor];
65  else {
66    [self subclassResponsibility:_cmd];
67    return -1;
68  }
69}
70
71/* buffering */
72
73- (void)synchronizeFile {
74  [self->stream flush];
75}
76
77/* reading */
78
79- (NSData *)readDataOfLength:(unsigned int)_length {
80  char   *buffer;
81  NSData *data;
82
83  *(&buffer) = NGMallocAtomic(_length);
84  *(&data)   = nil;
85
86  NS_DURING {
87    [stream safeReadBytes:buffer count:_length];
88    data = [[NSData alloc] initWithBytes:buffer length:_length];
89  }
90  NS_HANDLER {
91    if ([localException isKindOfClass:[NGEndOfStreamException class]]) {
92      data = [(NGEndOfStreamException *)localException readBytes];
93
94      data = data ? [data retain] : [[NSData alloc] init];
95    }
96    else {
97      if (buffer) {
98        NGFree(buffer);
99        buffer = NULL;
100      }
101      [localException raise];
102    }
103  }
104  NS_ENDHANDLER;
105
106  if (buffer) {
107    NGFree(buffer);
108    buffer = NULL;
109  }
110
111  return [data autorelease];
112}
113
114- (NSData *)readDataToEndOfFile {
115  NGBufferedStream *bs;
116  NSMutableData    *data;
117  char buf[2048];
118
119  *(&data) = [NSMutableData dataWithCapacity:2048];
120  *(&bs) = [self->stream isKindOfClass:[NGBufferedStream class]]
121    ? (id)[self->stream retain]
122    : [(NGBufferedStream *)[NGBufferedStream alloc]
123          initWithSource:self->stream];
124
125  NS_DURING {
126    while (1 == 1) {
127      unsigned got = [bs readBytes:buf count:2048];
128      [data appendBytes:buf length:got];
129    }
130  }
131  NS_HANDLER {
132    if (![localException isKindOfClass:[NGEndOfStreamException class]]) {
133      [bs release];
134      bs = nil;
135      [localException raise];
136    }
137  }
138  NS_ENDHANDLER;
139  [bs release]; bs = nil;
140
141  return data;
142}
143
144- (NSData *)availableData {
145  NSLog(@"NGConcreteStreamFileHandle(availableData) not implemented");
146  [self notImplemented:_cmd];
147  return nil;
148}
149
150/* writing */
151
152- (void)writeData:(NSData *)_data {
153  [self->stream safeWriteBytes:[_data bytes] count:[_data length]];
154}
155
156/* seeking */
157
158- (unsigned long long)seekToEndOfFile {
159  NSLog(@"NGConcreteStreamFileHandle(seekToEndOfFile) not implemented");
160  [self notImplemented:_cmd];
161  return 0;
162}
163- (void)seekToFileOffset:(unsigned long long)_offset {
164  [(id<NGPositionableStream>)stream moveToLocation:_offset];
165}
166
167- (unsigned long long)offsetInFile {
168  NSLog(@"_NGConcreteFileStreamFileHandle(offsetInFile:) not implemented, abort");
169  [self notImplemented:_cmd];
170  return 0;
171}
172
173/* asynchronous operations */
174
175- (void)acceptConnectionInBackgroundAndNotify {
176  NSLog(@"NGConcreteStreamFileHandle(acceptConnectionInBackgroundAndNotify) "
177        @"not implemented");
178  [self notImplemented:_cmd];
179}
180- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray *)_modes {
181  NSLog(@"NGConcreteStreamFileHandle(acceptConnectionInBackgroundAndNotifyForModes:) "
182        @"not implemented");
183  [self notImplemented:_cmd];
184}
185
186- (void)readInBackgroundAndNotify {
187  NSLog(@"NGConcreteStreamFileHandle(readInBackgroundAndNotify) not implemented");
188  [self notImplemented:_cmd];
189}
190- (void)readInBackgroundAndNotifyForModes:(NSArray *)_modes {
191  NSLog(@"NGConcreteStreamFileHandle(readInBackgroundAndNotifyForModes:) "
192        @"not implemented");
193  [self notImplemented:_cmd];
194}
195- (void)readToEndOfFileInBackgroundAndNotify {
196  NSLog(@"NGConcreteStreamFileHandle(readToEndOfFileInBackgroundAndNotify)"
197        @"not implemented");
198  [self notImplemented:_cmd];
199}
200- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray *)_modes {
201  NSLog(@"NGConcreteStreamFileHandle("
202        @"readToEndOfFileInBackgroundAndNotifyForModes:)"
203        @"not implemented");
204  [self notImplemented:_cmd];
205}
206
207- (void)waitForDataInBackgroundAndNotify {
208  NSLog(@"NGConcreteStreamFileHandle("
209        @"waitForDataInBackgroundAndNotify)"
210        @"not implemented");
211  [self notImplemented:_cmd];
212}
213- (void)waitForDataInBackgroundAndNotifyForModes:(NSArray *)_modes {
214  NSLog(@"NGConcreteStreamFileHandle("
215        @"waitForDataInBackgroundAndNotifyForModes:)"
216        @"not implemented");
217  [self notImplemented:_cmd];
218}
219
220@end /* NGConcreteStreamFileHandle */
221