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
2023-08-28 09:46:57 +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 :
2023-03-08 15:45:06 +08:00
//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 & ) ;
2023-08-26 16:37:26 +08:00
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
} ;
2023-08-26 16:37:26 +08:00
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 ;
2023-08-26 16:37:26 +08:00
ChunkParser m_Parser ;
2023-02-25 17:39:39 +08:00
2023-08-29 14:00:34 +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-08 15:45:06 +08:00
2023-03-05 22:31:11 +08:00
# pragma region Buffer Related
2023-02-27 15:16:04 +08:00
public :
2023-08-29 14:00:34 +08:00
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 :
2023-08-29 14:00:34 +08:00
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 ) {
2023-08-29 14:00:34 +08:00
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 ) {
2023-08-29 14:00:34 +08:00
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
} ;
}