From c8c2c6e20bba14d4bc90550cf1ef504424456efc Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 25 Aug 2023 17:35:45 +0800 Subject: [PATCH] write shit --- LibCmo/CK2/CKContext.cpp | 3 + LibCmo/CK2/CKFile.cpp | 188 ---------------- LibCmo/CK2/CKFile.hpp | 202 ++++++++++-------- LibCmo/CK2/CKFileOthers.cpp | 150 +++++++++++++ LibCmo/CK2/CKFileReader.cpp | 9 +- LibCmo/CK2/CKFileWriter.cpp | 2 +- .../CK2/CKManagerImplements/CKBaseManager.cpp | 34 ++- .../CK2/CKManagerImplements/CKBaseManager.hpp | 109 ++++++++-- LibCmo/CK2/CKObjectImplements/CKObject.hpp | 16 +- LibCmo/LibCmo.vcxproj | 2 +- LibCmo/LibCmo.vcxproj.filters | 2 +- LibCmo/VTUtils.cpp | 3 - LibCmo/VTUtils.hpp | 110 +++++++--- LibCmo/XContainer/XTypes.hpp | 53 +---- 14 files changed, 472 insertions(+), 411 deletions(-) delete mode 100644 LibCmo/CK2/CKFile.cpp create mode 100644 LibCmo/CK2/CKFileOthers.cpp diff --git a/LibCmo/CK2/CKContext.cpp b/LibCmo/CK2/CKContext.cpp index 7339096..c52e727 100644 --- a/LibCmo/CK2/CKContext.cpp +++ b/LibCmo/CK2/CKContext.cpp @@ -38,6 +38,9 @@ namespace LibCmo::CK2 { // put into slot m_ObjectsList[decided_id] = obj; + + // set out variable + return obj; } CKObject* CKContext::GetCKObject(CK_ID id) { diff --git a/LibCmo/CK2/CKFile.cpp b/LibCmo/CK2/CKFile.cpp deleted file mode 100644 index ef36785..0000000 --- a/LibCmo/CK2/CKFile.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "CKFile.hpp" -#include "CKStateChunk.hpp" -#include "CKMinContext.hpp" -#include - -namespace LibCmo::CK2 { - -#pragma region CKBufferParser - - CKBufferParser::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) { - ; - } - CKBufferParser::~CKBufferParser() { - if (this->m_NeedManualFree) delete[](this->m_MemBegin); - } - -#pragma endregion - -#pragma region CKFileInfo - - CKFileInfo::CKFileInfo() : - ProductVersion(0u), ProductBuild(0x01010000u), FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED), - FileVersion(8u), CKVersion(CKVERSION), FileSize(0u), - ObjectCount(0u), ManagerCount(0u), MaxIDSaved(0u), Crc(0u), - Hdr1PackSize(0u), Hdr1UnPackSize(0u), DataPackSize(0u), DataUnPackSize(0u) { - } - - CKFileInfo::CKFileInfo(const CKFileInfo& rhs) : - ProductVersion(rhs.ProductVersion), ProductBuild(rhs.ProductBuild), FileWriteMode(rhs.FileWriteMode), - FileVersion(rhs.FileVersion), CKVersion(rhs.CKVersion), FileSize(rhs.FileSize), - ObjectCount(rhs.ObjectCount), ManagerCount(rhs.ManagerCount), MaxIDSaved(rhs.MaxIDSaved), Crc(rhs.Crc), - Hdr1PackSize(rhs.Hdr1PackSize), Hdr1UnPackSize(rhs.Hdr1UnPackSize), - DataPackSize(rhs.DataPackSize), DataUnPackSize(rhs.DataUnPackSize) { - } - - CKFileInfo& CKFileInfo::operator=(const CKFileInfo& rhs) { - this->ProductVersion = rhs.ProductVersion; - this->ProductBuild = rhs.ProductBuild; - this->FileWriteMode = rhs.FileWriteMode; - this->FileVersion = rhs.FileVersion; - this->CKVersion = rhs.CKVersion; - this->FileSize = rhs.FileSize; - this->ObjectCount = rhs.ObjectCount; - this->ManagerCount = rhs.ManagerCount; - this->MaxIDSaved = rhs.MaxIDSaved; - this->Crc = rhs.Crc; - this->Hdr1PackSize = rhs.Hdr1PackSize; - this->Hdr1UnPackSize = rhs.Hdr1UnPackSize; - this->DataPackSize = rhs.DataPackSize; - this->DataUnPackSize = rhs.DataUnPackSize; - - return *this; - } - - CKFileInfo::~CKFileInfo() { - } - -#pragma endregion - -#pragma region CKFileObject - - CKFileObject::CKFileObject() : - ObjectId(0u), CreatedObject(0u), ObjectCid(CK_CLASSID::CKCID_OBJECT), Name(), - ObjPtr(nullptr), Data(nullptr), FileIndex(0u) { - } - - CKFileObject::CKFileObject(const CKFileObject& rhs) : - ObjectId(rhs.ObjectId), CreatedObject(rhs.CreatedObject), ObjectCid(rhs.ObjectCid), Name(rhs.Name), - ObjPtr(rhs.ObjPtr), Data(rhs.Data), FileIndex(rhs.FileIndex) { - - // CKObject is managed by CKMinContext, so we just copy its pointer. - // however, we need copy CKStateChunk. - if (this->Data != nullptr) { - this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data)); - } - - } - - CKFileObject& CKFileObject::operator=(const CKFileObject& rhs) { - this->ObjectId = rhs.ObjectId; - this->CreatedObject = rhs.CreatedObject; - this->ObjectCid = rhs.ObjectCid; - this->Name = rhs.Name; - this->FileIndex = rhs.FileIndex; - - // CKObject is managed by CKMinContext, so we just copy its pointer. - this->ObjPtr = rhs.ObjPtr; - - // however, we need copy CKStateChunk. - this->Data = rhs.Data; - if (this->Data != nullptr) { - this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data)); - } - - return *this; - } - - CKFileObject::~CKFileObject() { - if (Data != nullptr) delete Data; - } - -#pragma endregion - -#pragma region CKFileManagerData - - CKFileManagerData::CKFileManagerData() : - MgrPtr(nullptr), Data(nullptr), Manager(0u, 0u) { - } - - CKFileManagerData::CKFileManagerData(const CKFileManagerData& rhs) : - MgrPtr(rhs.MgrPtr), Data(rhs.Data), Manager(rhs.Manager) { - - if (this->Data != nullptr) { - this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data)); - } - - } - - CKFileManagerData& CKFileManagerData::operator=(const CKFileManagerData& rhs) { - this->Manager = rhs.Manager; - this->MgrPtr = rhs.MgrPtr; - - this->Data = rhs.Data; - if (this->Data != nullptr) { - this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data)); - } - - return *this; - } - - CKFileManagerData::~CKFileManagerData() { - if (Data != nullptr) delete Data; - } - -#pragma endregion - -#pragma region CKFilePluginDependencies - - CKFilePluginDependencies::CKFilePluginDependencies() : - m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() { - } - - CKFilePluginDependencies::CKFilePluginDependencies(const CKFilePluginDependencies& rhs) : - m_PluginCategory(rhs.m_PluginCategory), m_Guids(rhs.m_Guids) { - } - - CKFilePluginDependencies& CKFilePluginDependencies::operator=(const CKFilePluginDependencies& rhs) { - this->m_PluginCategory = rhs.m_PluginCategory; - this->m_Guids = rhs.m_Guids; - - return *this; - } - - CKFilePluginDependencies::~CKFilePluginDependencies() { - } - -#pragma endregion - -#pragma region ShallowDocument - - CKFileDocument::CKFileDocument() { - /*this->m_IndexByClassId.resize(static_cast(CK_CLASSID::CKCID_MAXCLASSID));*/ - } - - CKFileDocument::~CKFileDocument() { - - } - -#pragma endregion - -#pragma region CKFile Misc - - CKFile::CKFile(CKMinContext* ctx) : - m_MinCtx(ctx) { - ; - } - - CKFile::~CKFile() { - } - - -#pragma endregion - - -} diff --git a/LibCmo/CK2/CKFile.hpp b/LibCmo/CK2/CKFile.hpp index 953c30b..65ddb6a 100644 --- a/LibCmo/CK2/CKFile.hpp +++ b/LibCmo/CK2/CKFile.hpp @@ -1,7 +1,11 @@ #pragma once -#include "CKDefines.hpp" -#include "CKEnums.hpp" +#include "../VTAll.hpp" + +namespace LibCmo::XContainer { + using XIntArray = XArray; + using XFileObjectsTable = XHashTable; +} namespace LibCmo::CK2 { @@ -13,25 +17,31 @@ namespace LibCmo::CK2 { size_t m_MemSize; public: - CKBufferParser(void* ptr, size_t rsize, bool need_manual_free); - CKBufferParser(const CKBufferParser&) = delete; - CKBufferParser& operator=(const CKBufferParser&) = delete; - ~CKBufferParser(); + 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) { + ; + } + ~CKBufferParser() { + if (this->m_NeedManualFree) delete[](this->m_MemBegin); + } + LIBCMO_DISABLE_COPY_MOVE(CKBufferParser); - inline const void* GetPtr(void) { return (this->m_MemBegin + m_MemPos); } - inline void Read(void* data, size_t data_size) { + const void* GetPtr(void) { return (this->m_MemBegin + m_MemPos); } + void Read(void* data, size_t data_size) { std::memcpy(data, (this->m_MemBegin + m_MemPos), data_size); this->m_MemPos += data_size; } - inline void Write(const void* data, size_t data_size) { + void Write(const void* data, size_t data_size) { std::memcpy((this->m_MemBegin + m_MemPos), data, data_size); this->m_MemPos += data_size; } - inline void* GetBase(void) { return this->m_MemBegin; } - inline size_t GetSize(void) { return this->m_MemSize; } - inline size_t GetCursor(void) { return this->m_MemPos; } - inline void MoveCursor(size_t off) { this->m_MemPos += off; } - inline void SetCursor(size_t off) { this->m_MemPos = off; } + void* GetBase(void) { return this->m_MemBegin; } + size_t GetSize(void) { return this->m_MemSize; } + size_t GetCursor(void) { return this->m_MemPos; } + void MoveCursor(size_t off) { this->m_MemPos += off; } + void SetCursor(size_t off) { this->m_MemPos = off; } }; #pragma pack(push) @@ -58,104 +68,110 @@ namespace LibCmo::CK2 { class CKFileInfo { public: - CKFileInfo(); - CKFileInfo(const CKFileInfo&); - CKFileInfo& operator=(const CKFileInfo&); - ~CKFileInfo(); - - CKDWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) - CKDWORD ProductBuild; // Virtools Build Number. - CK_FILE_WRITEMODE FileWriteMode; // Options used to save this file. (CK_FILE_WRITEMODE) - CKDWORD FileVersion; // Version of file format when file was saved. - CKDWORD CKVersion; // Version of CK when file was saved. - size_t FileSize; // Size of file in bytes. - CKDWORD ObjectCount; // Number of objects stored in the file. - CKDWORD ManagerCount; // Number of managers which saved data in the file. - CKDWORD MaxIDSaved; // Maximum Object identifier saved - CKDWORD Crc; // Crc of data - CKDWORD Hdr1PackSize; // Reserved - CKDWORD Hdr1UnPackSize; // Reserved - CKDWORD DataPackSize; // Reserved - CKDWORD DataUnPackSize; // Reserved - private: + CKFileInfo() : + ProductVersion(0u), ProductBuild(0x01010000u), FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED), + FileVersion(8u), CKVersion(CKVERSION), FileSize(0u), + ObjectCount(0u), ManagerCount(0u), MaxIDSaved(0u), Crc(0u), + Hdr1PackSize(0u), Hdr1UnPackSize(0u), DataPackSize(0u), DataUnPackSize(0u) {} + ~CKFileInfo() {} + LIBCMO_DEFAULT_COPY_MOVE(CKFileInfo); + CKDWORD ProductVersion; ///< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) + CKDWORD ProductBuild; ///< Virtools Build Number. + CK_FILE_WRITEMODE FileWriteMode; ///< Options used to save this file. (CK_FILE_WRITEMODE) + CKDWORD FileVersion; ///< Version of file format when file was saved. + CKDWORD CKVersion; ///< Version of CK when file was saved. + CKDWORD FileSize; ///< Size of file in bytes. + CKDWORD ObjectCount; ///< Number of objects stored in the file. + CKDWORD ManagerCount; ///< Number of managers which saved data in the file. + CKDWORD MaxIDSaved; ///< Maximum Object identifier saved + CKDWORD Crc; ///< Crc of data + CKDWORD Hdr1PackSize; ///< Reserved + CKDWORD Hdr1UnPackSize; ///< Reserved + CKDWORD DataPackSize; ///< Reserved + CKDWORD DataUnPackSize; ///< Reserved }; class CKFileObject { public: CKFileObject(); CKFileObject(const CKFileObject&); + CKFileObject(CKFileObject&&); CKFileObject& operator=(const CKFileObject&); + CKFileObject& operator=(CKFileObject&&); ~CKFileObject(); - CK_ID ObjectId; // ID of the object being load/saved (as it will be/was saved in the file) - CK_ID CreatedObject; // ID of the object being created - CK_CLASSID ObjectCid; // Class Identifier of the object - CKObjectImplements::CKObject* ObjPtr; // A pointer to the object itself (as CreatedObject when loading) - std::string Name; // Name of the Object - CKStateChunk* Data; // A CKStateChunk that contains object information - CKDWORD FileIndex; // Position of the object data inside uncompressed file buffer - private: - + CK_ID ObjectId; ///< ID of the object being load/saved (as it will be/was saved in the file) + CK_ID CreatedObjectId; ///< ID of the object being created + CK_CLASSID ObjectCid; ///< Class Identifier of the object + CKObject* ObjPtr; ///< A pointer to the object itself (as CreatedObject when loading) + TypeHelper::MKString Name; ///< Name of the Object + CKStateChunk* Data; ///< A CKStateChunk that contains object information + //CKINT PostPackSize; ///< When compressed chunk by chunk : size of Data after compression + //CKINT PrePackSize; ///< When compressed chunk by chunk : size of Data before compression + CK_FO_OPTIONS Options; ///< When loading an object it may be renamed , use to replace another object + CKINT FileIndex; ///< Position of the object data inside uncompressed file buffer + CKDWORD SaveFlags; ///< Flags used when this object was saved. }; class CKFileManagerData { public: CKFileManagerData(); CKFileManagerData(const CKFileManagerData&); + CKFileManagerData(CKFileManagerData&&); CKFileManagerData& operator=(const CKFileManagerData&); + CKFileManagerData& operator=(CKFileManagerData&&); ~CKFileManagerData(); - CKManagerImplements::CKBaseManager* MgrPtr; CKStateChunk* Data; CKGUID Manager; - private: - }; class CKFilePluginDependencies { public: - CKFilePluginDependencies(); - CKFilePluginDependencies(const CKFilePluginDependencies&); - CKFilePluginDependencies& operator=(const CKFilePluginDependencies&); - ~CKFilePluginDependencies(); + CKFilePluginDependencies() : + m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() {} + ~CKFilePluginDependencies() {} + LIBCMO_DEFAULT_COPY_MOVE(CKFilePluginDependencies); CK_PLUGIN_TYPE m_PluginCategory; - XArray m_Guids; - private: - - }; - - class CKFileDocument { - public: - CKFileDocument(); - ~CKFileDocument(); - - int32_t m_SaveIDMax; - CKFileInfo m_FileInfo; - - XArray m_FileObjects; - XArray m_FileManagersData; - XClassArray m_PluginDep; - /*XClassArray m_IndexByClassId;*/ - XClassArray m_IncludedFiles; - private: - + XContainer::XArray m_Guids; + XContainer::XBitArray ValidGuids; }; + /** + @brief CKFile provides functions to save/load files in Virtools format. + @remark + + Use CKFile just like a normal C++ class with passing CKCotext pointer. + + Once created a CKFile can be used to save one or more objects to disk. + + Only can load objects when this CKFile is empty. Use ClearData() to clear any existed CKFile. + + In any case, CKFile can run Save(). So you can create a CKFile, add some obejcts and save it. + Or you can load a file by CKFile and add/modify something then save it. + */ class CKFile { public: - CKFile(CKMinContext* ctx); - CKFile(const CKFile&) = delete; - CKFile& operator=(const CKFile&) = delete; + CKFile(CKContext* ctx); ~CKFile(); + LIBCMO_DISABLE_COPY_MOVE(CKFile); + // ========== Reset CKFile ========== void ClearData(void); - CKERROR ShallowLoad(CKSTRING u8_filename, CKFileDocument** out_doc); - CKERROR DeepLoad(CKSTRING u8_filename, CKFileDocument** out_doc); + // ========== Loading ========== + CKERROR ShallowLoad(CKSTRING u8_filename); + CKERROR DeepLoad(CKSTRING u8_filename); - CKERROR Save(CKSTRING u8_filename, CKFileDocument* in_doc); + // ========== Loading Result ========== + const XContainer::XArray& GetFileObjects(); + const XContainer::XArray& GetIncludedFiles(); + + // ========== Saving Preparing ========== + CKBOOL AddSavedObject(CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL); + CKBOOL AddSavedObjects(CKObjectArray* objarray, CKDWORD flags = CK_STATESAVE_ALL); + CKBOOL AddSavedFile(CKSTRING u8FileName); + + // ========== Saving ========== + CKERROR Save(CKSTRING u8_filename); //CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags); //CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags); @@ -165,29 +181,33 @@ namespace LibCmo::CK2 { //CKERROR LoadFileData(void/*CKObjectArray list*/); //CKERROR FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags); - //int32_t m_SaveIDMax; - //XArray m_FileObject; - //XArray m_ManagersData; - //XClassArray m_PluginDep; - //XClassArray m_IndexByClassId; - //XClassArray m_IncludedFiles; + CKINT m_SaveIDMax; // Maximum CK_ID found when saving or loading objects + 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::XClassArray m_IndexByClassId; // List of index in the m_FileObjects table sorted by ClassID + XContainer::XArray m_IncludedFiles; // List of files that should be inserted in the CMO file. + CKFileInfo m_FileInfo; // Headers summary - //CKFileInfo m_FileInfo; - - //CK_LOAD_FLAGS m_Flags; - - - //bool m_ReadFileDataDone; + //XContainer::XFileObjectsTable m_ObjectsHashTable; + //CKBOOL m_ReadFileDataDone; + //CKBOOL m_SceneSaved; + //XContainer::XIntArray m_DuplicateNameFounds; // A List of file object index for which a existing object with the same name has been + // // found, this list is build if the load option contains CK_LOAD_AUTOMATICMODE or CK_LOAD_DODIALOG + //XContainer::XBitArray m_AlreadySavedMask; // BitArray of IDs already saved {secret} + //XContainer::XBitArray m_AlreadyReferencedMask; // BitArray of IDs already referenced {secret} + //XContainer::XObjectPointerArray m_ReferencedObjects; private: // reader function and variables - CKERROR ReadFileHeader(CKBufferParser* ParserPtr, CKFileDocument* doc); - CKERROR ReadFileData(CKBufferParser* ParserPtr, CKFileDocument* doc); + CKERROR ReadFileHeader(CKBufferParser* ParserPtr); + CKERROR ReadFileData(CKBufferParser* ParserPtr); // writer function and varibales // shared function and variables - CKMinContext* m_MinCtx; + bool mCanLoad; + CKContext* m_Ctx; }; } diff --git a/LibCmo/CK2/CKFileOthers.cpp b/LibCmo/CK2/CKFileOthers.cpp new file mode 100644 index 0000000..a44ba47 --- /dev/null +++ b/LibCmo/CK2/CKFileOthers.cpp @@ -0,0 +1,150 @@ +#include "CKFile.hpp" +#include "CKStateChunk.hpp" +#include + +namespace LibCmo::CK2 { + +#pragma region CKFileObject + + // CKObject is managed by CKMinContext, + // so we do not considering its memory leak + // however, we need process CKStateChunk. + + 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) {} + + 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) { + if (this->Data != nullptr) { + this->Data = new CKStateChunk(*(rhs.Data)); + } + } + + 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) { + rhs.Data = nullptr; + } + + CKFileObject& CKFileObject::operator=(const CKFileObject& rhs) { + this->ObjectId = rhs.ObjectId; + this->CreatedObjectId = rhs.CreatedObjectId; + this->ObjectCid = rhs.ObjectCid; + this->ObjPtr = rhs.ObjPtr; + this->Name = rhs.Name; + + this->Data = rhs.Data; + if (this->Data != nullptr) { + this->Data = new CKStateChunk(*(rhs.Data)); + } + + this->Options = rhs.Options; + this->FileIndex = rhs.FileIndex; + this->SaveFlags = rhs.SaveFlags; + + return *this; + } + + CKFileObject& CKFileObject::operator=(CKFileObject&& rhs) { + this->ObjectId = rhs.ObjectId; + this->CreatedObjectId = rhs.CreatedObjectId; + this->ObjectCid = rhs.ObjectCid; + this->ObjPtr = rhs.ObjPtr; + this->Name = rhs.Name; + + this->Data = rhs.Data; + rhs.Data = nullptr; + + this->Options = rhs.Options; + this->FileIndex = rhs.FileIndex; + this->SaveFlags = rhs.SaveFlags; + + } + + CKFileObject::~CKFileObject() { + if (Data != nullptr) delete Data; + } + +#pragma endregion + +#pragma region CKFileManagerData + + CKFileManagerData::CKFileManagerData() : + Data(nullptr), Manager(0u, 0u) {} + + CKFileManagerData::CKFileManagerData(const CKFileManagerData& rhs) : + Data(rhs.Data), Manager(rhs.Manager) { + + if (this->Data != nullptr) { + this->Data = new CKStateChunk(*(rhs.Data)); + } + + } + + CKFileManagerData::CKFileManagerData(CKFileManagerData&& rhs) : + Data(rhs.Data), Manager(rhs.Manager) { + rhs.Data = nullptr; + } + + CKFileManagerData& CKFileManagerData::operator=(const CKFileManagerData& rhs) { + this->Manager = rhs.Manager; + + this->Data = rhs.Data; + if (this->Data != nullptr) { + this->Data = new CKStateChunk(*(rhs.Data)); + } + + return *this; + } + + CKFileManagerData& CKFileManagerData::operator=(CKFileManagerData&& rhs) { + this->Manager = rhs.Manager; + + this->Data = rhs.Data; + rhs.Data = nullptr; + } + + CKFileManagerData::~CKFileManagerData() { + if (Data != nullptr) delete Data; + } + +#pragma endregion + +#pragma region CKFilePluginDependencies + + CKFilePluginDependencies::CKFilePluginDependencies() : + m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() {} + + CKFilePluginDependencies::CKFilePluginDependencies(const CKFilePluginDependencies& rhs) : + m_PluginCategory(rhs.m_PluginCategory), m_Guids(rhs.m_Guids) {} + + CKFilePluginDependencies& CKFilePluginDependencies::operator=(const CKFilePluginDependencies& rhs) { + this->m_PluginCategory = rhs.m_PluginCategory; + this->m_Guids = rhs.m_Guids; + + return *this; + } + + CKFilePluginDependencies::~CKFilePluginDependencies() {} + +#pragma endregion + +#pragma region CKFile Misc + + CKFile::CKFile(CKContext* ctx) : + m_Ctx(ctx) { + ; + } + + CKFile::~CKFile() {} + + +#pragma endregion + + +} diff --git a/LibCmo/CK2/CKFileReader.cpp b/LibCmo/CK2/CKFileReader.cpp index fb02847..045c960 100644 --- a/LibCmo/CK2/CKFileReader.cpp +++ b/LibCmo/CK2/CKFileReader.cpp @@ -1,9 +1,8 @@ #include "CKFile.hpp" -#include "CKGlobals.hpp" #include "CKStateChunk.hpp" -#include "CKObjects.hpp" -#include "VxMemoryMappedFile.hpp" -#include "CKMinContext.hpp" +#include "CKObjectImplements/CKObject.hpp" +#include "../VxMath/VxMemoryMappedFile.hpp" +#include "CKContext.hpp" #include namespace LibCmo::CK2 { @@ -15,7 +14,7 @@ namespace LibCmo::CK2 { * No need to support them. */ - CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileDocument** out_doc) { + CKERROR CKFile::ShallowLoad(CKSTRING u8_filename) { // preset value *out_doc = nullptr; diff --git a/LibCmo/CK2/CKFileWriter.cpp b/LibCmo/CK2/CKFileWriter.cpp index d741acd..3fcfb90 100644 --- a/LibCmo/CK2/CKFileWriter.cpp +++ b/LibCmo/CK2/CKFileWriter.cpp @@ -1,6 +1,6 @@ #include "CKFile.hpp" -namespace LibCmo { +namespace LibCmo::CK2 { diff --git a/LibCmo/CK2/CKManagerImplements/CKBaseManager.cpp b/LibCmo/CK2/CKManagerImplements/CKBaseManager.cpp index d2bcfa4..88b55ad 100644 --- a/LibCmo/CK2/CKManagerImplements/CKBaseManager.cpp +++ b/LibCmo/CK2/CKManagerImplements/CKBaseManager.cpp @@ -1,27 +1,21 @@ -#include "../CKManagers.hpp" +#include "CKBaseManager.hpp" -namespace LibCmo::CK2::CKManagerImplements { - - CKBaseManager::CKBaseManager(CKMinContext* ctx, CK_ID ckid) { - - } - CKBaseManager::~CKBaseManager() { - - } - - CKERROR CKBaseManager::LoadData(CKStateChunk* statechunk, CKFileDocument* doc) { - return CKERROR::CKERR_OK; - } - CKStateChunk* CKBaseManager::SaveData(CKFileDocument* doc) { - return nullptr; - } +namespace LibCmo::CK2 { + // todo: this file maybe not used anymore. if more manager added. i think this file can be removed. + + //CKERROR CKBaseManager::LoadData(CKStateChunk* statechunk, CKFileDocument* doc) { + // return CKERROR::CKERR_OK; + //} + //CKStateChunk* CKBaseManager::SaveData(CKFileDocument* doc) { + // return nullptr; + //} - CKAttributeManager::CKAttributeManager(CKMinContext* ctx, CK_ID ckid) : CKBaseManager(ctx, ckid) { + //CKAttributeManager::CKAttributeManager(CKMinContext* ctx, CK_ID ckid) : CKBaseManager(ctx, ckid) { - } - CKAttributeManager::~CKAttributeManager() { + //} + //CKAttributeManager::~CKAttributeManager() { - } + //} } diff --git a/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp b/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp index 6371734..f032c3e 100644 --- a/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp +++ b/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp @@ -1,33 +1,106 @@ #pragma once -#include "CKDefines.hpp" -#include "CKEnums.hpp" +#include "../../VTAll.hpp" -namespace LibCmo::CK2::CKManagerImplements { +namespace LibCmo::CK2 { + /** + @brief Base Class for managers. + @remark + + This class provides virtual methods that can be override by any managers. Any manager that inherits from CKBaseManager can override function to do some processing. + + The instances of managers may be retrieved through the global function CKContext::GetManagerByGuid() + + Some default managers implemented in Virtools can be accessed directly: See Managers Access + */ class CKBaseManager { public: - CKBaseManager(CKContext* ctx, CK_ID ckid); - CKBaseManager(const CKBaseManager&) = delete; - CKBaseManager& operator=(const CKBaseManager&) = delete; - virtual ~CKBaseManager(); + CKBaseManager(CKContext* ctx, CKGUID guid, CKSTRING name) : + m_ManagerGuid(guid), + m_ManagerName(name), + m_Context(ctx) + {} + virtual ~CKBaseManager() {} + LIBCMO_DISABLE_COPY_MOVE(CKBaseManager); - virtual CKERROR LoadData(CKStateChunk* statechunk, CKFileDocument* doc); - virtual CKStateChunk* SaveData(CKFileDocument* doc); + /** + @brief Acces to Manager GUID + @return CKGUID of this manager. + @remark + + Each Manager is given an unique GUID. When creating a new manager it should + assign itself a GUID and name before registering itsef. + ``` + CKAttributeManager::CKAttributeManager(CKContext *Context) : CKBaseManager(Context, ATTRIBUTE_MANAGER_GUID, "Attribute Manager") + { + // .... + // .... + Context->RegisterNewManager(this); + } + ``` + @see CKContext::RegisterNewManager, GetName + */ + CKGUID GetGuid() { + return m_ManagerGuid; + } + /** + @brief Acces to Manager name + @return Name of this manager. + @remark + + Each Manager is given an unique GUID. When creating a new manager it should + assign itself a GUID and name before registering itsef. + ``` + CKAttributeManager::CKAttributeManager(CKContext *Context) : CKBaseManager(Context, ATTRIBUTE_MANAGER_GUID, "Attribute Manager") + { + // .... + // .... + Context->RegisterNewManager(this); + } + ``` + */ + CKSTRING GetName() { + return m_ManagerName.c_str(); + } - private: + /** + @brief Called to save manager data. + @param SavedFile A pointer to the CKFile being saved. + @return This function should return a valid CKStateChunk that contain data to save or NULL if there is nothing to save. + @remark + + During a save operation, each manager is given the opportunity to save its data in the file. + + The file being saved is given for information only and must not be modified. It can be used to decide whether it is worth saving + data for your manager. + @see CKStateChunk, LoadData + */ + virtual CKStateChunk* SaveData(CKFile* SavedFile) { + return nullptr; + } + /** + @brief Called to load manager data. + @param chunk A pointer to a CKStateChunk that was saved in the file. + @param LoadedFile A pointer to the CKFile being loaded. + @return CK_OK if successful or an error code otherwise. + @remark + + During a load operation, each manager is automatically called if there was a chunk saved in the file with SaveData. + @see CKStateChunk, SaveData + */ + virtual CKERROR LoadData(CKStateChunk* chunk, CKFile* LoadedFile) { + return CKERROR::CKERR_OK; + } + + protected: + CKGUID m_ManagerGuid; ///> Manager GUID + TypeHelper::MKString m_ManagerName; ///> Manager Name + CKContext* m_Context; ///> A pointer to the CKContext on which this manager is valid. }; - class CKAttributeManager : public CKBaseManager { - public: - CKAttributeManager(CKContext* ctx, CK_ID ckid); - CKAttributeManager(const CKAttributeManager&) = delete; - CKAttributeManager& operator=(const CKAttributeManager&) = delete; - virtual ~CKAttributeManager(); + //class CKAttributeManager : public CKBaseManager { + //public: + // CKAttributeManager(CKContext* ctx, CK_ID ckid); + // CKAttributeManager(const CKAttributeManager&) = delete; + // CKAttributeManager& operator=(const CKAttributeManager&) = delete; + // virtual ~CKAttributeManager(); - private: + //private: - }; + //}; } diff --git a/LibCmo/CK2/CKObjectImplements/CKObject.hpp b/LibCmo/CK2/CKObjectImplements/CKObject.hpp index 8913870..6506382 100644 --- a/LibCmo/CK2/CKObjectImplements/CKObject.hpp +++ b/LibCmo/CK2/CKObjectImplements/CKObject.hpp @@ -9,7 +9,7 @@ namespace LibCmo::CK2 { public: CKObject(CKContext* ctx, CK_ID ckid, CKSTRING name) : m_ID(ckid), - m_HasName(name != nullptr ? CKTRUE : CKFALSE), m_Name(name != nullptr ? name : ""), + m_Name(name), m_Context(ctx), m_ObjectFlags(CK_OBJECT_FLAGS::CK_PARAMETERIN_DISABLED) {} @@ -20,17 +20,10 @@ namespace LibCmo::CK2 { return m_ID; } CKSTRING GetName(void) { - if (m_HasName) return m_Name.c_str(); - else return nullptr; + return m_Name.c_str(); } void SetName(CKSTRING u8_name) { - if (u8_name == nullptr) { - m_HasName = false; - m_Name.clear(); - } else { - m_HasName = true; - m_Name = u8_name; - } + m_Name = u8_name; } CK_OBJECT_FLAGS GetObjectFlags(void) { return m_ObjectFlags; @@ -53,8 +46,7 @@ namespace LibCmo::CK2 { private: CK_ID m_ID; - CKBOOL m_HasName; - std::string m_Name; + TypeHelper::MKString m_Name; CK_OBJECT_FLAGS m_ObjectFlags; CKContext* m_Context; }; diff --git a/LibCmo/LibCmo.vcxproj b/LibCmo/LibCmo.vcxproj index 18396ef..e239559 100644 --- a/LibCmo/LibCmo.vcxproj +++ b/LibCmo/LibCmo.vcxproj @@ -175,7 +175,7 @@ - + diff --git a/LibCmo/LibCmo.vcxproj.filters b/LibCmo/LibCmo.vcxproj.filters index 390b3e3..8a08ccb 100644 --- a/LibCmo/LibCmo.vcxproj.filters +++ b/LibCmo/LibCmo.vcxproj.filters @@ -60,7 +60,7 @@ Sources\VxMath - + Sources\CK2 diff --git a/LibCmo/VTUtils.cpp b/LibCmo/VTUtils.cpp index 846e974..fba3145 100644 --- a/LibCmo/VTUtils.cpp +++ b/LibCmo/VTUtils.cpp @@ -2,9 +2,6 @@ namespace LibCmo { - void SystemPanic(const char* reason) { - } - namespace StreamHelper { static constexpr const size_t CHUNK_SIZE = 10240; diff --git a/LibCmo/VTUtils.hpp b/LibCmo/VTUtils.hpp index 4667129..8156e0b 100644 --- a/LibCmo/VTUtils.hpp +++ b/LibCmo/VTUtils.hpp @@ -48,6 +48,7 @@ #include #include #include +#include #pragma region Batch Ctor operator= Operations @@ -57,40 +58,97 @@ CLSNAME& operator=(const CLSNAME&) = delete; \ CLSNAME& operator=(CLSNAME&&) = delete; +#define LIBCMO_DEFAULT_COPY_MOVE(CLSNAME) \ + CLSNAME(const CLSNAME&) = default; \ + CLSNAME(CLSNAME&&) = default; \ + CLSNAME& operator=(const CLSNAME&) = default; \ + CLSNAME& operator=(CLSNAME&&) = default; + #pragma endregion namespace LibCmo { - namespace EnumsHelper { - template, int> = 0> - inline TEnum Merge(std::initializer_list il) { - std::underlying_type_t result = 0; - for (auto it = il.begin(); it != il.end(); ++it) { - result |= static_cast>(*it); - } - return static_cast(result); - } + namespace TypeHelper { - template, int> = 0> - inline TEnum Inv(TEnum e) { - return static_cast(~(static_cast>(e))); - } + /** + * @brief HybridString is a compatible type. + * In some original Virtools case, we need CKSTRING to hold string. + * But CKSTRING is just a pointer and it is very cause memory leak. + * So I invent this. It like CKSTRING but will free memory automatically. + * And it is safe in CKSTRING copying. + * It operate like std::string. Have a function called c_str() to create usable CKSTRING. + * We call it as MKString. (memory-safe CKSTRING.) :pu: =.= + */ + class MKString { + public: + MKString() : m_HasStr(false), m_Str() {} + ~MKString() {} - template, int> = 0> - inline TEnum Rm(TEnum& e1, TEnum e2) { - e1 = static_cast(static_cast>(e1) & static_cast>(Inv(e2))); - } + MKString(const char* cstr) : m_HasStr(cstr != nullptr), m_Str(m_HasStr ? cstr : "") {} + MKString& operator=(const char* cstr) { + m_HasStr = cstr != nullptr; + m_Str = m_HasStr ? cstr : ""; + } + MKString(const std::string& cstr) : m_HasStr(true), m_Str(cstr) {} + MKString& operator=(const std::string& cstr) { + m_HasStr = true; + m_Str = cstr; + } - template, int> = 0> - inline TEnum Add(TEnum& e1, TEnum e2) { - e1 = static_cast(static_cast>(e1) | static_cast>(e2)); - } + MKString(const MKString& rhs) : m_HasStr(rhs.m_HasStr), m_Str(rhs.m_Str) {} + MKString(MKString&& rhs) noexcept : m_HasStr(rhs.m_HasStr), m_Str(std::move(rhs.m_Str)) { + rhs.m_HasStr = false; + } + MKString& operator=(const MKString& rhs) { + m_HasStr = rhs.m_HasStr; + m_Str = rhs.m_Str; + } + MKString& operator=(MKString&& rhs) noexcept { + m_HasStr = rhs.m_HasStr; + m_Str = std::move(rhs.m_Str); + rhs.m_HasStr = false; + } - template, int> = 0> - inline bool Has(TEnum e, TEnum probe) { - return static_cast(static_cast>(e) & static_cast>(probe)); - } - } + const char* c_str() const { + return m_HasStr ? m_Str.c_str() : nullptr; + } + private: + bool m_HasStr; + std::string m_Str; + }; + + } + + namespace EnumsHelper { + template, int> = 0> + inline TEnum Merge(std::initializer_list il) { + std::underlying_type_t result = 0; + for (auto it = il.begin(); it != il.end(); ++it) { + result |= static_cast>(*it); + } + return static_cast(result); + } + + template, int> = 0> + inline TEnum Inv(TEnum e) { + return static_cast(~(static_cast>(e))); + } + + template, int> = 0> + inline TEnum Rm(TEnum& e1, TEnum e2) { + e1 = static_cast(static_cast>(e1) & static_cast>(Inv(e2))); + } + + template, int> = 0> + inline TEnum Add(TEnum& e1, TEnum e2) { + e1 = static_cast(static_cast>(e1) | static_cast>(e2)); + } + + template, int> = 0> + inline bool Has(TEnum e, TEnum probe) { + return static_cast(static_cast>(e) & static_cast>(probe)); + } + } namespace StreamHelper { diff --git a/LibCmo/XContainer/XTypes.hpp b/LibCmo/XContainer/XTypes.hpp index 3eff615..a32619a 100644 --- a/LibCmo/XContainer/XTypes.hpp +++ b/LibCmo/XContainer/XTypes.hpp @@ -28,43 +28,22 @@ namespace LibCmo::XContainer { /** @brief Class representation of an array. @tparam T Element Type. - @remark This class now use std::vector. - @see XClassArray, XSArray + @remark + + This class now use std::vector. + + XSArray, XClassArray now redirect to this. */ template using XArray = std::vector; - /** - @brief Class representation of an array. - @tparam T Element Type. - @details Equivalent to XArray becasue memory reducing is useless. - @see XArray - */ - template - using XSArray = XArray; - /** - @brief Class representation of an array. - @tparam T Element Type. - @details Equivalent to XArray because std::vector can fufill the requirements. - @see XArray - */ - template - using XClassArray = XArray; /** @brief Container class for CKObject Id's. @remark + This class use the template container XArray to contain object CK_ID's. + Supports for Check, Load, Save, Add, Remove, Find functions in the Object CK_ID array. + + XSObjectArray now redirect to this. @todo May independ this class to implement the functions introduced in remarks. - @see XObjectPointerArray, CKObjectArray */ using XObjectArray = XArray; - /** - @brief Container class for CKObject Id's - @details Equivalent to XObjectArray becasue memory reducing is useless. - @see XObjectArray - */ - using XSObjectArray = XObjectArray; /** @brief Container class for CKObject pointers. @@ -72,15 +51,11 @@ namespace LibCmo::XContainer { + Exactly same as XObjectArray class, but uses XArray (Pre-allocated items) for storing pointers, and not IDs (more efficient to retrieve the objects). + Supports for Check, Load, Save, Add, Remove, Find functions in the CKObject Pointer array. + + XSObjectPointerArray now redirect to this. @todo May independ this class to implement the functions introduced in remarks. @see XObjectArray, CKObjectArray */ using XObjectPointerArray = XArray; - /** - @brief Container class for CKObject pointers. - @details Equivalent to XObjectPointerArray becasue memory reducing is useless.s - */ - using XSObjectPointerArray = XObjectPointerArray; /** @brief Class representation of an Hash Table container. @@ -88,24 +63,12 @@ namespace LibCmo::XContainer { @tparam T The type of element to insert @tparam H The hash function to hash the key @tparam Eq The equal function to the key - @remark This class now use std::unordered_map. + @remark + + This class now use std::unordered_map. + + XNHashTable, XSHashTable now redirect to this. */ template, class Eq = std::equal_to> using XHashTable = std::unordered_map; - /** - @copydoc XHashTable - @details Equivalent to XHashTable - @see XHashTable - */ - template, class Eq = std::equal_to> - using XNHashTable = XHashTable; - /** - @copydoc XHashTable - @details Equivalent to XHashTable because static allocation is useless. - @see XHashTable - */ - template, class Eq = std::equal_to> - using XSHashTable = XHashTable; }