diff src/console/Gzip_Reader.cxx @ 341:986f098da058 trunk

[svn] - merge in blargg's changes
author nenolod
date Thu, 07 Dec 2006 15:20:41 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console/Gzip_Reader.cxx	Thu Dec 07 15:20:41 2006 -0800
@@ -0,0 +1,108 @@
+// File_Extractor 0.4.0. http://www.slack.net/~ant/
+
+#include "Gzip_Reader.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 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 */
+
+#include "blargg_source.h"
+
+void Gzip_Reader::close()
+{
+	in    = 0;
+	tell_ = 0;
+	size_ = 0;
+	inflater.end();
+}
+
+Gzip_Reader::Gzip_Reader() { close(); }
+
+Gzip_Reader::~Gzip_Reader() { }
+
+static blargg_err_t gzip_reader_read( void* file, void* out, long* count )
+{
+	*count = ((File_Reader*) file)->read_avail( out, *count );
+	return (*count < 0 ? "Read error" : 0);
+}
+
+blargg_err_t Gzip_Reader::open( File_Reader* new_in )
+{
+	close();
+	
+	RETURN_ERR( inflater.begin( inflater.mode_auto, gzip_reader_read, new_in ) );
+	
+	size_ = -1; // defer seeking to end of file until size is actually needed
+	in    = new_in;
+	return 0;
+}
+
+blargg_err_t Gzip_Reader::calc_size()
+{
+	long size = in->size();
+	if ( inflater.deflated() )
+	{
+		byte trailer [4];
+		long pos = in->tell();
+		RETURN_ERR( in->seek( size - sizeof trailer ) );
+		RETURN_ERR( in->read( trailer, sizeof trailer ) );
+		RETURN_ERR( in->seek( pos ) );
+		size = get_le32( trailer );
+	}
+	size_ = size;
+	return 0;
+}
+
+long Gzip_Reader::remain() const
+{
+	if ( size_ < 0 )
+	{
+		if ( !in )
+			return 0;
+		
+		// need to cast away constness to change cached value
+		if ( ((Gzip_Reader*) this)->calc_size() )
+			return -1;
+	}
+	return size_ - tell_;
+}
+
+blargg_err_t Gzip_Reader::read_( void* out, long* count )
+{
+	blargg_err_t err = inflater.read( out, count, gzip_reader_read, in );
+	tell_ += *count;
+	if ( size_ >= 0 && tell_ > size_ )
+	{
+		tell_ = size_;
+		return "Corrupt gzip file";
+	}
+	return err;
+}
+
+blargg_err_t Gzip_Reader::read( void* out, long count )
+{
+	if ( in )
+	{
+		long actual = count;
+		RETURN_ERR( read_( out, &actual ) );
+		if ( actual == count )
+			return 0;
+	}
+	return eof_error;
+}
+
+long Gzip_Reader::read_avail( void* out, long count )
+{
+	if ( !in || read_( out, &count ) )
+		count = -1;
+	return count;
+}