1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-25 12:41:01 +00:00

Merge branch 'rm_base_esm_reader' into 'master'

Remove ESM::Reader base class

See merge request OpenMW/openmw!2388
This commit is contained in:
psi29a 2022-09-10 14:38:13 +00:00
commit 25fa8c3656
7 changed files with 77 additions and 159 deletions

View File

@ -9,6 +9,7 @@
#include <components/esm/esmcommon.hpp> #include <components/esm/esmcommon.hpp>
#include <components/esm4/reader.hpp> #include <components/esm4/reader.hpp>
#include <components/esm4/records.hpp> #include <components/esm4/records.hpp>
#include <components/to_utf8/to_utf8.hpp>
namespace EsmTool namespace EsmTool
{ {

View File

@ -80,7 +80,7 @@ add_component_dir (to_utf8
to_utf8 to_utf8
) )
add_component_dir(esm attr common defs esmcommon reader records util luascripts format) add_component_dir(esm attr common defs esmcommon records util luascripts format)
add_component_dir(fx pass technique lexer widgets stateupdater) add_component_dir(fx pass technique lexer widgets stateupdater)

View File

@ -1,86 +0,0 @@
#include "reader.hpp"
//#ifdef NDEBUG
//#undef NDEBUG
//#endif
#include <cassert>
#include <stdexcept>
#include <components/files/constrainedfilestream.hpp>
#include "components/esm3/esmreader.hpp"
#include "components/esm4/reader.hpp"
namespace ESM
{
Reader* Reader::getReader(const std::string &filename)
{
Files::IStreamPtr esmStream(Files::openConstrainedFileStream(filename));
std::uint32_t modVer = 0; // get the first 4 bytes of the record header only
esmStream->read((char*)&modVer, sizeof(modVer));
if (esmStream->gcount() == sizeof(modVer))
{
esmStream->seekg(0);
if (modVer == ESM4::REC_TES4)
{
return new ESM4::Reader(std::move(esmStream), filename);
}
else
{
//return new ESM3::ESMReader(esmStream, filename);
}
}
throw std::runtime_error("Unknown file format");
}
bool Reader::getStringImpl(std::string& str, std::size_t size,
std::istream& stream, const ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull)
{
std::size_t newSize = size;
if (encoder)
{
std::string input(size, '\0');
stream.read(input.data(), size);
if (stream.gcount() == static_cast<std::streamsize>(size))
{
encoder->getUtf8(input, ToUTF8::BufferAllocationPolicy::FitToRequiredSize, str);
return true;
}
}
else
{
if (hasNull)
newSize -= 1; // don't read the null terminator yet
str.resize(newSize); // assumed C++11
stream.read(str.data(), newSize);
if (static_cast<std::size_t>(stream.gcount()) == newSize)
{
if (hasNull)
{
char ch;
stream.read(&ch, 1); // read the null terminator
assert (ch == '\0'
&& "ESM4::Reader::getString string is not terminated with a null");
}
#if 0
else
{
// NOTE: normal ESMs don't but omwsave has locals or spells with null terminator
assert (str[newSize - 1] != '\0'
&& "ESM4::Reader::getString string is unexpectedly terminated with a null");
}
#endif
return true;
}
}
str.clear();
return false; // FIXME: throw instead?
}
}

View File

@ -1,59 +0,0 @@
#ifndef COMPONENT_ESM_READER_H
#define COMPONENT_ESM_READER_H
#include <vector>
#include <components/to_utf8/to_utf8.hpp>
#include "common.hpp" // MasterData
namespace ToUTF8
{
class Utf8Encoder;
}
namespace ESM
{
class Reader
{
std::vector<Reader*>* mGlobalReaderList;
public:
virtual ~Reader() {}
static Reader* getReader(const std::string& filename);
void setGlobalReaderList(std::vector<Reader*> *list) {mGlobalReaderList = list;}
std::vector<Reader*> *getGlobalReaderList() {return mGlobalReaderList;}
virtual inline bool isEsm4() const = 0;
virtual inline bool hasMoreRecs() const = 0;
virtual inline void setEncoder(const ToUTF8::StatelessUtf8Encoder* encoder) = 0;
// used to check for dependencies e.g. CS::Editor::run()
virtual inline const std::vector<ESM::MasterData>& getGameFiles() const = 0;
// used by ContentSelector::ContentModel::addFiles()
virtual inline const std::string getAuthor() const = 0;
virtual inline const std::string getDesc() const = 0;
virtual inline int getFormat() const = 0;
virtual inline std::string getFileName() const = 0;
// used by CSMWorld::Data::startLoading() and getTotalRecords() for loading progress bar
virtual inline int getRecordCount() const = 0;
virtual void setModIndex(std::uint32_t index) = 0;
// used by CSMWorld::Data::getTotalRecords()
virtual void close() = 0;
protected:
bool getStringImpl(std::string& str, std::size_t size,
std::istream& stream, const ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull = false);
};
}
#endif // COMPONENT_ESM_READER_H

View File

@ -28,6 +28,7 @@
#include <stdexcept> #include <stdexcept>
#include <iostream> // FIXME: testing only #include <iostream> // FIXME: testing only
#include <cstring>
#include "reader.hpp" #include "reader.hpp"
//#include "writer.hpp" //#include "writer.hpp"

View File

@ -50,6 +50,7 @@
#include <components/bsa/memorystream.hpp> #include <components/bsa/memorystream.hpp>
#include <components/misc/strings/lower.hpp> #include <components/misc/strings/lower.hpp>
#include <components/files/constrainedfilestream.hpp> #include <components/files/constrainedfilestream.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include "formid.hpp" #include "formid.hpp"
@ -646,4 +647,51 @@ void Reader::adjustGRUPFormId()
throw std::runtime_error(ss.str()); throw std::runtime_error(ss.str());
} }
bool Reader::getStringImpl(std::string& str, std::size_t size,
std::istream& stream, const ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull)
{
std::size_t newSize = size;
if (encoder)
{
std::string input(size, '\0');
stream.read(input.data(), size);
if (stream.gcount() == static_cast<std::streamsize>(size))
{
encoder->getUtf8(input, ToUTF8::BufferAllocationPolicy::FitToRequiredSize, str);
return true;
}
}
else
{
if (hasNull)
newSize -= 1; // don't read the null terminator yet
str.resize(newSize); // assumed C++11
stream.read(str.data(), newSize);
if (static_cast<std::size_t>(stream.gcount()) == newSize)
{
if (hasNull)
{
char ch;
stream.read(&ch, 1); // read the null terminator
assert (ch == '\0'
&& "ESM4::Reader::getString string is not terminated with a null");
}
#if 0
else
{
// NOTE: normal ESMs don't but omwsave has locals or spells with null terminator
assert (str[newSize - 1] != '\0'
&& "ESM4::Reader::getString string is unexpectedly terminated with a null");
}
#endif
return true;
}
}
str.clear();
return false; // FIXME: throw instead?
}
} }

View File

@ -30,10 +30,14 @@
#include "common.hpp" #include "common.hpp"
#include "loadtes4.hpp" #include "loadtes4.hpp"
#include "../esm/reader.hpp"
#include <components/files/istreamptr.hpp> #include <components/files/istreamptr.hpp>
namespace ToUTF8
{
class StatelessUtf8Encoder;
}
namespace ESM4 { namespace ESM4 {
// bytes read from group, updated by // bytes read from group, updated by
// getRecordHeader() in advance // getRecordHeader() in advance
@ -75,7 +79,7 @@ namespace ESM4 {
ReaderContext(); ReaderContext();
}; };
class Reader : public ESM::Reader class Reader
{ {
Header mHeader; // ESM4 header Header mHeader; // ESM4 header
@ -107,6 +111,8 @@ namespace ESM4 {
std::map<FormId, LStringOffset> mLStringIndex; std::map<FormId, LStringOffset> mLStringIndex;
std::vector<Reader*>* mGlobalReaderList = nullptr;
void buildLStringIndex(const std::string& stringFile, LocalizedStringType stringType); void buildLStringIndex(const std::string& stringFile, LocalizedStringType stringType);
inline bool hasLocalizedStrings() const { return (mHeader.mFlags & Rec_Localized) != 0; } inline bool hasLocalizedStrings() const { return (mHeader.mFlags & Rec_Localized) != 0; }
@ -126,6 +132,9 @@ namespace ESM4 {
Reader() = default; Reader() = default;
bool getStringImpl(std::string& str, std::size_t size,
std::istream& stream, const ToUTF8::StatelessUtf8Encoder* encoder, bool hasNull = false);
public: public:
Reader(Files::IStreamPtr&& esmStream, const std::string& filename); Reader(Files::IStreamPtr&& esmStream, const std::string& filename);
@ -136,22 +145,22 @@ namespace ESM4 {
void open(const std::string& filename); void open(const std::string& filename);
void close() final; void close();
inline bool isEsm4() const final { return true; } inline bool isEsm4() const { return true; }
inline void setEncoder(const ToUTF8::StatelessUtf8Encoder* encoder) final { mEncoder = encoder; }; inline void setEncoder(const ToUTF8::StatelessUtf8Encoder* encoder) { mEncoder = encoder; };
const std::vector<ESM::MasterData>& getGameFiles() const final { return mHeader.mMaster; } const std::vector<ESM::MasterData>& getGameFiles() const { return mHeader.mMaster; }
inline int getRecordCount() const final { return mHeader.mData.records; } inline int getRecordCount() const { return mHeader.mData.records; }
inline const std::string getAuthor() const final { return mHeader.mAuthor; } inline const std::string getAuthor() const { return mHeader.mAuthor; }
inline int getFormat() const final { return 0; }; // prob. not relevant for ESM4 inline int getFormat() const { return 0; }; // prob. not relevant for ESM4
inline const std::string getDesc() const final { return mHeader.mDesc; } inline const std::string getDesc() const { return mHeader.mDesc; }
inline std::string getFileName() const final { return mCtx.filename; }; // not used inline std::string getFileName() const { return mCtx.filename; }; // not used
inline bool hasMoreRecs() const final { return (mFileSize - mCtx.fileRead) > 0; } inline bool hasMoreRecs() const { return (mFileSize - mCtx.fileRead) > 0; }
// Methods added for updating loading progress bars // Methods added for updating loading progress bars
inline std::size_t getFileSize() const { return mFileSize; } inline std::size_t getFileSize() const { return mFileSize; }
@ -195,7 +204,7 @@ namespace ESM4 {
// The object setting up this reader needs to supply the file's load order index // The object setting up this reader needs to supply the file's load order index
// so that the formId's in this file can be adjusted with the file (i.e. mod) index. // so that the formId's in this file can be adjusted with the file (i.e. mod) index.
void setModIndex(std::uint32_t index) final { mCtx.modIndex = (index << 24) & 0xff000000; } void setModIndex(std::uint32_t index) { mCtx.modIndex = (index << 24) & 0xff000000; }
void updateModIndices(const std::vector<std::string>& files); void updateModIndices(const std::vector<std::string>& files);
// Maybe should throw an exception if called when not valid? // Maybe should throw an exception if called when not valid?
@ -292,6 +301,10 @@ namespace ESM4 {
// Used for error handling // Used for error handling
[[noreturn]] void fail(const std::string& msg); [[noreturn]] void fail(const std::string& msg);
void setGlobalReaderList(std::vector<Reader*> *list) { mGlobalReaderList = list; }
std::vector<Reader*> *getGlobalReaderList() { return mGlobalReaderList; }
}; };
} }