comparison 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
comparison
equal deleted inserted replaced
340:9e5a7158fa80 341:986f098da058
1 // File_Extractor 0.4.0. http://www.slack.net/~ant/
2
3 #include "Gzip_Reader.h"
4
5 #include "blargg_endian.h"
6
7 /* Copyright (C) 2006 Shay Green. This module is free software; you
8 can redistribute it and/or modify it under the terms of the GNU Lesser
9 General Public License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version. This
11 module is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 details. You should have received a copy of the GNU Lesser General Public
15 License along with this module; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18 #include "blargg_source.h"
19
20 void Gzip_Reader::close()
21 {
22 in = 0;
23 tell_ = 0;
24 size_ = 0;
25 inflater.end();
26 }
27
28 Gzip_Reader::Gzip_Reader() { close(); }
29
30 Gzip_Reader::~Gzip_Reader() { }
31
32 static blargg_err_t gzip_reader_read( void* file, void* out, long* count )
33 {
34 *count = ((File_Reader*) file)->read_avail( out, *count );
35 return (*count < 0 ? "Read error" : 0);
36 }
37
38 blargg_err_t Gzip_Reader::open( File_Reader* new_in )
39 {
40 close();
41
42 RETURN_ERR( inflater.begin( inflater.mode_auto, gzip_reader_read, new_in ) );
43
44 size_ = -1; // defer seeking to end of file until size is actually needed
45 in = new_in;
46 return 0;
47 }
48
49 blargg_err_t Gzip_Reader::calc_size()
50 {
51 long size = in->size();
52 if ( inflater.deflated() )
53 {
54 byte trailer [4];
55 long pos = in->tell();
56 RETURN_ERR( in->seek( size - sizeof trailer ) );
57 RETURN_ERR( in->read( trailer, sizeof trailer ) );
58 RETURN_ERR( in->seek( pos ) );
59 size = get_le32( trailer );
60 }
61 size_ = size;
62 return 0;
63 }
64
65 long Gzip_Reader::remain() const
66 {
67 if ( size_ < 0 )
68 {
69 if ( !in )
70 return 0;
71
72 // need to cast away constness to change cached value
73 if ( ((Gzip_Reader*) this)->calc_size() )
74 return -1;
75 }
76 return size_ - tell_;
77 }
78
79 blargg_err_t Gzip_Reader::read_( void* out, long* count )
80 {
81 blargg_err_t err = inflater.read( out, count, gzip_reader_read, in );
82 tell_ += *count;
83 if ( size_ >= 0 && tell_ > size_ )
84 {
85 tell_ = size_;
86 return "Corrupt gzip file";
87 }
88 return err;
89 }
90
91 blargg_err_t Gzip_Reader::read( void* out, long count )
92 {
93 if ( in )
94 {
95 long actual = count;
96 RETURN_ERR( read_( out, &actual ) );
97 if ( actual == count )
98 return 0;
99 }
100 return eof_error;
101 }
102
103 long Gzip_Reader::read_avail( void* out, long count )
104 {
105 if ( !in || read_( out, &count ) )
106 count = -1;
107 return count;
108 }