LCOV - code coverage report
Current view: top level - src - virtualseeker.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 34 34 100.0 %
Date: 2019-04-24 14:10:30 Functions: 9 9 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 Implementation file that defines zipios::VirtualSeeker.
      24             :  *
      25             :  * The zipios::VirtualSeeker is used to handle offsets of a Zip archive
      26             :  * defined within a larger file. See the
      27             :  * zipios::ZipFile::openEmbeddedZipFile() function and the appendzip
      28             :  * tool for additional information.
      29             :  *
      30             :  * \sa appendzip.cpp
      31             :  * \sa zipios::ZipFile::openEmbeddedZipFile()
      32             :  */
      33             : 
      34             : #include "zipios/virtualseeker.hpp"
      35             : 
      36             : #include "zipios/zipiosexceptions.hpp"
      37             : 
      38             : 
      39             : namespace zipios
      40             : {
      41             : 
      42             : 
      43             : /** \class VirtualSeeker
      44             :  * \brief A virtual class used to see in a file embedded in another.
      45             :  *
      46             :  * The virtual seeker class is a simple definition of an object
      47             :  * that keeps track of a set of specified (virtual) file pointers
      48             :  * that mark start and end of a file inside another.
      49             :  *
      50             :  * An example of its use (and its reason for existence) is to
      51             :  * keep track of the file endings of a Zip file embedded in another
      52             :  * file (see the \ref appendzip_anchor "appendzip tool" and
      53             :  * the ZipFile::openEmbeddedZipFile() function).
      54             :  *
      55             :  * \bug
      56             :  * The class is not linked to an input stream when created or
      57             :  * the offsets get modified. This means the seek and tell functions
      58             :  * cannot be sure that the offsets are valid of the specified
      59             :  * input buffer.
      60             :  */
      61             : 
      62             : 
      63             : /** \brief Create a virtual seeker.
      64             :  *
      65             :  * This constructor defines a virtual seeker start and end offsets
      66             :  * on initialization. By default it is initialized to a transparent
      67             :  * seeker since the start and end are set to zero.
      68             :  *
      69             :  * \note
      70             :  * If the offsets are left undefined (both set to zero) then the virtual
      71             :  * seeker is viewed as a transparent seeker, meaning that it seeks in
      72             :  * the input streams as if it did not exist.
      73             :  *
      74             :  * \warning
      75             :  * The virtual seek end offset is quite peculiar in that it is defined
      76             :  * as a POSITIVE number from the end of the file, going backward. The
      77             :  * normal seekg() command expects a negative number of an offset to be
      78             :  * applied from the end of the file.
      79             :  *
      80             :  * \warning
      81             :  * The class is not attached to one specific input stream so there is no
      82             :  * way to verify that the offsets are valid (i.e. not representing an
      83             :  * empty virtual file or having offsets completely outside of the available
      84             :  * range.)
      85             :  *
      86             :  * \exception InvalidException
      87             :  * The two offsets must be positive.
      88             :  *
      89             :  * \param[in] start_offset  The start offset of the embedded file.
      90             :  * \param[in] end_offset  The end offset of the embedded file.
      91             :  */
      92        1401 : VirtualSeeker::VirtualSeeker(offset_t start_offset, offset_t end_offset)
      93             :     : m_start_offset(start_offset)
      94        1401 :     , m_end_offset(end_offset)
      95             : {
      96        1401 :     if(m_start_offset < 0
      97         895 :     || m_end_offset < 0)
      98             :     {
      99         765 :         throw InvalidException("VirtualSeeker::VirtualSeeker(): the start and end offsets cannot be negative.");
     100             :     }
     101         636 : }
     102             : 
     103             : 
     104             : /** \brief Set the offsets of the virtual seeker.
     105             :  *
     106             :  * This function can be used to change the virtual seeker offsets.
     107             :  *
     108             :  * \exception InvalidException
     109             :  * The start offset must be before or equal to the end offset or
     110             :  * this exception is raised.
     111             :  *
     112             :  * \param[in] start_offset  The new start offset.
     113             :  * \param[in] end_offset  The new end offset.
     114             :  */
     115        1024 : void VirtualSeeker::setOffsets(offset_t start_offset, offset_t end_offset)
     116             : {
     117        1024 :     if(start_offset < 0
     118         512 :     || end_offset < 0)
     119             :     {
     120         768 :         throw InvalidException("VirtualSeeker::VirtualSeeker(): the start and end offsets cannot be negative.");
     121             :     }
     122             : 
     123         256 :     m_start_offset = start_offset;
     124         256 :     m_end_offset = end_offset;
     125         256 : }
     126             : 
     127             : 
     128             : /** \brief Retrieve the current offsets.
     129             :  *
     130             :  * This function retrieves the start and end offsets from the virtual
     131             :  * seeker object.
     132             :  *
     133             :  * \param[out] start_offset  Returns the start offset.
     134             :  * \param[out] end_offset  Returns the end offset.
     135             :  */
     136         512 : void VirtualSeeker::getOffsets(offset_t& start_offset, offset_t& end_offset) const
     137             : {
     138         512 :     start_offset = m_start_offset;
     139         512 :     end_offset = m_end_offset;
     140         512 : }
     141             : 
     142             : 
     143             : /** \brief Return the start offset.
     144             :  *
     145             :  * This function returns a copy of the start offset.
     146             :  *
     147             :  * \return The start offset.
     148             :  */
     149       97275 : offset_t VirtualSeeker::startOffset() const
     150             : {
     151       97275 :     return m_start_offset;
     152             : }
     153             : 
     154             : 
     155             : /** \brief Return the end offset.
     156             :  *
     157             :  * This function returns a copy of the end offset.
     158             :  *
     159             :  * \return The end offset.
     160             :  */
     161         512 : offset_t VirtualSeeker::endOffset() const
     162             : {
     163         512 :     return m_end_offset;
     164             : }
     165             : 
     166             : 
     167             : /** \brief Seek within the embedded file.
     168             :  *
     169             :  * This function changes the file pointer in \p is to the position
     170             :  * specified in offset.
     171             :  *
     172             :  * The direction can be indicated by \p sd.
     173             :  *
     174             :  * \param[in,out] is  The stream which pointer is to be changed.
     175             :  * \param[in] offset  Relative position to set the input pointer to.
     176             :  * \param[in] sd  The stream direction to use to apply offset.
     177             :  */
     178      161717 : void VirtualSeeker::vseekg(std::istream &is, offset_t offset, std::ios::seekdir sd) const
     179             : {
     180      161717 :     switch(sd)
     181             :     {
     182             :     case std::ios::cur:
     183         342 :         break;
     184             : 
     185             :     case std::ios::beg:
     186      109815 :         offset += m_start_offset;
     187      109815 :         break;
     188             : 
     189             :     case std::ios::end:
     190             :         // This definitively looks weird because this class makes use
     191             :         // of a POSITIVE offset from the end of the file as the end
     192             :         // offset. The parameter 'offset' is expected to be negative
     193             :         // or zero in this case.
     194         872 :         offset -= m_end_offset;
     195         872 :         break;
     196             : 
     197             :     default:
     198       50688 :         throw std::logic_error("VirtualSeekManager::vseekg(): error - unknown seekdir");
     199             : 
     200             :     }
     201             : 
     202      111029 :     is.seekg(offset, sd);
     203      111029 : }
     204             : 
     205             : 
     206             : /** \brief Current position within the sub-file.
     207             :  *
     208             :  * This function calculates the position (file current pointer) within
     209             :  * the embedded file in the specified stream.
     210             :  *
     211             :  * If the position in the existing file is too large or too small, then
     212             :  * the function returns -1.
     213             :  *
     214             :  * \param[in] is  The stream to get the position from.
     215             :  *
     216             :  * \return The stream offset within the embedded file.
     217             :  */
     218        2029 : std::streampos VirtualSeeker::vtellg(std::istream& is) const
     219             : {
     220             :     /** \TODO
     221             :      * We may want to get the size of the file and verify that the
     222             :      * resulting position is valid. The m_end_offset does not really
     223             :      * mean anything at this point that we could use to verify the
     224             :      * position boundaries (since it is a positive size from the
     225             :      * end of the file.)
     226             :      */
     227        2029 :     return is.tellg() - m_start_offset;
     228             : }
     229             : 
     230             : 
     231           3 : } // zipios namespace
     232             : 
     233             : // Local Variables:
     234             : // mode: cpp
     235             : // indent-tabs-mode: nil
     236             : // c-basic-offset: 4
     237             : // tab-width: 4
     238             : // End:
     239             : 
     240             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12