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-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 : 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 : #include <algorithm> 33 : 34 : 35 : namespace zipios 36 : { 37 : 38 : 39 : /** \class ZipInputStreambuf 40 : * \brief An input stream buffer for Zip data. 41 : * 42 : * The ZipInputStreambuf class is a Zip input streambuf filter that 43 : * automatically decompresses input data that was compressed using 44 : * the zlib library. 45 : */ 46 : 47 : 48 : /** \brief Initialize a ZipInputStreambuf. 49 : * 50 : * This ZipInputStreambuf constructor initializes the buffer from the 51 : * user specified buffer. 52 : * 53 : * \param[in,out] inbuf The streambuf to use for input. 54 : * \param[in] start_pos A position to reset the inbuf to before reading. 55 : * Specify -1 to read from the current position. 56 : */ 57 53061 : ZipInputStreambuf::ZipInputStreambuf(std::streambuf * inbuf, offset_t start_pos) 58 53061 : : InflateInputStreambuf(inbuf, start_pos) 59 : { 60 : // read the zip local header 61 53061 : std::istream is(m_inbuf); // istream does not destroy the streambuf. 62 53061 : is.exceptions(std::ios::eofbit | std::ios::failbit | std::ios::badbit); 63 : 64 : // if the read fails in any way it will throw 65 53061 : m_current_entry.read(is); 66 53061 : 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 53051 : switch(m_current_entry.getMethod()) 72 : { 73 50758 : case StorageMethod::DEFLATED: 74 50758 : reset() ; // reset inflatestream data structures 75 : //std::cerr << "deflated" << std::endl; 76 50758 : break; 77 : 78 2283 : case StorageMethod::STORED: 79 2283 : m_remain = m_current_entry.getSize(); 80 : // Force underflow on first read: 81 2283 : setg(&m_outvec[0], &m_outvec[0] + getBufferSize(), &m_outvec[0] + getBufferSize()); 82 : //std::cerr << "stored" << std::endl; 83 2283 : break; 84 : 85 10 : default: 86 : // file not supported... sorry! 87 10 : throw FileCollectionException("Unsupported compression format"); 88 : 89 : } 90 53101 : } 91 : 92 : 93 : /** \fn ZipInputStreambuf::ZipInputStreambuf(ZipInputStreambuf const & src); 94 : * \brief The copy constructor 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 106082 : ZipInputStreambuf::~ZipInputStreambuf() 109 : { 110 106082 : } 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 408014 : std::streambuf::int_type ZipInputStreambuf::underflow() 123 : { 124 408014 : switch(m_current_entry.getMethod()) 125 : { 126 399682 : case StorageMethod::DEFLATED: 127 : // inflate class takes care of it in this case 128 399682 : return InflateInputStreambuf::underflow(); 129 : 130 8332 : case StorageMethod::STORED: 131 : { 132 : // Ok, we are STORED, so we handle it ourselves. 133 8332 : offset_t const num_b(std::min(m_remain, static_cast<offset_t>(getBufferSize()))); 134 8332 : std::streamsize const g(m_inbuf->sgetn(&m_outvec[0], num_b)); 135 8332 : setg(&m_outvec[0], &m_outvec[0], &m_outvec[0] + g); 136 8332 : m_remain -= g; 137 8332 : if(g > 0) 138 : { 139 : // we got some data, return it 140 6049 : return traits_type::to_int_type(*gptr()); 141 : } 142 : 143 : // documentation says to return EOF if no data available 144 2283 : return traits_type::eof(); 145 : } 146 : 147 : default: // LCOV_EXCL_LINE 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 : } // 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