continue refactor project
This commit is contained in:
parent
1ddeeb3b68
commit
3c8266e7dd
@ -41,6 +41,9 @@ namespace LibCmo::CK2::MgrImpls {
|
||||
m_ObjectsList[decided_off] = obj;
|
||||
++m_ObjectCount;
|
||||
|
||||
// add into classid indexed object list
|
||||
m_ObjectsListByClass[static_cast<size_t>(cls)].push_back(Offset2Id(decided_off));
|
||||
|
||||
// set out variable
|
||||
return obj;
|
||||
}
|
||||
@ -76,9 +79,12 @@ namespace LibCmo::CK2::MgrImpls {
|
||||
CKDWORD off = Id2Offset(ids[i]);
|
||||
if (off >= m_ObjectsList.size()) continue;
|
||||
|
||||
// get object and free it
|
||||
// get object and its classid for future use
|
||||
ObjImpls::CKObject* obj = m_ObjectsList[off];
|
||||
if (obj == nullptr) continue;
|
||||
CK_CLASSID cls = obj->GetClassID();
|
||||
|
||||
// free it
|
||||
InternalDestroy(obj);
|
||||
|
||||
// return its allocated id.
|
||||
@ -87,6 +93,9 @@ namespace LibCmo::CK2::MgrImpls {
|
||||
m_ReturnedObjectOffsets.emplace_back(off);
|
||||
--m_ObjectCount;
|
||||
|
||||
// remove from classid indexed list
|
||||
std::erase(m_ObjectsListByClass[static_cast<size_t>(cls)], ids[i]);
|
||||
|
||||
}
|
||||
|
||||
// notice post
|
||||
@ -147,61 +156,59 @@ namespace LibCmo::CK2::MgrImpls {
|
||||
return result;
|
||||
}
|
||||
|
||||
CKDWORD CKObjectManager::AllocateGroupGlobalIndex(ObjImpls::CKObject* group) {
|
||||
// try find first nullptr position
|
||||
CKDWORD index = 0;
|
||||
for (const auto& ptr : m_GroupGlobalIndex) {
|
||||
if (ptr == nullptr) break;
|
||||
++index;
|
||||
bool CKObjectManager::IsObjectSafe(CK_ID objid) {
|
||||
CKDWORD off = Id2Offset(objid);
|
||||
if (off >= m_ObjectsList.size()) return false;
|
||||
return m_ObjectsList[off] != nullptr;
|
||||
}
|
||||
|
||||
bool CKObjectManager::IsObjectPointerSafe(const ObjImpls::CKObject* objptr) {
|
||||
if (objptr == nullptr) return false;
|
||||
|
||||
// iterate all object list to check
|
||||
for (const auto& ptr : m_ObjectsList) {
|
||||
if (ptr == objptr) return true;
|
||||
}
|
||||
// resize array for new position
|
||||
if (index == m_GroupGlobalIndex.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CKDWORD CKObjectManager::AllocateGroupGlobalIndex() {
|
||||
// try find first non-true position
|
||||
CKDWORD index;
|
||||
if (!XContainer::NSXBitArray::GetUnsetBitPosition(m_GroupGlobalIndex, 0, index)) {
|
||||
// failed. distribute new one
|
||||
index = static_cast<CKDWORD>(m_GroupGlobalIndex.size());
|
||||
m_GroupGlobalIndex.resize(m_GroupGlobalIndex.size() + 1);
|
||||
}
|
||||
|
||||
|
||||
// set to occupy
|
||||
m_GroupGlobalIndex[index] = group;
|
||||
m_GroupGlobalIndex[index] = true;
|
||||
return index;
|
||||
}
|
||||
|
||||
CKDWORD CKObjectManager::AllocateSceneGlobalIndex(ObjImpls::CKObject* scene) {
|
||||
CKDWORD CKObjectManager::AllocateSceneGlobalIndex() {
|
||||
// same as group
|
||||
CKDWORD index = 0;
|
||||
for (const auto& ptr : m_SceneGlobalIndex) {
|
||||
if (ptr == nullptr) break;
|
||||
++index;
|
||||
}
|
||||
// resize array for new position
|
||||
if (index == m_SceneGlobalIndex.size()) {
|
||||
CKDWORD index;
|
||||
if (!XContainer::NSXBitArray::GetUnsetBitPosition(m_SceneGlobalIndex, 0, index)) {
|
||||
index = static_cast<CKDWORD>(m_SceneGlobalIndex.size());
|
||||
m_SceneGlobalIndex.resize(m_SceneGlobalIndex.size() + 1);
|
||||
}
|
||||
|
||||
// set to occupy
|
||||
m_SceneGlobalIndex[index] = scene;
|
||||
|
||||
m_SceneGlobalIndex[index] = true;
|
||||
return index;
|
||||
}
|
||||
|
||||
ObjImpls::CKObject* CKObjectManager::GetGroupByGlobalIndex(CKDWORD index) {
|
||||
if (index >= m_GroupGlobalIndex.size()) return nullptr;
|
||||
else return m_GroupGlobalIndex[index];
|
||||
}
|
||||
|
||||
ObjImpls::CKObject* CKObjectManager::GetSceneByGlobalIndex(CKDWORD index) {
|
||||
if (index >= m_SceneGlobalIndex.size()) return nullptr;
|
||||
else return m_SceneGlobalIndex[index];
|
||||
}
|
||||
|
||||
void CKObjectManager::FreeGroupGlobalIndex(CKDWORD id) {
|
||||
// check position
|
||||
if (id >= m_GroupGlobalIndex.size()) return;
|
||||
// set value
|
||||
m_GroupGlobalIndex[id] = nullptr;
|
||||
m_GroupGlobalIndex[id] = false;
|
||||
}
|
||||
|
||||
void CKObjectManager::FreeSceneGlobalIndex(CKDWORD id) {
|
||||
// same as group
|
||||
if (id >= m_SceneGlobalIndex.size()) return;
|
||||
m_SceneGlobalIndex[id] = nullptr;
|
||||
m_SceneGlobalIndex[id] = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,12 +50,14 @@ namespace LibCmo::CK2::MgrImpls {
|
||||
XContainer::XObjectPointerArray GetObjectByNameAndClass(
|
||||
CKSTRING name, CK_CLASSID cid, bool derived);
|
||||
|
||||
// ========== Object Check ==========
|
||||
bool IsObjectSafe(CK_ID objid);
|
||||
bool IsObjectPointerSafe(const ObjImpls::CKObject* objptr);
|
||||
|
||||
// ========== Special Functions ==========
|
||||
|
||||
CKDWORD AllocateGroupGlobalIndex(ObjImpls::CKObject* group);
|
||||
CKDWORD AllocateSceneGlobalIndex(ObjImpls::CKObject* scene);
|
||||
ObjImpls::CKObject* GetGroupByGlobalIndex(CKDWORD index);
|
||||
ObjImpls::CKObject* GetSceneByGlobalIndex(CKDWORD index);
|
||||
CKDWORD AllocateGroupGlobalIndex();
|
||||
CKDWORD AllocateSceneGlobalIndex();
|
||||
void FreeGroupGlobalIndex(CKDWORD id);
|
||||
void FreeSceneGlobalIndex(CKDWORD id);
|
||||
|
||||
@ -77,11 +79,11 @@ namespace LibCmo::CK2::MgrImpls {
|
||||
|
||||
CKDWORD m_ObjectCount;
|
||||
XContainer::XObjectPointerArray m_ObjectsList;
|
||||
XContainer::XArray<XContainer::XArray<CKDWORD>> m_ObjectsListByClass;
|
||||
XContainer::XArray<XContainer::XList<CKDWORD>> m_ObjectsListByClass;
|
||||
std::deque<CKDWORD> m_ReturnedObjectOffsets;
|
||||
|
||||
XContainer::XObjectPointerArray m_GroupGlobalIndex;
|
||||
XContainer::XObjectPointerArray m_SceneGlobalIndex;
|
||||
XContainer::XBitArray m_GroupGlobalIndex;
|
||||
XContainer::XBitArray m_SceneGlobalIndex;
|
||||
|
||||
};
|
||||
|
||||
|
@ -8,16 +8,16 @@
|
||||
namespace LibCmo::CK2::ObjImpls {
|
||||
|
||||
CKBeObject::CKBeObject(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
||||
CKSceneObject(ctx, ckid, name) {}
|
||||
CKSceneObject(ctx, ckid, name), m_Groups() {}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
//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) {
|
||||
@ -36,12 +36,12 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
|
||||
bool CKBeObject::IsInGroup(CKGroup* group) {
|
||||
if (group == nullptr) return false;
|
||||
CKDWORD idx = group->CKBeObject_GetGroupIndex();
|
||||
CKDWORD idx = group->GetGroupIndex();
|
||||
if (idx >= m_Groups.size()) return false;
|
||||
return m_Groups[idx];
|
||||
}
|
||||
|
||||
void CKBeObject::CKGroup_SetGroups(CKDWORD pos, bool val) {
|
||||
void CKBeObject::ExplicitSetGroup(CKDWORD pos, bool val) {
|
||||
if (pos >= m_Groups.size()) m_Groups.resize(pos + 1);
|
||||
m_Groups[pos] = val;
|
||||
}
|
||||
|
@ -20,7 +20,13 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
//virtual void PostLoad() override;
|
||||
|
||||
bool IsInGroup(CKGroup* group);
|
||||
void CKGroup_SetGroups(CKDWORD pos, bool val);
|
||||
/**
|
||||
* @brief Directly set group data.
|
||||
* @param pos
|
||||
* @param val
|
||||
* @warning This function only should be called by CKGroup. Any other classes should not call this.
|
||||
*/
|
||||
void ExplicitSetGroup(CKDWORD pos, bool val);
|
||||
|
||||
protected:
|
||||
XContainer::XBitArray m_Groups;
|
||||
|
@ -9,7 +9,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
CKGroup::CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
||||
CKBeObject(ctx, ckid, name),
|
||||
m_ObjectArray(),
|
||||
m_GroupIndex(m_Context->GetObjectManager()->AllocateGroupGlobalIndex(this)) {}
|
||||
m_GroupIndex(m_Context->GetObjectManager()->AllocateGroupGlobalIndex()) {}
|
||||
|
||||
CKGroup::~CKGroup() {
|
||||
m_Context->GetObjectManager()->FreeGroupGlobalIndex(m_GroupIndex);
|
||||
@ -45,7 +45,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
if (beobj->IsInGroup(this)) continue;
|
||||
|
||||
// add good one
|
||||
beobj->CKGroup_SetGroups(m_GroupIndex, true);
|
||||
beobj->ExplicitSetGroup(m_GroupIndex, true);
|
||||
m_ObjectArray.emplace_back(beobj);
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
return true;
|
||||
}
|
||||
|
||||
CKDWORD CKGroup::CKBeObject_GetGroupIndex() {
|
||||
CKDWORD CKGroup::GetGroupIndex() {
|
||||
return m_GroupIndex;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
}
|
||||
|
||||
// set object
|
||||
o->CKGroup_SetGroups(m_GroupIndex, true);
|
||||
o->ExplicitSetGroup(m_GroupIndex, true);
|
||||
// set self
|
||||
m_ObjectArray.emplace_back(o);
|
||||
return CKERROR::CKERR_OK;
|
||||
@ -80,7 +80,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
auto it = m_ObjectArray.begin() + pos;
|
||||
CKBeObject* obj = static_cast<CKBeObject*>(*it);
|
||||
// set object
|
||||
obj->CKGroup_SetGroups(m_GroupIndex, false);
|
||||
obj->ExplicitSetGroup(m_GroupIndex, false);
|
||||
// remove self
|
||||
m_ObjectArray.erase(it);
|
||||
return obj;
|
||||
@ -91,7 +91,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
auto finder = std::find(m_ObjectArray.begin(), m_ObjectArray.end(), static_cast<CKObject*>(obj));
|
||||
if (finder != m_ObjectArray.end()) {
|
||||
// set object
|
||||
static_cast<CKBeObject*>(*finder)->CKGroup_SetGroups(m_GroupIndex, false);
|
||||
static_cast<CKBeObject*>(*finder)->ExplicitSetGroup(m_GroupIndex, false);
|
||||
// remove self
|
||||
m_ObjectArray.erase(finder);
|
||||
}
|
||||
@ -100,7 +100,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
void CKGroup::Clear() {
|
||||
for (auto& beobj : m_ObjectArray) {
|
||||
// set object
|
||||
static_cast<CKBeObject*>(beobj)->CKGroup_SetGroups(m_GroupIndex, false);
|
||||
static_cast<CKBeObject*>(beobj)->ExplicitSetGroup(m_GroupIndex, false);
|
||||
}
|
||||
|
||||
m_ObjectArray.clear();
|
||||
|
@ -19,7 +19,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file) override;
|
||||
//virtual void PostLoad() override;
|
||||
|
||||
CKDWORD CKBeObject_GetGroupIndex();
|
||||
CKDWORD GetGroupIndex();
|
||||
|
||||
// ===== Insert =====
|
||||
CKERROR AddObject(CKBeObject *o);
|
||||
|
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
#include "XTypes.hpp"
|
||||
#include "../CK2/CKContext.hpp"
|
||||
#include "../CK2/MgrImpls/CKObjectManager.hpp"
|
||||
#include "../CK2/ObjImpls/CKObject.hpp"
|
||||
#include <type_traits>
|
||||
|
||||
namespace LibCmo::XContainer {
|
||||
|
||||
@ -46,4 +49,84 @@ namespace LibCmo::XContainer {
|
||||
|
||||
}
|
||||
|
||||
template<class _Ty>
|
||||
constexpr bool GeneralXArrayCheck_TypeCheck() {
|
||||
return std::is_same_v<_Ty, CK2::CK_ID> || std::is_same_v<_Ty, CK2::ObjImpls::CKObject*>;
|
||||
}
|
||||
template<class _Ty, bool _IsPre>
|
||||
bool GeneralXArrayCheck_ItemCheck(const _Ty& item, CK2::CKContext* ctx) {
|
||||
static_assert(GeneralXArrayCheck_TypeCheck<_Ty>());
|
||||
if (ctx == nullptr) return false;
|
||||
|
||||
if constexpr (_IsPre) {
|
||||
CK2::ObjImpls::CKObject* obj = nullptr;
|
||||
if constexpr (std::is_same_v<_Ty, CK2::CK_ID>) {
|
||||
obj = ctx->GetObject(item);
|
||||
if (obj == nullptr) return false;
|
||||
} else {
|
||||
obj = item;
|
||||
}
|
||||
if (EnumsHelper::Has(obj->GetObjectFlags(), CK2::CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED)) return false;
|
||||
} else {
|
||||
CK2::MgrImpls::CKObjectManager* objmgr = ctx->GetObjectManager();
|
||||
if constexpr (std::is_same_v<_Ty, CK2::CK_ID>) {
|
||||
if (!objmgr->IsObjectSafe(item)) return false;
|
||||
} else {
|
||||
if (!objmgr->IsObjectPointerSafe(item)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
namespace NSXObjectArray {
|
||||
|
||||
void PreDeletedCheck(XObjectArray& objarray, CK2::CKContext* ctx) {
|
||||
if (ctx == nullptr) return;
|
||||
std::erase_if(objarray, [ctx](const CK2::CK_ID& item) -> bool {
|
||||
return GeneralXArrayCheck_ItemCheck<CK2::CK_ID, true>(item, ctx);
|
||||
});
|
||||
}
|
||||
|
||||
void PostDeletedCheck(XObjectArray& objarray, CK2::CKContext* ctx) {
|
||||
if (ctx == nullptr) return;
|
||||
std::erase_if(objarray, [ctx](const CK2::CK_ID& item) -> bool {
|
||||
return GeneralXArrayCheck_ItemCheck<CK2::CK_ID, false>(item, ctx);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
namespace NSXObjectPointerArray {
|
||||
|
||||
void PreDeletedCheck(XObjectPointerArray& objarray, CK2::CKContext* ctx) {
|
||||
if (ctx == nullptr) return;
|
||||
std::erase_if(objarray, [ctx](CK2::ObjImpls::CKObject* const& item) -> bool {
|
||||
return GeneralXArrayCheck_ItemCheck<CK2::ObjImpls::CKObject*, true>(item, ctx);
|
||||
});
|
||||
}
|
||||
|
||||
void PostDeletedCheck(XObjectPointerArray& objarray, CK2::CKContext* ctx) {
|
||||
if (ctx == nullptr) return;
|
||||
std::erase_if(objarray, [ctx](CK2::ObjImpls::CKObject* const& item) -> bool {
|
||||
return GeneralXArrayCheck_ItemCheck<CK2::ObjImpls::CKObject*, false>(item, ctx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void PreDeletedCheck(XList<CK2::ObjImpls::CKObject*>& objarray, CK2::CKContext* ctx) {
|
||||
if (ctx == nullptr) return;
|
||||
std::erase_if(objarray, [ctx](CK2::ObjImpls::CKObject* const& item) -> bool {
|
||||
return GeneralXArrayCheck_ItemCheck<CK2::ObjImpls::CKObject*, true>(item, ctx);
|
||||
});
|
||||
}
|
||||
|
||||
void PostDeletedCheck(XList<CK2::ObjImpls::CKObject*>& objarray, CK2::CKContext* ctx) {
|
||||
if (ctx == nullptr) return;
|
||||
std::erase_if(objarray, [ctx](CK2::ObjImpls::CKObject* const& item) -> bool {
|
||||
return GeneralXArrayCheck_ItemCheck<CK2::ObjImpls::CKObject*, false>(item, ctx);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
/**
|
||||
* @brief The X container part of LibCmo.
|
||||
@ -34,6 +35,13 @@ namespace LibCmo::XContainer {
|
||||
*/
|
||||
template<typename T>
|
||||
using XArray = std::vector<T>;
|
||||
|
||||
/**
|
||||
* @brief Double-linked list.
|
||||
* @tparam T Element Type.
|
||||
*/
|
||||
template<typename T>
|
||||
using XList = std::list<T>;
|
||||
|
||||
/**
|
||||
@brief Container class for CKObject Id's.
|
||||
@ -105,5 +113,54 @@ namespace LibCmo::XContainer {
|
||||
|
||||
}
|
||||
|
||||
namespace NSXObjectArray {
|
||||
|
||||
/**
|
||||
* @brief Check Object ID validation and remove invalid IDs before deletion.
|
||||
* @param objarray
|
||||
* @param ctx
|
||||
*/
|
||||
void PreDeletedCheck(XObjectArray& objarray, CK2::CKContext* ctx);
|
||||
/**
|
||||
* @brief Check Object ID validation and remove invalid IDs after deletion.
|
||||
* @param objarray
|
||||
* @param ctx
|
||||
*/
|
||||
void PostDeletedCheck(XObjectArray& objarray, CK2::CKContext* ctx);
|
||||
|
||||
}
|
||||
|
||||
namespace NSXObjectPointerArray {
|
||||
|
||||
/**
|
||||
* @brief Check Object pointer validation and remove invalid pointers before deletion.
|
||||
* @param objarray
|
||||
* @param ctx
|
||||
*/
|
||||
void PreDeletedCheck(XObjectPointerArray& objarray, CK2::CKContext* ctx);
|
||||
/**
|
||||
* @brief Check Object pointer validation and remove invalid pointers after deletion.
|
||||
* @param objarray
|
||||
* @param ctx
|
||||
* @remark The performance of this function is extremely low. Use it carefully.
|
||||
*/
|
||||
void PostDeletedCheck(XObjectPointerArray& objarray, CK2::CKContext* ctx);
|
||||
|
||||
/**
|
||||
* @brief Check Object pointer validation and remove invalid pointers before deletion.
|
||||
* @param objarray
|
||||
* @param ctx
|
||||
*/
|
||||
void PreDeletedCheck(XList<CK2::ObjImpls::CKObject*>& objarray, CK2::CKContext* ctx);
|
||||
/**
|
||||
* @brief Check Object pointer validation and remove invalid pointers after deletion.
|
||||
* @param objarray
|
||||
* @param ctx
|
||||
* @remark The performance of this function is extremely low. Use it carefully.
|
||||
*/
|
||||
void PostDeletedCheck(XList<CK2::ObjImpls::CKObject*>& objarray, CK2::CKContext* ctx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user