86 lines
2.1 KiB
C++
86 lines
2.1 KiB
C++
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
|
|
|
#include "Gzip_Reader.h"
|
|
|
|
#include "blargg_endian.h"
|
|
|
|
/* Copyright (C) 2006-2009 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"
|
|
|
|
Gzip_Reader::Gzip_Reader()
|
|
{
|
|
close();
|
|
}
|
|
|
|
Gzip_Reader::~Gzip_Reader()
|
|
{ }
|
|
|
|
static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
|
|
{
|
|
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
|
|
}
|
|
|
|
blargg_err_t Gzip_Reader::calc_size()
|
|
{
|
|
size_ = in->size();
|
|
crc32_ = 0;
|
|
if ( inflater.deflated() )
|
|
{
|
|
byte trailer [8];
|
|
int old_pos = in->tell();
|
|
RETURN_ERR( in->seek( size_ - sizeof trailer ) );
|
|
RETURN_ERR( in->read( trailer, sizeof trailer ) );
|
|
RETURN_ERR( in->seek( old_pos ) );
|
|
crc32_ = get_le32( trailer + 0 );
|
|
|
|
unsigned n = get_le32( trailer + 4 );
|
|
if ( n > INT_MAX )
|
|
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" );
|
|
|
|
size_ = n;
|
|
}
|
|
return blargg_ok;
|
|
}
|
|
|
|
blargg_err_t Gzip_Reader::open( File_Reader* new_in )
|
|
{
|
|
close();
|
|
|
|
in = new_in;
|
|
RETURN_ERR( in->seek( 0 ) );
|
|
RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) );
|
|
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
|
|
RETURN_ERR( calc_size() );
|
|
set_remain( size_ );
|
|
|
|
return blargg_ok;
|
|
}
|
|
|
|
void Gzip_Reader::close()
|
|
{
|
|
in = NULL;
|
|
inflater.end();
|
|
}
|
|
|
|
blargg_err_t Gzip_Reader::read_v( void* out, int count )
|
|
{
|
|
assert( in );
|
|
int actual = count;
|
|
RETURN_ERR( inflater.read( out, &actual ) );
|
|
|
|
if ( actual != count )
|
|
return blargg_err_file_corrupt;
|
|
|
|
return blargg_ok;
|
|
}
|