write other CKStateChunk writer and remove sub chunk function
This commit is contained in:
parent
3e265cdf1d
commit
6870fca911
@ -326,7 +326,7 @@ namespace LibCmo::CK2 {
|
||||
|
||||
CKDWORD CKFileVisitor::GetIndexByObjectID(CK_ID objid) {
|
||||
// see CKFile::SaveFindObjectIndex in IDA
|
||||
CKDWORD idx = -1;
|
||||
CKDWORD idx = static_cast<CKDWORD>(-1);
|
||||
if (m_IsReader) return idx;
|
||||
|
||||
auto finder = m_Writer->m_ObjectsHashTable.find(objid);
|
||||
|
@ -232,6 +232,29 @@ namespace LibCmo::CK2 {
|
||||
*/
|
||||
bool EnsureReadSpace(CKDWORD dword_required);
|
||||
|
||||
/**
|
||||
* @brief The helper writer of m_ObjectList, m_ManagerList and m_ChunkList.
|
||||
*
|
||||
* Add a position indicator into list which represent a single data.
|
||||
*
|
||||
* @param entry_ls[in] The list to be written.
|
||||
* @param pos[int] The written position data.
|
||||
* @remark:
|
||||
* + IntList::AddEntry() redirect to this.
|
||||
*/
|
||||
void AddEntry(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos);
|
||||
/**
|
||||
* @brief The helper writer of m_ObjectList, m_ManagerList and m_ChunkList.
|
||||
*
|
||||
* Add a position indicator into list which represent a series of data.
|
||||
*
|
||||
* @param entry_ls[in] The list to be written.
|
||||
* @param pos[int] The written position data.
|
||||
* @remark:
|
||||
* + IntList::AddEntries() redirect to this.
|
||||
*/
|
||||
void AddEntries(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Read Function
|
||||
@ -368,12 +391,12 @@ namespace LibCmo::CK2 {
|
||||
return ReadManagerInt(&guid, &intval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read sub chunk
|
||||
* @return Returned a new created of CKStateChunk if success, otherwise nullptr.
|
||||
* Returned CKStateChunk should be manually released!
|
||||
*/
|
||||
CKStateChunk* ReadSubChunk();
|
||||
///**
|
||||
// * @brief Read sub chunk
|
||||
// * @return Returned a new created of CKStateChunk if success, otherwise nullptr.
|
||||
// * Returned CKStateChunk should be manually released!
|
||||
//*/
|
||||
//CKStateChunk* ReadSubChunk();
|
||||
|
||||
/* ========== Buffer Functions ==========*/
|
||||
|
||||
@ -480,17 +503,17 @@ namespace LibCmo::CK2 {
|
||||
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>
|
||||
bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls);
|
||||
inline bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>& ls) {
|
||||
return ReadSubChunkSequence(&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>
|
||||
//bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls);
|
||||
//inline bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>& ls) {
|
||||
// return ReadSubChunkSequence(&ls);
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief Read Object Array (actually still is CK_ID)
|
||||
@ -601,7 +624,7 @@ namespace LibCmo::CK2 {
|
||||
|
||||
public:
|
||||
bool WriteObjectIDSequence(const XContainer::XObjectArray* ls);
|
||||
inline bool ReadObjectIDSequence(const XContainer::XObjectArray& ls) {
|
||||
inline bool WriteObjectIDSequence(const XContainer::XObjectArray& ls) {
|
||||
return WriteObjectIDSequence(&ls);
|
||||
}
|
||||
|
||||
|
@ -303,6 +303,14 @@ namespace LibCmo::CK2 {
|
||||
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
|
||||
}
|
||||
|
||||
void CKStateChunk::AddEntry(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos) {
|
||||
entry_ls.emplace_back(pos);
|
||||
}
|
||||
|
||||
void CKStateChunk::AddEntries(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos) {
|
||||
entry_ls.emplace_back(static_cast<CKDWORD>(-1));
|
||||
entry_ls.emplace_back(pos);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
@ -205,98 +205,98 @@ namespace LibCmo::CK2 {
|
||||
return true;
|
||||
}
|
||||
|
||||
CKStateChunk* CKStateChunk::ReadSubChunk(void) {
|
||||
CKStateChunk* subchunk = nullptr;
|
||||
//CKStateChunk* CKStateChunk::ReadSubChunk(void) {
|
||||
// CKStateChunk* subchunk = nullptr;
|
||||
|
||||
// get size and do a enough space check
|
||||
CKDWORD subDwordChunkSize;
|
||||
if (!this->ReadStruct(subDwordChunkSize)) goto subchunk_defer;
|
||||
if (!this->EnsureReadSpace(subDwordChunkSize)) goto subchunk_defer;
|
||||
// // get size and do a enough space check
|
||||
// CKDWORD subDwordChunkSize;
|
||||
// if (!this->ReadStruct(subDwordChunkSize)) goto subchunk_defer;
|
||||
// if (!this->EnsureReadSpace(subDwordChunkSize)) goto subchunk_defer;
|
||||
|
||||
// create statechunk
|
||||
subchunk = new CKStateChunk(this->m_BindFile, this->m_BindContext);
|
||||
// // create statechunk
|
||||
// subchunk = new CKStateChunk(this->m_BindFile, this->m_BindContext);
|
||||
|
||||
// start read data
|
||||
// read class id
|
||||
if (!this->ReadStruct(subchunk->m_ClassId)) goto subchunk_defer;
|
||||
// // start read data
|
||||
// // read class id
|
||||
// if (!this->ReadStruct(subchunk->m_ClassId)) goto subchunk_defer;
|
||||
|
||||
// different read strategy by chunk version
|
||||
if (this->m_ChunkVersion >= CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
|
||||
// new file
|
||||
// // different read strategy by chunk version
|
||||
// if (this->m_ChunkVersion >= CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
|
||||
// // new file
|
||||
|
||||
// read combined version
|
||||
CKDWORD versionInfo;
|
||||
if (!this->ReadStruct(versionInfo)) goto subchunk_defer;
|
||||
subchunk->m_DataVersion = static_cast<CK_STATECHUNK_DATAVERSION>(versionInfo & 0xffff);
|
||||
subchunk->m_ChunkVersion = static_cast<CK_STATECHUNK_CHUNKVERSION>((versionInfo >> 16) & 0xffff);
|
||||
// // read combined version
|
||||
// CKDWORD versionInfo;
|
||||
// if (!this->ReadStruct(versionInfo)) goto subchunk_defer;
|
||||
// subchunk->m_DataVersion = static_cast<CK_STATECHUNK_DATAVERSION>(versionInfo & 0xffff);
|
||||
// subchunk->m_ChunkVersion = static_cast<CK_STATECHUNK_CHUNKVERSION>((versionInfo >> 16) & 0xffff);
|
||||
|
||||
// read data size and create it
|
||||
if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
|
||||
subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
|
||||
// // read data size and create it
|
||||
// if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
|
||||
// subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
|
||||
|
||||
// has bind file?
|
||||
CKDWORD hasBindFile;
|
||||
if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
|
||||
if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
|
||||
// // has bind file?
|
||||
// CKDWORD hasBindFile;
|
||||
// if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
|
||||
// if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
|
||||
|
||||
// 3 list size
|
||||
// manager only existed when ver > 4
|
||||
CKDWORD lssize;
|
||||
if (!this->ReadStruct(lssize)) goto subchunk_defer;
|
||||
subchunk->m_ObjectList.resize(lssize);
|
||||
if (!this->ReadStruct(lssize)) goto subchunk_defer;
|
||||
subchunk->m_ChunkList.resize(lssize);
|
||||
if (this->m_ChunkVersion > CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
|
||||
if (!this->ReadStruct(lssize)) goto subchunk_defer;
|
||||
subchunk->m_ManagerList.resize(lssize);
|
||||
}
|
||||
// // 3 list size
|
||||
// // manager only existed when ver > 4
|
||||
// CKDWORD lssize;
|
||||
// if (!this->ReadStruct(lssize)) goto subchunk_defer;
|
||||
// subchunk->m_ObjectList.resize(lssize);
|
||||
// if (!this->ReadStruct(lssize)) goto subchunk_defer;
|
||||
// subchunk->m_ChunkList.resize(lssize);
|
||||
// if (this->m_ChunkVersion > CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
|
||||
// if (!this->ReadStruct(lssize)) goto subchunk_defer;
|
||||
// subchunk->m_ManagerList.resize(lssize);
|
||||
// }
|
||||
|
||||
// core data
|
||||
if (subchunk->m_DataDwSize != 0) {
|
||||
if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
|
||||
}
|
||||
// // core data
|
||||
// if (subchunk->m_DataDwSize != 0) {
|
||||
// if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
|
||||
// }
|
||||
|
||||
// 3 list data
|
||||
if (!subchunk->m_ObjectList.empty()) {
|
||||
if (!this->ReadByteData(
|
||||
subchunk->m_ObjectList.data(),
|
||||
static_cast<CKDWORD>(subchunk->m_ObjectList.size()) * CKSizeof(CKDWORD)
|
||||
)) goto subchunk_defer;
|
||||
}
|
||||
if (!subchunk->m_ChunkList.empty()) {
|
||||
if (!this->ReadByteData(
|
||||
subchunk->m_ChunkList.data(),
|
||||
static_cast<CKDWORD>(subchunk->m_ChunkList.size()) * CKSizeof(CKDWORD)
|
||||
)) goto subchunk_defer;
|
||||
}
|
||||
if (!subchunk->m_ManagerList.empty()) {
|
||||
if (!this->ReadByteData(
|
||||
subchunk->m_ManagerList.data(),
|
||||
static_cast<CKDWORD>(subchunk->m_ManagerList.size()) * CKSizeof(CKDWORD)
|
||||
)) goto subchunk_defer;
|
||||
}
|
||||
// // 3 list data
|
||||
// if (!subchunk->m_ObjectList.empty()) {
|
||||
// if (!this->ReadByteData(
|
||||
// subchunk->m_ObjectList.data(),
|
||||
// static_cast<CKDWORD>(subchunk->m_ObjectList.size()) * CKSizeof(CKDWORD)
|
||||
// )) goto subchunk_defer;
|
||||
// }
|
||||
// if (!subchunk->m_ChunkList.empty()) {
|
||||
// if (!this->ReadByteData(
|
||||
// subchunk->m_ChunkList.data(),
|
||||
// static_cast<CKDWORD>(subchunk->m_ChunkList.size()) * CKSizeof(CKDWORD)
|
||||
// )) goto subchunk_defer;
|
||||
// }
|
||||
// if (!subchunk->m_ManagerList.empty()) {
|
||||
// if (!this->ReadByteData(
|
||||
// subchunk->m_ManagerList.data(),
|
||||
// static_cast<CKDWORD>(subchunk->m_ManagerList.size()) * CKSizeof(CKDWORD)
|
||||
// )) goto subchunk_defer;
|
||||
// }
|
||||
|
||||
} else {
|
||||
// old file
|
||||
// } else {
|
||||
// // old file
|
||||
|
||||
// read data size and create it
|
||||
if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
|
||||
subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
|
||||
// // read data size and create it
|
||||
// if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
|
||||
// subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
|
||||
|
||||
// skip one?
|
||||
// I don't know why
|
||||
this->Skip(1u);
|
||||
// // skip one?
|
||||
// // I don't know why
|
||||
// this->Skip(1u);
|
||||
|
||||
// read core buf
|
||||
if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
|
||||
// // read core buf
|
||||
// if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
return subchunk;
|
||||
subchunk_defer:
|
||||
if (subchunk != nullptr) delete subchunk;
|
||||
return nullptr;
|
||||
}
|
||||
// return subchunk;
|
||||
//subchunk_defer:
|
||||
// if (subchunk != nullptr) delete subchunk;
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
/* ========== Buffer Functions ==========*/
|
||||
|
||||
@ -427,38 +427,38 @@ namespace LibCmo::CK2 {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKStateChunk::ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls) {
|
||||
if (ls == nullptr) return false;
|
||||
//bool CKStateChunk::ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls) {
|
||||
// if (ls == nullptr) return false;
|
||||
|
||||
// clear first
|
||||
for (auto& item : *ls) {
|
||||
if (item != nullptr)
|
||||
delete (item);
|
||||
}
|
||||
ls->clear();
|
||||
// // clear first
|
||||
// for (auto& item : *ls) {
|
||||
// if (item != nullptr)
|
||||
// delete (item);
|
||||
// }
|
||||
// ls->clear();
|
||||
|
||||
// read count
|
||||
CKDWORD count;
|
||||
if (!this->ReadStruct(count)) return false;
|
||||
// // read count
|
||||
// CKDWORD count;
|
||||
// if (!this->ReadStruct(count)) return false;
|
||||
|
||||
// resize list and read it
|
||||
ls->resize(count, nullptr);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
(*ls)[i] = this->ReadSubChunk();
|
||||
if ((*ls)[i] == nullptr) {
|
||||
// fail. remove all created statechunk and clear it
|
||||
for (auto& item : *ls) {
|
||||
if (item != nullptr)
|
||||
delete (item);
|
||||
}
|
||||
ls->clear();
|
||||
// return
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// // resize list and read it
|
||||
// ls->resize(count, nullptr);
|
||||
// for (size_t i = 0; i < count; ++i) {
|
||||
// (*ls)[i] = this->ReadSubChunk();
|
||||
// if ((*ls)[i] == nullptr) {
|
||||
// // fail. remove all created statechunk and clear it
|
||||
// for (auto& item : *ls) {
|
||||
// if (item != nullptr)
|
||||
// delete (item);
|
||||
// }
|
||||
// ls->clear();
|
||||
// // return
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
// return true;
|
||||
//}
|
||||
|
||||
bool CKStateChunk::ReadXObjectArray(XContainer::XObjectArray* ls) {
|
||||
if (ls == nullptr) return false;
|
||||
|
@ -3,6 +3,22 @@
|
||||
#include "CKContext.hpp"
|
||||
#include "ObjImpls/CKObject.hpp"
|
||||
|
||||
/*
|
||||
Memorandum:
|
||||
|
||||
No need to write any data in m_ObjectList when writing Object ID.
|
||||
Because m_ObjectList only need to be written in when no bind CKFile
|
||||
according to IDA reversed code.
|
||||
However we assuem all CKStateChunk have bind file so no need to treat it.
|
||||
|
||||
However, m_ManagerList should be filled when writing Manager Int.
|
||||
This is also instructed by IDA revsersed code.
|
||||
|
||||
For m_ChunkList, it is same as m_ManagerList. We need write it.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
void CKStateChunk::StartWrite() {
|
||||
@ -129,7 +145,7 @@ namespace LibCmo::CK2 {
|
||||
}
|
||||
|
||||
bool CKStateChunk::WriteString(const XContainer::XString* strl) {
|
||||
if (strl == nullptr) return;
|
||||
if (strl == nullptr) return false;
|
||||
|
||||
// convert encoding
|
||||
XContainer::XString cache;
|
||||
@ -156,17 +172,15 @@ namespace LibCmo::CK2 {
|
||||
}
|
||||
|
||||
bool CKStateChunk::WriteObjectPointer(ObjImpls::CKObject* obj) {
|
||||
CK_ID objid;
|
||||
if (obj != nullptr) {
|
||||
objid = obj->GetID();
|
||||
}
|
||||
CK_ID objid = 0;
|
||||
if (obj != nullptr) objid = obj->GetID();
|
||||
|
||||
return WriteObjectID(objid);
|
||||
}
|
||||
|
||||
bool CKStateChunk::WriteManagerInt(const CKGUID* guid, CKINT intval) {
|
||||
// push into manager list
|
||||
m_ManagerList.emplace_back(m_Parser.m_CurrentPos);
|
||||
AddEntry(m_ManagerList, m_Parser.m_CurrentPos);
|
||||
// write data
|
||||
if (!this->WriteStruct(guid)) return false;
|
||||
if (!this->WriteStruct(intval)) return false;
|
||||
@ -207,19 +221,63 @@ namespace LibCmo::CK2 {
|
||||
/* ========== Sequence Functions ==========*/
|
||||
|
||||
bool CKStateChunk::WriteObjectIDSequence(const XContainer::XObjectArray* ls) {
|
||||
return false;
|
||||
if (ls == nullptr) return false;
|
||||
|
||||
// MARK: there is a recording oper for object list when no bind file.
|
||||
// but we always have bind file, so ignore it
|
||||
|
||||
// write size first
|
||||
CKDWORD objidsize = static_cast<CKDWORD>(ls->size());
|
||||
if (!this->WriteStruct(objidsize)) return false;
|
||||
|
||||
// write each data
|
||||
for (auto objid : *ls) {
|
||||
// MARK: originally we should not call WriteObjectID like ReadObjectIDSequence.
|
||||
// because we do not write position data in obj list for each item.
|
||||
// even if bind file always is not nullptr.
|
||||
if (!this->WriteStruct(m_BindFile->GetIndexByObjectID(objid))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKStateChunk::WriteManagerIntSequence(const CKGUID* guid, const XContainer::XArray<CKINT>* ls) {
|
||||
return false;
|
||||
if (guid == nullptr || ls == nullptr) return false;
|
||||
|
||||
// add current pos into manager list
|
||||
AddEntries(m_ManagerList, m_Parser.m_CurrentPos);
|
||||
|
||||
// write data length
|
||||
CKDWORD lssize = static_cast<CKDWORD>(ls->size());
|
||||
if (!this->WriteStruct(lssize)) return false;
|
||||
// write guid
|
||||
if (!this->WriteStruct(guid)) return false;
|
||||
|
||||
// then write each items
|
||||
for (auto iv : *ls) {
|
||||
// MARK: we should not call WriteManagerInt like ReadManagerIntSequence.
|
||||
// because we do not want to write postion info into manager list for each item.
|
||||
if (!this->WriteStruct(iv)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKStateChunk::WriteXObjectArray(const XContainer::XObjectArray* ls) {
|
||||
return false;
|
||||
// same as WriteObjectIDSequence.
|
||||
return WriteObjectIDSequence(ls);
|
||||
}
|
||||
|
||||
bool CKStateChunk::WriteXObjectPointerArray(const XContainer::XObjectPointerArray* ls) {
|
||||
return false;
|
||||
if (ls == nullptr) return false;
|
||||
|
||||
XContainer::XObjectArray conv;
|
||||
for (auto obj : *ls) {
|
||||
if (obj == nullptr) conv.emplace_back(0);
|
||||
else conv.emplace_back(obj->GetID());
|
||||
}
|
||||
|
||||
return WriteObjectIDSequence(conv);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user