#pragma once #include "CKDefines.hpp" #include "CKEnums.hpp" #include #include namespace LibCmo::CK2 { class CKStateChunk { public: //CKStateChunk(); CKStateChunk(CKFileDocument* doc, CKMinContext* ctx); CKStateChunk(const CKStateChunk&); CKStateChunk& operator=(const CKStateChunk&); ~CKStateChunk(); private: enum class CKStateChunkStatus : int32_t { IDLE, READ, WRITE }; CK_CLASSID m_ClassId; CKDWORD m_DataDwSize; CKDWORD* m_pData; CK_STATECHUNK_DATAVERSION m_DataVersion; CK_STATECHUNK_CHUNKVERSION m_ChunkVersion; struct { CKStateChunkStatus m_Status; CKDWORD m_CurrentPos; CKDWORD m_DataSize; CKDWORD m_PrevIdentifierPos; }m_Parser; std::vector m_ObjectList; std::vector m_ChunkList; std::vector m_ManagerList; CKFileDocument* m_BindDoc; CKMinContext* m_BindContext; #pragma region Buffer Related public: bool ConvertFromBuffer(const void* buf); CKDWORD ConvertToBuffer(void* buf); #pragma endregion #pragma region Misc Functions public: //bool UnPack(CKDWORD DestSize); void Clear(void); CKDWORD GetDataSize(void); CK_STATECHUNK_DATAVERSION GetDataVersion(); void SetDataVersion(CK_STATECHUNK_DATAVERSION version); void DeleteBuffer(void* buf); bool Skip(CKDWORD DwordCount); private: size_t GetCeilDwordSize(size_t char_size); bool ResizeBuffer(CKDWORD new_dwsize); bool EnsureWriteSpace(CKDWORD dwsize); bool EnsureReadSpace(CKDWORD dword_required); #pragma endregion #pragma region Read Function public: void StartRead(void); void StopRead(void); /* ========== Identifier Functions ==========*/ bool SeekIdentifierDword(CKDWORD identifier); bool SeekIdentifierDwordAndReturnSize(CKDWORD identifier, CKDWORD* out_size); template inline bool SeekIdentifier(TEnum enum_v) { return SeekIdentifierDword(static_cast(enum_v)); } template inline bool SeekIdentifierAndReturnSize(TEnum enum_v, CKDWORD* out_size) { return SeekIdentifierDwordAndReturnSize(static_cast(enum_v), out_size); } /* ========== Basic Data Read Functions ==========*/ private: /// /// The base read function for all data. /// This function will check all read requirements. /// If you have use this function or functions calling this function. You do not need check any reading requirements anymore /// /// the pointer to data. must be allocated first. /// the size of data in byte. /// bool ReadByteData(void* data_ptr, CKDWORD size_in_byte); public: /// /// Read Struct /// Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc... /// Struct type: ReadGuid, ReadVector, ReadMatrix, etc... /// Both of them are redirected to this. /// /// /// /// template bool ReadStruct(T* data) { return ReadByteData(data, static_cast(sizeof(T))); } /// /// Read Struct /// A wrapper for ReadStructPtr. /// Use reference, not pointer. /// /// /// /// template inline bool ReadStruct(T& data) { return ReadByteData(&data, static_cast(sizeof(T))); } /// /// Read string /// /// /// bool ReadString(std::string* strl); inline bool ReadString(std::string& strl) { return ReadString(&strl); } /* ========== Complex Data Read Functions ==========*/ bool ReadObjectID(CK_ID* id); inline bool ReadObjectID(CK_ID& id) { return ReadObjectID(&id); } bool ReadManagerInt(CKGUID* guid, CKINT* intval); inline bool ReadManagerInt(CKGUID& guid, CKINT& intval) { return ReadManagerInt(&guid, &intval); } /// /// Read sub chunk /// Return nullptr if failed. /// Returned CKStateChunk should be manually released! /// /// /// CKStateChunk* ReadSubChunk(void); /* ========== Buffer Functions ==========*/ /* Buffer related function implements: ReadBuffer(void**) Read Byte based size. -> ReadBuffer ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadNoSizeBuffer ReadAndFillBuffer(void*) Read Byte based size. -> ReadBuffer ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadNoSizeBuffer ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadBuffer ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadNoSizeBuffer ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer */ /// /// Read a buffer with unknow size (order user specific it). /// ReadAndFillBuffer(int, void*), ReadAndFillBuffer_LEndian(int, void*), ReadAndFillBuffer_LEndian16(int, void*) are redirected to this. /// The buffer should be allocated by caller first. /// /// /// /// bool ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf); /// /// Read a buffer with knowen size stored in chunk. /// ReadBuffer(void**), ReadAndFillBuffer(void*), ReadAndFillBuffer_LEndian(void*), ReadAndFillBuffer_LEndian16(void*) are redirected to this. /// The buffer will be allocated by function. /// Use CKStateChunk::DeleteBuffer() to delete it. /// /// a pointer to the pointer receiving data start address. /// a pointer to the variable receiving the length of gotten buffer. /// bool ReadBuffer(void** buf, CKDWORD* len_in_byte); /* ========== Sequence Functions ==========*/ /// /// Read Object ID Sequence /// The combination using of StartReadSequence(), ReadObjectID(), and ReadObject() redirect to this. /// /// /// bool ReadObjectIDSequence(std::vector* ls); inline bool ReadObjectIDSequence(std::vector& ls) { return ReadObjectIDSequence(&ls); } /// /// Read Manager Sequence /// The combination using of StartManagerReadSequence() and ReadManagerIntSequence() redirect to this. /// /// /// /// bool ReadManagerIntSequence(CKGUID* guid, std::vector* ls); inline bool ReadManagerIntSequence(CKGUID& guid, std::vector& ls) { return ReadManagerIntSequence(&guid, &ls); } /// /// Read Sub Chunk Sequence /// The combination using of StartReadSequence() and ReadSubChunk() redirect to this. /// The item of returned CKStateChunk* list should be manually released! /// /// /// bool ReadSubChunkSequence(std::vector* ls); inline bool ReadSubChunkSequence(std::vector& ls) { return ReadSubChunkSequence(&ls); } /// /// Read Object Array (actually still is CK_ID) /// ReadXObjectArray() and ReadObjectArray() redirect to this. /// /// /// bool ReadObjectArray(std::vector* ls); inline bool ReadObjectArray(std::vector& ls) { return ReadObjectArray(&ls); } //int ReadInt(); //int StartReadSequence(); //CK_ID ReadObjectID(); //CKStateChunk* ReadSubChunk(); //int StartManagerReadSequence(CKGUID* guid); //CKGUID ReadGuid(); //void ReadAndFillBuffer_LEndian(void* buffer); //void ReadAndFillBuffer_LEndian16(void* buffer); //float ReadFloat(); //CKWORD ReadWord(); //CKDWORD ReadDword(); //CKDWORD ReadDwordAsWords(); //void ReadVector(VxMath::VxVector* v); //void ReadMatrix(VxMath::VxMatrix& mat); //CKObjectImplements::CKObject* ReadObject(CKMinContext*); //void ReadAndFillBuffer(void* buffer); //CKBYTE* ReadRawBitmap(VxMath::VxImageDescEx& desc); //XObjectArray ReadXObjectArray(void); #pragma endregion #pragma region Write Function public: void StartWrite(); //void WriteIdentifier(CKDWORD id); //void AddChunkAndDelete(CKStateChunk*); //void StartObjectIDSequence(int count); //void WriteObjectSequence(CKObjectImplements::CKObject* obj); //void WriteInt(int data); //void WriteFloat(float data); //void WriteDword(CKDWORD data); //void WriteDwordAsWords(CKDWORD data); //void WriteVector(const VxMath::VxVector* v); //void WriteMatrix(const VxMath::VxMatrix& mat); //void WriteObject(CKObjectImplements::CKObject* obj); //void WriteBuffer_LEndian(int size, void* buf); //void WriteBuffer_LEndian16(int size, void* buf); //void WriteBufferNoSize_LEndian(int size, void* buf); ///*void UpdateDataSize();*/ //void* LockWriteBuffer(int DwordCount); /* * Old Name: CloseChunk(); */ void StopWrite(void); #pragma endregion }; }