finish manager split

This commit is contained in:
yyc12345 2023-09-06 10:42:23 +08:00
parent 2ec66131cf
commit a1acdf10c6
12 changed files with 146 additions and 82 deletions

View File

@ -8,34 +8,23 @@
namespace LibCmo::CK2 { 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 #pragma region Ctor Dtor
CKContext::CKContext() : CKContext::CKContext() :
// setup manager // setup manager
m_ManagerList(), m_ManagerList(),
m_ObjectManager(nullptr), m_PathManager(nullptr), m_ObjectManager(nullptr), m_PathManager(nullptr),
// setup object cache
m_ObjectCache(), m_ObjectPointerCache(),
// setup file save/load options // setup file save/load options
m_CompressionLevel(5), m_CompressionLevel(5),
m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED), m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED),
m_GlobalImagesSaveOptions(CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA), m_GlobalImagesSaveOptions(CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA),
m_GlobalSoundsSaveOptions(CK_SOUND_SAVEOPTIONS::CKSOUND_EXTERNAL), m_GlobalSoundsSaveOptions(CK_SOUND_SAVEOPTIONS::CKSOUND_EXTERNAL),
m_GlobalImagesSaveFormat(nullptr), // todo: setup save format m_GlobalImagesSaveFormat(nullptr), // todo: setup save format
// misc init // misc init
m_NameEncoding(), m_TempFolder(), m_NameEncoding(),
m_OutputCallback(nullptr) 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);
// setup managers // setup managers
m_ObjectManager = new MgrImpls::CKObjectManager(this); m_ObjectManager = new MgrImpls::CKObjectManager(this);
@ -97,37 +86,35 @@ namespace LibCmo::CK2 {
return m_ObjectManager->DestroyObjects(obj_ids, Count); 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) { ObjImpls::CKObject* CKContext::GetObjectByName(CKSTRING name, ObjImpls::CKObject* previous) {
if (name == nullptr) return nullptr; if (name == nullptr) return nullptr;
auto result = m_ObjectManager->GetObjectByNameAndClass(name, CK_CLASSID::CKCID_OBJECT, true); if (previous == nullptr) {
m_ObjectPointerCache = m_ObjectManager->GetObjectByNameAndClass(name, CK_CLASSID::CKCID_OBJECT, true);
auto finder = std::find(result.begin(), result.end(), previous); }
if (finder == result.end()) return nullptr; return GeneralPrevFinder(m_ObjectPointerCache, previous);
++finder;
if (finder == result.end()) return nullptr;
return *finder;
} }
ObjImpls::CKObject* CKContext::GetObjectByNameAndClass(CKSTRING name, CK_CLASSID cid, ObjImpls::CKObject* previous) { ObjImpls::CKObject* CKContext::GetObjectByNameAndClass(CKSTRING name, CK_CLASSID cid, ObjImpls::CKObject* previous) {
if (name == nullptr) return nullptr; if (name == nullptr) return nullptr;
auto result = m_ObjectManager->GetObjectByNameAndClass(name, cid, false); if (previous == nullptr) {
m_ObjectPointerCache = m_ObjectManager->GetObjectByNameAndClass(name, cid, false);
auto finder = std::find(result.begin(), result.end(), previous); }
if (finder == result.end()) return nullptr; return GeneralPrevFinder(m_ObjectPointerCache, previous);
++finder;
if (finder == result.end()) return nullptr;
return *finder;
} }
ObjImpls::CKObject* CKContext::GetObjectByNameAndParentClass(CKSTRING name, CK_CLASSID pcid, ObjImpls::CKObject* previous) { ObjImpls::CKObject* CKContext::GetObjectByNameAndParentClass(CKSTRING name, CK_CLASSID pcid, ObjImpls::CKObject* previous) {
if (name == nullptr) return nullptr; if (name == nullptr) return nullptr;
auto result = m_ObjectManager->GetObjectByNameAndClass(name, pcid, true); if (previous == nullptr) {
m_ObjectPointerCache = m_ObjectManager->GetObjectByNameAndClass(name, pcid, true);
auto finder = std::find(result.begin(), result.end(), previous); }
if (finder == result.end()) return nullptr; return GeneralPrevFinder(m_ObjectPointerCache, previous);
++finder;
if (finder == result.end()) return nullptr;
return *finder;
} }
const XContainer::XObjectPointerArray CKContext::GetObjectListByType(CK_CLASSID cid, bool derived) { const XContainer::XObjectPointerArray CKContext::GetObjectListByType(CK_CLASSID cid, bool derived) {
@ -136,17 +123,23 @@ namespace LibCmo::CK2 {
CKDWORD CKContext::GetObjectsCountByClassID(CK_CLASSID cid) { CKDWORD CKContext::GetObjectsCountByClassID(CK_CLASSID cid) {
auto result = m_ObjectManager->GetObjectByNameAndClass(nullptr, cid, false); auto result = m_ObjectManager->GetObjectByNameAndClass(nullptr, cid, false);
return static_cast<CKDWORD>(result.size());
m_ObjectCache.clear();
for (auto& obj : result) {
m_ObjectCache.emplace_back(obj->GetID());
}
return static_cast<CKDWORD>(m_ObjectCache.size());
} }
CK_ID* CKContext::GetObjectsListByClassID(CK_CLASSID cid) { CK_ID* CKContext::GetObjectsListByClassID(CK_CLASSID cid) {
// todo: impl internal buffer return m_ObjectCache.data();
} }
#pragma endregion #pragma endregion
#pragma region Common Managers #pragma region Common Managers
MgrImpls::CKObjectManager* CKContext::GetObjectManager() { MgrImpls::CKObjectManager* CKContext::GetObjectManager() {
return m_ObjectManager; return m_ObjectManager;
} }
@ -278,24 +271,6 @@ namespace LibCmo::CK2 {
#pragma endregion #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 #pragma region Encoding utilities
void CKContext::GetUtf8String(const std::string& native_name, std::string& u8_name) { 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); success = LibCmo::EncodingHelper::GetNativeVirtoolsName(u8_name, native_name, token);
if (success) break; if (success) break;
} }
// fallback // fallback
if (!success) { if (!success) {
native_name = u8_name; native_name = u8_name;

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "../VTAll.hpp" #include "../VTAll.hpp"
#include <filesystem>
#include <map> #include <map>
#include <deque> #include <deque>
#include <functional> #include <functional>
@ -46,11 +45,15 @@ namespace LibCmo::CK2 {
ObjImpls::CKObject* GetObjectByName(CKSTRING name, ObjImpls::CKObject *previous = nullptr); ObjImpls::CKObject* GetObjectByName(CKSTRING name, ObjImpls::CKObject *previous = nullptr);
ObjImpls::CKObject* GetObjectByNameAndClass(CKSTRING name, CK_CLASSID cid, 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); const XContainer::XObjectPointerArray GetObjectListByType(CK_CLASSID cid, bool derived);
CKDWORD GetObjectsCountByClassID(CK_CLASSID cid); CKDWORD GetObjectsCountByClassID(CK_CLASSID cid);
CK_ID* GetObjectsListByClassID(CK_CLASSID cid); CK_ID* GetObjectsListByClassID(CK_CLASSID cid);
protected:
XContainer::XObjectPointerArray m_ObjectPointerCache;
XContainer::XObjectArray m_ObjectCache;
// ========== Common Managers ========== // ========== Common Managers ==========
public: public:
MgrImpls::CKObjectManager* GetObjectManager(); MgrImpls::CKObjectManager* GetObjectManager();
@ -104,14 +107,6 @@ namespace LibCmo::CK2 {
protected: protected:
std::vector<EncodingHelper::ENCODING_TOKEN> m_NameEncoding; std::vector<EncodingHelper::ENCODING_TOKEN> 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 ========== // ========== Print utilities ==========
public: public:
using OutputCallback = std::function<void(CKSTRING)>; using OutputCallback = std::function<void(CKSTRING)>;

View File

@ -1,6 +1,7 @@
#include "CKFile.hpp" #include "CKFile.hpp"
#include "CKStateChunk.hpp" #include "CKStateChunk.hpp"
#include "ObjImpls/CKObject.hpp" #include "ObjImpls/CKObject.hpp"
#include "MgrImpls/CKPathManager.hpp"
#include "../VxMath/VxMemoryMappedFile.hpp" #include "../VxMath/VxMemoryMappedFile.hpp"
#include "CKContext.hpp" #include "CKContext.hpp"
#include <memory> #include <memory>
@ -313,7 +314,7 @@ namespace LibCmo::CK2 {
parser->Read(&filebodylen, sizeof(CKDWORD)); parser->Read(&filebodylen, sizeof(CKDWORD));
// read file body // 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"); FILE* fp = EncodingHelper::U8FOpen(tempfilename.c_str(), "wb");
if (fp != nullptr) { if (fp != nullptr) {
std::fwrite(parser->GetPtr(), sizeof(char), filebodylen, fp); std::fwrite(parser->GetPtr(), sizeof(char), filebodylen, fp);

View File

@ -3,6 +3,7 @@
#include "CKStateChunk.hpp" #include "CKStateChunk.hpp"
#include "ObjImpls/CKObject.hpp" #include "ObjImpls/CKObject.hpp"
#include "MgrImpls/CKBaseManager.hpp" #include "MgrImpls/CKBaseManager.hpp"
#include "MgrImpls/CKPathManager.hpp"
#include "../VxMath/VxMemoryMappedFile.hpp" #include "../VxMath/VxMemoryMappedFile.hpp"
#include <memory> #include <memory>
@ -315,7 +316,7 @@ namespace LibCmo::CK2 {
std::fwrite(name_conv.data(), sizeof(char), filenamelen, fs); std::fwrite(name_conv.data(), sizeof(char), filenamelen, fs);
// try mapping file. // 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<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(tempfilename.c_str())); std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(tempfilename.c_str()));
if (mappedFile->IsValid()) { if (mappedFile->IsValid()) {
// write file length // write file length

View File

@ -143,6 +143,8 @@ namespace LibCmo::CK2::MgrImpls {
} }
} }
} }
return result;
} }
CKDWORD CKObjectManager::AllocateGroupGlobalIndex(ObjImpls::CKObject* group) { CKDWORD CKObjectManager::AllocateGroupGlobalIndex(ObjImpls::CKObject* group) {

View File

@ -40,6 +40,13 @@ namespace LibCmo::CK2::MgrImpls {
// ========== Objects Access ========== // ========== 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( XContainer::XObjectPointerArray GetObjectByNameAndClass(
CKSTRING name, CK_CLASSID cid, bool derived); CKSTRING name, CK_CLASSID cid, bool derived);

View File

@ -2,5 +2,49 @@
namespace LibCmo::CK2::MgrImpls { 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;
}
} }

View File

@ -2,18 +2,42 @@
#include "../../VTAll.hpp" #include "../../VTAll.hpp"
#include "CKBaseManager.hpp" #include "CKBaseManager.hpp"
#include <filesystem>
namespace LibCmo::CK2::MgrImpls { namespace LibCmo::CK2::MgrImpls {
class CKPathManager : public CKBaseManager { class CKPathManager : public CKBaseManager {
public: public:
CKPathManager(CKContext* ctx) : CKPathManager(CKContext* ctx);
CKBaseManager(ctx, PATH_MANAGER_GUID, "Path Manager") {} virtual ~CKPathManager();
virtual ~CKPathManager() {}
LIBCMO_DISABLE_COPY_MOVE(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: protected:
std::filesystem::path m_TempFolder;
}; };
} }

View File

@ -1,10 +1,25 @@
#include "CKSceneObject.hpp" #include "CKSceneObject.hpp"
#include "../CKStateChunk.hpp" #include "../CKStateChunk.hpp"
#include "../CKContext.hpp"
#include "../MgrImpls/CKObjectManager.hpp"
#include "CKBeObject.hpp" #include "CKBeObject.hpp"
#include "CKGroup.hpp" #include "CKGroup.hpp"
namespace LibCmo::CK2::ObjImpls { 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<CKGroup*>(m_Context->GetObjectManager()->GetGroupByGlobalIndex(static_cast<CKDWORD>(i)));
group->RemoveObject(this);
}
}
}
bool CKBeObject::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool CKBeObject::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {
bool suc = CKSceneObject::Save(chunk, file, flags); bool suc = CKSceneObject::Save(chunk, file, flags);
if (!suc) return false; if (!suc) return false;

View File

@ -7,10 +7,8 @@ namespace LibCmo::CK2::ObjImpls {
class CKBeObject : public CKSceneObject { class CKBeObject : public CKSceneObject {
public: public:
CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name) : CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name);
CKSceneObject(ctx, ckid, name) virtual ~CKBeObject();
{}
virtual ~CKBeObject() {}
LIBCMO_DISABLE_COPY_MOVE(CKBeObject); LIBCMO_DISABLE_COPY_MOVE(CKBeObject);
virtual CK_CLASSID GetClassID(void) override { virtual CK_CLASSID GetClassID(void) override {

View File

@ -1,6 +1,7 @@
#include "CKGroup.hpp" #include "CKGroup.hpp"
#include "../CKStateChunk.hpp" #include "../CKStateChunk.hpp"
#include "../CKContext.hpp" #include "../CKContext.hpp"
#include "../MgrImpls/CKObjectManager.hpp"
#include <algorithm> #include <algorithm>
namespace LibCmo::CK2::ObjImpls { namespace LibCmo::CK2::ObjImpls {
@ -8,10 +9,10 @@ namespace LibCmo::CK2::ObjImpls {
CKGroup::CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) : CKGroup::CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) :
CKBeObject(ctx, ckid, name), CKBeObject(ctx, ckid, name),
m_ObjectArray(), m_ObjectArray(),
m_GroupIndex(m_Context->AllocateGroupGlobalIndex()) {} m_GroupIndex(m_Context->GetObjectManager()->AllocateGroupGlobalIndex(this)) {}
CKGroup::~CKGroup() { CKGroup::~CKGroup() {
m_Context->FreeGroupGlobalIndex(m_GroupIndex); m_Context->GetObjectManager()->FreeGroupGlobalIndex(m_GroupIndex);
} }
bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {

View File

@ -11,6 +11,7 @@
#undef GetObject #undef GetObject
#undef GetClassName #undef GetClassName
#undef LoadImage #undef LoadImage
#undef GetTempPath
#else #else
#include <iconv.h> #include <iconv.h>
#endif #endif