Line data Source code
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 :
22 : /** \file
23 : * \brief Implementation of zipios::ZipInputStreambuf.
24 : *
25 : * This is the implementation of the Zip input std::streambuf class.
26 : */
27 :
28 : #include "zipinputstreambuf.hpp"
29 :
30 : #include "zipios/zipiosexceptions.hpp"
31 :
32 :
33 : namespace zipios
34 : {
35 :
36 :
37 : /** \class ZipInputStreambuf
38 : * \brief An input stream buffer for Zip data.
39 : *
40 : * The ZipInputStreambuf class is a Zip input streambuf filter that
41 : * automatically decompresses input data that was compressed using
42 : * the zlib library.
43 : */
44 :
45 :
46 : /** \brief Initialize a ZipInputStreambuf.
47 : *
48 : * This ZipInputStreambuf constructor initializes the buffer from the
49 : * user specified buffer.
50 : *
51 : * \param[in,out] inbuf The streambuf to use for input.
52 : * \param[in] start_pos A position to reset the inbuf to before reading.
53 : * Specify -1 to read from the current position.
54 : */
55 96763 : ZipInputStreambuf::ZipInputStreambuf(std::streambuf *inbuf, offset_t start_pos)
56 96783 : : InflateInputStreambuf(inbuf, start_pos)
57 : //, m_current_entry() -- auto-init
58 : //, m_remain(0) -- auto-init
59 : {
60 : // read the zip local header
61 193526 : std::istream is(m_inbuf); // istream does not destroy the streambuf.
62 96763 : is.exceptions(std::ios::eofbit | std::ios::failbit | std::ios::badbit);
63 :
64 : // if the read fails in any way it will throw
65 96763 : m_current_entry.read(is);
66 96763 : if(m_current_entry.isValid() && m_current_entry.hasTrailingDataDescriptor())
67 : {
68 10 : throw FileCollectionException("Trailing data descriptor in zip file not supported");
69 : }
70 :
71 96753 : switch(m_current_entry.getMethod())
72 : {
73 : case StorageMethod::DEFLATED:
74 94668 : reset() ; // reset inflatestream data structures
75 : //std::cerr << "deflated" << std::endl;
76 94668 : break;
77 :
78 : case StorageMethod::STORED:
79 2075 : m_remain = m_current_entry.getSize();
80 : // Force underflow on first read:
81 2075 : setg(&m_outvec[0], &m_outvec[0] + getBufferSize(), &m_outvec[0] + getBufferSize());
82 : //std::cerr << "stored" << std::endl;
83 2075 : break;
84 :
85 : default:
86 : // file not supported... sorry!
87 10 : throw FileCollectionException("Unsupported compression format");
88 :
89 : }
90 96743 : }
91 :
92 :
93 : /** \fn ZipInputStreambuf::ZipInputStreambuf(ZipInputStreambuf const & src);
94 : * \brief The copy contructor is deleted.
95 : *
96 : * ZipInputStreambuf objects cannot be copied so the copy constructor
97 : * is deleted.
98 : *
99 : * \param[in] src The source to copy.
100 : */
101 :
102 :
103 :
104 : /** \brief Clean up a ZipInputStreambuf object.
105 : *
106 : * The destructor ensures that all resources get released.
107 : */
108 193486 : ZipInputStreambuf::~ZipInputStreambuf()
109 : {
110 193486 : }
111 :
112 :
113 : /** \brief Called when more data is required.
114 : *
115 : * The function ensures that at least one byte is available
116 : * in the input area by updating the pointers to the input area
117 : * and reading more data in from the input sequence if required.
118 : *
119 : * \return The value of that character on success or
120 : * std::streambuf::traits_type::eof() on failure.
121 : */
122 773407 : std::streambuf::int_type ZipInputStreambuf::underflow()
123 : {
124 773407 : switch(m_current_entry.getMethod())
125 : {
126 : case StorageMethod::DEFLATED:
127 : // inflate class takes care of it in this case
128 763145 : return InflateInputStreambuf::underflow();
129 :
130 : case StorageMethod::STORED:
131 : {
132 : // Ok, we are STORED, so we handle it ourselves.
133 10262 : offset_t const num_b(std::min(m_remain, static_cast<offset_t>(getBufferSize())));
134 10262 : std::streamsize const g(m_inbuf->sgetn(&m_outvec[0], num_b));
135 10262 : setg(&m_outvec[0], &m_outvec[0], &m_outvec[0] + g);
136 10262 : m_remain -= g;
137 10262 : if(g > 0)
138 : {
139 : // we got some data, return it
140 8187 : return traits_type::to_int_type(*gptr());
141 : }
142 :
143 : // documentation says to return EOF if no data available
144 2075 : return traits_type::eof();
145 : }
146 :
147 : default:
148 : // This should NEVER be reached or the constructor let something
149 : // go through that should not have gone through
150 : throw std::logic_error("ZipInputStreambuf::underflow(): unknown storage method"); // LCOV_EXCL_LINE
151 :
152 : }
153 : }
154 :
155 :
156 3 : } // namespace
157 :
158 : // Local Variables:
159 : // mode: cpp
160 : // indent-tabs-mode: nil
161 : // c-basic-offset: 4
162 : // tab-width: 4
163 : // End:
164 :
165 : // vim: ts=4 sw=4 et
|