zipios 2.3.4
Zipios -- a small C++ library providing 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-2022 Made to Order Software Corp. All Rights Reserved
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{
75 // NOTICE: It is important that this constructor and the methods it
76 // calls doesn't do anything with the input streambuf inbuf, other
77 // than repositioning it to the specified \p start_pos. The reason is
78 // that this class can be sub-classed, and the sub-class should get a
79 // chance to read from the buffer first
80
81 reset(start_pos);
82 // We are not checking the return value of reset() and throwing
83 // an exception in case of an error, because we cannot catch the
84 // exception in the constructors of sub-classes with all compilers.
85}
86
87
93{
94 // Dealloc z_stream
95 int const err(inflateEnd(&m_zs));
96 if(err != Z_OK)
97 {
98 // in a destructor we cannot throw...
99 OutputStringStream msgs; // LCOV_EXCL_LINE
100 msgs << "InflateInputStreambuf::~InflateInputStreambuf(): inflateEnd() failed" // LCOV_EXCL_LINE
101 << ": " << zError(err); // LCOV_EXCL_LINE
106 std::cerr << msgs.str() << std::endl; // LCOV_EXCL_LINE
107 }
108}
109
110
123std::streambuf::int_type InflateInputStreambuf::underflow()
124{
125 // If not really underflow do not fill buffer
126 // (is that really possible?!)
127 if(gptr() < egptr())
128 {
129 return traits_type::to_int_type(*gptr()); // LCOV_EXCL_LINE
130 }
131
132 // Prepare _outvec and get array pointers
133 m_zs.avail_out = getBufferSize();
134 m_zs.next_out = reinterpret_cast<unsigned char *>(&m_outvec[0]);
135
136 // Inflate until _outvec is full
137 // eof (or I/O prob) on _inbuf will break out of loop too.
138 int err(Z_OK);
139 while(m_zs.avail_out > 0 && err == Z_OK)
140 {
141 if(m_zs.avail_in == 0)
142 {
143 // fill m_invec
144 std::streamsize const bc(m_inbuf->sgetn(&m_invec[0], getBufferSize()));
148 m_zs.next_in = reinterpret_cast<unsigned char *>(&m_invec[0]);
149 m_zs.avail_in = bc;
150 // If we could not read any new data (bc == 0) and inflate is not
151 // done it will return Z_BUF_ERROR and thus breaks out of the
152 // loop. This means we do not have to respond to the situation
153 // where we cannot read more bytes here.
154 }
155
156 err = inflate(&m_zs, Z_NO_FLUSH);
157 }
158
159 // Normally the number of inflated bytes will be the
160 // full length of the output buffer, but if we can't read
161 // more input from the _inbuf streambuf, we end up with
162 // less.
163 offset_t const inflated_bytes = getBufferSize() - m_zs.avail_out;
164 setg(&m_outvec[0], &m_outvec[0], &m_outvec[0] + inflated_bytes);
165
172 if(err != Z_OK && err != Z_STREAM_END)
173 {
175 msgs << "InflateInputStreambuf::underflow(): inflate failed"
176 << ": " << zError(err);
177 // Throw an exception to immediately exit to the read() or similar
178 // function and make istream set badbit
179 throw IOException(msgs.str());
180 }
181
182 if(inflated_bytes > 0)
183 {
184 return traits_type::to_int_type(*gptr());
185 }
186
187 return traits_type::eof();
188}
189
190
191
208{
209 if(stream_position >= 0)
210 {
211 // reposition m_inbuf
212 m_inbuf->pubseekpos(stream_position);
213 }
214
215 // m_zs.next_in and avail_in must be set according to
216 // zlib.h (inline doc).
217 m_zs.next_in = reinterpret_cast<Bytef *>(&m_invec[0]);
218 m_zs.avail_in = 0;
219
220 int err(Z_OK);
222 {
223 // just reset it
224 err = inflateReset(&m_zs);
225 }
226 else
227 {
228 // initialize it
229 err = inflateInit2(&m_zs, -MAX_WBITS);
230 /* windowBits is passed < 0 to tell that there is no zlib header.
231 Note that in this case inflate *requires* an extra "dummy" byte
232 after the compressed stream in order to complete decompression
233 and return Z_STREAM_END. We always have an extra "dummy" byte,
234 because there is always some trailing data after the compressed
235 data (either the next entry or the central directory). */
236 m_zs_initialized = true;
237 }
238
239 // streambuf init:
240 // The important thing here, is that
241 // - the pointers are not NULL (which would mean unbuffered)
242 // - and that gptr() is not less than egptr() (so we trigger underflow
243 // the first time data is read).
244 setg(&m_outvec[0], &m_outvec[0] + getBufferSize(), &m_outvec[0] + getBufferSize());
245
246 return err == Z_OK;
247}
248
249
250} // zipios namespace
251
252// Local Variables:
253// mode: cpp
254// indent-tabs-mode: nil
255// c-basic-offset: 4
256// tab-width: 4
257// End:
258
259// 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
size_t getBufferSize()
std::ostringstream OutputStringStream
An output stream using strings.
Various functions used throughout the library.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.