2 #include "zipios++/zipios-config.h"
4 #include "zipios++/meta-iostreams.h"
8 #include "zipios++/fcollexceptions.h"
9 #include "zipios++/inflateinputstreambuf.h"
11 #include "outputstringstream.h"
18 InflateInputStreambuf::InflateInputStreambuf( streambuf *inbuf, int s_pos, bool del_inbuf )
19 : FilterInputStreambuf( inbuf, del_inbuf ),
20 _zs_initialized ( false ),
22 _invec ( _invecsize ),
24 _outvec ( _outvecsize )
26 // NOTICE: It is important that this constructor and the methods it
27 // calls doesn't do anything with the input streambuf _inbuf, other
28 // than repositioning it to the specified position. The reason is
29 // that this class can be subclassed, and the subclass should get a
30 // chance to read from the buffer first)
38 // We're not checking the return value of reset() and throwing
39 // an exception in case of an error, because we cannot catch the exception
40 // in the constructors of subclasses with all compilers.
43 InflateInputStreambuf::~InflateInputStreambuf() {
44 // Dealloc z_stream stuff
45 int err = inflateEnd( &_zs ) ;
47 cerr << "~inflatebuf: inflateEnd failed" ;
49 cerr << ": " << zError( err ) ;
56 int InflateInputStreambuf::underflow() {
57 // If not underflow don't fill buffer
58 if ( gptr() < egptr() )
59 return static_cast< unsigned char >( *gptr() ) ;
61 // Prepare _outvec and get array pointers
62 _zs.avail_out = _outvecsize ;
63 _zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
65 // Inflate until _outvec is full
66 // eof (or I/O prob) on _inbuf will break out of loop too.
68 while ( _zs.avail_out > 0 && err == Z_OK ) {
69 if ( _zs.avail_in == 0 ) { // fill _invec
70 int bc = static_cast< int >( _inbuf->sgetn( &(_invec[ 0 ] ) ,
72 // FIXME: handle i/o problems.
73 _zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[0] ) ) ;
75 // If we could not read any new data (bc == 0) and inflate isn't
76 // done it will return Z_BUF_ERROR and thus breaks out of the
77 // loop. This means we don't have to respond to the situation
78 // where we can't read more bytes here.
81 err = inflate( &_zs, Z_NO_FLUSH ) ;
83 // Normally the number of inflated bytes will be the
84 // full length of the output buffer, but if we can't read
85 // more input from the _inbuf streambuf, we end up with
87 int inflated_bytes = _outvecsize - _zs.avail_out ;
88 setg( &( _outvec[ 0 ] ),
90 &( _outvec[ 0 ] ) + inflated_bytes ) ;
91 // FIXME: look at the error returned from inflate here, if there is
92 // some way to report it to the InflateInputStreambuf user.
93 // Until I find out I'll just print a warning to stdout.
94 if( err != Z_OK && err != Z_STREAM_END ) {
95 #if defined (HAVE_STD_IOSTREAM) && defined (USE_STD_IOSTREAM)
96 // Throw an exception to make istream set badbit
97 OutputStringStream msgs ;
98 msgs << "InflateInputStreambuf: inflate failed" ;
100 msgs << ": " << zError( err ) ;
102 throw IOException( msgs.str() ) ;
104 // If HAVE_STD_IOSTREAM not defined we just return eof
105 // if no output is produced, and that happens anyway
107 if (inflated_bytes > 0 )
108 return static_cast< unsigned char >( *gptr() ) ;
110 return EOF ; // traits_type::eof() ;
115 // This method is called in the constructor, so it must not
116 // read anything from the input streambuf _inbuf (see notice in constructor)
117 bool InflateInputStreambuf::reset( int stream_position ) {
118 if ( stream_position >= 0 ) { // reposition _inbuf
119 _inbuf->pubseekpos( stream_position ) ;
122 // _zs.next_in and avail_in must be set according to
123 // zlib.h (inline doc).
124 _zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[0] ) ) ;
128 if( _zs_initialized ) { // just reset it
129 err = inflateReset( &_zs ) ;
131 err = inflateInit2( &_zs, -MAX_WBITS ) ;
132 /* windowBits is passed < 0 to tell that there is no zlib header.
133 Note that in this case inflate *requires* an extra "dummy" byte
134 after the compressed stream in order to complete decompression
135 and return Z_STREAM_END. We always have an extra "dummy" byte,
136 because there is always some trailing data after the compressed
137 data (either the next entry or the central directory. */
138 _zs_initialized = true ;
142 // The important thing here, is that
143 // - the pointers are not NULL (which would mean unbuffered)
144 // - and that gptr() is not less than egptr() (so we trigger underflow
145 // the first time data is read).
146 setg( &( _outvec[ 0 ] ),
147 &( _outvec[ 0 ] ) + _outvecsize,
148 &( _outvec[ 0 ] ) + _outvecsize ) ;
159 Implementation of InflateInputStreambuf.
163 Zipios++ - a small C++ library that provides easy access to .zip files.
164 Copyright (C) 2000 Thomas Søndergaard
166 This library is free software; you can redistribute it and/or
167 modify it under the terms of the GNU Lesser General Public
168 License as published by the Free Software Foundation; either
169 version 2 of the License, or (at your option) any later version.
171 This library is distributed in the hope that it will be useful,
172 but WITHOUT ANY WARRANTY; without even the implied warranty of
173 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
174 Lesser General Public License for more details.
176 You should have received a copy of the GNU Lesser General Public
177 License along with this library; if not, write to the Free Software
178 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA