zipios 2.2.0
Zipios -- a small C++ library that provides easy access to .zip files.
inflateinputstreambuf.cpp
Go to the documentation of this file.
1/*
2 Zipios -- a small C++ library that provides easy access to .zip files.
3
4 Copyright (C) 2000-2007 Thomas Sondergaard
5 Copyright (C) 2015-2019 Made to Order Software Corporation
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
31
33
34#include "zipios_common.hpp"
35
36
37namespace zipios
38{
39
72 , m_outvec(getBufferSize())
73 , m_invec(getBufferSize())
74 //, m_zs() -- auto-init
75 //, m_zs_initialized(false) -- auto-init
76{
77 // NOTICE: It is important that this constructor and the methods it
78 // calls doesn't do anything with the input streambuf inbuf, other
79 // than repositioning it to the specified position. The reason is
80 // that this class can be subclassed, and the subclass should get a
81 // chance to read from the buffer first)
82
83 // zlib init:
84 m_zs.zalloc = Z_NULL;
85 m_zs.zfree = Z_NULL;
86 m_zs.opaque = Z_NULL;
87
88 reset(start_pos);
89 // We are not checking the return value of reset() and throwing
90 // an exception in case of an error, because we cannot catch the exception
91 // in the constructors of subclasses with all compilers.
92}
93
94
100{
101 // Dealloc z_stream stuff
102 int const err(inflateEnd(&m_zs));
103 if(err != Z_OK)
104 {
105 // in a destructor we cannot throw...
106 OutputStringStream msgs; // LCOV_EXCL_LINE
107 msgs << "InflateInputStreambuf::~InflateInputStreambuf(): inflateEnd() failed" // LCOV_EXCL_LINE
108 << ": " << zError(err); // LCOV_EXCL_LINE
113 std::cerr << msgs.str() << std::endl; // LCOV_EXCL_LINE
114 }
115}
116
117
130std::streambuf::int_type InflateInputStreambuf::underflow()
131{
132 // If not really underflow do not fill buffer
133 // (is that really possible?!)
134 if(gptr() < egptr())
135 {
136 return traits_type::to_int_type(*gptr()); // LCOV_EXCL_LINE
137 }
138
139 // Prepare _outvec and get array pointers
140 m_zs.avail_out = getBufferSize();
141 m_zs.next_out = reinterpret_cast<unsigned char *>(&m_outvec[0]);
142
143 // Inflate until _outvec is full
144 // eof (or I/O prob) on _inbuf will break out of loop too.
145 int err(Z_OK);
146 while(m_zs.avail_out > 0 && err == Z_OK)
147 {
148 if(m_zs.avail_in == 0)
149 {
150 // fill m_invec
151 std::streamsize const bc(m_inbuf->sgetn(&m_invec[0], getBufferSize()));
155 m_zs.next_in = reinterpret_cast<unsigned char *>(&m_invec[0]);
156 m_zs.avail_in = bc;
157 // If we could not read any new data (bc == 0) and inflate is not
158 // done it will return Z_BUF_ERROR and thus breaks out of the
159 // loop. This means we do not have to respond to the situation
160 // where we cannot read more bytes here.
161 }
162
163 err = inflate(&m_zs, Z_NO_FLUSH);
164 }
165
166 // Normally the number of inflated bytes will be the
167 // full length of the output buffer, but if we can't read
168 // more input from the _inbuf streambuf, we end up with
169 // less.
170 offset_t const inflated_bytes = getBufferSize() - m_zs.avail_out;
171 setg(&m_outvec[0], &m_outvec[0], &m_outvec[0] + inflated_bytes);
172
180 if(err != Z_OK && err != Z_STREAM_END)
181 {
183 msgs << "InflateInputStreambuf::underflow(): inflate failed"
184 << ": " << zError(err);
185 // Throw an exception to immediately exit to the read() or similar
186 // function and make istream set badbit
187 throw IOException(msgs.str());
188 }
189
190 if(inflated_bytes > 0)
191 {
192 return traits_type::to_int_type(*gptr());
193 }
194
195 return traits_type::eof();
196}
197
198
199
216{
217 if(stream_position >= 0)
218 {
219 // reposition m_inbuf
220 m_inbuf->pubseekpos(stream_position);
221 }
222
223 // m_zs.next_in and avail_in must be set according to
224 // zlib.h (inline doc).
225 m_zs.next_in = reinterpret_cast<Bytef *>(&m_invec[0]);
226 m_zs.avail_in = 0;
227
228 int err(Z_OK);
230 {
231 // just reset it
232 err = inflateReset(&m_zs);
233 }
234 else
235 {
236 // initialize it
237 err = inflateInit2(&m_zs, -MAX_WBITS);
238 /* windowBits is passed < 0 to tell that there is no zlib header.
239 Note that in this case inflate *requires* an extra "dummy" byte
240 after the compressed stream in order to complete decompression
241 and return Z_STREAM_END. We always have an extra "dummy" byte,
242 because there is always some trailing data after the compressed
243 data (either the next entry or the central directory. */
244 m_zs_initialized = true;
245 }
246
247 // streambuf init:
248 // The important thing here, is that
249 // - the pointers are not NULL (which would mean unbuffered)
250 // - and that gptr() is not less than egptr() (so we trigger underflow
251 // the first time data is read).
252 setg(&m_outvec[0], &m_outvec[0] + getBufferSize(), &m_outvec[0] + getBufferSize());
253
254 return err == Z_OK;
255}
256
257
258} // zipios namespace
259
260// Local Variables:
261// mode: cpp
262// indent-tabs-mode: nil
263// c-basic-offset: 4
264// tab-width: 4
265// End:
266
267// vim: ts=4 sw=4 et
A base class to develop input stream filters.
An IOException is used to signal an I/O error.
virtual ~InflateInputStreambuf()
Clean up the InflateInputStreambuf object.
virtual std::streambuf::int_type underflow() override
Called when more data is required.
InflateInputStreambuf(std::streambuf *inbuf, offset_t s_pos=-1)
Initialize a InflateInputStreambuf.
bool reset(offset_t stream_position=-1)
Initializes the stream buffer.
Define zipios::InflateInputStreambuf to decompress files.
The zipios namespace includes the Zipios library definitions.
std::streamoff offset_t
std::ostringstream OutputStringStream
An output stream using strings.
size_t getBufferSize()
Various functions used throughout the library.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.