Browse Source

Add more documentation to src/stream/slice.hpp

coverity_scan
Daniel Scharrer 13 years ago
parent
commit
8761518b6f
  1. 8
      src/stream/chunk.hpp
  2. 4
      src/stream/file.hpp
  3. 37
      src/stream/slice.cpp
  4. 104
      src/stream/slice.hpp

8
src/stream/chunk.hpp

@ -19,11 +19,11 @@
*/
/*!
* Wrapper to read and decompress a chunk from a \ref slice_reader.
* Wrapper to read and decompress a chunk from a \ref stream::slice_reader.
*
* A chunk consists of one compression stream (one of \ref compression_method) and
* A chunk consists of one compression stream (one of \ref stream::compression_method) and
* contains one or more files. Files may also have additional filters managed by
* \ref file_reader.
* \ref stream::file_reader.
*/
#ifndef INNOEXTRACT_STREAM_CHUNK_HPP
#define INNOEXTRACT_STREAM_CHUNK_HPP
@ -62,6 +62,8 @@ enum compression_method {
* Information specifying a compressed chunk.
*
* This data is stored in \ref setup::data entries.
*
* Chunks specified by this struct can be read using \ref chunk_reader.
*/
struct chunk {

4
src/stream/file.hpp

@ -19,7 +19,7 @@
*/
/*!
* Wrapper to read a single file from a chunk (\ref chunk_reader).
* Wrapper to read a single file from a chunk (\ref stream::chunk_reader).
*/
#ifndef INNOEXTRACT_STREAM_FILE_HPP
#define INNOEXTRACT_STREAM_FILE_HPP
@ -44,6 +44,8 @@ enum compression_filter {
* Information specifying a single file inside a compressed chunk.
*
* This data is stored in \ref setup::data entries.
*
* Files specified by this struct can be read using \ref file_reader.
*/
struct file {

37
src/stream/slice.cpp

@ -43,8 +43,10 @@ const char slice_ids[][8] = {
} // anonymous namespace
slice_reader::slice_reader(std::istream * istream, boost::uint32_t data_offset)
: dir(), last_dir(), base_file(), data_offset(data_offset), slices_per_disk(1),
current_slice(0), is(istream) {
: data_offset(data_offset),
dir(), last_dir(), base_file(), slices_per_disk(1),
current_slice(0), slice_file(), slice_size(0),
ifs(), is(istream) {
std::streampos max_size = std::streampos(std::numeric_limits<boost::int32_t>::max());
@ -52,15 +54,16 @@ slice_reader::slice_reader(std::istream * istream, boost::uint32_t data_offset)
slice_size = boost::uint32_t(std::min(file_size, max_size));
if(is->seekg(data_offset).fail()) {
log_error << "could not seek to data";
throw slice_error("could not seek to data");
}
}
slice_reader::slice_reader(const path_type & dir, const path_type & base_file,
size_t slices_per_disk)
: dir(dir), last_dir(dir), base_file(base_file), data_offset(0),
slices_per_disk(slices_per_disk), current_slice(0), slice_size(0),
is(&ifs) { }
: data_offset(0),
dir(dir), last_dir(dir), base_file(base_file), slices_per_disk(slices_per_disk),
current_slice(0), slice_file(), slice_size(0),
ifs(), is(&ifs) { }
bool slice_reader::seek(size_t slice) {
@ -69,8 +72,7 @@ bool slice_reader::seek(size_t slice) {
}
if(data_offset != 0) {
log_error << "[slice] cannot change slices in single-file setup";
return false;
throw slice_error("[slice] cannot change slices in single-file setup");
}
return open(slice, path_type());
@ -94,8 +96,7 @@ bool slice_reader::open_file(const path_type & file) {
char magic[8];
if(ifs.read(magic, 8).fail()) {
ifs.close();
log_error << "[slice] error reading magic number";
return false;
throw slice_error("error reading slice magic number");
}
bool found = false;
for(size_t i = 0; ARRAY_SIZE(slice_ids); i++) {
@ -105,24 +106,24 @@ bool slice_reader::open_file(const path_type & file) {
}
}
if(!found) {
log_error << "[slice] bad magic number";
ifs.close();
return false;
throw slice_error("bad slice magic number");
}
slice_size = load_number<boost::uint32_t>(ifs);
if(ifs.fail()) {
log_error << "[slice] error reading slice size";
ifs.close();
return false;
throw slice_error("error reading slice size");
} else if(std::streampos(slice_size) > file_size) {
log_error << "[slice] bad slice size: " << slice_size << " > " << file_size;
ifs.close();
return false;
std::ostringstream oss;
oss << "bad slice size: " << slice_size << " > " << file_size;
throw slice_error(oss.str());
} else if(std::streampos(slice_size) < ifs.tellg()) {
log_error << "[slice] bad slice size: " << slice_size << " < " << ifs.tellg();
ifs.close();
return false;
std::ostringstream oss;
oss << "bad slice size: " << slice_size << " < " << ifs.tellg();
throw slice_error(oss.str());
}
slice_file = file;

104
src/stream/slice.hpp

@ -18,9 +18,14 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
/*!
* Abstraction for reading the embedded or external raw setup data.
*/
#ifndef INNOEXTRACT_STREAM_SLICEREADER_HPP
#define INNOEXTRACT_STREAM_SLICEREADER_HPP
#include <ios>
#include <boost/iostreams/concepts.hpp>
#include <boost/filesystem/path.hpp>
@ -28,42 +33,117 @@
namespace stream {
//! Error thrown by \ref chunk_reader if there was a problem.
struct slice_error : public std::ios_base::failure {
explicit slice_error(std::string msg) : std::ios_base::failure(msg) { }
};
/*!
* Abstraction for reading either data embedded inside the setup executable or from
* multiple external slices.
*
* Setup data contained in the executable is located by a non-zeore
* \ref loader::offsets::data_offset.
*
* The contained data is made up of one or more \ref chunk "chunks"
* (read by \ref chunk_reader), which in turn contain one or more \ref file "files"
* (read by \ref file_reader).
*/
class slice_reader : public boost::iostreams::source {
typedef boost::filesystem::path path_type;
path_type dir;
path_type last_dir;
path_type base_file;
// Information for reading embedded setup data
const boost::uint32_t data_offset;
const size_t slices_per_disk;
size_t current_slice;
path_type slice_file;
boost::uint32_t slice_size;
// Information for eading external setup data
path_type dir; //!< Slice directory specified at construction.
path_type last_dir; //!< Directory containing the current slice.
path_type base_file; //!< Base file name for slices.
const size_t slices_per_disk; //!< Number of slices grouped into each disk (for names).
util::ifstream ifs;
// Information about the current slice
size_t current_slice; //!< Number of the currently opened slice.
path_type slice_file; //!< Filename of the currently opened slice.
boost::uint32_t slice_size; //!< Size in bytes of the currently opened slice.
std::istream * is;
// Streams
util::ifstream ifs; //!< File input stream used when reading from external slices.
std::istream * is; //!< Input stream to read from.
bool seek(size_t slice);
bool open_file(const path_type & file);
bool open(size_t slice, const path_type & slice_file);
public:
/*!
* Construct a \ref slice_reader to read from data inside the setup file.
* Seeking to anything except the zeroeth slice is not allowed.
*
* \param istream A seekable input stream for the setup executable.
* The initial read position of the stream is ignored.
* \param data_offset The offset within the given stream where the setup data starts.
* This offset is given by \ref loader::offsets::data_offset.
*
* The constructed reader will allow reading the byte range [data_offset, file end)
* from the setup executable and provide this as the range [0, file end - data_offset).
*/
slice_reader(std::istream * istream, boost::uint32_t data_offset);
slice_reader(const path_type & dir, const path_type & base_file, size_t slices_per_disk);
/*!
* Construct a \ref slice_reader to read from external data slices (aka disks).
*
* Slice files must be located at \c <dir>/<base_file>-<disk>.bin
* or \c <dir>/<base_file>-<disk><sliceletter>.bin if \ref slices_per_disk is greater
* than \c 1.
*
* The disk number is given by \code slice / slices_per_disk + 1 \endcode while
* the sliceletter is the ASCII char \code 'a' + (slice % slices_per_disk) \endcode.
*
* \param dir The directory containing the slice files.
* \param basename The base name for slice files.
* \param slices_per_disk How many slices are grouped into one disk. Must not be \c 0.
*/
slice_reader(const path_type & dir, const path_type & basename, size_t slices_per_disk);
/*!
* Attempt to seek to an offset within a slice.
*
* \param slice The slice to seek to.
* \param offset The byte offset to seek to within the given slice.
*
* \return \c false if the requested slice could not be opened, or if the requested
* offset is not a valid position in that slice - \c true otherwise.
*/
bool seek(size_t slice, boost::uint32_t offset);
/*!
* Read a number of bytes starting at the current slice and offset within that slice.
*
* \param buffer Buffer to receive the bytes read.
* \param bytes Number of bytes to read.
*
* The current offset will be advanced by the number of bytes read. It is not an error
* to read past the end of the current slice (unless it is the last slice). Doing so
* will automatically seek to the start of the next slice and continue reading from
* there.
*
* \return The number of bytes read or \c -1 if there was an error. Unless we are at the
* end of the last slice, this function blocks until the number of requested
* bytes have been read.
*/
std::streamsize read(char * buffer, std::streamsize bytes);
//! \return the number currently opened slice.
size_t slice() { return current_slice; }
path_type & file() { return slice_file; }
bool open(size_t slice, const path_type & slice_file);
//! \return filename for the currently opened slice.
path_type & file() { return slice_file; }
//! \return true a slice is currently open.
bool is_open() { return (is != &ifs || ifs.is_open()); }
};

Loading…
Cancel
Save