diff --git a/LibCmo/CK2/CKContext.cpp b/LibCmo/CK2/CKContext.cpp index ab9244a..ad9751c 100644 --- a/LibCmo/CK2/CKContext.cpp +++ b/LibCmo/CK2/CKContext.cpp @@ -93,10 +93,47 @@ namespace LibCmo::CK2 { #pragma endregion +#pragma region Common Manager Functions + + CKINT CKContext::GetManagerCount() { + return 0; + } + + MgrImpls::CKBaseManager* CKContext::GetManager(int index) { + return nullptr; + } + +#pragma endregion + +#pragma region File Save/Load Options + + void CKContext::SetCompressionLevel(CKINT level) { + if (level > 0 && level < 10) { + m_CompressionLevel = level; + } + } + + CKINT CKContext::GetCompressionLevel() { + return m_CompressionLevel; + } + + void CKContext::SetFileWriteMode(CK_FILE_WRITEMODE mode) { + m_FileWriteMode = mode; + } + + CK_FILE_WRITEMODE CKContext::GetFileWriteMode() { + return m_FileWriteMode; + } + + +#pragma endregion + + #pragma region Ctor Dtor CKContext::CKContext() : m_ObjectsList(), m_ReturnedObjectIds(), + m_CompressionLevel(5), m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED), m_NameEncoding(), m_TempFolder(), m_OutputCallback(nullptr) { diff --git a/LibCmo/CK2/CKContext.hpp b/LibCmo/CK2/CKContext.hpp index ba3bc9c..af932a9 100644 --- a/LibCmo/CK2/CKContext.hpp +++ b/LibCmo/CK2/CKContext.hpp @@ -57,6 +57,19 @@ namespace LibCmo::CK2 { //CKINT GetObjectsCountByClassID(CK_CLASSID cid); //CK_ID* GetObjectsListByClassID(CK_CLASSID cid); + // ========== Common Managers Functions ========== + + CKINT GetManagerCount(); + MgrImpls::CKBaseManager* GetManager(int index); + + // ========== File Save/Load Options ========== + + void SetCompressionLevel(CKINT level); + CKINT GetCompressionLevel(); + + void SetFileWriteMode(CK_FILE_WRITEMODE mode); + CK_FILE_WRITEMODE GetFileWriteMode(); + // ========== Encoding utilities ========== void GetUtf8String(const std::string& native_name, std::string& u8_name); @@ -81,6 +94,10 @@ namespace LibCmo::CK2 { XContainer::XArray m_ObjectsList; std::deque m_ReturnedObjectIds; + // ========== File Save/Load Options ========== + CKINT m_CompressionLevel; + CK_FILE_WRITEMODE m_FileWriteMode; + // ========== Encoding utilities ========== std::vector m_NameEncoding; diff --git a/LibCmo/CK2/CKFile.hpp b/LibCmo/CK2/CKFile.hpp index eb0bcda..d8ea959 100644 --- a/LibCmo/CK2/CKFile.hpp +++ b/LibCmo/CK2/CKFile.hpp @@ -17,12 +17,26 @@ namespace LibCmo::CK2 { size_t m_MemSize; public: + /** + * @brief Create CKBufferParser from a existed buffer. + * @param ptr The start pointer of buffer. This buffer should be allocated by 'new[]', not 'new' or 'malloc()'. + * @param rsize The size of buffer. + * @param need_manual_free True if provided buffer need freed by CKBufferParser automatically. + */ CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) : m_MemBegin(static_cast(ptr)), m_MemPos(0u), m_MemSize(rsize), - m_NeedManualFree(need_manual_free) { - ; - } + m_NeedManualFree(need_manual_free) + {} + /** + * @brief Create CKBufferParser from a new created buffer. + * @param newsize The size of new buffer. + */ + CKBufferParser(size_t newsize) : + m_MemBegin(new char[newsize]), + m_MemPos(0u), m_MemSize(newsize), + m_NeedManualFree(true) + {} ~CKBufferParser() { if (this->m_NeedManualFree) delete[](this->m_MemBegin); } @@ -209,6 +223,22 @@ namespace LibCmo::CK2 { CKERROR Save(CKSTRING u8_filename); protected: + CKBOOL m_Done; + /** + * True if this writer is copy from reader. + * The data copied from reader mean that calling just only do some small modification. + * So we don't need try getting some managers or save file options from CKContext. + * Just apply the data coming from reader. + * Also, Add object functions is not allowed when writer copying from reader. + */ + CKBOOL m_IsCopyFromReader; + + XContainer::XArray m_FileObjects; /**< List of objects being saved / loaded */ + XContainer::XArray m_ManagersData; /**< Manager Data loaded */ + XContainer::XArray m_PluginsDep; /**< Plugins dependencies for this file */ + XContainer::XArray m_IncludedFiles; /**< List of files that should be inserted in the CMO file. */ + CKFileInfo m_FileInfo; /**< Headers summary */ + CKContext* m_Ctx; CKFileVisitor m_Visitor; }; diff --git a/LibCmo/CK2/CKFileOthers.cpp b/LibCmo/CK2/CKFileOthers.cpp index 14a34dc..b0bcc22 100644 --- a/LibCmo/CK2/CKFileOthers.cpp +++ b/LibCmo/CK2/CKFileOthers.cpp @@ -13,12 +13,12 @@ namespace LibCmo::CK2 { CKFileObject::CKFileObject() : ObjectId(0u), CreatedObjectId(0u), ObjectCid(CK_CLASSID::CKCID_OBJECT), ObjPtr(nullptr), Name(), Data(nullptr), Options(CK_FO_OPTIONS::CK_FO_DEFAULT), - FileIndex(0u), SaveFlags(0u) {} + FileIndex(0u), SaveFlags(CK_STATESAVE_ALL) {} CKFileObject::CKFileObject(const CKFileObject& rhs) : ObjectId(rhs.ObjectId), CreatedObjectId(rhs.CreatedObjectId), ObjectCid(rhs.ObjectCid), ObjPtr(rhs.ObjPtr), Name(rhs.Name), Data(rhs.Data), Options(rhs.Options), - FileIndex(rhs.FileIndex), SaveFlags(0u) { + FileIndex(rhs.FileIndex), SaveFlags(rhs.SaveFlags) { if (this->Data != nullptr) { this->Data = new CKStateChunk(*(rhs.Data)); } @@ -27,7 +27,7 @@ namespace LibCmo::CK2 { CKFileObject::CKFileObject(CKFileObject&& rhs) : ObjectId(rhs.ObjectId), CreatedObjectId(rhs.CreatedObjectId), ObjectCid(rhs.ObjectCid), ObjPtr(rhs.ObjPtr), Name(rhs.Name), Data(rhs.Data), Options(rhs.Options), - FileIndex(rhs.FileIndex), SaveFlags(0u) { + FileIndex(rhs.FileIndex), SaveFlags(rhs.SaveFlags) { rhs.Data = nullptr; } @@ -158,22 +158,81 @@ namespace LibCmo::CK2 { #pragma region CKFileWriter CKFileWriter::CKFileWriter(CKContext* ctx) : - m_Ctx(ctx), m_Visitor(this) {} + m_Ctx(ctx), m_Visitor(this), + m_Done(false), m_IsCopyFromReader(false), + m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(), + m_FileInfo() + {} CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader) : - m_Ctx(ctx), m_Visitor(this) {} + m_Ctx(ctx), m_Visitor(this), + m_Done(false), m_IsCopyFromReader(true), + m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(), + m_FileInfo() + { + // copy objects + for (const auto& item : reader->GetFileObjects()) { + CKFileObject obj; + // copy CKObject pointer + obj.ObjPtr = item.ObjPtr; + // and use ctor to copy CKStateChunk + if (item.Data == nullptr) { + obj.Data = nullptr; + } else { + obj.Data = new CKStateChunk(*item.Data); + } + + // copy save flag + obj.SaveFlags = item.SaveFlags; + + // insert + m_FileObjects.emplace_back(std::move(obj)); + } + + // copy managers + for (const auto& item : reader->GetManagersData()) { + CKFileManagerData mgr; + // copy guid + mgr.Manager = item.Manager; + // copy chunk + if (item.Data == nullptr) { + mgr.Data = nullptr; + } else { + mgr.Data = new CKStateChunk(*item.Data); + } + + // insert + m_ManagersData.emplace_back(std::move(mgr)); + } + + // copy plugin dep + for (const auto& item : reader->GetPluginsDep()) { + // direct copy + m_PluginsDep.emplace_back(item); + } + + // copy included file + for (const auto& item : reader->GetIncludedFiles()) { + // direct copy + m_IncludedFiles.emplace_back(item); + } + + } CKFileWriter::~CKFileWriter() {} CKBOOL CKFileWriter::AddSavedObject(ObjImpls::CKObject* obj, CKDWORD flags) { + if (m_Done || m_IsCopyFromReader) return CKFALSE; return CKFALSE; } CKBOOL CKFileWriter::AddSavedObjects(CKObjectArray* objarray, CKDWORD flags) { + if (m_Done || m_IsCopyFromReader) return CKFALSE; return CKFALSE; } CKBOOL CKFileWriter::AddSavedFile(CKSTRING u8FileName) { + if (m_Done || m_IsCopyFromReader) return CKFALSE; return CKFALSE; } diff --git a/LibCmo/CK2/CKGlobals.cpp b/LibCmo/CK2/CKGlobals.cpp index 7086e49..87409de 100644 --- a/LibCmo/CK2/CKGlobals.cpp +++ b/LibCmo/CK2/CKGlobals.cpp @@ -155,11 +155,12 @@ namespace LibCmo::CK2 { CKBOOL CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) { // get corresponding index first + // if we can't find it, return false anyway. auto finder = g_CKClassInfoId2Idx.find(child); - if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID."); + if (finder == g_CKClassInfoId2Idx.end()) return CKFALSE; size_t child_idx = finder->second; finder = g_CKClassInfoId2Idx.find(parent); - if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID."); + if (finder == g_CKClassInfoId2Idx.end()) return CKFALSE; size_t parent_idx = finder->second; return g_CKClassInfo[child_idx].Parents[parent_idx]; diff --git a/LibCmo/VTUtils.hpp b/LibCmo/VTUtils.hpp index 86b12ae..d750cbf 100644 --- a/LibCmo/VTUtils.hpp +++ b/LibCmo/VTUtils.hpp @@ -119,6 +119,11 @@ namespace LibCmo { const char* c_str() const { return m_HasStr ? m_Str.c_str() : nullptr; } + + const size_t size() const { + return m_HasStr ? m_Str.size() : 0u; + } + private: bool m_HasStr; std::string m_Str;