write CKStateChunk
This commit is contained in:
parent
5a69ce338e
commit
bf0fca756b
@ -387,16 +387,16 @@ namespace LibCmo::CK2 {
|
|||||||
// todo: special treat for CK_LEVEL
|
// todo: special treat for CK_LEVEL
|
||||||
// try parsing data
|
// try parsing data
|
||||||
obj.Data->StartRead();
|
obj.Data->StartRead();
|
||||||
err = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
bool success = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
||||||
obj.Data->StopRead();
|
obj.Data->StopRead();
|
||||||
if (err != CKERROR::CKERR_OK) {
|
if (success) {
|
||||||
// if failed, delete it
|
|
||||||
m_MinCtx->DestroyCKObject(obj.ObjectId);
|
|
||||||
obj.ObjPtr = nullptr;
|
|
||||||
} else {
|
|
||||||
// if success, clear CKStateChunk*
|
// if success, clear CKStateChunk*
|
||||||
delete obj.Data;
|
delete obj.Data;
|
||||||
obj.Data = nullptr;
|
obj.Data = nullptr;
|
||||||
|
} else {
|
||||||
|
// if failed, delete it
|
||||||
|
m_MinCtx->DestroyCKObject(obj.ObjectId);
|
||||||
|
obj.ObjPtr = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ namespace LibCmo::CK2::CKObjectImplements {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKObject::Load(CKStateChunk* chunk, const CKFileDocument* doc) {
|
bool CKObject::Load(CKStateChunk* chunk, const CKFileDocument* doc) {
|
||||||
if (chunk->SeekIdentifier(Identifiers::CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
|
if (chunk->SeekIdentifier(Identifiers::CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
|
||||||
EnumsHelper::FlagEnumRm(this->m_ObjectFlags,
|
EnumsHelper::FlagEnumRm(this->m_ObjectFlags,
|
||||||
{ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE,
|
{ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE,
|
||||||
@ -43,7 +43,7 @@ namespace LibCmo::CK2::CKObjectImplements {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CKERROR::CKERR_OK;
|
return true;
|
||||||
}
|
}
|
||||||
CKStateChunk* CKObject::Save(const CKFileDocument* doc) {
|
CKStateChunk* CKObject::Save(const CKFileDocument* doc) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -25,7 +25,7 @@ namespace LibCmo::CK2::CKObjectImplements {
|
|||||||
void SetObjectFlags(CK_OBJECT_FLAGS flags) { this->m_ObjectFlags = flags; }
|
void SetObjectFlags(CK_OBJECT_FLAGS flags) { this->m_ObjectFlags = flags; }
|
||||||
|
|
||||||
virtual CK_CLASSID GetClassID(void) { return CK_CLASSID::CKCID_OBJECT; }
|
virtual CK_CLASSID GetClassID(void) { return CK_CLASSID::CKCID_OBJECT; }
|
||||||
virtual CKERROR Load(CKStateChunk* chunk, const CKFileDocument* doc);
|
virtual bool Load(CKStateChunk* chunk, const CKFileDocument* doc);
|
||||||
virtual CKStateChunk* Save(const CKFileDocument* doc);
|
virtual CKStateChunk* Save(const CKFileDocument* doc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,9 +91,37 @@ namespace LibCmo::CK2 {
|
|||||||
this->m_DataVersion = version;
|
this->m_DataVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKStateChunk::EnsureReadSpace(CKDWORD dword_required) {
|
void CKStateChunk::DeleteBuffer(void* buf) {
|
||||||
return (m_Parser.m_Status == CKStateChunkStatus::READ) &&
|
if (buf == nullptr) return;
|
||||||
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
|
delete[] reinterpret_cast<char*>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::Skip(CKDWORD DwordCount) {
|
||||||
|
bool result;
|
||||||
|
switch (this->m_Parser.m_Status) {
|
||||||
|
case CKStateChunkStatus::READ:
|
||||||
|
result = EnsureReadSpace(DwordCount);
|
||||||
|
break;
|
||||||
|
case CKStateChunkStatus::WRITE:
|
||||||
|
result = EnsureWriteSpace(DwordCount);
|
||||||
|
break;
|
||||||
|
case CKStateChunkStatus::IDLE:
|
||||||
|
default:
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if success, move cursor
|
||||||
|
if (result) {
|
||||||
|
this->m_Parser.m_CurrentPos += DwordCount;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t CKStateChunk::GetCeilDwordSize(size_t char_size) {
|
||||||
|
return (char_size + 3) >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKStateChunk::ResizeBuffer(CKDWORD new_dwsize) {
|
bool CKStateChunk::ResizeBuffer(CKDWORD new_dwsize) {
|
||||||
@ -141,26 +169,9 @@ namespace LibCmo::CK2 {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKStateChunk::Skip(CKDWORD DwordCount) {
|
bool CKStateChunk::EnsureReadSpace(CKDWORD dword_required) {
|
||||||
bool result;
|
return (m_Parser.m_Status == CKStateChunkStatus::READ) &&
|
||||||
switch (this->m_Parser.m_Status) {
|
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
|
||||||
case CKStateChunkStatus::READ:
|
|
||||||
result = EnsureReadSpace(DwordCount);
|
|
||||||
break;
|
|
||||||
case CKStateChunkStatus::WRITE:
|
|
||||||
result = EnsureWriteSpace(DwordCount);
|
|
||||||
break;
|
|
||||||
case CKStateChunkStatus::IDLE:
|
|
||||||
default:
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if success, move cursor
|
|
||||||
if (result) {
|
|
||||||
this->m_Parser.m_CurrentPos += DwordCount;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -344,6 +355,17 @@ namespace LibCmo::CK2 {
|
|||||||
this->m_Parser.m_Status = CKStateChunkStatus::READ;
|
this->m_Parser.m_Status = CKStateChunkStatus::READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::StopRead(void) {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return;
|
||||||
|
|
||||||
|
this->m_Parser.m_CurrentPos = 0u;
|
||||||
|
this->m_Parser.m_DataSize = this->m_DataDwSize;
|
||||||
|
this->m_Parser.m_PrevIdentifierPos = 0u;
|
||||||
|
this->m_Parser.m_Status = CKStateChunkStatus::IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Identifier Functions ==========*/
|
||||||
|
|
||||||
bool CKStateChunk::SeekIdentifierDword(CKDWORD identifier) {
|
bool CKStateChunk::SeekIdentifierDword(CKDWORD identifier) {
|
||||||
CKDWORD cache;
|
CKDWORD cache;
|
||||||
return SeekIdentifierDwordAndReturnSize(identifier, &cache);
|
return SeekIdentifierDwordAndReturnSize(identifier, &cache);
|
||||||
@ -376,38 +398,74 @@ namespace LibCmo::CK2 {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKStateChunk::ReadString(std::string& strl) {
|
/* ========== Basic Data Read Functions ==========*/
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadByteData(void* data_ptr, CKDWORD size_in_byte) {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
||||||
|
if (data_ptr == nullptr) return false;
|
||||||
|
|
||||||
|
CKDWORD size_in_dword = this->GetCeilDwordSize(size_in_byte);
|
||||||
|
if (this->EnsureReadSpace(size_in_dword)) {
|
||||||
|
std::memcpy(data_ptr, this->m_pData + this->m_Parser.m_CurrentPos, size_in_byte);
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadString(std::string* strl) {
|
||||||
|
if (strl == nullptr) return false;
|
||||||
|
|
||||||
// get byte based size
|
// get byte based size
|
||||||
CKDWORD strByteSize = 0u;
|
CKDWORD strByteSize = 0u;
|
||||||
CKERROR err = this->ReadStructPtr(&strByteSize);
|
if (!this->ReadStruct(strByteSize)) {
|
||||||
if (err != CKERROR::CKERR_OK) {
|
strl->clear();
|
||||||
strl.clear();
|
return false;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert to DWORD based
|
// read data
|
||||||
CKDWORD strDwordSize = this->GetCeilDwordSize(strByteSize);
|
strl->resize(strByteSize);
|
||||||
|
if (!this->ReadByteData(strl->data(), strByteSize)) {
|
||||||
// cp
|
strl->clear();
|
||||||
if (this->EnsureReadSpace(strDwordSize)) {
|
return false;
|
||||||
strl.resize(strByteSize);
|
}
|
||||||
std::memcpy(strl.data(), this->m_pData + this->m_Parser.m_CurrentPos, strByteSize);
|
return true;
|
||||||
this->m_Parser.m_CurrentPos += strDwordSize;
|
|
||||||
} else strl.clear();
|
|
||||||
|
|
||||||
return CKERROR::CKERR_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf) {
|
||||||
void CKStateChunk::StopRead(void) {
|
if (allocatedBuf == nullptr) return false;
|
||||||
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return;
|
return this->ReadByteData(allocatedBuf, size_in_byte);
|
||||||
|
|
||||||
this->m_Parser.m_CurrentPos = 0u;
|
|
||||||
this->m_Parser.m_DataSize = this->m_DataDwSize;
|
|
||||||
this->m_Parser.m_PrevIdentifierPos = 0u;
|
|
||||||
this->m_Parser.m_Status = CKStateChunkStatus::IDLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadBuffer(void** buf, CKDWORD* len_in_byte) {
|
||||||
|
if (buf == nullptr || len_in_byte == nullptr) return false;
|
||||||
|
|
||||||
|
// get buffer size.
|
||||||
|
CKDWORD bufByteSize = 0u;
|
||||||
|
if (!this->ReadStruct(bufByteSize)) {
|
||||||
|
*buf = nullptr;
|
||||||
|
*len_in_byte = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*len_in_byte = bufByteSize;
|
||||||
|
|
||||||
|
// create buffer
|
||||||
|
*buf = new(std::nothrow) char[bufByteSize];
|
||||||
|
if (*buf == nullptr) {
|
||||||
|
*len_in_byte = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data
|
||||||
|
if (!this->ReadByteData(*buf, bufByteSize)) {
|
||||||
|
this->DeleteBuffer(*buf);
|
||||||
|
*buf = nullptr;
|
||||||
|
*len_in_byte = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,29 +39,42 @@ namespace LibCmo::CK2 {
|
|||||||
std::vector<CKDWORD> m_ChunkList;
|
std::vector<CKDWORD> m_ChunkList;
|
||||||
std::vector<CKDWORD> m_ManagerList;
|
std::vector<CKDWORD> m_ManagerList;
|
||||||
|
|
||||||
private:
|
#pragma region Buffer Related
|
||||||
inline size_t GetCeilDwordSize(size_t char_size) {
|
|
||||||
return (char_size + 3) >> 3;
|
|
||||||
}
|
|
||||||
bool ResizeBuffer(CKDWORD new_dwsize);
|
|
||||||
bool EnsureWriteSpace(CKDWORD dwsize);
|
|
||||||
bool EnsureReadSpace(CKDWORD dword_required);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool ConvertFromBuffer(const void* buf);
|
bool ConvertFromBuffer(const void* buf);
|
||||||
CKDWORD ConvertToBuffer(void* buf);
|
CKDWORD ConvertToBuffer(void* buf);
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Misc Functions
|
||||||
|
|
||||||
|
public:
|
||||||
//bool UnPack(CKDWORD DestSize);
|
//bool UnPack(CKDWORD DestSize);
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
CKDWORD GetDataSize(void);
|
CKDWORD GetDataSize(void);
|
||||||
CK_STATECHUNK_DATAVERSION GetDataVersion();
|
CK_STATECHUNK_DATAVERSION GetDataVersion();
|
||||||
void SetDataVersion(CK_STATECHUNK_DATAVERSION version);
|
void SetDataVersion(CK_STATECHUNK_DATAVERSION version);
|
||||||
|
void DeleteBuffer(void* buf);
|
||||||
bool Skip(CKDWORD DwordCount);
|
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
|
#pragma region Read Function
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void StartRead(void);
|
void StartRead(void);
|
||||||
|
void StopRead(void);
|
||||||
|
|
||||||
|
/* ========== Identifier Functions ==========*/
|
||||||
|
|
||||||
bool SeekIdentifierDword(CKDWORD identifier);
|
bool SeekIdentifierDword(CKDWORD identifier);
|
||||||
bool SeekIdentifierDwordAndReturnSize(CKDWORD identifier, CKDWORD* out_size);
|
bool SeekIdentifierDwordAndReturnSize(CKDWORD identifier, CKDWORD* out_size);
|
||||||
template<typename TEnum>
|
template<typename TEnum>
|
||||||
@ -73,44 +86,90 @@ namespace LibCmo::CK2 {
|
|||||||
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
|
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* ========== Basic Data Read Functions ==========*/
|
||||||
* Read Struct
|
|
||||||
Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc...
|
private:
|
||||||
Struct type: ReadGuid, ReadVector, ReadMatrix, etc...
|
/// <summary>
|
||||||
Both of them are redirected to this.
|
/// The base read function for all data.
|
||||||
*/
|
/// <para>This function will check all read requirements.</para>
|
||||||
|
/// <para>If you have use this function or functions calling this function. You do not need check any reading requirements anymore</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data_ptr">the pointer to data. must be allocated first.</param>
|
||||||
|
/// <param name="size_in_byte">the size of data in byte.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
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>
|
template<typename T>
|
||||||
CKERROR ReadStructPtr(T* data) {
|
bool ReadStruct(T* data) {
|
||||||
size_t size = GetCeilDwordSize(sizeof(T));
|
return ReadByteData(data, static_cast<CKDWORD>(sizeof(T)));
|
||||||
if (EnsureReadSpace(static_cast<CKDWORD>(size))) {
|
|
||||||
std::memcpy(data, this->m_pData + this->m_Parser.m_CurrentPos, size);
|
|
||||||
|
|
||||||
} else return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
return CKERROR::CKERR_OK;
|
|
||||||
}
|
}
|
||||||
/*
|
/// <summary>
|
||||||
* Read Struct
|
/// Read Struct
|
||||||
A wrapper for ReadStructPtr.
|
/// <para>A wrapper for ReadStructPtr.</para>
|
||||||
Use reference, not pointer.
|
/// <para>Use reference, not pointer.</para>
|
||||||
*/
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline CKERROR ReadStructRef(T& data) {
|
inline bool ReadStruct(T& data) {
|
||||||
return ReadStructPtr(&data);
|
return ReadByteData(&data, static_cast<CKDWORD>(sizeof(T)));
|
||||||
}
|
}
|
||||||
///*
|
|
||||||
//* Read Enum Data
|
|
||||||
//A wrapper for ReadStructPtr.
|
|
||||||
//All Enum read redirect to this.
|
|
||||||
//*/
|
|
||||||
//template<typename T>
|
|
||||||
//inline CKERROR ReadEnum(T& data) {
|
|
||||||
// return ReadStructPtr(reinterpret_cast<std::underlying_type_t<T>*>(&data));
|
|
||||||
//}
|
|
||||||
|
|
||||||
CKERROR ReadString(std::string& strl);
|
/// <summary>
|
||||||
|
/// Read string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="strl"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool ReadString(std::string* strl);
|
||||||
|
inline bool ReadString(std::string& strl) {
|
||||||
|
return ReadString(&strl);
|
||||||
|
}
|
||||||
|
|
||||||
CKERROR ReadBuffer(void* allocatedBuf);
|
/* ========== Buffer Functions ==========*/
|
||||||
CKERROR ReadNoSizeBuffer(CKDWORD size, void* allocatedBuf);
|
|
||||||
|
/*
|
||||||
|
Buffer related function implements:
|
||||||
|
|
||||||
|
ReadBuffer(void**) Read Byte based size.
|
||||||
|
ReadAndFillBuffer(int, void*) User give Byte based size.
|
||||||
|
ReadAndFillBuffer(void*) Read Byte based size.
|
||||||
|
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size.
|
||||||
|
ReadAndFillBuffer_LEndian(void*) Read Byte based size.
|
||||||
|
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size.
|
||||||
|
ReadAndFillBuffer_LEndian16(void*) Read Byte based size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <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);
|
||||||
|
|
||||||
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
//int ReadInt();
|
//int ReadInt();
|
||||||
//int StartReadSequence();
|
//int StartReadSequence();
|
||||||
@ -130,7 +189,6 @@ namespace LibCmo::CK2 {
|
|||||||
//void ReadAndFillBuffer(void* buffer);
|
//void ReadAndFillBuffer(void* buffer);
|
||||||
//CKBYTE* ReadRawBitmap(VxMath::VxImageDescEx& desc);
|
//CKBYTE* ReadRawBitmap(VxMath::VxImageDescEx& desc);
|
||||||
//XObjectArray ReadXObjectArray(void);
|
//XObjectArray ReadXObjectArray(void);
|
||||||
void StopRead(void);
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user