PageRenderTime 45ms CodeModel.GetById 17ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/gme/Data_Reader.cpp

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