LCOV - code coverage report
Current view: top level - src - backbuffer.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 20 20 100.0 %
Date: 2019-04-24 14:10:30 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          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 The implementation file of zipios::BackBuffer.
      24             :  *
      25             :  * This class implements the functions necessary to read a file
      26             :  * backward.
      27             :  */
      28             : 
      29             : #include "backbuffer.hpp"
      30             : 
      31             : #include "zipios/zipiosexceptions.hpp"
      32             : 
      33             : #include <algorithm>
      34             : 
      35             : namespace zipios
      36             : {
      37             : 
      38             : /** \class BackBuffer
      39             :  * \brief To read a file by chunk from the end.
      40             :  *
      41             :  * A BackBuffer instance is useful for reading the last part of a
      42             :  * file in an efficient manner, when it is not known exactly how far
      43             :  * back (towards the front!) to go, to find the start of the desired
      44             :  * data block.
      45             :  *
      46             :  * BackBuffer is an std::vector<unsigned char> that fills
      47             :  * itself with data from a file by reading chunks from the end of the
      48             :  * file progressing towards the start. Upon construction the
      49             :  * BackBuffer instance is associated with a file and a chunksize can
      50             :  * be specified. To read a chunk of the file into the BackBuffer call
      51             :  * readChunk().
      52             :  *
      53             :  * Note that this is not a good option for really large files as the
      54             :  * buffer is enlarged using an insert() on each call to readChunk().
      55             :  */
      56             : 
      57             : 
      58             : 
      59             : /** BackBuffer constructor.
      60             :  *
      61             :  * Initialize a buffer that reads data backward.
      62             :  *
      63             :  * The content of the buffer is defined as the content of the \p is
      64             :  * stream. The stream must be open and seekable. The file pointer
      65             :  * of the stream is modified by this constructor and on each
      66             :  * call to readChunk().
      67             :  *
      68             :  * \exception IOException
      69             :  * This exception is raised when the VirtualSeeker (\p vs) returns
      70             :  * an invalid answer determining the size of the stream.
      71             :  *
      72             :  * \param[in,out] is  The istream to read the data from. The stream must
      73             :  *                    be seekable, as BackBuffer will reposition the
      74             :  *                    file pointer to read chunks from the back of the
      75             :  *                    file.
      76             :  * \param[in] vs  The virtual seeker used to change the file pointer.
      77             :  * \param[in] chunk_size   Specifies the size of the chunks to read the
      78             :  *                         file into the BackBuffer in.
      79             :  */
      80         378 : BackBuffer::BackBuffer(std::istream & is, VirtualSeeker const & vs, ssize_t const chunk_size)
      81             :     : m_vs(vs)
      82             :     , m_chunk_size(chunk_size)
      83             :     , m_is(is)
      84         397 :     , m_file_pos(0)
      85             : {
      86         378 :     if(!m_is)
      87             :     {
      88           1 :         throw InvalidException("BackBuffer() initialized with an invalid input stream.");
      89             :     }
      90         377 :     if(m_chunk_size <= 0)
      91             :     {
      92          17 :         throw InvalidException("Invalid chunk_size parameter, it has to be larger than zero.");
      93             :     }
      94             : 
      95         360 :     m_vs.vseekg(m_is, 0, std::ios::end);
      96         360 :     m_file_pos = m_vs.vtellg(m_is);
      97             : 
      98             :     // The following should only happens when m_vs.startOffset() is a
      99             :     // position in the file that lies after m_vs.endOffset(), which
     100             :     // is clearly not a valid situation. However, vtellg() may just
     101             :     // fail too.
     102         360 :     if(m_file_pos < 0)
     103             :     {
     104           1 :         throw IOException("Invalid virtual file endings.");
     105             :     }
     106         359 : }
     107             : 
     108             : 
     109             : /** \brief Read a chunk of data.
     110             :  *
     111             :  * Reads another chunk and returns the size of the chunk that has
     112             :  * been read. Returns 0 on I/O failure.
     113             :  *
     114             :  * When a new chunk is read in the already stored bytes change
     115             :  * position in the BackBuffer. \p read_pointer is assumed by
     116             :  * readChunk() to be a pointer into a position in the BackBuffer,
     117             :  * and is updated to point to the same position in the file
     118             :  * as it pointed to before the new chunk was prepended.
     119             :  *
     120             :  * When first calling readChunk(), \p read_pointer is expected
     121             :  * to be zero and represent the position of EOF.
     122             :  *
     123             :  * \warning
     124             :  * The file is read backward.
     125             :  *
     126             :  * \warning
     127             :  * The function may change m_chunk_size. In the end will be
     128             :  * zero and no more data can be read.
     129             :  *
     130             :  * \warning
     131             :  * The function changes the file pointer of the attached stream.
     132             :  *
     133             :  * \bug
     134             :  * We may want to throw an error if m_is.is_good() returns false.
     135             :  *
     136             :  * \param[in,out] read_pointer  The buffer pointer.
     137             :  *
     138             :  * \return The number of bytes read if any, otherwise zero. Note that if
     139             :  *         an error occurs, the function also returns zero.
     140             :  */
     141         395 : ssize_t BackBuffer::readChunk(ssize_t& read_pointer)
     142             : {
     143             :     // Update m_chunk_size and file position
     144         395 :     m_chunk_size = std::min<ssize_t>(static_cast<ssize_t>(m_file_pos), m_chunk_size);
     145         395 :     m_file_pos -= m_chunk_size;
     146         395 :     m_vs.vseekg(m_is, m_file_pos, std::ios::beg);
     147             : 
     148             :     // Make space for m_chunk_size new bytes
     149         395 :     insert(begin(), m_chunk_size, static_cast<char>(0));
     150             : 
     151             :     // Read in the next m_chunk_size bytes
     152         395 :     zipRead(m_is, *this, m_chunk_size);
     153         395 :     read_pointer += m_chunk_size;
     154             : 
     155         395 :     return m_is.good() ? m_chunk_size : 0;
     156             : }
     157             : 
     158             : 
     159           3 : } // zipios namespace
     160             : // Local Variables:
     161             : // mode: cpp
     162             : // indent-tabs-mode: nil
     163             : // c-basic-offset: 4
     164             : // tab-width: 4
     165             : // End:
     166             : 
     167             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12