1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-30 16:20:21 +00:00

Merge branch 'istream_unique_ptr' into 'master'

Use unique_ptr to store istream

See merge request OpenMW/openmw!1793
This commit is contained in:
psi29a 2022-04-23 11:19:27 +00:00
commit cfcc88f64c
21 changed files with 211 additions and 189 deletions

View File

@ -44,7 +44,7 @@ void VideoWidget::playVideo(const std::string &video)
return; return;
} }
mPlayer->playVideo(videoStream, video); mPlayer->playVideo(std::move(videoStream), video);
osg::ref_ptr<osg::Texture2D> texture = mPlayer->getVideoTexture(); osg::ref_ptr<osg::Texture2D> texture = mPlayer->getVideoTexture();
if (!texture) if (!texture)

View File

@ -23,7 +23,7 @@ namespace
Files::IStreamPtr open() override Files::IStreamPtr open() override
{ {
return std::make_shared<std::stringstream>(mContent, std::ios_base::in); return std::make_unique<std::stringstream>(mContent, std::ios_base::in);
} }
private: private:

View File

@ -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

View File

@ -370,7 +370,7 @@ Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord)
fileStream->read(reinterpret_cast<char*>(&uncompressedSize), sizeof(uint32_t)); fileStream->read(reinterpret_cast<char*>(&uncompressedSize), sizeof(uint32_t));
size -= sizeof(uint32_t); size -= sizeof(uint32_t);
} }
std::shared_ptr<Bsa::MemoryInputStream> memoryStreamPtr = std::make_shared<MemoryInputStream>(uncompressedSize); auto memoryStreamPtr = std::make_unique<MemoryInputStream>(uncompressedSize);
if (compressed) if (compressed)
{ {
@ -403,7 +403,7 @@ Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord)
fileStream->read(memoryStreamPtr->getRawData(), size); fileStream->read(memoryStreamPtr->getRawData(), size);
} }
return std::shared_ptr<std::istream>(memoryStreamPtr, (std::istream*)memoryStreamPtr.get()); return std::make_unique<Files::StreamWithBuffer<MemoryInputStream>>(std::move(memoryStreamPtr));
} }
BsaVersion CompressedBSAFile::detectVersion(const std::string& filePath) BsaVersion CompressedBSAFile::detectVersion(const std::string& filePath)

View File

@ -26,7 +26,7 @@ namespace ESM
if (modVer == ESM4::REC_TES4) if (modVer == ESM4::REC_TES4)
{ {
return new ESM4::Reader(esmStream, filename); return new ESM4::Reader(std::move(esmStream), filename);
} }
else else
{ {
@ -38,15 +38,15 @@ namespace ESM
} }
bool Reader::getStringImpl(std::string& str, std::size_t size, bool Reader::getStringImpl(std::string& str, std::size_t size,
Files::IStreamPtr filestream, ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull) std::istream& stream, ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull)
{ {
std::size_t newSize = size; std::size_t newSize = size;
if (encoder) if (encoder)
{ {
std::string input(size, '\0'); std::string input(size, '\0');
filestream->read(input.data(), size); stream.read(input.data(), size);
if (filestream->gcount() == static_cast<std::streamsize>(size)) if (stream.gcount() == static_cast<std::streamsize>(size))
{ {
encoder->getUtf8(input, ToUTF8::BufferAllocationPolicy::FitToRequiredSize, str); encoder->getUtf8(input, ToUTF8::BufferAllocationPolicy::FitToRequiredSize, str);
return true; return true;
@ -58,13 +58,13 @@ namespace ESM
newSize -= 1; // don't read the null terminator yet newSize -= 1; // don't read the null terminator yet
str.resize(newSize); // assumed C++11 str.resize(newSize); // assumed C++11
filestream->read(&str[0], newSize); stream.read(&str[0], newSize);
if ((std::size_t)filestream->gcount() == newSize) if (static_cast<std::size_t>(stream.gcount()) == newSize)
{ {
if (hasNull) if (hasNull)
{ {
char ch; char ch;
filestream->read(&ch, 1); // read the null terminator stream.read(&ch, 1); // read the null terminator
assert (ch == '\0' assert (ch == '\0'
&& "ESM4::Reader::getString string is not terminated with a null"); && "ESM4::Reader::getString string is not terminated with a null");
} }

View File

@ -53,7 +53,7 @@ namespace ESM
protected: protected:
bool getStringImpl(std::string& str, std::size_t size, bool getStringImpl(std::string& str, std::size_t size,
Files::IStreamPtr filestream, ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull = false); std::istream& stream, ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull = false);
}; };
} }

View File

@ -64,8 +64,8 @@ ReaderContext::ReaderContext() : modIndex(0), recHeaderSize(sizeof(RecordHeader)
currCellGrid.grid.y = 0; currCellGrid.grid.y = 0;
} }
Reader::Reader(Files::IStreamPtr esmStream, const std::string& filename) Reader::Reader(Files::IStreamPtr&& esmStream, const std::string& filename)
: mEncoder(nullptr), mFileSize(0), mStream(esmStream) : mEncoder(nullptr), mFileSize(0), mStream(std::move(esmStream))
{ {
// used by ESMReader only? // used by ESMReader only?
mCtx.filename = filename; mCtx.filename = filename;
@ -130,8 +130,7 @@ bool Reader::restoreContext(const ReaderContext& ctx)
{ {
if (mSavedStream) // TODO: doesn't seem to ever happen if (mSavedStream) // TODO: doesn't seem to ever happen
{ {
mStream = mSavedStream; mStream = std::move(mSavedStream);
mSavedStream.reset();
} }
mCtx.groupStack.clear(); // probably not necessary since it will be overwritten mCtx.groupStack.clear(); // probably not necessary since it will be overwritten
@ -148,11 +147,11 @@ void Reader::close()
//mHeader.blank(); //mHeader.blank();
} }
void Reader::openRaw(Files::IStreamPtr esmStream, const std::string& filename) void Reader::openRaw(Files::IStreamPtr&& stream, const std::string& filename)
{ {
close(); close();
mStream = esmStream; mStream = std::move(stream);
mCtx.filename = filename; mCtx.filename = filename;
mCtx.fileRead = 0; mCtx.fileRead = 0;
mStream->seekg(0, mStream->end); mStream->seekg(0, mStream->end);
@ -161,9 +160,9 @@ void Reader::openRaw(Files::IStreamPtr esmStream, const std::string& filename)
} }
void Reader::open(Files::IStreamPtr esmStream, const std::string &filename) void Reader::open(Files::IStreamPtr&& stream, const std::string &filename)
{ {
openRaw(esmStream, filename); openRaw(std::move(stream), filename);
// should at least have the size of ESM3 record header (20 or 24 bytes for ESM4) // should at least have the size of ESM3 record header (20 or 24 bytes for ESM4)
assert (mFileSize >= 16); assert (mFileSize >= 16);
@ -210,32 +209,33 @@ void Reader::buildLStringIndex(const std::string& stringFile, LocalizedStringTyp
sp.type = stringType; sp.type = stringType;
// TODO: possibly check if the resource exists? // TODO: possibly check if the resource exists?
Files::IStreamPtr filestream = Files::IStreamPtr(Files::openConstrainedFileStream(stringFile)); Files::IStreamPtr filestream = Files::openConstrainedFileStream(stringFile);
filestream->seekg(0, std::ios::end); filestream->seekg(0, std::ios::end);
std::size_t fileSize = filestream->tellg(); std::size_t fileSize = filestream->tellg();
filestream->seekg(0, std::ios::beg); filestream->seekg(0, std::ios::beg);
std::istream* stream = filestream.get();
switch (stringType) switch (stringType)
{ {
case Type_Strings: mStrings = filestream; break; case Type_Strings: mStrings = std::move(filestream); break;
case Type_ILStrings: mILStrings = filestream; break; case Type_ILStrings: mILStrings = std::move(filestream); break;
case Type_DLStrings: mDLStrings = filestream; break; case Type_DLStrings: mDLStrings = std::move(filestream); break;
default: default:
throw std::runtime_error("ESM4::Reader::unknown localised string type"); throw std::runtime_error("ESM4::Reader::unknown localised string type");
} }
filestream->read((char*)&numEntries, sizeof(numEntries)); stream->read((char*)&numEntries, sizeof(numEntries));
filestream->read((char*)&dataSize, sizeof(dataSize)); stream->read((char*)&dataSize, sizeof(dataSize));
std::size_t dataStart = fileSize - dataSize; std::size_t dataStart = fileSize - dataSize;
for (unsigned int i = 0; i < numEntries; ++i) for (unsigned int i = 0; i < numEntries; ++i)
{ {
filestream->read((char*)&stringId, sizeof(stringId)); stream->read((char*)&stringId, sizeof(stringId));
filestream->read((char*)&sp.offset, sizeof(sp.offset)); stream->read((char*)&sp.offset, sizeof(sp.offset));
sp.offset += (std::uint32_t)dataStart; sp.offset += (std::uint32_t)dataStart;
mLStringIndex[stringId] = sp; mLStringIndex[stringId] = sp;
} }
//assert (dataStart - filestream->tell() == 0 && "String file start of data section mismatch"); //assert (dataStart - stream->tell() == 0 && "String file start of data section mismatch");
} }
void Reader::getLocalizedString(std::string& str) void Reader::getLocalizedString(std::string& str)
@ -256,13 +256,13 @@ void Reader::getLocalizedStringImpl(const FormId stringId, std::string& str)
if (it != mLStringIndex.end()) if (it != mLStringIndex.end())
{ {
Files::IStreamPtr filestream; std::istream* filestream = nullptr;
switch (it->second.type) switch (it->second.type)
{ {
case Type_Strings: // no string size provided case Type_Strings: // no string size provided
{ {
filestream = mStrings; filestream = mStrings.get();
filestream->seekg(it->second.offset); filestream->seekg(it->second.offset);
char ch; char ch;
@ -275,8 +275,8 @@ void Reader::getLocalizedStringImpl(const FormId stringId, std::string& str)
str = std::string(data.data()); str = std::string(data.data());
return; return;
} }
case Type_ILStrings: filestream = mILStrings; break; case Type_ILStrings: filestream = mILStrings.get(); break;
case Type_DLStrings: filestream = mDLStrings; break; case Type_DLStrings: filestream = mDLStrings.get(); break;
default: default:
throw std::runtime_error("ESM4::Reader::getLocalizedString unknown string type"); throw std::runtime_error("ESM4::Reader::getLocalizedString unknown string type");
} }
@ -285,7 +285,7 @@ void Reader::getLocalizedStringImpl(const FormId stringId, std::string& str)
filestream->seekg(it->second.offset); filestream->seekg(it->second.offset);
std::uint32_t size = 0; std::uint32_t size = 0;
filestream->read((char*)&size, sizeof(size)); filestream->read((char*)&size, sizeof(size));
getStringImpl(str, size, filestream, mEncoder, true); // expect null terminated string getStringImpl(str, size, *filestream, mEncoder, true); // expect null terminated string
} }
else else
throw std::runtime_error("ESM4::Reader::getLocalizedString localized string not found"); throw std::runtime_error("ESM4::Reader::getLocalizedString localized string not found");
@ -296,8 +296,7 @@ bool Reader::getRecordHeader()
// FIXME: this seems very hacky but we may have skipped subrecords from within an inflated data block // FIXME: this seems very hacky but we may have skipped subrecords from within an inflated data block
if (/*mStream->eof() && */mSavedStream) if (/*mStream->eof() && */mSavedStream)
{ {
mStream = mSavedStream; mStream = std::move(mSavedStream);
mSavedStream.reset();
} }
mStream->read((char*)&mCtx.recordHeader, mCtx.recHeaderSize); mStream->read((char*)&mCtx.recordHeader, mCtx.recHeaderSize);
@ -336,12 +335,11 @@ void Reader::getRecordData(bool dump)
Bsa::MemoryInputStream compressedRecord(recordSize); Bsa::MemoryInputStream compressedRecord(recordSize);
mStream->read(compressedRecord.getRawData(), recordSize); mStream->read(compressedRecord.getRawData(), recordSize);
std::istream *fileStream = (std::istream*)&compressedRecord; std::istream *fileStream = (std::istream*)&compressedRecord;
mSavedStream = mStream; mSavedStream = std::move(mStream);
mCtx.recordHeader.record.dataSize = uncompressedSize - sizeof(uncompressedSize); mCtx.recordHeader.record.dataSize = uncompressedSize - sizeof(uncompressedSize);
std::shared_ptr<Bsa::MemoryInputStream> memoryStreamPtr auto memoryStreamPtr = std::make_unique<Bsa::MemoryInputStream>(uncompressedSize);
= std::make_shared<Bsa::MemoryInputStream>(uncompressedSize);
boost::iostreams::filtering_streambuf<boost::iostreams::input> inputStreamBuf; boost::iostreams::filtering_streambuf<boost::iostreams::input> inputStreamBuf;
inputStreamBuf.push(boost::iostreams::zlib_decompressor()); inputStreamBuf.push(boost::iostreams::zlib_decompressor());
@ -370,7 +368,7 @@ if (dump)
std::cout << ss.str() << std::endl; std::cout << ss.str() << std::endl;
} }
//#endif //#endif
mStream = std::shared_ptr<std::istream>(memoryStreamPtr, (std::istream*)memoryStreamPtr.get()); mStream = std::make_unique<Files::StreamWithBuffer<Bsa::MemoryInputStream>>(std::move(memoryStreamPtr));
} }
} }

View File

@ -114,17 +114,17 @@ namespace ESM4 {
//void close(); //void close();
// Raw opening. Opens the file and sets everything up but doesn't parse the header. // Raw opening. Opens the file and sets everything up but doesn't parse the header.
void openRaw(Files::IStreamPtr esmStream, const std::string& filename); void openRaw(Files::IStreamPtr&& stream, const std::string& filename);
// Load ES file from a new stream, parses the header. // Load ES file from a new stream, parses the header.
// Closes the currently open file first, if any. // Closes the currently open file first, if any.
void open(Files::IStreamPtr esmStream, const std::string& filename); void open(Files::IStreamPtr&& stream, const std::string& filename);
Reader() = default; Reader() = default;
public: public:
Reader(Files::IStreamPtr esmStream, const std::string& filename); Reader(Files::IStreamPtr&& esmStream, const std::string& filename);
~Reader(); ~Reader();
// FIXME: should be private but ESMTool uses it // FIXME: should be private but ESMTool uses it
@ -280,10 +280,10 @@ namespace ESM4 {
// Note: uses the string size from the subrecord header rather than checking null termination // Note: uses the string size from the subrecord header rather than checking null termination
bool getZString(std::string& str) { bool getZString(std::string& str) {
return getStringImpl(str, mCtx.subRecordHeader.dataSize, mStream, mEncoder, true); return getStringImpl(str, mCtx.subRecordHeader.dataSize, *mStream, mEncoder, true);
} }
bool getString(std::string& str) { bool getString(std::string& str) {
return getStringImpl(str, mCtx.subRecordHeader.dataSize, mStream, mEncoder); return getStringImpl(str, mCtx.subRecordHeader.dataSize, *mStream, mEncoder);
} }
void enterGroup(); void enterGroup();

View File

@ -1,116 +1,9 @@
#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
{
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())
, mBuf(std::move(buf))
{
}
IStreamPtr openConstrainedFileStream(const std::string& filename, std::size_t start, std::size_t length) IStreamPtr openConstrainedFileStream(const std::string& filename, std::size_t start, std::size_t length)
{ {
return std::make_shared<ConstrainedFileStream>(std::make_unique<ConstrainedFileStreamBuf>(filename, start, length)); return std::make_unique<ConstrainedFileStream>(std::make_unique<ConstrainedFileStreamBuf>(filename, start, length));
} }
} }

View File

@ -1,6 +1,9 @@
#ifndef OPENMW_CONSTRAINEDFILESTREAM_H #ifndef OPENMW_CONSTRAINEDFILESTREAM_H
#define OPENMW_CONSTRAINEDFILESTREAM_H #define OPENMW_CONSTRAINEDFILESTREAM_H
#include "constrainedfilestreambuf.hpp"
#include "streamwithbuffer.hpp"
#include <istream> #include <istream>
#include <memory> #include <memory>
#include <limits> #include <limits>
@ -10,17 +13,9 @@ 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 using ConstrainedFileStream = StreamWithBuffer<ConstrainedFileStreamBuf>;
{
public:
ConstrainedFileStream(std::unique_ptr<std::streambuf> buf);
virtual ~ConstrainedFileStream() {};
private: typedef std::unique_ptr<std::istream> IStreamPtr;
std::unique_ptr<std::streambuf> mBuf;
};
typedef std::shared_ptr<std::istream> IStreamPtr;
IStreamPtr openConstrainedFileStream(const std::string& filename, std::size_t start = 0, IStreamPtr openConstrainedFileStream(const std::string& filename, std::size_t start = 0,
std::size_t length = std::numeric_limits<std::size_t>::max()); std::size_t length = std::numeric_limits<std::size_t>::max());

View 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;
}
}

View 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

View File

@ -0,0 +1,23 @@
#ifndef OPENMW_COMPONENTS_FILES_STREAMWITHBUFFER_H
#define OPENMW_COMPONENTS_FILES_STREAMWITHBUFFER_H
#include <istream>
#include <memory>
namespace Files
{
template <class Buffer>
class StreamWithBuffer final : public std::istream
{
public:
explicit StreamWithBuffer(std::unique_ptr<Buffer>&& buffer)
: std::istream(buffer.get())
, mBuffer(std::move(buffer))
{}
private:
std::unique_ptr<Buffer> mBuffer;
};
}
#endif

View File

@ -137,12 +137,12 @@ namespace
} }
} }
[[noreturn]] void fail (Files::IStreamPtr file, const std::string& fileName, const std::string& message) [[noreturn]] void fail(std::istream& stream, const std::string& fileName, const std::string& message)
{ {
std::stringstream error; std::stringstream error;
error << "Font loading error: " << message; error << "Font loading error: " << message;
error << "\n File: " << fileName; error << "\n File: " << fileName;
error << "\n Offset: 0x" << std::hex << file->tellg(); error << "\n Offset: 0x" << std::hex << stream.tellg();
throw std::runtime_error(error.str()); throw std::runtime_error(error.str());
} }
@ -252,33 +252,33 @@ namespace Gui
float fontSize; float fontSize;
file->read((char*)&fontSize, sizeof(fontSize)); file->read((char*)&fontSize, sizeof(fontSize));
if (!file->good()) if (!file->good())
fail(file, fileName, "File too small to be a valid font"); fail(*file, fileName, "File too small to be a valid font");
int one; int one;
file->read((char*)&one, sizeof(one)); file->read((char*)&one, sizeof(one));
if (!file->good()) if (!file->good())
fail(file, fileName, "File too small to be a valid font"); fail(*file, fileName, "File too small to be a valid font");
if (one != 1) if (one != 1)
fail(file, fileName, "Unexpected value"); fail(*file, fileName, "Unexpected value");
file->read((char*)&one, sizeof(one)); file->read((char*)&one, sizeof(one));
if (!file->good()) if (!file->good())
fail(file, fileName, "File too small to be a valid font"); fail(*file, fileName, "File too small to be a valid font");
if (one != 1) if (one != 1)
fail(file, fileName, "Unexpected value"); fail(*file, fileName, "Unexpected value");
char name_[284]; char name_[284];
file->read(name_, sizeof(name_)); file->read(name_, sizeof(name_));
if (!file->good()) if (!file->good())
fail(file, fileName, "File too small to be a valid font"); fail(*file, fileName, "File too small to be a valid font");
std::string name(name_); std::string name(name_);
GlyphInfo data[256]; GlyphInfo data[256];
file->read((char*)data, sizeof(data)); file->read((char*)data, sizeof(data));
if (!file->good()) if (!file->good())
fail(file, fileName, "File too small to be a valid font"); fail(*file, fileName, "File too small to be a valid font");
file.reset(); file.reset();
@ -292,16 +292,16 @@ namespace Gui
bitmapFile->read((char*)&height, sizeof(int)); bitmapFile->read((char*)&height, sizeof(int));
if (!bitmapFile->good()) if (!bitmapFile->good())
fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap"); fail(*bitmapFile, bitmapFilename, "File too small to be a valid bitmap");
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
fail(bitmapFile, bitmapFilename, "Width and height must be positive"); fail(*bitmapFile, bitmapFilename, "Width and height must be positive");
std::vector<char> textureData; std::vector<char> textureData;
textureData.resize(width*height*4); textureData.resize(width*height*4);
bitmapFile->read(&textureData[0], width*height*4); bitmapFile->read(&textureData[0], width*height*4);
if (!bitmapFile->good()) if (!bitmapFile->good())
fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap"); fail(*bitmapFile, bitmapFilename, "File too small to be a valid bitmap");
bitmapFile.reset(); bitmapFile.reset();
std::string resourceName; std::string resourceName;

View File

@ -12,10 +12,10 @@ namespace Nif
{ {
/// Open a NIF stream. The name is used for error messages. /// Open a NIF stream. The name is used for error messages.
NIFFile::NIFFile(Files::IStreamPtr stream, const std::string &name) NIFFile::NIFFile(Files::IStreamPtr&& stream, const std::string &name)
: filename(name) : filename(name)
{ {
parse(stream); parse(std::move(stream));
} }
template <typename NodeType, RecordType recordType> template <typename NodeType, RecordType recordType>
@ -170,12 +170,12 @@ std::string NIFFile::printVersion(unsigned int version)
return stream.str(); return stream.str();
} }
void NIFFile::parse(Files::IStreamPtr stream) void NIFFile::parse(Files::IStreamPtr&& stream)
{ {
const std::array<std::uint64_t, 2> fileHash = Files::getHash(filename, *stream); const std::array<std::uint64_t, 2> fileHash = Files::getHash(filename, *stream);
hash.append(reinterpret_cast<const char*>(fileHash.data()), fileHash.size() * sizeof(std::uint64_t)); hash.append(reinterpret_cast<const char*>(fileHash.data()), fileHash.size() * sizeof(std::uint64_t));
NIFStream nif (this, stream); NIFStream nif (this, std::move(stream));
// Check the header string // Check the header string
std::string head = nif.getVersionString(); std::string head = nif.getVersionString();

View File

@ -69,7 +69,7 @@ class NIFFile final : public File
static std::atomic_bool sLoadUnsupportedFiles; static std::atomic_bool sLoadUnsupportedFiles;
/// Parse the file /// Parse the file
void parse(Files::IStreamPtr stream); void parse(Files::IStreamPtr&& stream);
/// Get the file's version in a human readable form /// Get the file's version in a human readable form
///\returns A string containing a human readable NIF version number ///\returns A string containing a human readable NIF version number
@ -107,7 +107,7 @@ public:
} }
/// Open a NIF stream. The name is used for error messages. /// Open a NIF stream. The name is used for error messages.
NIFFile(Files::IStreamPtr stream, const std::string &name); NIFFile(Files::IStreamPtr&& stream, const std::string &name);
/// Get a given record /// Get a given record
Record *getRecord(size_t index) const override Record *getRecord(size_t index) const override

View File

@ -62,7 +62,7 @@ public:
NIFFile * const file; NIFFile * const file;
NIFStream (NIFFile * file, Files::IStreamPtr inp): inp (inp), file (file) {} NIFStream (NIFFile * file, Files::IStreamPtr&& inp): inp (std::move(inp)), file (file) {}
void skip(size_t size) { inp->ignore(size); } void skip(size_t size) { inp->ignore(size); }

View File

@ -27,7 +27,7 @@ void VideoPlayer::setAudioFactory(MovieAudioFactory *factory)
mAudioFactory.reset(factory); mAudioFactory.reset(factory);
} }
void VideoPlayer::playVideo(std::shared_ptr<std::istream> inputstream, const std::string& name) void VideoPlayer::playVideo(std::unique_ptr<std::istream>&& inputstream, const std::string& name)
{ {
if(mState) if(mState)
close(); close();
@ -35,7 +35,7 @@ void VideoPlayer::playVideo(std::shared_ptr<std::istream> inputstream, const std
try { try {
mState = new VideoState; mState = new VideoState;
mState->setAudioFactory(mAudioFactory.get()); mState->setAudioFactory(mAudioFactory.get());
mState->init(inputstream, name); mState->init(std::move(inputstream), name);
// wait until we have the first picture // wait until we have the first picture
while (mState->video_st && !mState->mTexture.get()) while (mState->video_st && !mState->mTexture.get())

View File

@ -42,7 +42,7 @@ namespace Video
/// Play the given video. If a video is already playing, the old video is closed first. /// Play the given video. If a video is already playing, the old video is closed first.
/// @note The video will be unpaused by default. Use the pause() and play() methods to control pausing. /// @note The video will be unpaused by default. Use the pause() and play() methods to control pausing.
/// @param name A name for the video stream - only used for logging purposes. /// @param name A name for the video stream - only used for logging purposes.
void playVideo (std::shared_ptr<std::istream> inputstream, const std::string& name); void playVideo(std::unique_ptr<std::istream>&& inputstream, const std::string& name);
/// Get the current playback time position in the video, in seconds /// Get the current playback time position in the video, in seconds
double getCurrentTime(); double getCurrentTime();

View File

@ -714,7 +714,7 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx)
return 0; return 0;
} }
void VideoState::init(std::shared_ptr<std::istream> inputstream, const std::string &name) void VideoState::init(std::unique_ptr<std::istream>&& inputstream, const std::string &name)
{ {
int video_index = -1; int video_index = -1;
int audio_index = -1; int audio_index = -1;

View File

@ -128,7 +128,7 @@ struct VideoState {
void setAudioFactory(MovieAudioFactory* factory); void setAudioFactory(MovieAudioFactory* factory);
void init(std::shared_ptr<std::istream> inputstream, const std::string& name); void init(std::unique_ptr<std::istream>&& inputstream, const std::string& name);
void deinit(); void deinit();
void setPaused(bool isPaused); void setPaused(bool isPaused);
@ -165,7 +165,7 @@ struct VideoState {
ExternalClock mExternalClock; ExternalClock mExternalClock;
std::shared_ptr<std::istream> stream; std::unique_ptr<std::istream> stream;
AVFormatContext* format_ctx; AVFormatContext* format_ctx;
AVCodecContext* video_ctx; AVCodecContext* video_ctx;
AVCodecContext* audio_ctx; AVCodecContext* audio_ctx;