write CKStateChunk
This commit is contained in:
parent
5a69ce338e
commit
bf0fca756b
@ -387,16 +387,16 @@ namespace LibCmo::CK2 {
|
||||
// todo: special treat for CK_LEVEL
|
||||
// try parsing data
|
||||
obj.Data->StartRead();
|
||||
err = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
||||
bool success = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
||||
obj.Data->StopRead();
|
||||
if (err != CKERROR::CKERR_OK) {
|
||||
// if failed, delete it
|
||||
m_MinCtx->DestroyCKObject(obj.ObjectId);
|
||||
obj.ObjPtr = nullptr;
|
||||
} else {
|
||||
if (success) {
|
||||
// if success, clear CKStateChunk*
|
||||
delete obj.Data;
|
||||
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)) {
|
||||
EnumsHelper::FlagEnumRm(this->m_ObjectFlags,
|
||||
{ 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) {
|
||||
return nullptr;
|
||||
|
@ -25,7 +25,7 @@ namespace LibCmo::CK2::CKObjectImplements {
|
||||
void SetObjectFlags(CK_OBJECT_FLAGS flags) { this->m_ObjectFlags = flags; }
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -91,9 +91,37 @@ namespace LibCmo::CK2 {
|
||||
this->m_DataVersion = version;
|
||||
}
|
||||
|
||||
bool CKStateChunk::EnsureReadSpace(CKDWORD dword_required) {
|
||||
return (m_Parser.m_Status == CKStateChunkStatus::READ) &&
|
||||
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
|
||||
void CKStateChunk::DeleteBuffer(void* buf) {
|
||||
if (buf == nullptr) return;
|
||||
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) {
|
||||
@ -141,26 +169,9 @@ namespace LibCmo::CK2 {
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
bool CKStateChunk::EnsureReadSpace(CKDWORD dword_required) {
|
||||
return (m_Parser.m_Status == CKStateChunkStatus::READ) &&
|
||||
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
|
||||
}
|
||||
|
||||
|
||||
@ -344,6 +355,17 @@ namespace LibCmo::CK2 {
|
||||
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) {
|
||||
CKDWORD cache;
|
||||
return SeekIdentifierDwordAndReturnSize(identifier, &cache);
|
||||
@ -376,38 +398,74 @@ namespace LibCmo::CK2 {
|
||||
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
|
||||
CKDWORD strByteSize = 0u;
|
||||
CKERROR err = this->ReadStructPtr(&strByteSize);
|
||||
if (err != CKERROR::CKERR_OK) {
|
||||
strl.clear();
|
||||
return err;
|
||||
if (!this->ReadStruct(strByteSize)) {
|
||||
strl->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert to DWORD based
|
||||
CKDWORD strDwordSize = this->GetCeilDwordSize(strByteSize);
|
||||
|
||||
// cp
|
||||
if (this->EnsureReadSpace(strDwordSize)) {
|
||||
strl.resize(strByteSize);
|
||||
std::memcpy(strl.data(), this->m_pData + this->m_Parser.m_CurrentPos, strByteSize);
|
||||
this->m_Parser.m_CurrentPos += strDwordSize;
|
||||
} else strl.clear();
|
||||
|
||||
return CKERROR::CKERR_OK;
|
||||
// read data
|
||||
strl->resize(strByteSize);
|
||||
if (!this->ReadByteData(strl->data(), strByteSize)) {
|
||||
strl->clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
bool CKStateChunk::ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf) {
|
||||
if (allocatedBuf == nullptr) return false;
|
||||
return this->ReadByteData(allocatedBuf, size_in_byte);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -39,29 +39,42 @@ namespace LibCmo::CK2 {
|
||||
std::vector<CKDWORD> m_ChunkList;
|
||||
std::vector<CKDWORD> m_ManagerList;
|
||||
|
||||
private:
|
||||
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);
|
||||
#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<typename TEnum>
|
||||
@ -73,44 +86,90 @@ namespace LibCmo::CK2 {
|
||||
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read Struct
|
||||
Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc...
|
||||
Struct type: ReadGuid, ReadVector, ReadMatrix, etc...
|
||||
Both of them are redirected to this.
|
||||
*/
|
||||
/* ========== Basic Data Read Functions ==========*/
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// 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>
|
||||
CKERROR ReadStructPtr(T* data) {
|
||||
size_t size = GetCeilDwordSize(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;
|
||||
bool ReadStruct(T* data) {
|
||||
return ReadByteData(data, static_cast<CKDWORD>(sizeof(T)));
|
||||
}
|
||||
/*
|
||||
* Read Struct
|
||||
A wrapper for ReadStructPtr.
|
||||
Use reference, not pointer.
|
||||
*/
|
||||
/// <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>
|
||||
template<typename T>
|
||||
inline CKERROR ReadStructRef(T& data) {
|
||||
return ReadStructPtr(&data);
|
||||
inline bool ReadStruct(T& 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);
|
||||
CKERROR ReadNoSizeBuffer(CKDWORD size, void* allocatedBuf);
|
||||
/* ========== Buffer Functions ==========*/
|
||||
|
||||
/*
|
||||
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 StartReadSequence();
|
||||
@ -130,7 +189,6 @@ namespace LibCmo::CK2 {
|
||||
//void ReadAndFillBuffer(void* buffer);
|
||||
//CKBYTE* ReadRawBitmap(VxMath::VxImageDescEx& desc);
|
||||
//XObjectArray ReadXObjectArray(void);
|
||||
void StopRead(void);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user