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:
commit
25fa8c3656
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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?
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
@ -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"
|
||||||
|
@ -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?
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user