diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console/Data_Reader.cxx	Thu Nov 30 19:54:33 2006 -0800
@@ -0,0 +1,316 @@
+// File_Extractor 0.4.0. http://www.slack.net/~ant/
+
+#include "Data_Reader.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+const char Data_Reader::eof_error [] = "Unexpected end of file";
+
+typedef Data_Reader::error_t error_t;
+
+error_t Data_Reader::read( void* p, long s )
+{
+	long result = read_avail( p, s );
+	if ( result != s )
+	{
+		if ( result >= 0 && result < s )
+			return eof_error;
+		
+		return "Read error";
+	}
+	
+	return 0;
+}
+
+error_t Data_Reader::skip( long count )
+{
+	char buf [512];
+	while ( count )
+	{
+		long n = sizeof buf;
+		if ( n > count )
+			n = count;
+		count -= n;
+		error_t err = read( buf, n );
+		if ( err )
+			return err;
+	}
+	return 0;
+}
+
+long File_Reader::remain() const { return size() - tell(); }
+
+error_t File_Reader::skip( long n )
+{
+	assert( n >= 0 );
+	return n ? seek( tell() + n ) : 0;
+}
+
+// Subset_Reader
+
+Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
+{
+	in = dr;
+	remain_ = dr->remain();
+	if ( remain_ > size )
+		remain_ = size;
+}
+
+long Subset_Reader::remain() const { return remain_; }
+
+long Subset_Reader::read_avail( void* p, long s )
+{
+	if ( s > remain_ )
+		s = remain_;
+	remain_ -= s;
+	return in->read_avail( p, s );
+}
+
+// Remaining_Reader
+
+Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
+{
+	header = (char const*) h;
+	header_end = header + size;
+	in = r;
+}
+
+long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
+
+long Remaining_Reader::read_first( void* out, long count )
+{
+	long first = header_end - header;
+	if ( first )
+	{
+		if ( first > count )
+			first = count;
+		void const* in = header;
+		header += first;
+		memcpy( out, in, first );
+	}
+	return first;
+}
+
+long Remaining_Reader::read_avail( void* out, long count )
+{
+	long first = read_first( out, count );
+	long remain = count - first;
+	if ( remain )
+	{
+		remain = in->read_avail( (char*) out + first, remain );
+		if ( remain <= 0 )
+			return remain;
+	}
+	return first + remain;
+}
+
+error_t Remaining_Reader::read( void* out, long count )
+{
+	long first = read_first( out, count );
+	long remain = count - first;
+	if ( !remain )
+		return 0;
+	return in->read( (char*) out + first, remain );
+}
+
+// Mem_File_Reader
+
+Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
+	begin( (const char*) p ),
+	size_( s )
+{
+	pos = 0;
+}
+	
+long Mem_File_Reader::size() const { return size_; }
+
+long Mem_File_Reader::read_avail( void* p, long s )
+{
+	long r = remain();
+	if ( s > r )
+		s = r;
+	memcpy( p, begin + pos, s );
+	pos += s;
+	return s;
+}
+
+long Mem_File_Reader::tell() const { return pos; }
+
+error_t Mem_File_Reader::seek( long n )
+{
+	if ( n > size_ )
+		return eof_error;
+	pos = n;
+	return 0;
+}
+
+// Std_File_Reader
+
+Std_File_Reader::Std_File_Reader() : file_( 0 ) { }
+
+Std_File_Reader::~Std_File_Reader() { close(); }
+
+error_t Std_File_Reader::open( const char* path )
+{
+	file_ = fopen( path, "rb" );
+	if ( !file_ )
+		return "Couldn't open file";
+	return 0;
+}
+
+long Std_File_Reader::size() const
+{
+	long pos = tell();
+	fseek( (FILE*) file_, 0, SEEK_END );
+	long result = tell();
+	fseek( (FILE*) file_, pos, SEEK_SET );
+	return result;
+}
+
+long Std_File_Reader::read_avail( void* p, long s )
+{
+	return fread( p, 1, s, (FILE*) file_ );
+}
+
+error_t Std_File_Reader::read( void* p, long s )
+{
+	if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
+		return 0;
+	if ( feof( (FILE*) file_ ) )
+		return eof_error;
+	return "Couldn't read from file";
+}
+
+long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); }
+
+error_t Std_File_Reader::seek( long n )
+{
+	if ( !fseek( (FILE*) file_, n, SEEK_SET ) )
+		return 0;
+	if ( n > size() )
+		return eof_error;
+	return "Error seeking in file";
+}
+
+void Std_File_Reader::close()
+{
+	if ( file_ )
+	{
+		fclose( (FILE*) file_ );
+		file_ = 0;
+	}
+}
+
+// Callback_Reader
+
+Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
+	callback( c ),
+	data( d )
+{
+	remain_ = size;
+}
+
+long Callback_Reader::remain() const { return remain_; }
+
+long Callback_Reader::read_avail( void* out, long count )
+{
+	if ( count > remain_ )
+		count = remain_;
+	if ( Callback_Reader::read( out, count ) )
+		count = -1;
+	return count;
+}
+
+Callback_Reader::error_t Callback_Reader::read( void* out, long count )
+{
+	if ( count > remain_ )
+		return eof_error;
+	return callback( data, out, count );
+}
+
+// Gzip_File_Reader
+
+#ifdef HAVE_ZLIB_H
+
+#include "zlib.h"
+
+static const char* get_gzip_eof( const char* path, long* eof )
+{
+	FILE* file = fopen( path, "rb" );
+	if ( !file )
+		return "Couldn't open file";
+	
+	unsigned char buf [4];
+	if ( fread( buf, 2, 1, file ) == 1 && buf [0] == 0x1F && buf [1] == 0x8B )
+	{
+		fseek( file, -4, SEEK_END );
+		fread( buf, 4, 1, file );
+		*eof = buf [3] * 0x1000000L + buf [2] * 0x10000L + buf [1] * 0x100L + buf [0];
+	}
+	else
+	{
+		fseek( file, 0, SEEK_END );
+		*eof = ftell( file );
+	}
+	const char* err = (ferror( file ) || feof( file )) ? "Couldn't get file size" : 0;
+	fclose( file );
+	return err;
+}
+
+Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { }
+
+Gzip_File_Reader::~Gzip_File_Reader() { close(); }
+
+error_t Gzip_File_Reader::open( const char* path )
+{
+	close();
+	
+	error_t err = get_gzip_eof( path, &size_ );
+	if ( err )
+		return err;
+	
+	file_ = gzopen( path, "rb" );
+	if ( !file_ )
+		return "Couldn't open file";
+	
+	return 0;
+}
+
+long Gzip_File_Reader::size() const { return size_; }
+
+long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); }
+
+long Gzip_File_Reader::tell() const { return gztell( file_ ); }
+
+error_t Gzip_File_Reader::seek( long n )
+{
+	if ( gzseek( file_, n, SEEK_SET ) >= 0 )
+		return 0;
+	if ( n > size_ )
+		return eof_error;
+	return "Error seeking in file";
+}
+
+void Gzip_File_Reader::close()
+{
+	if ( file_ )
+	{
+		gzclose( file_ );
+		file_ = 0;
+	}
+}
+
+#endif