From 3dc0d71403b2677ef224018ac31c66716b0a0325 Mon Sep 17 00:00:00 2001 From: parax0 Date: Tue, 23 Aug 2016 20:42:05 -0600 Subject: [PATCH] Implemented binary serializer classes --- src/Common/CAssetID.cpp | 8 +- src/Common/Common.pro | 6 +- src/Common/Serialization/CBasicBinaryReader.h | 78 +++++++++ src/Common/Serialization/CBasicBinaryWriter.h | 84 ++++++++++ src/Common/Serialization/CBinaryReader.h | 148 ++++++++++++++++++ src/Common/Serialization/CBinaryWriter.h | 123 +++++++++++++++ src/Common/Serialization/CXMLReader.h | 10 +- src/Common/Serialization/CXMLWriter.h | 9 +- src/Common/Serialization/IArchive.h | 18 ++- src/Core/GameProject/CResourceIterator.h | 20 ++- src/Core/Resource/TResPtr.h | 7 +- src/FileIO/CFileOutStream.cpp | 4 +- src/FileIO/CFileOutStream.h | 2 +- src/FileIO/CMemoryOutStream.cpp | 4 +- src/FileIO/CMemoryOutStream.h | 2 +- src/FileIO/CVectorOutStream.cpp | 4 +- src/FileIO/CVectorOutStream.h | 2 +- src/FileIO/IInputStream.cpp | 15 ++ src/FileIO/IInputStream.h | 2 + src/FileIO/IOutputStream.cpp | 12 ++ src/FileIO/IOutputStream.h | 4 +- 21 files changed, 519 insertions(+), 43 deletions(-) create mode 100644 src/Common/Serialization/CBasicBinaryReader.h create mode 100644 src/Common/Serialization/CBasicBinaryWriter.h create mode 100644 src/Common/Serialization/CBinaryReader.h create mode 100644 src/Common/Serialization/CBinaryWriter.h diff --git a/src/Common/CAssetID.cpp b/src/Common/CAssetID.cpp index 23d12506..8042aad2 100644 --- a/src/Common/CAssetID.cpp +++ b/src/Common/CAssetID.cpp @@ -68,13 +68,7 @@ TString CAssetID::ToString() const bool CAssetID::IsValid() const { - if (mLength == e32Bit) - return (*this != skInvalidID32); - - else if (mLength == e64Bit) - return (*this != skInvalidID64); - - else return false; + return *this != InvalidID(mLength); } // ************ STATIC ************ diff --git a/src/Common/Common.pro b/src/Common/Common.pro index f49e190e..a37e68ed 100644 --- a/src/Common/Common.pro +++ b/src/Common/Common.pro @@ -81,7 +81,11 @@ HEADERS += \ Serialization/IArchive.h \ Serialization/CXMLWriter.h \ Serialization/CXMLReader.h \ - EGame.h + EGame.h \ + Serialization/CBasicBinaryWriter.h \ + Serialization/CBasicBinaryReader.h \ + Serialization/CBinaryWriter.h \ + Serialization/CBinaryReader.h # Source Files SOURCES += \ diff --git a/src/Common/Serialization/CBasicBinaryReader.h b/src/Common/Serialization/CBasicBinaryReader.h new file mode 100644 index 00000000..99e15614 --- /dev/null +++ b/src/Common/Serialization/CBasicBinaryReader.h @@ -0,0 +1,78 @@ +#ifndef CBASICBINARYREADER +#define CBASICBINARYREADER + +#include "IArchive.h" +#include "Common/CFourCC.h" +#include + +// This is a basic binary reader that doesn't do any checks on parameter names. +// This is the fastest serializer, but it relies entirely on parameter order so +// changes to file structure will break old versions of the file. Use carefully! +class CBasicBinaryReader : public IArchive +{ + IInputStream *mpStream; + bool mOwnsStream; + +public: + CBasicBinaryReader(const TString& rkFilename, IOUtil::EEndianness = IOUtil::eLittleEndian) + : IArchive(true, false) + , mOwnsStream(true) + { + mpStream = new CFileInStream(rkFilename.ToStdString(), IOUtil::eBigEndian); + ASSERT(mpStream->IsValid()); + + mFileVersion = mpStream->ReadShort(); + mArchiveVersion = mpStream->ReadShort(); + mGame = GetGameForID( CFourCC(*mpStream) ); + } + + CBasicBinaryReader(IInputStream *pStream) + : IArchive(true, false) + , mOwnsStream(false) + { + ASSERT(pStream->IsValid()); + mpStream = pStream; + + mFileVersion = mpStream->ReadShort(); + mArchiveVersion = mpStream->ReadShort(); + mGame = GetGameForID( CFourCC(*mpStream) ); + } + + ~CBasicBinaryReader() + { + if (mOwnsStream) delete mpStream; + } + + // Interface + virtual bool ParamBegin(const char*) { return true; } + virtual void ParamEnd() { } + + virtual void SerializeContainerSize(u32& rSize) { SerializePrimitive(rSize); } + virtual void SerializeAbstractObjectType(u32& rType) { SerializePrimitive(rType); } + virtual void SerializePrimitive(bool& rValue) { rValue = mpStream->ReadBool(); } + virtual void SerializePrimitive(char& rValue) { rValue = mpStream->ReadByte(); } + virtual void SerializePrimitive(s8& rValue) { rValue = mpStream->ReadByte(); } + virtual void SerializePrimitive(u8& rValue) { rValue = mpStream->ReadByte(); } + virtual void SerializePrimitive(s16& rValue) { rValue = mpStream->ReadShort(); } + virtual void SerializePrimitive(u16& rValue) { rValue = mpStream->ReadShort(); } + virtual void SerializePrimitive(s32& rValue) { rValue = mpStream->ReadLong(); } + virtual void SerializePrimitive(u32& rValue) { rValue = mpStream->ReadLong(); } + virtual void SerializePrimitive(s64& rValue) { rValue = mpStream->ReadLongLong(); } + virtual void SerializePrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); } + virtual void SerializePrimitive(float& rValue) { rValue = mpStream->ReadFloat(); } + virtual void SerializePrimitive(double& rValue) { rValue = mpStream->ReadDouble(); } + virtual void SerializePrimitive(TString& rValue) { rValue = mpStream->ReadSizedString(); } + virtual void SerializePrimitive(CAssetID& rValue) { rValue = CAssetID(*mpStream, mGame); } + + virtual void SerializeHexPrimitive(s8& rValue) { rValue = mpStream->ReadByte(); } + virtual void SerializeHexPrimitive(u8& rValue) { rValue = mpStream->ReadByte(); } + virtual void SerializeHexPrimitive(s16& rValue) { rValue = mpStream->ReadShort(); } + virtual void SerializeHexPrimitive(u16& rValue) { rValue = mpStream->ReadShort(); } + virtual void SerializeHexPrimitive(s32& rValue) { rValue = mpStream->ReadLong(); } + virtual void SerializeHexPrimitive(u32& rValue) { rValue = mpStream->ReadLong(); } + virtual void SerializeHexPrimitive(s64& rValue) { rValue = mpStream->ReadLongLong(); } + virtual void SerializeHexPrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); } +}; + +#endif // CBASICBINARYREADER + diff --git a/src/Common/Serialization/CBasicBinaryWriter.h b/src/Common/Serialization/CBasicBinaryWriter.h new file mode 100644 index 00000000..b8b0c90b --- /dev/null +++ b/src/Common/Serialization/CBasicBinaryWriter.h @@ -0,0 +1,84 @@ +#ifndef CBASICBINARYWRITER +#define CBASICBINARYWRITER + +#include "IArchive.h" +#include "Common/CFourCC.h" +#include + +// This is a basic binary reader that doesn't do any checks on parameter names. +// This is the fastest serializer, but it relies entirely on parameter order so +// changes to file structure will break old versions of the file. Use carefully! +class CBasicBinaryWriter : public IArchive +{ + IOutputStream *mpStream; + bool mOwnsStream; + +public: + CBasicBinaryWriter(const TString& rkFilename, u32 FileVersion, EGame Game = eUnknownGame, IOUtil::EEndianness = IOUtil::eLittleEndian) + : IArchive(false, true) + , mOwnsStream(true) + { + mpStream = new CFileOutStream(rkFilename.ToStdString(), IOUtil::eBigEndian); + ASSERT(mpStream->IsValid()); + + mFileVersion = FileVersion; + mGame = Game; + + mpStream->WriteShort((u16) FileVersion); + mpStream->WriteShort((u16) skCurrentArchiveVersion); + GetGameID(Game).Write(*mpStream); + } + + CBasicBinaryWriter(IOutputStream *pStream, u32 FileVersion, EGame Game = eUnknownGame) + : IArchive(false, true) + , mOwnsStream(false) + { + ASSERT(pStream->IsValid()); + mpStream = pStream; + + mFileVersion = FileVersion; + mGame = Game; + + mpStream->WriteShort((u16) FileVersion); + mpStream->WriteShort((u16) skCurrentArchiveVersion); + GetGameID(Game).Write(*mpStream); + } + + ~CBasicBinaryWriter() + { + if (mOwnsStream) delete mpStream; + } + + // Interface + virtual bool ParamBegin(const char*) { return true; } + virtual void ParamEnd() { } + + virtual void SerializeContainerSize(u32& rSize) { SerializePrimitive(rSize); } + virtual void SerializeAbstractObjectType(u32& rType) { SerializePrimitive(rType); } + virtual void SerializePrimitive(bool& rValue) { mpStream->WriteBool(rValue); } + virtual void SerializePrimitive(char& rValue) { mpStream->WriteByte(rValue); } + virtual void SerializePrimitive(s8& rValue) { mpStream->WriteByte(rValue); } + virtual void SerializePrimitive(u8& rValue) { mpStream->WriteByte(rValue); } + virtual void SerializePrimitive(s16& rValue) { mpStream->WriteShort(rValue); } + virtual void SerializePrimitive(u16& rValue) { mpStream->WriteShort(rValue); } + virtual void SerializePrimitive(s32& rValue) { mpStream->WriteLong(rValue); } + virtual void SerializePrimitive(u32& rValue) { mpStream->WriteLong(rValue); } + virtual void SerializePrimitive(s64& rValue) { mpStream->WriteLongLong(rValue); } + virtual void SerializePrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); } + virtual void SerializePrimitive(float& rValue) { mpStream->WriteFloat(rValue); } + virtual void SerializePrimitive(double& rValue) { mpStream->WriteDouble(rValue); } + virtual void SerializePrimitive(TString& rValue) { mpStream->WriteSizedString(rValue.ToStdString()); } + virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream); } + + virtual void SerializeHexPrimitive(s8& rValue) { mpStream->WriteByte(rValue); } + virtual void SerializeHexPrimitive(u8& rValue) { mpStream->WriteByte(rValue); } + virtual void SerializeHexPrimitive(s16& rValue) { mpStream->WriteShort(rValue); } + virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); } + virtual void SerializeHexPrimitive(s32& rValue) { mpStream->WriteLong(rValue); } + virtual void SerializeHexPrimitive(u32& rValue) { mpStream->WriteLong(rValue); } + virtual void SerializeHexPrimitive(s64& rValue) { mpStream->WriteLongLong(rValue); } + virtual void SerializeHexPrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); } +}; + +#endif // CBASICBINARYWRITER + diff --git a/src/Common/Serialization/CBinaryReader.h b/src/Common/Serialization/CBinaryReader.h new file mode 100644 index 00000000..a6c1332b --- /dev/null +++ b/src/Common/Serialization/CBinaryReader.h @@ -0,0 +1,148 @@ +#ifndef CBINARYREADER +#define CBINARYREADER + +#include "IArchive.h" +#include "Common/CFourCC.h" + +class CBinaryReader : public IArchive +{ + struct SParameter + { + u32 Offset; + u16 Size; + bool HasChildren; + }; + std::vector mParamStack; + + IInputStream *mpStream; + bool mOwnsStream; + +public: + CBinaryReader(const TString& rkFilename) + : IArchive(true, false) + , mOwnsStream(true) + { + mpStream = new CFileInStream(rkFilename.ToStdString(), IOUtil::eBigEndian); + ASSERT(mpStream->IsValid()); + + mFileVersion = mpStream->ReadShort(); + mArchiveVersion = mpStream->ReadShort(); + mGame = GetGameForID( CFourCC(*mpStream) ); + + mParamStack.reserve(20); + } + + CBinaryReader(IInputStream *pStream) + : IArchive(true, false) + , mOwnsStream(false) + { + ASSERT(pStream->IsValid()); + mpStream = pStream; + + mFileVersion = mpStream->ReadShort(); + mArchiveVersion = mpStream->ReadShort(); + mGame = GetGameForID( CFourCC(*mpStream) ); + + mParamStack.reserve(20); + } + + ~CBinaryReader() + { + if (mOwnsStream) delete mpStream; + } + + // Interface + virtual bool ParamBegin(const char *pkName) + { + // If this is the parent parameter's first child, then skip the child count + if (!mParamStack.empty() && !mParamStack.back().HasChildren) + { + mpStream->Seek(0x2, SEEK_CUR); + mParamStack.back().HasChildren = true; + } + + // Check the next parameter ID first and check whether it's a match for the current parameter + u32 ParamID = TString(pkName).Hash32(); + u32 Offset = mpStream->Tell(); + u32 NextID = mpStream->ReadLong(); + u16 NextSize = mpStream->ReadShort(); + + // Does the next parameter ID match the current one? + if (NextID == ParamID) + { + mParamStack.push_back( SParameter { Offset, NextSize, false } ); + return true; + } + + // It's not a match - return to the parent parameter's first child and check all children to find a match + if (!mParamStack.empty()) + { + u32 ParentOffset = mParamStack.back().Offset; + mpStream->Seek(ParentOffset, SEEK_SET); + mpStream->Seek(0x6, SEEK_CUR); + u16 NumChildren = mpStream->ReadShort(); + + for (u32 iChild = 0; iChild < NumChildren; iChild++) + { + u32 ChildID = mpStream->ReadLong(); + u16 ChildSize = mpStream->ReadShort(); + + if (ChildID != ParamID) + mpStream->Seek(ChildSize, SEEK_CUR); + else + { + mParamStack.push_back( SParameter { mpStream->Tell() - 6, NextSize, false } ); + return true; + } + } + } + + // None of the children were a match - this parameter isn't in the file + mpStream->Seek(Offset, SEEK_SET); + return false; + } + + virtual void ParamEnd() + { + // Make sure we're at the end of the parameter + SParameter& rParam = mParamStack.back(); + u32 EndOffset = rParam.Offset + rParam.Size + 6; + mpStream->Seek(EndOffset, SEEK_SET); + mParamStack.pop_back(); + } + + void SerializeContainerSize(u32& rSize) + { + // Mostly handled by ParamBegin, we just need to return the size correctly so the container can be resized + rSize = (u32) mpStream->PeekShort(); + } + + void SerializeAbstractObjectType(u32& rType) { rType = mpStream->ReadLong(); } + + void SerializePrimitive(bool& rValue) { rValue = mpStream->ReadBool(); } + void SerializePrimitive(char& rValue) { rValue = mpStream->ReadByte(); } + void SerializePrimitive(s8& rValue) { rValue = mpStream->ReadByte(); } + void SerializePrimitive(u8& rValue) { rValue = mpStream->ReadByte(); } + void SerializePrimitive(s16& rValue) { rValue = mpStream->ReadShort(); } + void SerializePrimitive(u16& rValue) { rValue = mpStream->ReadShort(); } + void SerializePrimitive(s32& rValue) { rValue = mpStream->ReadLong(); } + void SerializePrimitive(u32& rValue) { rValue = mpStream->ReadLong(); } + void SerializePrimitive(s64& rValue) { rValue = mpStream->ReadLongLong(); } + void SerializePrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); } + void SerializePrimitive(float& rValue) { rValue = mpStream->ReadFloat(); } + void SerializePrimitive(double& rValue) { rValue = mpStream->ReadDouble(); } + void SerializePrimitive(TString& rValue) { rValue = mpStream->ReadSizedString(); } + void SerializePrimitive(CAssetID& rValue) { rValue = CAssetID(*mpStream, Game()); } + + void SerializeHexPrimitive(s8& rValue) { rValue = mpStream->ReadByte(); } + void SerializeHexPrimitive(u8& rValue) { rValue = mpStream->ReadByte(); } + void SerializeHexPrimitive(s16& rValue) { rValue = mpStream->ReadShort(); } + void SerializeHexPrimitive(u16& rValue) { rValue = mpStream->ReadShort(); } + void SerializeHexPrimitive(s32& rValue) { rValue = mpStream->ReadLong(); } + void SerializeHexPrimitive(u32& rValue) { rValue = mpStream->ReadLong(); } + void SerializeHexPrimitive(s64& rValue) { rValue = mpStream->ReadLongLong(); } + void SerializeHexPrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); } +}; + +#endif // CBINARYREADER + diff --git a/src/Common/Serialization/CBinaryWriter.h b/src/Common/Serialization/CBinaryWriter.h new file mode 100644 index 00000000..295eaf0e --- /dev/null +++ b/src/Common/Serialization/CBinaryWriter.h @@ -0,0 +1,123 @@ +#ifndef CBINARYWRITER +#define CBINARYWRITER + +#include "IArchive.h" +#include "Common/CFourCC.h" + +class CBinaryWriter : public IArchive +{ + struct SParameter + { + u32 Offset; + u16 NumSubParams; + }; + std::vector mParamStack; + + IOutputStream *mpStream; + bool mOwnsStream; + +public: + CBinaryWriter(const TString& rkFilename, u32 FileVersion, EGame Game = eUnknownGame) + : IArchive(false, true) + , mOwnsStream(true) + { + mpStream = new CFileOutStream(rkFilename.ToStdString(), IOUtil::eBigEndian); + ASSERT(mpStream->IsValid()); + + mFileVersion = FileVersion; + mGame = Game; + + mpStream->WriteShort((u16) FileVersion); + mpStream->WriteShort((u16) skCurrentArchiveVersion); + GetGameID(Game).Write(*mpStream); + } + + CBinaryWriter(IOutputStream *pStream, u32 FileVersion, EGame Game = eUnknownGame) + : IArchive(false, true) + , mOwnsStream(false) + { + ASSERT(pStream->IsValid()); + mpStream = pStream; + + mFileVersion = FileVersion; + mGame = Game; + + mpStream->WriteShort((u16) FileVersion); + mpStream->WriteShort((u16) skCurrentArchiveVersion); + GetGameID(Game).Write(*mpStream); + } + + ~CBinaryWriter() + { + if (mOwnsStream) delete mpStream; + } + + // Interface + virtual bool ParamBegin(const char *pkName) + { + if (!mParamStack.empty()) + { + mParamStack.back().NumSubParams++; + + if (mParamStack.back().NumSubParams == 1) + mpStream->WriteShort(-1); // Sub-param count filler + } + + mParamStack.push_back( SParameter { mpStream->Tell(), 0 } ); + + u32 ParamID = TString(pkName).Hash32(); + mpStream->WriteLong(ParamID); + mpStream->WriteShort((u16) 0xFFFF); // Param size filler + return true; + } + + virtual void ParamEnd() + { + SParameter& rParam = mParamStack.back(); + u32 StartOffset = rParam.Offset; + u32 EndOffset = mpStream->Tell(); + u16 ParamSize = (EndOffset - StartOffset) - 6; + + mpStream->Seek(StartOffset + 4, SEEK_SET); + mpStream->WriteShort(ParamSize); + if (rParam.NumSubParams > 0) mpStream->WriteShort(rParam.NumSubParams); + mpStream->Seek(EndOffset, SEEK_SET); + mParamStack.pop_back(); + } + + void SerializeContainerSize(u32& rSize) + { + // Normally handled by ParamBegin and ParamEnd but we need to do something here to account for zero-sized containers + if (rSize == 0) + mpStream->WriteShort(0); + } + + void SerializeAbstractObjectType(u32& rType) { mpStream->WriteLong(rType); } + + void SerializePrimitive(bool& rValue) { mpStream->WriteBool(rValue); } + void SerializePrimitive(char& rValue) { mpStream->WriteByte(rValue); } + void SerializePrimitive(s8& rValue) { mpStream->WriteByte(rValue); } + void SerializePrimitive(u8& rValue) { mpStream->WriteByte(rValue); } + void SerializePrimitive(s16& rValue) { mpStream->WriteShort(rValue); } + void SerializePrimitive(u16& rValue) { mpStream->WriteShort(rValue); } + void SerializePrimitive(s32& rValue) { mpStream->WriteLong(rValue); } + void SerializePrimitive(u32& rValue) { mpStream->WriteLong(rValue); } + void SerializePrimitive(s64& rValue) { mpStream->WriteLongLong(rValue); } + void SerializePrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); } + void SerializePrimitive(float& rValue) { mpStream->WriteFloat(rValue); } + void SerializePrimitive(double& rValue) { mpStream->WriteDouble(rValue); } + void SerializePrimitive(TString& rValue) { mpStream->WriteSizedString(rValue.ToStdString()); } + void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream); } + + void SerializeHexPrimitive(s8& rValue) { mpStream->WriteByte(rValue); } + void SerializeHexPrimitive(u8& rValue) { mpStream->WriteByte(rValue); } + void SerializeHexPrimitive(s16& rValue) { mpStream->WriteShort(rValue); } + void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); } + void SerializeHexPrimitive(s32& rValue) { mpStream->WriteLong(rValue); } + void SerializeHexPrimitive(u32& rValue) { mpStream->WriteLong(rValue); } + void SerializeHexPrimitive(s64& rValue) { mpStream->WriteLongLong(rValue); } + void SerializeHexPrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); } +}; + +#endif // CBINARYWRITER + diff --git a/src/Common/Serialization/CXMLReader.h b/src/Common/Serialization/CXMLReader.h index 8b2d8d6e..7dddac7d 100644 --- a/src/Common/Serialization/CXMLReader.h +++ b/src/Common/Serialization/CXMLReader.h @@ -12,7 +12,7 @@ class CXMLReader : public IArchive public: CXMLReader(const TString& rkFileName) - : IArchive() + : IArchive(true, false) , mJustEndedParam(false) { // Load XML and set current element to the root element; read version @@ -26,12 +26,7 @@ public: mGame = pkGameAttr ? GetGameForID( CFourCC(pkGameAttr) ) : eUnknownGame; } -protected: - // Interface Implementation - bool IsReader() const { return true; } - bool IsWriter() const { return false; } - -protected: + // Interface virtual bool ParamBegin(const char *pkName) { // Push new parent if needed @@ -82,6 +77,7 @@ protected: mJustEndedParam = true; } +protected: TString ReadParam() { return TString(mpCurElem->GetText()); diff --git a/src/Common/Serialization/CXMLWriter.h b/src/Common/Serialization/CXMLWriter.h index b467aeeb..e0f46751 100644 --- a/src/Common/Serialization/CXMLWriter.h +++ b/src/Common/Serialization/CXMLWriter.h @@ -14,7 +14,7 @@ class CXMLWriter : public IArchive public: CXMLWriter(const TString& rkFileName, const TString& rkRootName, u32 FileVersion, EGame Game = eUnknownGame) - : IArchive() + : IArchive(false, true) , mOutFilename(rkFileName) { mFileVersion = FileVersion; @@ -38,11 +38,7 @@ public: mDoc.SaveFile(*mOutFilename); } - // Interface Implementation - bool IsReader() const { return false; } - bool IsWriter() const { return true; } - -protected: + // Interface virtual bool ParamBegin(const char *pkName) { tinyxml2::XMLElement *pElem = mDoc.NewElement(pkName); @@ -56,6 +52,7 @@ protected: mpCurElem = mpCurElem->Parent()->ToElement(); } +protected: void WriteParam(const char *pkValue) { mpCurElem->SetText(pkValue); diff --git a/src/Common/Serialization/IArchive.h b/src/Common/Serialization/IArchive.h index 0e995bc5..93cd4469 100644 --- a/src/Common/Serialization/IArchive.h +++ b/src/Common/Serialization/IArchive.h @@ -169,11 +169,20 @@ protected: s32 mFileVersion; s32 mArchiveVersion; EGame mGame; + bool mIsReader; + bool mIsWriter; public: static const u32 skCurrentArchiveVersion = 0; - IArchive() : mFileVersion(0), mArchiveVersion(skCurrentArchiveVersion), mGame(eUnknownGame) {} + IArchive(bool IsReader, bool IsWriter) + : mFileVersion(0) + , mArchiveVersion(skCurrentArchiveVersion) + , mGame(eUnknownGame) + , mIsReader(IsReader) + , mIsWriter(IsWriter) + {} + virtual ~IArchive() {} #define ENABLE_FOR_SERIAL_TYPE(SType) typename std::enable_if::Type == SerialType::##SType, int>::type = 0 @@ -355,14 +364,9 @@ public: } // Interface - virtual bool IsReader() const = 0; - virtual bool IsWriter() const = 0; - -protected: virtual bool ParamBegin(const char *pkName) = 0; virtual void ParamEnd() = 0; -public: virtual void SerializeContainerSize(u32& rSize) = 0; virtual void SerializeAbstractObjectType(u32& rType) = 0; @@ -394,6 +398,8 @@ public: inline u32 FileVersion() const { return mFileVersion; } inline u32 ArchiveVersion() const { return mArchiveVersion; } inline EGame Game() const { return mGame; } + inline bool IsReader() const { return mIsReader; } + inline bool IsWriter() const { return mIsWriter; } }; // Container serialize methods diff --git a/src/Core/GameProject/CResourceIterator.h b/src/Core/GameProject/CResourceIterator.h index fcbbbd6b..ca5a011e 100644 --- a/src/Core/GameProject/CResourceIterator.h +++ b/src/Core/GameProject/CResourceIterator.h @@ -6,6 +6,7 @@ class CResourceIterator { +protected: CResourceStore *mpStore; std::map::iterator mIter; CResourceEntry *mpCurEntry; @@ -19,7 +20,7 @@ public: Next(); } - inline CResourceEntry* Next() + virtual CResourceEntry* Next() { if (mIter != mpStore->mResourceEntries.end()) { @@ -65,5 +66,22 @@ public: } }; +template +class TResourceIterator : public CResourceIterator +{ +public: + TResourceIterator(CResourceStore *pStore = gpResourceStore) + : CResourceIterator(pStore) {} + + virtual CResourceEntry* Next() + { + do { + CResourceIterator::Next(); + } while (mpCurEntry && mpCurEntry->ResourceType() != ResType::StaticType()); + + return mpCurEntry; + } +}; + #endif // CRESOURCEITERATOR diff --git a/src/Core/Resource/TResPtr.h b/src/Core/Resource/TResPtr.h index d427368e..edc8eecd 100644 --- a/src/Core/Resource/TResPtr.h +++ b/src/Core/Resource/TResPtr.h @@ -33,13 +33,10 @@ public: inline void Serialize(IArchive& rArc) { - bool IsReader = rArc.IsReader(); - EGame ActiveGame = gpResourceStore->ActiveProject()->Game(); - - CAssetID ID = (mpRes && !IsReader ? mpRes->ID() : (ActiveGame <= eEchoes ? CAssetID::skInvalidID32 : CAssetID::skInvalidID64)); + CAssetID ID = (mpRes && !rArc.IsReader() ? mpRes->ID() : CAssetID::InvalidID(rArc.Game())); rArc.SerializePrimitive(ID); - if (IsReader) + if (rArc.IsReader()) { CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); *this = (pEntry ? pEntry->Load() : nullptr); diff --git a/src/FileIO/CFileOutStream.cpp b/src/FileIO/CFileOutStream.cpp index e1b4fc2f..e13c4f41 100644 --- a/src/FileIO/CFileOutStream.cpp +++ b/src/FileIO/CFileOutStream.cpp @@ -65,10 +65,10 @@ void CFileOutStream::Close() mSize = 0; } -void CFileOutStream::WriteBytes(void *pSrc, unsigned long Count) +void CFileOutStream::WriteBytes(const void *pkSrc, unsigned long Count) { if (!IsValid()) return; - fwrite(pSrc, 1, Count, mpFStream); + fwrite(pkSrc, 1, Count, mpFStream); if ((unsigned long) Tell() > mSize) mSize = Tell(); } diff --git a/src/FileIO/CFileOutStream.h b/src/FileIO/CFileOutStream.h index 2b407d6f..77356735 100644 --- a/src/FileIO/CFileOutStream.h +++ b/src/FileIO/CFileOutStream.h @@ -21,7 +21,7 @@ public: void Update(const std::string& rkFile, IOUtil::EEndianness FileEndianness); void Close(); - void WriteBytes(void *pSrc, unsigned long Count); + void WriteBytes(const void *pkSrc, unsigned long Count); bool Seek(long Offset, long Origin); bool Seek64(long long Offset, long Origin); long Tell() const; diff --git a/src/FileIO/CMemoryOutStream.cpp b/src/FileIO/CMemoryOutStream.cpp index ea76708b..f8e227ad 100644 --- a/src/FileIO/CMemoryOutStream.cpp +++ b/src/FileIO/CMemoryOutStream.cpp @@ -26,11 +26,11 @@ void CMemoryOutStream::SetData(void *pData, unsigned long Size, IOUtil::EEndiann mDataEndianness = DataEndianness; } -void CMemoryOutStream::WriteBytes(void *pSrc, unsigned long Count) +void CMemoryOutStream::WriteBytes(const void *pkSrc, unsigned long Count) { if (!IsValid()) return; - memcpy(mpDataStart + mPos, pSrc, Count); + memcpy(mpDataStart + mPos, pkSrc, Count); mPos += Count; if (mPos > mUsed) mUsed = mPos; } diff --git a/src/FileIO/CMemoryOutStream.h b/src/FileIO/CMemoryOutStream.h index de7e7cde..991bf267 100644 --- a/src/FileIO/CMemoryOutStream.h +++ b/src/FileIO/CMemoryOutStream.h @@ -16,7 +16,7 @@ public: ~CMemoryOutStream(); void SetData(void *pData, unsigned long Size, IOUtil::EEndianness mDataEndianness); - void WriteBytes(void *pSrc, unsigned long Count); + void WriteBytes(const void *pkSrc, unsigned long Count); bool Seek(long Offset, long Origin); long Tell() const; bool EoF() const; diff --git a/src/FileIO/CVectorOutStream.cpp b/src/FileIO/CVectorOutStream.cpp index 47f2a147..54f26659 100644 --- a/src/FileIO/CVectorOutStream.cpp +++ b/src/FileIO/CVectorOutStream.cpp @@ -41,14 +41,14 @@ CVectorOutStream::~CVectorOutStream() if (mOwnsVector) delete mpVector; } -void CVectorOutStream::WriteBytes(void *pSrc, unsigned long Count) +void CVectorOutStream::WriteBytes(const void *pkSrc, unsigned long Count) { if (!IsValid()) return; if ((mPos + Count) > mpVector->size()) mpVector->resize(mPos + Count); - memcpy(mpVector->data() + mPos, pSrc, Count); + memcpy(mpVector->data() + mPos, pkSrc, Count); mPos += Count; if (mPos > mUsed) mUsed = mPos; } diff --git a/src/FileIO/CVectorOutStream.h b/src/FileIO/CVectorOutStream.h index bfcaef81..f31e8036 100644 --- a/src/FileIO/CVectorOutStream.h +++ b/src/FileIO/CVectorOutStream.h @@ -18,7 +18,7 @@ public: CVectorOutStream(std::vector *pVector, IOUtil::EEndianness DataEndianness); ~CVectorOutStream(); - void WriteBytes(void *pSrc, unsigned long Count); + void WriteBytes(const void *pkSrc, unsigned long Count); bool Seek(long Offset, long Origin); long Tell() const; bool EoF() const; diff --git a/src/FileIO/IInputStream.cpp b/src/FileIO/IInputStream.cpp index b4759e36..750be70f 100644 --- a/src/FileIO/IInputStream.cpp +++ b/src/FileIO/IInputStream.cpp @@ -84,6 +84,14 @@ std::string IInputStream::ReadString(unsigned long Count) return Str; } +std::string IInputStream::ReadSizedString() +{ + unsigned int StringSize = ReadLong(); + std::string Str(StringSize, 0); + ReadBytes(&Str[0], Str.size()); + return Str; +} + std::wstring IInputStream::ReadWString() { std::wstring WStr; @@ -108,6 +116,13 @@ std::wstring IInputStream::ReadWString(unsigned long Count) return WStr; } +std::wstring IInputStream::ReadSizedWString() +{ + unsigned int StringSize = ReadLong(); + std::wstring WStr(StringSize, 0); + ReadBytes(&WStr[0], WStr.size() * 2); + return WStr; +} char IInputStream::PeekByte() { diff --git a/src/FileIO/IInputStream.h b/src/FileIO/IInputStream.h index 1378567f..38c7c5fc 100644 --- a/src/FileIO/IInputStream.h +++ b/src/FileIO/IInputStream.h @@ -21,8 +21,10 @@ public: double ReadDouble(); std::string ReadString(); std::string ReadString(unsigned long Count); + std::string ReadSizedString(); std::wstring ReadWString(); std::wstring ReadWString(unsigned long Count); + std::wstring ReadSizedWString(); char PeekByte(); short PeekShort(); diff --git a/src/FileIO/IOutputStream.cpp b/src/FileIO/IOutputStream.cpp index 56bf5233..4fc177e1 100644 --- a/src/FileIO/IOutputStream.cpp +++ b/src/FileIO/IOutputStream.cpp @@ -63,6 +63,12 @@ void IOutputStream::WriteString(const std::string& rkVal, unsigned long Count, b WriteByte(0); } +void IOutputStream::WriteSizedString(const std::string& rkVal) +{ + WriteLong(rkVal.size()); + WriteBytes(rkVal.data(), rkVal.size()); +} + void IOutputStream::WriteWideString(const std::wstring& rkVal) { for (unsigned int iChr = 0; iChr < rkVal.size(); iChr++) @@ -81,6 +87,12 @@ void IOutputStream::WriteWideString(const std::wstring& rkVal, unsigned long Cou WriteShort(0); } +void IOutputStream::WriteSizedWideString(const std::wstring& rkVal) +{ + WriteLong(rkVal.size()); + WriteBytes(rkVal.data(), rkVal.size() * 2); +} + void IOutputStream::WriteToBoundary(unsigned long Boundary, unsigned char Fill) { long Num = Boundary - (Tell() % Boundary); diff --git a/src/FileIO/IOutputStream.h b/src/FileIO/IOutputStream.h index 67e52e43..826c0881 100644 --- a/src/FileIO/IOutputStream.h +++ b/src/FileIO/IOutputStream.h @@ -20,8 +20,10 @@ public: void WriteDouble(double Val); void WriteString(const std::string& rkVal); void WriteString(const std::string& rkVal, unsigned long Count, bool Terminate = false); + void WriteSizedString(const std::string& rkVal); void WriteWideString(const std::wstring& rkVal); void WriteWideString(const std::wstring& rkVal, unsigned long Count, bool Terminate = false); + void WriteSizedWideString(const std::wstring& rkVal); void WriteToBoundary(unsigned long Boundary, unsigned char Fill); void SetEndianness(IOUtil::EEndianness Endianness); @@ -30,7 +32,7 @@ public: std::string GetDestString() const; virtual ~IOutputStream(); - virtual void WriteBytes(void *pSrc, unsigned long Count) = 0; + virtual void WriteBytes(const void *pkSrc, unsigned long Count) = 0; virtual bool Seek(long Offset, long Origin) = 0; virtual bool Seek64(long long Offset, long Origin); virtual long Tell() const = 0;