libcmo21/LibCmo/CK2/CKStateChunk.hpp

370 lines
11 KiB
C++
Raw Normal View History

2023-02-25 17:39:39 +08:00
#pragma once
2023-08-25 21:57:22 +08:00
#include "../VTAll.hpp"
2023-09-11 22:20:45 +08:00
#include <memory>
#include <functional>
2023-02-25 17:39:39 +08:00
2023-02-26 21:48:03 +08:00
namespace LibCmo::CK2 {
2023-02-25 17:39:39 +08:00
struct ChunkProfile {
CK_CLASSID m_ClassId;
CKDWORD m_DataDwSize;
CKDWORD* m_pData;
CK_STATECHUNK_DATAVERSION m_DataVersion;
CK_STATECHUNK_CHUNKVERSION m_ChunkVersion;
size_t m_ObjectListSize, m_ChunkListSize, m_ManagerListSize;
CKFileVisitor* m_BindFile;
CKContext* m_BindContext;
};
2023-08-27 22:14:02 +08:00
struct IdentifierProfile {
CKDWORD m_Identifier;
void* m_DataPtr;
CKDWORD m_AreaSize;
};
2023-02-25 17:39:39 +08:00
class CKStateChunk {
public:
//CKStateChunk();
2023-08-25 21:57:22 +08:00
CKStateChunk(CKFileVisitor* visitor, CKContext* ctx);
2023-02-26 13:57:32 +08:00
CKStateChunk(const CKStateChunk&);
2023-08-25 21:57:22 +08:00
CKStateChunk(CKStateChunk&&);
2023-02-26 13:57:32 +08:00
CKStateChunk& operator=(const CKStateChunk&);
CKStateChunk& operator=(CKStateChunk&&);
2023-02-25 17:39:39 +08:00
~CKStateChunk();
private:
2023-02-26 13:57:32 +08:00
enum class CKStateChunkStatus : int32_t {
IDLE,
READ,
WRITE
};
struct ChunkParser {
CKStateChunkStatus m_Status;
CKDWORD m_CurrentPos;
CKDWORD m_DataSize;
CKDWORD m_PrevIdentifierPos;
};
2023-02-26 13:57:32 +08:00
2023-02-25 17:39:39 +08:00
CK_CLASSID m_ClassId;
CKDWORD m_DataDwSize;
CKDWORD* m_pData;
CK_STATECHUNK_DATAVERSION m_DataVersion;
CK_STATECHUNK_CHUNKVERSION m_ChunkVersion;
ChunkParser m_Parser;
2023-02-25 17:39:39 +08:00
XContainer::XArray<CKDWORD> m_ObjectList;
XContainer::XArray<CKDWORD> m_ChunkList;
XContainer::XArray<CKDWORD> m_ManagerList;
2023-02-25 17:39:39 +08:00
2023-08-25 21:57:22 +08:00
CKFileVisitor* m_BindFile;
CKContext* m_BindContext;
2023-03-05 22:31:11 +08:00
#pragma region Buffer Related
2023-02-27 15:16:04 +08:00
public:
bool ConvertFromBuffer(const void* buf);
2023-02-27 15:16:04 +08:00
CKDWORD ConvertToBuffer(void* buf);
2023-03-05 22:31:11 +08:00
#pragma endregion
#pragma region Misc Functions
public:
2023-08-29 10:42:13 +08:00
const ChunkProfile GetStateChunkProfile();
2023-02-27 15:16:04 +08:00
//bool UnPack(CKDWORD DestSize);
void Clear(void);
CKDWORD GetDataSize(void);
CK_STATECHUNK_DATAVERSION GetDataVersion();
void SetDataVersion(CK_STATECHUNK_DATAVERSION version);
bool Skip(CKDWORD DwordCount);
2023-03-05 22:31:11 +08:00
private:
CKDWORD GetCeilDwordSize(size_t char_size);
2023-09-11 22:20:45 +08:00
void* GetCurrentPointer();
2023-03-05 22:31:11 +08:00
bool ResizeBuffer(CKDWORD new_dwsize);
bool EnsureWriteSpace(CKDWORD dwsize);
bool EnsureReadSpace(CKDWORD dword_required);
#pragma endregion
2023-02-27 15:16:04 +08:00
#pragma region Read Function
public:
void StartRead(void);
2023-03-05 22:31:11 +08:00
void StopRead(void);
/* ========== Identifier Functions ==========*/
2023-02-28 14:04:38 +08:00
bool SeekIdentifierDword(CKDWORD identifier);
bool SeekIdentifierDwordAndReturnSize(CKDWORD identifier, CKDWORD* out_size);
template<typename TEnum>
inline bool SeekIdentifier(TEnum enum_v) {
return SeekIdentifierDword(static_cast<CKDWORD>(enum_v));
}
template<typename TEnum>
inline bool SeekIdentifierAndReturnSize(TEnum enum_v, CKDWORD* out_size) {
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
}
2023-08-29 10:42:13 +08:00
const XContainer::XArray<IdentifierProfile> GetIdentifierProfile();
2023-02-28 14:04:38 +08:00
2023-03-05 22:31:11 +08:00
/* ========== Basic Data Read Functions ==========*/
2023-02-27 15:16:04 +08:00
2023-03-05 22:31:11 +08:00
private:
2023-09-01 13:27:46 +08:00
/**
* @brief 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.
* @param data_ptr[out] the pointer to data. must be allocated first.
* @param size_in_byte[in] the size of data in byte.
* @return True if success.
*/
2023-03-05 22:31:11 +08:00
bool ReadByteData(void* data_ptr, CKDWORD size_in_byte);
public:
/// <summary>
/// Read Struct
/// <para>Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc...</para>
/// <para>Struct type: ReadGuid, ReadVector, ReadMatrix, etc...</para>
/// <para>Both of them are redirected to this.</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <returns></returns>
template<typename T>
bool ReadStruct(T* data) {
return ReadByteData(data, CKSizeof(T));
2023-02-27 15:16:04 +08:00
}
2023-03-05 22:31:11 +08:00
/// <summary>
/// Read Struct
/// <para>A wrapper for ReadStructPtr.</para>
/// <para>Use reference, not pointer.</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <returns></returns>
2023-02-27 15:16:04 +08:00
template<typename T>
2023-03-05 22:31:11 +08:00
inline bool ReadStruct(T& data) {
return ReadByteData(&data, CKSizeof(T));
2023-03-05 22:31:11 +08:00
}
/// <summary>
2023-09-10 21:33:43 +08:00
/// Read string. The content of string will automatically converted into UTF8 format.
2023-03-05 22:31:11 +08:00
/// </summary>
/// <param name="strl"></param>
/// <returns></returns>
2023-09-16 18:31:25 +08:00
bool ReadString(XContainer::XString* strl);
inline bool ReadString(XContainer::XString& strl) {
2023-03-05 22:31:11 +08:00
return ReadString(&strl);
2023-02-26 13:57:32 +08:00
}
2023-02-28 14:04:38 +08:00
2023-03-08 10:56:43 +08:00
/* ========== 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);
}
/// <summary>
/// Read sub chunk
/// <para>Return nullptr if failed.</para>
/// <para>Returned CKStateChunk should be manually released!</para>
/// </summary>
/// <param name=""></param>
/// <returns></returns>
CKStateChunk* ReadSubChunk(void);
2023-03-05 22:31:11 +08:00
/* ========== Buffer Functions ==========*/
2023-02-27 15:16:04 +08:00
2023-03-05 22:31:11 +08:00
/*
Buffer related function implements:
2023-03-08 10:56:43 +08:00
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
2023-03-05 22:31:11 +08:00
*/
2023-09-11 22:20:45 +08:00
/**
* @brief The deleter for std::unique_ptr of CKStateChunk created buffer.
*/
struct BufferDeleter {
BufferDeleter() = default;
BufferDeleter(const BufferDeleter&) noexcept {}
void operator()(void* buf);
};
/**
* @brief The type of CKStateChunk auto free buffer.
*/
using TBuffer = std::unique_ptr<void, BufferDeleter>;
2023-03-05 22:31:11 +08:00
/// <summary>
/// Read a buffer with unknow size (order user specific it).
/// <para>ReadAndFillBuffer(int, void*), ReadAndFillBuffer_LEndian(int, void*), ReadAndFillBuffer_LEndian16(int, void*) are redirected to this.</para>
/// <para>The buffer should be allocated by caller first.</para>
/// </summary>
/// <param name="size"></param>
/// <param name="allocatedBuf"></param>
/// <returns></returns>
bool ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf);
/// <summary>
/// Read a buffer with knowen size stored in chunk.
/// <para>ReadBuffer(void**), ReadAndFillBuffer(void*), ReadAndFillBuffer_LEndian(void*), ReadAndFillBuffer_LEndian16(void*) are redirected to this.</para>
/// <para>The buffer will be allocated by function.</para>
/// <para>Use CKStateChunk::DeleteBuffer() to delete it.</para>
/// </summary>
/// <param name="buf">a pointer to the pointer receiving data start address.</param>
/// <param name="len">a pointer to the variable receiving the length of gotten buffer.</param>
/// <returns></returns>
bool ReadBuffer(void** buf, CKDWORD* len_in_byte);
2023-09-11 22:20:45 +08:00
/**
* @brief A auto free wrapper for ReadBuffer
* @param uptr The pointer to unique_ptr receiving data.
* @param len_in_byte The size of gotten buffer.
* @return
*/
bool ReadBufferWrapper(TBuffer* uptr, CKDWORD* len_in_byte);
/**
* @brief Perform a dry buffer reading.
* This function will only make sure there is enough space for your reading.
* And return the start memory address to you.
* And will not create any extra memory like ReadBuffer.
* @param buf[out] a pointer to the pointer receiving data start address.
* @param ordered_sizepin] your expected length of this buffer.
* @return
*/
bool ReadDryBuffer(const void** buf, CKDWORD ordered_size);
/**
* @brief Free the buffer allocated by CKStateChunk reading functions.
* @param buf The buffer need to be free.
*/
void DeleteBuffer(const void* buf);
2023-03-05 22:31:11 +08:00
/* ========== Sequence Functions ==========*/
2023-02-27 15:16:04 +08:00
2023-03-08 10:56:43 +08:00
/// <summary>
/// Read Object ID Sequence
/// <para>The combination using of StartReadSequence(), ReadObjectID(), and ReadObject() redirect to this.</para>
/// </summary>
/// <param name="ls"></param>
/// <returns></returns>
2023-09-01 13:27:46 +08:00
bool ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls);
inline bool ReadObjectIDSequence(XContainer::XArray<CK_ID>& ls) {
2023-03-08 10:56:43 +08:00
return ReadObjectIDSequence(&ls);
}
/// <summary>
/// Read Manager Sequence
/// <para>The combination using of StartManagerReadSequence() and ReadManagerIntSequence() redirect to this.</para>
/// </summary>
/// <param name="guid"></param>
/// <param name="ls"></param>
/// <returns></returns>
2023-09-01 13:27:46 +08:00
bool ReadManagerIntSequence(CKGUID* guid, XContainer::XArray<CKINT>* ls);
inline bool ReadManagerIntSequence(CKGUID& guid, XContainer::XArray<CKINT>& ls) {
2023-03-08 10:56:43 +08:00
return ReadManagerIntSequence(&guid, &ls);
}
/// <summary>
/// Read Sub Chunk Sequence
/// <para>The combination using of StartReadSequence() and ReadSubChunk() redirect to this.</para>
/// <para>The item of returned CKStateChunk* list should be manually released!</para>
/// </summary>
/// <param name="ls"></param>
/// <returns></returns>
2023-09-01 13:27:46 +08:00
bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls);
inline bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>& ls) {
2023-03-08 10:56:43 +08:00
return ReadSubChunkSequence(&ls);
}
2023-09-01 13:27:46 +08:00
/**
* @brief Read Object Array (actually still is CK_ID)
* @remark ReadObjectArray() and XObjectArray::Load redirect to this.
* @param ls The list
* @return True if success.
*/
bool ReadXObjectArray(XContainer::XObjectArray* ls);
inline bool ReadXObjectArray(XContainer::XObjectArray& ls) {
return ReadXObjectArray(&ls);
}
/**
* @brief Read Object Array (actually is CKObject*)
* @remark ReadXObjectArray() and XObjectPointerArray::Load redirect to this.
* @param ls The list
* @return True if success
*/
bool ReadXObjectPointerArray(XContainer::XObjectPointerArray* ls);
inline bool ReadXObjectPointerArray(XContainer::XObjectPointerArray& ls) {
return ReadXObjectPointerArray(&ls);
2023-03-08 10:56:43 +08:00
}
2023-02-27 15:16:04 +08:00
//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
2023-02-25 17:39:39 +08:00
};
}