From a1acdf10c6dd339d1ca30e9dde064007e8a2375e Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Wed, 6 Sep 2023 10:42:23 +0800 Subject: [PATCH] finish manager split --- LibCmo/CK2/CKContext.cpp | 95 +++++++++---------------- LibCmo/CK2/CKContext.hpp | 15 ++-- LibCmo/CK2/CKFileReader.cpp | 3 +- LibCmo/CK2/CKFileWriter.cpp | 3 +- LibCmo/CK2/MgrImpls/CKObjectManager.cpp | 2 + LibCmo/CK2/MgrImpls/CKObjectManager.hpp | 7 ++ LibCmo/CK2/MgrImpls/CKPathManager.cpp | 44 ++++++++++++ LibCmo/CK2/MgrImpls/CKPathManager.hpp | 32 +++++++-- LibCmo/CK2/ObjImpls/CKBeObject.cpp | 15 ++++ LibCmo/CK2/ObjImpls/CKBeObject.hpp | 6 +- LibCmo/CK2/ObjImpls/CKGroup.cpp | 5 +- LibCmo/VTEncoding.hpp | 1 + 12 files changed, 146 insertions(+), 82 deletions(-) diff --git a/LibCmo/CK2/CKContext.cpp b/LibCmo/CK2/CKContext.cpp index 9258786..a7af4e9 100644 --- a/LibCmo/CK2/CKContext.cpp +++ b/LibCmo/CK2/CKContext.cpp @@ -8,34 +8,23 @@ namespace LibCmo::CK2 { -#if defined(LIBCMO_OS_WIN32) - static wchar_t g_UniqueFolder[] = L"LibCmo"; -#else - static char g_UniqueFolder[] = "LibCmo"; -#endif - #pragma region Ctor Dtor CKContext::CKContext() : // setup manager m_ManagerList(), m_ObjectManager(nullptr), m_PathManager(nullptr), + // setup object cache + m_ObjectCache(), m_ObjectPointerCache(), // setup file save/load options - m_CompressionLevel(5), - m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED), + m_CompressionLevel(5), + m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED), m_GlobalImagesSaveOptions(CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA), m_GlobalSoundsSaveOptions(CK_SOUND_SAVEOPTIONS::CKSOUND_EXTERNAL), m_GlobalImagesSaveFormat(nullptr), // todo: setup save format // misc init - m_NameEncoding(), m_TempFolder(), - m_OutputCallback(nullptr) - { - // preset for temp folder - // todo: add current CKContext pointer as the part of temp path. - // thus multiple CKContext can work. - m_TempFolder = std::filesystem::temp_directory_path(); - m_TempFolder /= g_UniqueFolder; - std::filesystem::create_directory(m_TempFolder); + m_NameEncoding(), + m_OutputCallback(nullptr) { // setup managers m_ObjectManager = new MgrImpls::CKObjectManager(this); @@ -97,37 +86,35 @@ namespace LibCmo::CK2 { return m_ObjectManager->DestroyObjects(obj_ids, Count); } + ObjImpls::CKObject* GeneralPrevFinder(XContainer::XObjectPointerArray& objptrs, ObjImpls::CKObject* previous) { + auto finder = std::find(objptrs.begin(), objptrs.end(), previous); + if (finder == objptrs.end()) return nullptr; + ++finder; + if (finder == objptrs.end()) return nullptr; + return *finder; + } ObjImpls::CKObject* CKContext::GetObjectByName(CKSTRING name, ObjImpls::CKObject* previous) { if (name == nullptr) return nullptr; - auto result = m_ObjectManager->GetObjectByNameAndClass(name, CK_CLASSID::CKCID_OBJECT, true); - - auto finder = std::find(result.begin(), result.end(), previous); - if (finder == result.end()) return nullptr; - ++finder; - if (finder == result.end()) return nullptr; - return *finder; + if (previous == nullptr) { + m_ObjectPointerCache = m_ObjectManager->GetObjectByNameAndClass(name, CK_CLASSID::CKCID_OBJECT, true); + } + return GeneralPrevFinder(m_ObjectPointerCache, previous); } ObjImpls::CKObject* CKContext::GetObjectByNameAndClass(CKSTRING name, CK_CLASSID cid, ObjImpls::CKObject* previous) { if (name == nullptr) return nullptr; - auto result = m_ObjectManager->GetObjectByNameAndClass(name, cid, false); - - auto finder = std::find(result.begin(), result.end(), previous); - if (finder == result.end()) return nullptr; - ++finder; - if (finder == result.end()) return nullptr; - return *finder; + if (previous == nullptr) { + m_ObjectPointerCache = m_ObjectManager->GetObjectByNameAndClass(name, cid, false); + } + return GeneralPrevFinder(m_ObjectPointerCache, previous); } ObjImpls::CKObject* CKContext::GetObjectByNameAndParentClass(CKSTRING name, CK_CLASSID pcid, ObjImpls::CKObject* previous) { if (name == nullptr) return nullptr; - auto result = m_ObjectManager->GetObjectByNameAndClass(name, pcid, true); - - auto finder = std::find(result.begin(), result.end(), previous); - if (finder == result.end()) return nullptr; - ++finder; - if (finder == result.end()) return nullptr; - return *finder; + if (previous == nullptr) { + m_ObjectPointerCache = m_ObjectManager->GetObjectByNameAndClass(name, pcid, true); + } + return GeneralPrevFinder(m_ObjectPointerCache, previous); } const XContainer::XObjectPointerArray CKContext::GetObjectListByType(CK_CLASSID cid, bool derived) { @@ -136,17 +123,23 @@ namespace LibCmo::CK2 { CKDWORD CKContext::GetObjectsCountByClassID(CK_CLASSID cid) { auto result = m_ObjectManager->GetObjectByNameAndClass(nullptr, cid, false); - return static_cast(result.size()); + + m_ObjectCache.clear(); + for (auto& obj : result) { + m_ObjectCache.emplace_back(obj->GetID()); + } + + return static_cast(m_ObjectCache.size()); } CK_ID* CKContext::GetObjectsListByClassID(CK_CLASSID cid) { - // todo: impl internal buffer + return m_ObjectCache.data(); } #pragma endregion #pragma region Common Managers - + MgrImpls::CKObjectManager* CKContext::GetObjectManager() { return m_ObjectManager; } @@ -278,24 +271,6 @@ namespace LibCmo::CK2 { #pragma endregion -#pragma region Temp IO utilities - - void CKContext::SetTempPath(CKSTRING u8_temp) { - EncodingHelper::U8PathToStdPath(this->m_TempFolder, u8_temp); - } - - std::string CKContext::GetTempFilePath(CKSTRING u8_filename) { - std::filesystem::path stdfilename; - EncodingHelper::U8PathToStdPath(stdfilename, u8_filename); - auto realfile = this->m_TempFolder / stdfilename; - - std::string result; - EncodingHelper::StdPathToU8Path(result, realfile); - return result; - } - -#pragma endregion - #pragma region Encoding utilities void CKContext::GetUtf8String(const std::string& native_name, std::string& u8_name) { @@ -318,7 +293,7 @@ namespace LibCmo::CK2 { success = LibCmo::EncodingHelper::GetNativeVirtoolsName(u8_name, native_name, token); if (success) break; } - + // fallback if (!success) { native_name = u8_name; diff --git a/LibCmo/CK2/CKContext.hpp b/LibCmo/CK2/CKContext.hpp index c89fc2a..e3bfd0f 100644 --- a/LibCmo/CK2/CKContext.hpp +++ b/LibCmo/CK2/CKContext.hpp @@ -1,7 +1,6 @@ #pragma once #include "../VTAll.hpp" -#include #include #include #include @@ -46,11 +45,15 @@ namespace LibCmo::CK2 { ObjImpls::CKObject* GetObjectByName(CKSTRING name, ObjImpls::CKObject *previous = nullptr); ObjImpls::CKObject* GetObjectByNameAndClass(CKSTRING name, CK_CLASSID cid, ObjImpls::CKObject *previous = nullptr); - ObjImpls::CKObject* GetObjectByNameAndParentClass(CKSTRING name, CK_CLASSID pcid, ObjImpls::CKObject* previous); + ObjImpls::CKObject* GetObjectByNameAndParentClass(CKSTRING name, CK_CLASSID pcid, ObjImpls::CKObject* previous = nullptr); const XContainer::XObjectPointerArray GetObjectListByType(CK_CLASSID cid, bool derived); CKDWORD GetObjectsCountByClassID(CK_CLASSID cid); CK_ID* GetObjectsListByClassID(CK_CLASSID cid); + protected: + XContainer::XObjectPointerArray m_ObjectPointerCache; + XContainer::XObjectArray m_ObjectCache; + // ========== Common Managers ========== public: MgrImpls::CKObjectManager* GetObjectManager(); @@ -104,14 +107,6 @@ namespace LibCmo::CK2 { protected: std::vector m_NameEncoding; - // ========== Temp IO utilities ========== - public: - void SetTempPath(CKSTRING u8_temp); - std::string GetTempFilePath(CKSTRING u8_filename); - - protected: - std::filesystem::path m_TempFolder; - // ========== Print utilities ========== public: using OutputCallback = std::function; diff --git a/LibCmo/CK2/CKFileReader.cpp b/LibCmo/CK2/CKFileReader.cpp index c1c6aef..643d6c2 100644 --- a/LibCmo/CK2/CKFileReader.cpp +++ b/LibCmo/CK2/CKFileReader.cpp @@ -1,6 +1,7 @@ #include "CKFile.hpp" #include "CKStateChunk.hpp" #include "ObjImpls/CKObject.hpp" +#include "MgrImpls/CKPathManager.hpp" #include "../VxMath/VxMemoryMappedFile.hpp" #include "CKContext.hpp" #include @@ -313,7 +314,7 @@ namespace LibCmo::CK2 { parser->Read(&filebodylen, sizeof(CKDWORD)); // read file body - std::string tempfilename = m_Ctx->GetTempFilePath(file.c_str()); + std::string tempfilename = m_Ctx->GetPathManager()->GetTempFilePath(file.c_str()); FILE* fp = EncodingHelper::U8FOpen(tempfilename.c_str(), "wb"); if (fp != nullptr) { std::fwrite(parser->GetPtr(), sizeof(char), filebodylen, fp); diff --git a/LibCmo/CK2/CKFileWriter.cpp b/LibCmo/CK2/CKFileWriter.cpp index 2c751ba..fe3ca35 100644 --- a/LibCmo/CK2/CKFileWriter.cpp +++ b/LibCmo/CK2/CKFileWriter.cpp @@ -3,6 +3,7 @@ #include "CKStateChunk.hpp" #include "ObjImpls/CKObject.hpp" #include "MgrImpls/CKBaseManager.hpp" +#include "MgrImpls/CKPathManager.hpp" #include "../VxMath/VxMemoryMappedFile.hpp" #include @@ -315,7 +316,7 @@ namespace LibCmo::CK2 { std::fwrite(name_conv.data(), sizeof(char), filenamelen, fs); // try mapping file. - std::string tempfilename = m_Ctx->GetTempFilePath(fentry.c_str()); + std::string tempfilename = m_Ctx->GetPathManager()->GetTempFilePath(fentry.c_str()); std::unique_ptr mappedFile(new VxMath::VxMemoryMappedFile(tempfilename.c_str())); if (mappedFile->IsValid()) { // write file length diff --git a/LibCmo/CK2/MgrImpls/CKObjectManager.cpp b/LibCmo/CK2/MgrImpls/CKObjectManager.cpp index 829f0bb..ed93334 100644 --- a/LibCmo/CK2/MgrImpls/CKObjectManager.cpp +++ b/LibCmo/CK2/MgrImpls/CKObjectManager.cpp @@ -143,6 +143,8 @@ namespace LibCmo::CK2::MgrImpls { } } } + + return result; } CKDWORD CKObjectManager::AllocateGroupGlobalIndex(ObjImpls::CKObject* group) { diff --git a/LibCmo/CK2/MgrImpls/CKObjectManager.hpp b/LibCmo/CK2/MgrImpls/CKObjectManager.hpp index 9cc104a..c1ea690 100644 --- a/LibCmo/CK2/MgrImpls/CKObjectManager.hpp +++ b/LibCmo/CK2/MgrImpls/CKObjectManager.hpp @@ -40,6 +40,13 @@ namespace LibCmo::CK2::MgrImpls { // ========== Objects Access ========== + /** + * @brief General object list query. + * @param name nullptr if no requirement. + * @param cid the class id + * @param derived whether considering derived class + * @return the result pointer list. + */ XContainer::XObjectPointerArray GetObjectByNameAndClass( CKSTRING name, CK_CLASSID cid, bool derived); diff --git a/LibCmo/CK2/MgrImpls/CKPathManager.cpp b/LibCmo/CK2/MgrImpls/CKPathManager.cpp index 9525ae7..42365e4 100644 --- a/LibCmo/CK2/MgrImpls/CKPathManager.cpp +++ b/LibCmo/CK2/MgrImpls/CKPathManager.cpp @@ -2,5 +2,49 @@ namespace LibCmo::CK2::MgrImpls { +#if defined(LIBCMO_OS_WIN32) + static wchar_t g_UniqueFolder[] = L"LibCmo"; +#else + static char g_UniqueFolder[] = "LibCmo"; +#endif + + CKPathManager::CKPathManager(CKContext* ctx) : + CKBaseManager(ctx, PATH_MANAGER_GUID, "Path Manager"), + m_TempFolder() { + // preset for temp folder + // todo: add current CKContext pointer as the part of temp path. + // thus multiple CKContext can work. + m_TempFolder = std::filesystem::temp_directory_path(); + m_TempFolder /= g_UniqueFolder; + std::filesystem::create_directories(m_TempFolder); + + } + CKPathManager::~CKPathManager() {} + + void CKPathManager::SetTempFolder(CKSTRING u8_temp) { + EncodingHelper::U8PathToStdPath(this->m_TempFolder, u8_temp); + } + + std::string CKPathManager::GetTempFolder() { + std::string result; + EncodingHelper::StdPathToU8Path(result, this->m_TempFolder); + return result; + } + + std::string CKPathManager::GetTempFilePath(CKSTRING u8_filename) { + std::filesystem::path stdfilename; + EncodingHelper::U8PathToStdPath(stdfilename, u8_filename); + auto realfile = this->m_TempFolder / stdfilename; + + std::string result; + EncodingHelper::StdPathToU8Path(result, realfile); + return result; + } + + bool CKPathManager::ResolveFileName(std::string& u8_filename) { + // todo: finish resolve file name + return false; + } + } diff --git a/LibCmo/CK2/MgrImpls/CKPathManager.hpp b/LibCmo/CK2/MgrImpls/CKPathManager.hpp index 675e7d8..8a9de29 100644 --- a/LibCmo/CK2/MgrImpls/CKPathManager.hpp +++ b/LibCmo/CK2/MgrImpls/CKPathManager.hpp @@ -2,18 +2,42 @@ #include "../../VTAll.hpp" #include "CKBaseManager.hpp" +#include namespace LibCmo::CK2::MgrImpls { class CKPathManager : public CKBaseManager { public: - CKPathManager(CKContext* ctx) : - CKBaseManager(ctx, PATH_MANAGER_GUID, "Path Manager") {} - virtual ~CKPathManager() {} + CKPathManager(CKContext* ctx); + virtual ~CKPathManager(); LIBCMO_DISABLE_COPY_MOVE(CKPathManager); + + /** + * @brief Set the temp folder of current context. + * @param u8_temp + */ + void SetTempFolder(CKSTRING u8_temp); + /** + * @brief Get current temp folder. + * @return + */ + std::string GetTempFolder(); + /** + * @brief Get the path of temp file. + * @param u8_filename The relative path of file. + * @return The path of given path based on temp folder. + */ + std::string GetTempFilePath(CKSTRING u8_filename); + + /** + * @brief Finds a file in the paths + * @param u8_filename[inout] The given file path. overwritten by the final path if success. + * @return true if success + */ + bool ResolveFileName(std::string& u8_filename); protected: - + std::filesystem::path m_TempFolder; }; } diff --git a/LibCmo/CK2/ObjImpls/CKBeObject.cpp b/LibCmo/CK2/ObjImpls/CKBeObject.cpp index 86d718e..f2c9955 100644 --- a/LibCmo/CK2/ObjImpls/CKBeObject.cpp +++ b/LibCmo/CK2/ObjImpls/CKBeObject.cpp @@ -1,10 +1,25 @@ #include "CKSceneObject.hpp" #include "../CKStateChunk.hpp" +#include "../CKContext.hpp" +#include "../MgrImpls/CKObjectManager.hpp" #include "CKBeObject.hpp" #include "CKGroup.hpp" namespace LibCmo::CK2::ObjImpls { + CKBeObject::CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name) : + CKSceneObject(ctx, ckid, name) {} + + CKBeObject::~CKBeObject() { + // remove self from all group + for (size_t i = 0; i < m_Groups.size(); ++i) { + if (m_Groups[i]) { + CKGroup* group = static_cast(m_Context->GetObjectManager()->GetGroupByGlobalIndex(static_cast(i))); + group->RemoveObject(this); + } + } + } + bool CKBeObject::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool suc = CKSceneObject::Save(chunk, file, flags); if (!suc) return false; diff --git a/LibCmo/CK2/ObjImpls/CKBeObject.hpp b/LibCmo/CK2/ObjImpls/CKBeObject.hpp index a21e1a2..3e340a2 100644 --- a/LibCmo/CK2/ObjImpls/CKBeObject.hpp +++ b/LibCmo/CK2/ObjImpls/CKBeObject.hpp @@ -7,10 +7,8 @@ namespace LibCmo::CK2::ObjImpls { class CKBeObject : public CKSceneObject { public: - CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name) : - CKSceneObject(ctx, ckid, name) - {} - virtual ~CKBeObject() {} + CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name); + virtual ~CKBeObject(); LIBCMO_DISABLE_COPY_MOVE(CKBeObject); virtual CK_CLASSID GetClassID(void) override { diff --git a/LibCmo/CK2/ObjImpls/CKGroup.cpp b/LibCmo/CK2/ObjImpls/CKGroup.cpp index aa48192..9aedb11 100644 --- a/LibCmo/CK2/ObjImpls/CKGroup.cpp +++ b/LibCmo/CK2/ObjImpls/CKGroup.cpp @@ -1,6 +1,7 @@ #include "CKGroup.hpp" #include "../CKStateChunk.hpp" #include "../CKContext.hpp" +#include "../MgrImpls/CKObjectManager.hpp" #include namespace LibCmo::CK2::ObjImpls { @@ -8,10 +9,10 @@ namespace LibCmo::CK2::ObjImpls { CKGroup::CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) : CKBeObject(ctx, ckid, name), m_ObjectArray(), - m_GroupIndex(m_Context->AllocateGroupGlobalIndex()) {} + m_GroupIndex(m_Context->GetObjectManager()->AllocateGroupGlobalIndex(this)) {} CKGroup::~CKGroup() { - m_Context->FreeGroupGlobalIndex(m_GroupIndex); + m_Context->GetObjectManager()->FreeGroupGlobalIndex(m_GroupIndex); } bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { diff --git a/LibCmo/VTEncoding.hpp b/LibCmo/VTEncoding.hpp index df8c085..a5c5ecc 100644 --- a/LibCmo/VTEncoding.hpp +++ b/LibCmo/VTEncoding.hpp @@ -11,6 +11,7 @@ #undef GetObject #undef GetClassName #undef LoadImage +#undef GetTempPath #else #include #endif