mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-25 16:43:33 +00:00
Move ConstrainedStreamBuf into separate file
This commit is contained in:
parent
ddd01ac777
commit
9d6d0c6ffb
@ -206,7 +206,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
add_component_dir (files
|
add_component_dir (files
|
||||||
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager
|
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager
|
||||||
lowlevelfile constrainedfilestream memorystream hash configfileparser openfile
|
lowlevelfile constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (compiler
|
add_component_dir (compiler
|
||||||
|
@ -1,109 +1,8 @@
|
|||||||
#include "constrainedfilestream.hpp"
|
#include "constrainedfilestream.hpp"
|
||||||
|
|
||||||
#include <streambuf>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "lowlevelfile.hpp"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// somewhat arbitrary though 64KB buffers didn't seem to improve performance any
|
|
||||||
const size_t sBufferSize = 8192;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Files
|
namespace Files
|
||||||
{
|
{
|
||||||
class ConstrainedFileStreamBuf : public std::streambuf
|
ConstrainedFileStream::ConstrainedFileStream(std::unique_ptr<ConstrainedFileStreamBuf> buf)
|
||||||
{
|
|
||||||
|
|
||||||
size_t mOrigin;
|
|
||||||
size_t mSize;
|
|
||||||
|
|
||||||
LowLevelFile mFile;
|
|
||||||
|
|
||||||
char mBuffer[sBufferSize]{0};
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConstrainedFileStreamBuf(const std::string &fname, size_t start, size_t length)
|
|
||||||
{
|
|
||||||
mFile.open (fname.c_str ());
|
|
||||||
mSize = length != std::numeric_limits<std::size_t>::max() ? length : mFile.size () - start;
|
|
||||||
|
|
||||||
if (start != 0)
|
|
||||||
mFile.seek(start);
|
|
||||||
|
|
||||||
setg(nullptr,nullptr,nullptr);
|
|
||||||
|
|
||||||
mOrigin = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
int_type underflow() override
|
|
||||||
{
|
|
||||||
if(gptr() == egptr())
|
|
||||||
{
|
|
||||||
size_t toRead = std::min((mOrigin+mSize)-(mFile.tell()), sBufferSize);
|
|
||||||
// Read in the next chunk of data, and set the read pointers on success
|
|
||||||
// Failure will throw exception in LowLevelFile
|
|
||||||
size_t got = mFile.read(mBuffer, toRead);
|
|
||||||
setg(&mBuffer[0], &mBuffer[0], &mBuffer[0]+got);
|
|
||||||
}
|
|
||||||
if(gptr() == egptr())
|
|
||||||
return traits_type::eof();
|
|
||||||
|
|
||||||
return traits_type::to_int_type(*gptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) override
|
|
||||||
{
|
|
||||||
if((mode&std::ios_base::out) || !(mode&std::ios_base::in))
|
|
||||||
return traits_type::eof();
|
|
||||||
|
|
||||||
// new file position, relative to mOrigin
|
|
||||||
size_t newPos;
|
|
||||||
switch (whence)
|
|
||||||
{
|
|
||||||
case std::ios_base::beg:
|
|
||||||
newPos = offset;
|
|
||||||
break;
|
|
||||||
case std::ios_base::cur:
|
|
||||||
newPos = (mFile.tell() - mOrigin - (egptr() - gptr())) + offset;
|
|
||||||
break;
|
|
||||||
case std::ios_base::end:
|
|
||||||
newPos = mSize + offset;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return traits_type::eof();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newPos > mSize)
|
|
||||||
return traits_type::eof();
|
|
||||||
|
|
||||||
mFile.seek(mOrigin+newPos);
|
|
||||||
|
|
||||||
// Clear read pointers so underflow() gets called on the next read attempt.
|
|
||||||
setg(nullptr, nullptr, nullptr);
|
|
||||||
|
|
||||||
return newPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override
|
|
||||||
{
|
|
||||||
if((mode&std::ios_base::out) || !(mode&std::ios_base::in))
|
|
||||||
return traits_type::eof();
|
|
||||||
|
|
||||||
if ((size_t)pos > mSize)
|
|
||||||
return traits_type::eof();
|
|
||||||
|
|
||||||
mFile.seek(mOrigin + pos);
|
|
||||||
|
|
||||||
// Clear read pointers so underflow() gets called on the next read attempt.
|
|
||||||
setg(nullptr, nullptr, nullptr);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
ConstrainedFileStream::ConstrainedFileStream(std::unique_ptr<std::streambuf> buf)
|
|
||||||
: std::istream(buf.get())
|
: std::istream(buf.get())
|
||||||
, mBuf(std::move(buf))
|
, mBuf(std::move(buf))
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef OPENMW_CONSTRAINEDFILESTREAM_H
|
#ifndef OPENMW_CONSTRAINEDFILESTREAM_H
|
||||||
#define OPENMW_CONSTRAINEDFILESTREAM_H
|
#define OPENMW_CONSTRAINEDFILESTREAM_H
|
||||||
|
|
||||||
|
#include "constrainedfilestreambuf.hpp"
|
||||||
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -10,14 +12,13 @@ namespace Files
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// A file stream constrained to a specific region in the file, specified by the 'start' and 'length' parameters.
|
/// A file stream constrained to a specific region in the file, specified by the 'start' and 'length' parameters.
|
||||||
class ConstrainedFileStream : public std::istream
|
class ConstrainedFileStream final : public std::istream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConstrainedFileStream(std::unique_ptr<std::streambuf> buf);
|
explicit ConstrainedFileStream(std::unique_ptr<ConstrainedFileStreamBuf> buf);
|
||||||
virtual ~ConstrainedFileStream() {};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<std::streambuf> mBuf;
|
std::unique_ptr<ConstrainedFileStreamBuf> mBuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<std::istream> IStreamPtr;
|
typedef std::shared_ptr<std::istream> IStreamPtr;
|
||||||
|
83
components/files/constrainedfilestreambuf.cpp
Normal file
83
components/files/constrainedfilestreambuf.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "constrainedfilestreambuf.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
ConstrainedFileStreamBuf::ConstrainedFileStreamBuf(const std::string& fname, std::size_t start, std::size_t length)
|
||||||
|
: mOrigin(start)
|
||||||
|
{
|
||||||
|
mFile.open(fname.c_str());
|
||||||
|
mSize = length != std::numeric_limits<std::size_t>::max() ? length : mFile.size () - start;
|
||||||
|
|
||||||
|
if (start != 0)
|
||||||
|
mFile.seek(start);
|
||||||
|
|
||||||
|
setg(nullptr, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streambuf::int_type ConstrainedFileStreamBuf::underflow()
|
||||||
|
{
|
||||||
|
if (gptr() == egptr())
|
||||||
|
{
|
||||||
|
const std::size_t toRead = std::min((mOrigin + mSize) - (mFile.tell()), sizeof(mBuffer));
|
||||||
|
// Read in the next chunk of data, and set the read pointers on success
|
||||||
|
// Failure will throw exception in LowLevelFile
|
||||||
|
const std::size_t got = mFile.read(mBuffer, toRead);
|
||||||
|
setg(&mBuffer[0], &mBuffer[0], &mBuffer[0] + got);
|
||||||
|
}
|
||||||
|
if (gptr() == egptr())
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
return traits_type::to_int_type(*gptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streambuf::pos_type ConstrainedFileStreamBuf::seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode)
|
||||||
|
{
|
||||||
|
if ((mode & std::ios_base::out) || !(mode & std::ios_base::in))
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
// new file position, relative to mOrigin
|
||||||
|
size_t newPos;
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case std::ios_base::beg:
|
||||||
|
newPos = offset;
|
||||||
|
break;
|
||||||
|
case std::ios_base::cur:
|
||||||
|
newPos = (mFile.tell() - mOrigin - (egptr() - gptr())) + offset;
|
||||||
|
break;
|
||||||
|
case std::ios_base::end:
|
||||||
|
newPos = mSize + offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPos > mSize)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
mFile.seek(mOrigin + newPos);
|
||||||
|
|
||||||
|
// Clear read pointers so underflow() gets called on the next read attempt.
|
||||||
|
setg(nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streambuf::pos_type ConstrainedFileStreamBuf::seekpos(pos_type pos, std::ios_base::openmode mode)
|
||||||
|
{
|
||||||
|
if ((mode & std::ios_base::out) || !(mode & std::ios_base::in))
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
if (static_cast<std::size_t>(pos) > mSize)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
mFile.seek(mOrigin + pos);
|
||||||
|
|
||||||
|
// Clear read pointers so underflow() gets called on the next read attempt.
|
||||||
|
setg(nullptr, nullptr, nullptr);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
30
components/files/constrainedfilestreambuf.hpp
Normal file
30
components/files/constrainedfilestreambuf.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef OPENMW_CONSTRAINEDFILESTREAMBUF_H
|
||||||
|
#define OPENMW_CONSTRAINEDFILESTREAMBUF_H
|
||||||
|
|
||||||
|
#include "lowlevelfile.hpp"
|
||||||
|
|
||||||
|
#include <streambuf>
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
/// A file streambuf constrained to a specific region in the file, specified by the 'start' and 'length' parameters.
|
||||||
|
class ConstrainedFileStreamBuf final : public std::streambuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConstrainedFileStreamBuf(const std::string& fname, std::size_t start, std::size_t length);
|
||||||
|
|
||||||
|
int_type underflow() final;
|
||||||
|
|
||||||
|
pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) final;
|
||||||
|
|
||||||
|
pos_type seekpos(pos_type pos, std::ios_base::openmode mode) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t mOrigin;
|
||||||
|
std::size_t mSize;
|
||||||
|
LowLevelFile mFile;
|
||||||
|
char mBuffer[8192]{0};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user