comparison src/console/Data_Reader.cxx @ 316:fb513e10174e trunk

[svn] - merge libconsole-blargg into mainline libconsole: + obsoletes plugins-ugly:sapplug
author nenolod
date Thu, 30 Nov 2006 19:54:33 -0800
parents
children 986f098da058
comparison
equal deleted inserted replaced
315:2294f3a6f136 316:fb513e10174e
1 // File_Extractor 0.4.0. http://www.slack.net/~ant/
2
3 #include "Data_Reader.h"
4
5 #include <assert.h>
6 #include <string.h>
7 #include <stdio.h>
8
9 /* Copyright (C) 2005-2006 Shay Green. This module is free software; you
10 can redistribute it and/or modify it under the terms of the GNU Lesser
11 General Public License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version. This
13 module is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16 details. You should have received a copy of the GNU Lesser General Public
17 License along with this module; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
20 const char Data_Reader::eof_error [] = "Unexpected end of file";
21
22 typedef Data_Reader::error_t error_t;
23
24 error_t Data_Reader::read( void* p, long s )
25 {
26 long result = read_avail( p, s );
27 if ( result != s )
28 {
29 if ( result >= 0 && result < s )
30 return eof_error;
31
32 return "Read error";
33 }
34
35 return 0;
36 }
37
38 error_t Data_Reader::skip( long count )
39 {
40 char buf [512];
41 while ( count )
42 {
43 long n = sizeof buf;
44 if ( n > count )
45 n = count;
46 count -= n;
47 error_t err = read( buf, n );
48 if ( err )
49 return err;
50 }
51 return 0;
52 }
53
54 long File_Reader::remain() const { return size() - tell(); }
55
56 error_t File_Reader::skip( long n )
57 {
58 assert( n >= 0 );
59 return n ? seek( tell() + n ) : 0;
60 }
61
62 // Subset_Reader
63
64 Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
65 {
66 in = dr;
67 remain_ = dr->remain();
68 if ( remain_ > size )
69 remain_ = size;
70 }
71
72 long Subset_Reader::remain() const { return remain_; }
73
74 long Subset_Reader::read_avail( void* p, long s )
75 {
76 if ( s > remain_ )
77 s = remain_;
78 remain_ -= s;
79 return in->read_avail( p, s );
80 }
81
82 // Remaining_Reader
83
84 Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
85 {
86 header = (char const*) h;
87 header_end = header + size;
88 in = r;
89 }
90
91 long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
92
93 long Remaining_Reader::read_first( void* out, long count )
94 {
95 long first = header_end - header;
96 if ( first )
97 {
98 if ( first > count )
99 first = count;
100 void const* in = header;
101 header += first;
102 memcpy( out, in, first );
103 }
104 return first;
105 }
106
107 long Remaining_Reader::read_avail( void* out, long count )
108 {
109 long first = read_first( out, count );
110 long remain = count - first;
111 if ( remain )
112 {
113 remain = in->read_avail( (char*) out + first, remain );
114 if ( remain <= 0 )
115 return remain;
116 }
117 return first + remain;
118 }
119
120 error_t Remaining_Reader::read( void* out, long count )
121 {
122 long first = read_first( out, count );
123 long remain = count - first;
124 if ( !remain )
125 return 0;
126 return in->read( (char*) out + first, remain );
127 }
128
129 // Mem_File_Reader
130
131 Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
132 begin( (const char*) p ),
133 size_( s )
134 {
135 pos = 0;
136 }
137
138 long Mem_File_Reader::size() const { return size_; }
139
140 long Mem_File_Reader::read_avail( void* p, long s )
141 {
142 long r = remain();
143 if ( s > r )
144 s = r;
145 memcpy( p, begin + pos, s );
146 pos += s;
147 return s;
148 }
149
150 long Mem_File_Reader::tell() const { return pos; }
151
152 error_t Mem_File_Reader::seek( long n )
153 {
154 if ( n > size_ )
155 return eof_error;
156 pos = n;
157 return 0;
158 }
159
160 // Std_File_Reader
161
162 Std_File_Reader::Std_File_Reader() : file_( 0 ) { }
163
164 Std_File_Reader::~Std_File_Reader() { close(); }
165
166 error_t Std_File_Reader::open( const char* path )
167 {
168 file_ = fopen( path, "rb" );
169 if ( !file_ )
170 return "Couldn't open file";
171 return 0;
172 }
173
174 long Std_File_Reader::size() const
175 {
176 long pos = tell();
177 fseek( (FILE*) file_, 0, SEEK_END );
178 long result = tell();
179 fseek( (FILE*) file_, pos, SEEK_SET );
180 return result;
181 }
182
183 long Std_File_Reader::read_avail( void* p, long s )
184 {
185 return fread( p, 1, s, (FILE*) file_ );
186 }
187
188 error_t Std_File_Reader::read( void* p, long s )
189 {
190 if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
191 return 0;
192 if ( feof( (FILE*) file_ ) )
193 return eof_error;
194 return "Couldn't read from file";
195 }
196
197 long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); }
198
199 error_t Std_File_Reader::seek( long n )
200 {
201 if ( !fseek( (FILE*) file_, n, SEEK_SET ) )
202 return 0;
203 if ( n > size() )
204 return eof_error;
205 return "Error seeking in file";
206 }
207
208 void Std_File_Reader::close()
209 {
210 if ( file_ )
211 {
212 fclose( (FILE*) file_ );
213 file_ = 0;
214 }
215 }
216
217 // Callback_Reader
218
219 Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
220 callback( c ),
221 data( d )
222 {
223 remain_ = size;
224 }
225
226 long Callback_Reader::remain() const { return remain_; }
227
228 long Callback_Reader::read_avail( void* out, long count )
229 {
230 if ( count > remain_ )
231 count = remain_;
232 if ( Callback_Reader::read( out, count ) )
233 count = -1;
234 return count;
235 }
236
237 Callback_Reader::error_t Callback_Reader::read( void* out, long count )
238 {
239 if ( count > remain_ )
240 return eof_error;
241 return callback( data, out, count );
242 }
243
244 // Gzip_File_Reader
245
246 #ifdef HAVE_ZLIB_H
247
248 #include "zlib.h"
249
250 static const char* get_gzip_eof( const char* path, long* eof )
251 {
252 FILE* file = fopen( path, "rb" );
253 if ( !file )
254 return "Couldn't open file";
255
256 unsigned char buf [4];
257 if ( fread( buf, 2, 1, file ) == 1 && buf [0] == 0x1F && buf [1] == 0x8B )
258 {
259 fseek( file, -4, SEEK_END );
260 fread( buf, 4, 1, file );
261 *eof = buf [3] * 0x1000000L + buf [2] * 0x10000L + buf [1] * 0x100L + buf [0];
262 }
263 else
264 {
265 fseek( file, 0, SEEK_END );
266 *eof = ftell( file );
267 }
268 const char* err = (ferror( file ) || feof( file )) ? "Couldn't get file size" : 0;
269 fclose( file );
270 return err;
271 }
272
273 Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { }
274
275 Gzip_File_Reader::~Gzip_File_Reader() { close(); }
276
277 error_t Gzip_File_Reader::open( const char* path )
278 {
279 close();
280
281 error_t err = get_gzip_eof( path, &size_ );
282 if ( err )
283 return err;
284
285 file_ = gzopen( path, "rb" );
286 if ( !file_ )
287 return "Couldn't open file";
288
289 return 0;
290 }
291
292 long Gzip_File_Reader::size() const { return size_; }
293
294 long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); }
295
296 long Gzip_File_Reader::tell() const { return gztell( file_ ); }
297
298 error_t Gzip_File_Reader::seek( long n )
299 {
300 if ( gzseek( file_, n, SEEK_SET ) >= 0 )
301 return 0;
302 if ( n > size_ )
303 return eof_error;
304 return "Error seeking in file";
305 }
306
307 void Gzip_File_Reader::close()
308 {
309 if ( file_ )
310 {
311 gzclose( file_ );
312 file_ = 0;
313 }
314 }
315
316 #endif