basically finish register. still have bug
This commit is contained in:
parent
230b18c0ba
commit
c6608dec57
@ -162,7 +162,7 @@ namespace LibCmo::CK2 {
|
|||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
CreateImage(width, height, i);
|
CreateImage(width, height, i);
|
||||||
if (ReadSpecificFormatBitmap(chunk, GetImageDesc(i))) {
|
if (ReadSpecificFormatBitmap(chunk, GetImageDesc(i))) {
|
||||||
hasReadSlot[i] = true;
|
XContainer::NSXBitArray::Set(hasReadSlot, i);
|
||||||
} else {
|
} else {
|
||||||
ReleaseImage(i);
|
ReleaseImage(i);
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ namespace LibCmo::CK2 {
|
|||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
VxMath::VxImageDescEx rawcache;
|
VxMath::VxImageDescEx rawcache;
|
||||||
if (ReadRawBitmap(chunk, &rawcache)) {
|
if (ReadRawBitmap(chunk, &rawcache)) {
|
||||||
hasReadSlot[i] = true;
|
XContainer::NSXBitArray::Set(hasReadSlot, i);
|
||||||
|
|
||||||
// do upside down blit
|
// do upside down blit
|
||||||
CreateImage(rawcache.GetWidth(), rawcache.GetHeight(), i);
|
CreateImage(rawcache.GetWidth(), rawcache.GetHeight(), i);
|
||||||
@ -202,7 +202,7 @@ namespace LibCmo::CK2 {
|
|||||||
// MARK: a rough implement because we do not support this identifier
|
// MARK: a rough implement because we do not support this identifier
|
||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
if (ReadOldRawBitmap(chunk, GetImageDesc(i))) {
|
if (ReadOldRawBitmap(chunk, GetImageDesc(i))) {
|
||||||
hasReadSlot[i] = true;
|
XContainer::NSXBitArray::Set(hasReadSlot, i);
|
||||||
} else {
|
} else {
|
||||||
ReleaseImage(i);
|
ReleaseImage(i);
|
||||||
}
|
}
|
||||||
@ -224,7 +224,7 @@ namespace LibCmo::CK2 {
|
|||||||
chunk->ReadString(filename);
|
chunk->ReadString(filename);
|
||||||
if (filename.empty()) continue;
|
if (filename.empty()) continue;
|
||||||
|
|
||||||
bool isNotLoaded = (i >= hasReadSlot.size()) || (!hasReadSlot[i]);
|
bool isNotLoaded = (i >= hasReadSlot.size()) || (!XContainer::NSXBitArray::IsSet(hasReadSlot, i));
|
||||||
if (isNotLoaded) {
|
if (isNotLoaded) {
|
||||||
// if this image is not loaded.
|
// if this image is not loaded.
|
||||||
// try resolve its file name and load it.
|
// try resolve its file name and load it.
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "CKGlobals.hpp"
|
#include "CKGlobals.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
#include "ObjImpls/CKObject.hpp"
|
#include "ObjImpls/CKObject.hpp"
|
||||||
#include "ObjImpls/CKSceneObject.hpp"
|
#include "ObjImpls/CKSceneObject.hpp"
|
||||||
@ -111,6 +112,20 @@ namespace LibCmo::CK2 {
|
|||||||
|
|
||||||
static XContainer::XArray<CKClassDesc> g_CKClassInfo;
|
static XContainer::XArray<CKClassDesc> g_CKClassInfo;
|
||||||
|
|
||||||
|
static bool GetClassIdIndex(CK_CLASSID cid, size_t& intcid) {
|
||||||
|
intcid = static_cast<size_t>(cid);
|
||||||
|
if (intcid >= g_CKClassInfo.size()) return false;
|
||||||
|
if (!g_CKClassInfo[intcid].IsValid) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo) {
|
||||||
|
size_t idxListener, idxListenTo;
|
||||||
|
if (!GetClassIdIndex(listener, idxListener) || !GetClassIdIndex(listenTo, idxListenTo)) return;
|
||||||
|
|
||||||
|
XContainer::NSXBitArray::Set(g_CKClassInfo[idxListener].ToBeNotify, static_cast<CKDWORD>(idxListenTo));
|
||||||
|
}
|
||||||
|
|
||||||
CK_CLASSID CKClassGetNewIdentifier() {
|
CK_CLASSID CKClassGetNewIdentifier() {
|
||||||
size_t classsize = g_CKClassInfo.size();
|
size_t classsize = g_CKClassInfo.size();
|
||||||
if (classsize < static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID)) {
|
if (classsize < static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID)) {
|
||||||
@ -120,64 +135,8 @@ namespace LibCmo::CK2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ComputeParentsTable(CKClassDesc& desc) {
|
|
||||||
// if it has done, do not process it again.
|
|
||||||
if (desc.Done) return;
|
|
||||||
|
|
||||||
// find direct parent
|
|
||||||
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
|
|
||||||
if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
|
|
||||||
|
|
||||||
// if it is not self inheritance, call recursively
|
|
||||||
if (desc.Self != desc.Parent) {
|
|
||||||
ComputeParentsTable(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy parent's parents
|
|
||||||
desc.Parents = parent.Parents;
|
|
||||||
// and set self as its parent
|
|
||||||
desc.Parents[static_cast<size_t>(desc.Self)] = true;
|
|
||||||
|
|
||||||
// set derivation level
|
|
||||||
desc.DerivationLevel = parent.DerivationLevel + 1;
|
|
||||||
|
|
||||||
// set done
|
|
||||||
desc.Done = true;
|
|
||||||
}
|
|
||||||
static void CKBuildClassHierarchyTable() {
|
|
||||||
// set Done to false and resize all XBitArray
|
|
||||||
size_t classCount = g_CKClassInfo.size();
|
|
||||||
for (auto& item : g_CKClassInfo) {
|
|
||||||
if (!item.IsValid) continue;
|
|
||||||
|
|
||||||
item.Done = false;
|
|
||||||
item.Parents.resize(classCount, false);
|
|
||||||
item.Children.resize(classCount, false);
|
|
||||||
}
|
|
||||||
// compute parents
|
|
||||||
for (auto& item : g_CKClassInfo) {
|
|
||||||
if (!item.IsValid) continue;
|
|
||||||
|
|
||||||
ComputeParentsTable(item);
|
|
||||||
}
|
|
||||||
// compute children by parents table
|
|
||||||
// iterate CKClassDesc::Parents and register it self to gotten parents
|
|
||||||
for (auto& item : g_CKClassInfo) {
|
|
||||||
if (!item.IsValid) continue;
|
|
||||||
|
|
||||||
for (size_t idx = 0; idx < classCount; ++idx) {
|
|
||||||
if (!g_CKClassInfo[idx].IsValid) continue;
|
|
||||||
|
|
||||||
// if this idx is its parent,
|
|
||||||
// add self to parent.
|
|
||||||
if (item.Parents[idx]) {
|
|
||||||
g_CKClassInfo[idx].Children[static_cast<size_t>(item.Self)] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
||||||
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) {
|
CKClassRegisterFct regFct, CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) {
|
||||||
|
|
||||||
// resize class desc array
|
// resize class desc array
|
||||||
size_t intcid = static_cast<size_t>(cid);
|
size_t intcid = static_cast<size_t>(cid);
|
||||||
@ -190,6 +149,7 @@ namespace LibCmo::CK2 {
|
|||||||
desc.IsValid = true;
|
desc.IsValid = true;
|
||||||
desc.Self = cid;
|
desc.Self = cid;
|
||||||
desc.Parent = parentCid;
|
desc.Parent = parentCid;
|
||||||
|
desc.RegisterFct = regFct;
|
||||||
desc.CreationFct = createFct;
|
desc.CreationFct = createFct;
|
||||||
desc.ReleaseFct = relFct;
|
desc.ReleaseFct = relFct;
|
||||||
desc.NameFct = nameFct;
|
desc.NameFct = nameFct;
|
||||||
@ -200,13 +160,6 @@ namespace LibCmo::CK2 {
|
|||||||
|
|
||||||
#pragma region Class Hierarchy Management
|
#pragma region Class Hierarchy Management
|
||||||
|
|
||||||
static bool GetClassIdIndex(CK_CLASSID cid, size_t& intcid) {
|
|
||||||
intcid = static_cast<size_t>(cid);
|
|
||||||
if (intcid >= g_CKClassInfo.size()) return false;
|
|
||||||
if (!g_CKClassInfo[intcid].IsValid) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CKDWORD CKGetClassCount() {
|
CKDWORD CKGetClassCount() {
|
||||||
return static_cast<CKDWORD>(g_CKClassInfo.size());
|
return static_cast<CKDWORD>(g_CKClassInfo.size());
|
||||||
}
|
}
|
||||||
@ -248,18 +201,172 @@ namespace LibCmo::CK2 {
|
|||||||
return cid1;
|
return cid1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid) {
|
||||||
|
const CKClassDesc* desc = CKGetClassDesc(listener);
|
||||||
|
if (desc == nullptr) return false;
|
||||||
|
return XContainer::NSXBitArray::IsSet(desc->CommonToBeNotify, static_cast<CKDWORD>(deletedObjCid));
|
||||||
|
}
|
||||||
|
|
||||||
|
XContainer::XBitArray CKGetAllNotifyClassID(const XContainer::XBitArray& delObjCids) {
|
||||||
|
XContainer::XBitArray result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < delObjCids.size(); ++i) {
|
||||||
|
if (!XContainer::NSXBitArray::IsSet(delObjCids, static_cast<CKDWORD>(i))) continue;
|
||||||
|
|
||||||
|
const CKClassDesc* desc = CKGetClassDesc(static_cast<CK_CLASSID>(i));
|
||||||
|
if (desc == nullptr) continue;
|
||||||
|
|
||||||
|
XContainer::NSXBitArray::Or(result, desc->ToNotify);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Initializations functions
|
#pragma region Initializations functions
|
||||||
|
|
||||||
CKERROR CKStartUp() {
|
static void ComputeParentsTable(CKClassDesc& desc) {
|
||||||
|
// if it has done, do not process it again.
|
||||||
|
if (desc.Done) return;
|
||||||
|
|
||||||
|
// find direct parent
|
||||||
|
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
|
||||||
|
if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
|
||||||
|
|
||||||
|
// if it is not self inheritance, call recursively
|
||||||
|
if (desc.Self != desc.Parent) {
|
||||||
|
ComputeParentsTable(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy parent's parents
|
||||||
|
desc.Parents = parent.Parents;
|
||||||
|
// and set self as its parent
|
||||||
|
XContainer::NSXBitArray::Set(desc.Parents, static_cast<CKDWORD>(desc.Self));
|
||||||
|
|
||||||
|
// set derivation level
|
||||||
|
desc.DerivationLevel = parent.DerivationLevel + 1;
|
||||||
|
|
||||||
|
// set done
|
||||||
|
desc.Done = true;
|
||||||
|
}
|
||||||
|
static void ComputeParentsNotifyTable(CKClassDesc& desc) {
|
||||||
|
// if it has done, do not process it again.
|
||||||
|
if (desc.Done) return;
|
||||||
|
|
||||||
|
// find direct parent
|
||||||
|
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
|
||||||
|
if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
|
||||||
|
|
||||||
|
// if it is not self inheritance, call recursively
|
||||||
|
if (desc.Self != desc.Parent) {
|
||||||
|
ComputeParentsNotifyTable(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy self notify first
|
||||||
|
desc.CommonToBeNotify = desc.ToBeNotify;
|
||||||
|
// and merge parent notify list
|
||||||
|
XContainer::NSXBitArray::Or(desc.CommonToBeNotify, parent.CommonToBeNotify);
|
||||||
|
|
||||||
|
// set done
|
||||||
|
desc.Done = true;
|
||||||
|
}
|
||||||
|
static void CKBuildClassHierarchyTable() {
|
||||||
|
size_t classCount = g_CKClassInfo.size();
|
||||||
|
|
||||||
|
// ===== Build Inhertance Hierarchy =====
|
||||||
|
// set Done to false and resize inhertance XBitArray
|
||||||
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
|
item.Done = false;
|
||||||
|
|
||||||
|
XContainer::NSXBitArray::Resize(item.Parents, static_cast<CKDWORD>(classCount));
|
||||||
|
XContainer::NSXBitArray::Resize(item.Children, static_cast<CKDWORD>(classCount));
|
||||||
|
}
|
||||||
|
// compute parents
|
||||||
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
|
ComputeParentsTable(item);
|
||||||
|
}
|
||||||
|
// compute children by parents table
|
||||||
|
// iterate CKClassDesc::Parents and register it self to gotten parents
|
||||||
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
|
for (size_t idx = 0; idx < classCount; ++idx) {
|
||||||
|
if (!g_CKClassInfo[idx].IsValid) continue;
|
||||||
|
|
||||||
|
// if this idx is its parent,
|
||||||
|
// add self to parent.
|
||||||
|
if (XContainer::NSXBitArray::IsSet(item.Parents, static_cast<CKDWORD>(idx))) {
|
||||||
|
XContainer::NSXBitArray::Set(g_CKClassInfo[idx].Children, static_cast<CKDWORD>(item.Self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Register =====
|
||||||
|
// run register
|
||||||
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid || item.RegisterFct == nullptr) continue;
|
||||||
|
item.RegisterFct();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Build Notify Hierarchy =====
|
||||||
|
// set Done to false and resize notify XBitArray
|
||||||
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
|
item.Done = false;
|
||||||
|
|
||||||
|
XContainer::NSXBitArray::Resize(item.ToBeNotify, static_cast<CKDWORD>(classCount));
|
||||||
|
XContainer::NSXBitArray::Resize(item.CommonToBeNotify, static_cast<CKDWORD>(classCount));
|
||||||
|
XContainer::NSXBitArray::Resize(item.ToNotify, static_cast<CKDWORD>(classCount));
|
||||||
|
}
|
||||||
|
// compute notify
|
||||||
|
for (auto& item : g_CKClassInfo) {
|
||||||
|
if (!item.IsValid) continue;
|
||||||
|
|
||||||
|
ComputeParentsNotifyTable(item);
|
||||||
|
}
|
||||||
|
// compute ToNotify table
|
||||||
|
// for each desc(represented as outter 'for'), iterate all desc(represented as inner 'for'), and check whether its
|
||||||
|
// CommonToBeNotify contain this desc. If true, add checking desc into this desc's ToNotify.
|
||||||
|
for (size_t idx = 0; idx < classCount; ++idx) {
|
||||||
|
if (!g_CKClassInfo[idx].IsValid) continue;
|
||||||
|
|
||||||
|
for (const auto& checkingDesc : g_CKClassInfo) {
|
||||||
|
if(!checkingDesc.IsValid) continue;
|
||||||
|
|
||||||
|
// if checkingDesc's CommonToBeNotify order this desc,
|
||||||
|
// add checking desc to ToNofity
|
||||||
|
if (XContainer::NSXBitArray::IsSet(checkingDesc.CommonToBeNotify, static_cast<CKDWORD>(idx))) {
|
||||||
|
XContainer::NSXBitArray::Set(g_CKClassInfo[idx].ToNotify, static_cast<CKDWORD>(checkingDesc.Self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NeedNotificationWrapper(CK_CLASSID thiscid, std::initializer_list<CK_CLASSID> il) {
|
||||||
|
for (auto it = il.begin(); it != il.end(); ++it) {
|
||||||
|
CKClassNeedNotificationFrom(thiscid, *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CKERROR CKStartUp() {
|
||||||
// reserve class info array.
|
// reserve class info array.
|
||||||
g_CKClassInfo.reserve(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
g_CKClassInfo.reserve(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
||||||
|
|
||||||
// todo: add class type registrations
|
// todo: add class type registrations
|
||||||
#define EasyClassReg(clsname, cid, parentCid, strName) \
|
#define EasyClassReg(clsname, cid, parentCid, strName) \
|
||||||
CKClassRegister(cid, parentCid, \
|
CKClassRegister(cid, parentCid, \
|
||||||
|
nullptr, \
|
||||||
|
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
|
||||||
|
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
|
||||||
|
[]() -> CKSTRING { return strName; });
|
||||||
|
#define EasyClassRegWithNotify(clsname, cid, parentCid, strName, notifyCids) \
|
||||||
|
CKClassRegister(cid, parentCid, \
|
||||||
|
[]() -> void { NeedNotificationWrapper(cid, notifyCids); }, \
|
||||||
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
|
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
|
||||||
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
|
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
|
||||||
[]() -> CKSTRING { return strName; });
|
[]() -> CKSTRING { return strName; });
|
||||||
@ -267,7 +374,7 @@ CKClassRegister(cid, parentCid, \
|
|||||||
EasyClassReg(ObjImpls::CKObject, CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT, "Basic Object");
|
EasyClassReg(ObjImpls::CKObject, CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT, "Basic Object");
|
||||||
EasyClassReg(ObjImpls::CKSceneObject, CK_CLASSID::CKCID_SCENEOBJECT, CK_CLASSID::CKCID_OBJECT, "Scene Object");
|
EasyClassReg(ObjImpls::CKSceneObject, CK_CLASSID::CKCID_SCENEOBJECT, CK_CLASSID::CKCID_OBJECT, "Scene Object");
|
||||||
EasyClassReg(ObjImpls::CKBeObject, CK_CLASSID::CKCID_BEOBJECT, CK_CLASSID::CKCID_SCENEOBJECT, "Behavioral Object");
|
EasyClassReg(ObjImpls::CKBeObject, CK_CLASSID::CKCID_BEOBJECT, CK_CLASSID::CKCID_SCENEOBJECT, "Behavioral Object");
|
||||||
EasyClassReg(ObjImpls::CKGroup, CK_CLASSID::CKCID_GROUP, CK_CLASSID::CKCID_BEOBJECT, "Group");
|
EasyClassRegWithNotify(ObjImpls::CKGroup, CK_CLASSID::CKCID_GROUP, CK_CLASSID::CKCID_BEOBJECT, "Group", { CK_CLASSID::CKCID_BEOBJECT });
|
||||||
EasyClassReg(ObjImpls::CKRenderObject, CK_CLASSID::CKCID_RENDEROBJECT, CK_CLASSID::CKCID_BEOBJECT, "Render Object");
|
EasyClassReg(ObjImpls::CKRenderObject, CK_CLASSID::CKCID_RENDEROBJECT, CK_CLASSID::CKCID_BEOBJECT, "Render Object");
|
||||||
EasyClassReg(ObjImpls::CK3dEntity, CK_CLASSID::CKCID_3DENTITY, CK_CLASSID::CKCID_RENDEROBJECT, "3D Entity");
|
EasyClassReg(ObjImpls::CK3dEntity, CK_CLASSID::CKCID_3DENTITY, CK_CLASSID::CKCID_RENDEROBJECT, "3D Entity");
|
||||||
EasyClassReg(ObjImpls::CK3dObject, CK_CLASSID::CKCID_3DOBJECT, CK_CLASSID::CKCID_3DENTITY, "3D Object");
|
EasyClassReg(ObjImpls::CK3dObject, CK_CLASSID::CKCID_3DOBJECT, CK_CLASSID::CKCID_3DENTITY, "3D Object");
|
||||||
@ -275,6 +382,7 @@ CKClassRegister(cid, parentCid, \
|
|||||||
EasyClassReg(ObjImpls::CKMaterial, CK_CLASSID::CKCID_MATERIAL, CK_CLASSID::CKCID_BEOBJECT, "Material");
|
EasyClassReg(ObjImpls::CKMaterial, CK_CLASSID::CKCID_MATERIAL, CK_CLASSID::CKCID_BEOBJECT, "Material");
|
||||||
|
|
||||||
#undef EasyClassReg
|
#undef EasyClassReg
|
||||||
|
#undef EasyClassRegWithNotify
|
||||||
|
|
||||||
CKBuildClassHierarchyTable();
|
CKBuildClassHierarchyTable();
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ namespace LibCmo::CK2 {
|
|||||||
|
|
||||||
// ========== Class registration utilities ==========
|
// ========== Class registration utilities ==========
|
||||||
|
|
||||||
//using CKClassRegisterFct = std::function<void()>;
|
using CKClassRegisterFct = std::function<void()>;
|
||||||
using CKClassCreationFct = std::function<ObjImpls::CKObject* (CKContext*, CK_ID, CKSTRING)>;
|
using CKClassCreationFct = std::function<ObjImpls::CKObject* (CKContext*, CK_ID, CKSTRING)>;
|
||||||
using CKClassReleaseFct = std::function<void(CKContext*, ObjImpls::CKObject*)>;
|
using CKClassReleaseFct = std::function<void(CKContext*, ObjImpls::CKObject*)>;
|
||||||
using CKClassNameFct = std::function<CKSTRING()>;
|
using CKClassNameFct = std::function<CKSTRING()>;
|
||||||
@ -87,7 +87,7 @@ namespace LibCmo::CK2 {
|
|||||||
// Initialized upon class registration
|
// Initialized upon class registration
|
||||||
CK_CLASSID Self;
|
CK_CLASSID Self;
|
||||||
CK_CLASSID Parent; // Class Identifier of parent class
|
CK_CLASSID Parent; // Class Identifier of parent class
|
||||||
//CKClassRegisterFct RegisterFct; // Pointer to Class Specific Registration function
|
CKClassRegisterFct RegisterFct; // Pointer to Class Specific Registration function
|
||||||
CKClassCreationFct CreationFct; // Pointer to Class instance creation function
|
CKClassCreationFct CreationFct; // Pointer to Class instance creation function
|
||||||
CKClassReleaseFct ReleaseFct; // Pointer to Class instance release function
|
CKClassReleaseFct ReleaseFct; // Pointer to Class instance release function
|
||||||
CKClassNameFct NameFct; // Pointer to Class name function
|
CKClassNameFct NameFct; // Pointer to Class name function
|
||||||
@ -106,26 +106,27 @@ namespace LibCmo::CK2 {
|
|||||||
CKINT DerivationLevel; // O => CKObject , etc..
|
CKINT DerivationLevel; // O => CKObject , etc..
|
||||||
XContainer::XBitArray Parents; // Bit Mask of parents classes
|
XContainer::XBitArray Parents; // Bit Mask of parents classes
|
||||||
XContainer::XBitArray Children; // Bit Mask of children classes
|
XContainer::XBitArray Children; // Bit Mask of children classes
|
||||||
//XContainer::XBitArray ToBeNotify; // Mask for Classes that should warn the objects of this class when they are deleted
|
XContainer::XBitArray ToBeNotify; // User specified notify list, only for current class.
|
||||||
//XContainer::XBitArray CommonToBeNotify; // idem but merged with sub classes masks
|
XContainer::XBitArray CommonToBeNotify; // Same as ToBeNotify, but merging all parents' notify list.
|
||||||
//XContainer::XSArray<CK_CLASSID> ToNotify; // List of ClassID to notify when an object of this class is deleted (inverse of ToBeNotify)
|
XContainer::XBitArray ToNotify; // The ClassID to notify when an object of this class is deleted (inverse of ToBeNotify)
|
||||||
|
|
||||||
CKClassDesc() :
|
CKClassDesc() :
|
||||||
IsValid(false),
|
IsValid(false),
|
||||||
Done(false),
|
Done(false),
|
||||||
Self(CK_CLASSID::CKCID_OBJECT), Parent(CK_CLASSID::CKCID_OBJECT),
|
Self(CK_CLASSID::CKCID_OBJECT), Parent(CK_CLASSID::CKCID_OBJECT),
|
||||||
CreationFct(nullptr), ReleaseFct(nullptr), NameFct(nullptr),
|
RegisterFct(nullptr), CreationFct(nullptr), ReleaseFct(nullptr), NameFct(nullptr),
|
||||||
DerivationLevel(0),
|
DerivationLevel(0),
|
||||||
Parents(), Children()
|
Parents(), Children(), ToBeNotify(), CommonToBeNotify()
|
||||||
{}
|
{}
|
||||||
LIBCMO_DEFAULT_COPY_MOVE(CKClassDesc);
|
LIBCMO_DEFAULT_COPY_MOVE(CKClassDesc);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== CKClass Registration ==========
|
// ========== CKClass Registration ==========
|
||||||
|
|
||||||
|
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo);
|
||||||
CK_CLASSID CKClassGetNewIdentifier();
|
CK_CLASSID CKClassGetNewIdentifier();
|
||||||
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
||||||
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
CKClassRegisterFct regFct, CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
||||||
|
|
||||||
// ========== Class Hierarchy Management ==========
|
// ========== Class Hierarchy Management ==========
|
||||||
|
|
||||||
@ -137,6 +138,21 @@ namespace LibCmo::CK2 {
|
|||||||
CK_CLASSID CKGetParentClassID(CK_CLASSID child);
|
CK_CLASSID CKGetParentClassID(CK_CLASSID child);
|
||||||
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2);
|
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether 'listener' need notified by the deletion of 'deletedObjCid'
|
||||||
|
* @param listener
|
||||||
|
* @param deletedObjCid
|
||||||
|
* @return true if need notify
|
||||||
|
*/
|
||||||
|
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid);
|
||||||
|
/**
|
||||||
|
* @brief Get all object cid need to be notified when 'delObjCids' matched objects are deleting.
|
||||||
|
* @param delObjCids
|
||||||
|
* @param cidCount
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
XContainer::XBitArray CKGetAllNotifyClassID(const XContainer::XBitArray& delObjCids);
|
||||||
|
|
||||||
// ========== Initializations functions ==========
|
// ========== Initializations functions ==========
|
||||||
CKERROR CKStartUp();
|
CKERROR CKStartUp();
|
||||||
CKERROR CKShutdown();
|
CKERROR CKShutdown();
|
||||||
|
@ -72,17 +72,55 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CKObjectManager::DestroyObjects(CK_ID* ids, CKDWORD count) {
|
void CKObjectManager::DestroyObjects(CK_ID* ids, CKDWORD count) {
|
||||||
// notice pre
|
// pre notice manager
|
||||||
m_Context->ExecuteManagersOnSequenceToBeDeleted(ids, count);
|
m_Context->ExecuteManagersOnSequenceToBeDeleted(ids, count);
|
||||||
|
|
||||||
|
// collect object data
|
||||||
|
// remove invalid object first, set them to be deleted
|
||||||
|
// collection deleted object class ids
|
||||||
|
XContainer::XObjectArray validObjIds;
|
||||||
|
XContainer::XBitArray cids;
|
||||||
for (CKDWORD i = 0; i < count; ++i) {
|
for (CKDWORD i = 0; i < count; ++i) {
|
||||||
CKDWORD off = Id2Offset(ids[i]);
|
CKDWORD off = Id2Offset(ids[i]);
|
||||||
if (off >= m_ObjectsList.size()) continue;
|
if (off >= m_ObjectsList.size()) continue;
|
||||||
|
|
||||||
// get object and its classid for future use
|
|
||||||
ObjImpls::CKObject* obj = m_ObjectsList[off];
|
ObjImpls::CKObject* obj = m_ObjectsList[off];
|
||||||
if (obj == nullptr) continue;
|
if (obj == nullptr) continue;
|
||||||
CK_CLASSID cls = obj->GetClassID();
|
|
||||||
|
// set to be deleted
|
||||||
|
CK_OBJECT_FLAGS objflag = obj->GetObjectFlags();
|
||||||
|
EnumsHelper::Add(objflag, CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED);
|
||||||
|
obj->SetObjectFlags(objflag);
|
||||||
|
|
||||||
|
// collect class id
|
||||||
|
XContainer::NSXBitArray::Set(cids, static_cast<CKDWORD>(obj->GetClassID()));
|
||||||
|
|
||||||
|
// add into list
|
||||||
|
validObjIds.emplace_back(ids[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then remove deleted object from m_ObjectListByClass
|
||||||
|
// because we have set to be deleted flag.
|
||||||
|
for (size_t i = 0; i < m_ObjectsListByClass.size(); ++i) {
|
||||||
|
if (!XContainer::NSXBitArray::IsSet(cids, static_cast<CKDWORD>(i)))
|
||||||
|
continue;
|
||||||
|
XContainer::NSXObjectArray::PreDeletedCheck(m_ObjectsListByClass[i], m_Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// use collected cid to get all class ids which need receive notify
|
||||||
|
// and use m_ObjectListByClass to notify them
|
||||||
|
XContainer::XBitArray notifyCids = CKGetAllNotifyClassID(cids);
|
||||||
|
for (size_t i = 0; i < m_ObjectsListByClass.size(); ++i) {
|
||||||
|
if (!XContainer::NSXBitArray::IsSet(notifyCids, static_cast<CKDWORD>(i)))
|
||||||
|
continue;
|
||||||
|
for (auto& objid : m_ObjectsListByClass[i]) {
|
||||||
|
m_ObjectsList[Id2Offset(objid)]->CheckPreDeletion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then free all valid object
|
||||||
|
for (const auto& objid : validObjIds) {
|
||||||
|
CKDWORD off = Id2Offset(objid);
|
||||||
|
ObjImpls::CKObject* obj = m_ObjectsList[off];
|
||||||
|
|
||||||
// free it
|
// free it
|
||||||
InternalDestroy(obj);
|
InternalDestroy(obj);
|
||||||
@ -92,10 +130,15 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
m_ObjectsList[off] = nullptr;
|
m_ObjectsList[off] = nullptr;
|
||||||
m_ReturnedObjectOffsets.emplace_back(off);
|
m_ReturnedObjectOffsets.emplace_back(off);
|
||||||
--m_ObjectCount;
|
--m_ObjectCount;
|
||||||
|
}
|
||||||
|
|
||||||
// remove from classid indexed list
|
// run post deletion for notify object
|
||||||
std::erase(m_ObjectsListByClass[static_cast<size_t>(cls)], ids[i]);
|
for (size_t i = 0; i < m_ObjectsListByClass.size(); ++i) {
|
||||||
|
if (!XContainer::NSXBitArray::IsSet(notifyCids, static_cast<CKDWORD>(i)))
|
||||||
|
continue;
|
||||||
|
for (auto& objid : m_ObjectsListByClass[i]) {
|
||||||
|
m_ObjectsList[Id2Offset(objid)]->CheckPostDeletion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// notice post
|
// notice post
|
||||||
@ -156,6 +199,8 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma region Object Check
|
||||||
|
|
||||||
bool CKObjectManager::IsObjectSafe(CK_ID objid) {
|
bool CKObjectManager::IsObjectSafe(CK_ID objid) {
|
||||||
CKDWORD off = Id2Offset(objid);
|
CKDWORD off = Id2Offset(objid);
|
||||||
if (off >= m_ObjectsList.size()) return false;
|
if (off >= m_ObjectsList.size()) return false;
|
||||||
@ -172,6 +217,10 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Special Functions
|
||||||
|
|
||||||
CKDWORD CKObjectManager::AllocateGroupGlobalIndex() {
|
CKDWORD CKObjectManager::AllocateGroupGlobalIndex() {
|
||||||
// try find first non-true position
|
// try find first non-true position
|
||||||
CKDWORD index;
|
CKDWORD index;
|
||||||
@ -182,7 +231,7 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set to occupy
|
// set to occupy
|
||||||
m_GroupGlobalIndex[index] = true;
|
XContainer::NSXBitArray::Set(m_GroupGlobalIndex, index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +243,7 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
m_SceneGlobalIndex.resize(m_SceneGlobalIndex.size() + 1);
|
m_SceneGlobalIndex.resize(m_SceneGlobalIndex.size() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_SceneGlobalIndex[index] = true;
|
XContainer::NSXBitArray::Set(m_SceneGlobalIndex, index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,13 +251,15 @@ namespace LibCmo::CK2::MgrImpls {
|
|||||||
// check position
|
// check position
|
||||||
if (id >= m_GroupGlobalIndex.size()) return;
|
if (id >= m_GroupGlobalIndex.size()) return;
|
||||||
// set value
|
// set value
|
||||||
m_GroupGlobalIndex[id] = false;
|
XContainer::NSXBitArray::Unset(m_GroupGlobalIndex, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKObjectManager::FreeSceneGlobalIndex(CKDWORD id) {
|
void CKObjectManager::FreeSceneGlobalIndex(CKDWORD id) {
|
||||||
// same as group
|
// same as group
|
||||||
if (id >= m_SceneGlobalIndex.size()) return;
|
if (id >= m_SceneGlobalIndex.size()) return;
|
||||||
m_SceneGlobalIndex[id] = false;
|
XContainer::NSXBitArray::Unset(m_SceneGlobalIndex, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,13 +37,15 @@ namespace LibCmo::CK2::ObjImpls {
|
|||||||
bool CKBeObject::IsInGroup(CKGroup* group) {
|
bool CKBeObject::IsInGroup(CKGroup* group) {
|
||||||
if (group == nullptr) return false;
|
if (group == nullptr) return false;
|
||||||
CKDWORD idx = group->GetGroupIndex();
|
CKDWORD idx = group->GetGroupIndex();
|
||||||
if (idx >= m_Groups.size()) return false;
|
return XContainer::NSXBitArray::IsSet(m_Groups, idx);
|
||||||
return m_Groups[idx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKBeObject::ExplicitSetGroup(CKDWORD pos, bool val) {
|
void CKBeObject::ExplicitSetGroup(CKDWORD pos, bool val) {
|
||||||
if (pos >= m_Groups.size()) m_Groups.resize(pos + 1);
|
if (val) {
|
||||||
m_Groups[pos] = val;
|
XContainer::NSXBitArray::Set(m_Groups, pos);
|
||||||
|
} else {
|
||||||
|
XContainer::NSXBitArray::Unset(m_Groups, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
namespace LibCmo::CK2::ObjImpls {
|
namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
|
void CKObject::CheckPreDeletion() {}
|
||||||
|
void CKObject::CheckPostDeletion() {}
|
||||||
|
|
||||||
void CKObject::PreSave(CKFileVisitor* file, CKDWORD flags) {}
|
void CKObject::PreSave(CKFileVisitor* file, CKDWORD flags) {}
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ namespace LibCmo::CK2::ObjImpls {
|
|||||||
virtual CK_CLASSID GetClassID(void) {
|
virtual CK_CLASSID GetClassID(void) {
|
||||||
return CK_CLASSID::CKCID_OBJECT;
|
return CK_CLASSID::CKCID_OBJECT;
|
||||||
}
|
}
|
||||||
|
virtual void CheckPreDeletion();
|
||||||
|
virtual void CheckPostDeletion();
|
||||||
virtual void PreSave(CKFileVisitor* file, CKDWORD flags);
|
virtual void PreSave(CKFileVisitor* file, CKDWORD flags);
|
||||||
virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags);
|
virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags);
|
||||||
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file);
|
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file);
|
||||||
|
@ -75,6 +75,10 @@ namespace LibCmo {
|
|||||||
#define LIBPANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg);
|
#define LIBPANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg);
|
||||||
|
|
||||||
namespace EnumsHelper {
|
namespace EnumsHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return 'e1 | e2 | ... | en'
|
||||||
|
*/
|
||||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||||
inline TEnum Merge(std::initializer_list<TEnum> il) {
|
inline TEnum Merge(std::initializer_list<TEnum> il) {
|
||||||
std::underlying_type_t<TEnum> result = 0;
|
std::underlying_type_t<TEnum> result = 0;
|
||||||
@ -84,26 +88,41 @@ namespace LibCmo {
|
|||||||
return static_cast<TEnum>(result);
|
return static_cast<TEnum>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return '~(e)'
|
||||||
|
*/
|
||||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||||
inline TEnum Inv(TEnum e) {
|
inline TEnum Inv(TEnum e) {
|
||||||
return static_cast<TEnum>(~(static_cast<std::underlying_type_t<TEnum>>(e)));
|
return static_cast<TEnum>(~(static_cast<std::underlying_type_t<TEnum>>(e)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Operate e1 &= (~e2)
|
||||||
|
*/
|
||||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||||
inline void Rm(TEnum& e1, TEnum e2) {
|
inline void Rm(TEnum& e1, TEnum e2) {
|
||||||
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) & static_cast<std::underlying_type_t<TEnum>>(Inv(e2)));
|
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) & static_cast<std::underlying_type_t<TEnum>>(Inv(e2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Operate e1 &= e2
|
||||||
|
*/
|
||||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||||
inline void Mask(TEnum& e1, TEnum e2) {
|
inline void Mask(TEnum& e1, TEnum e2) {
|
||||||
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) & static_cast<std::underlying_type_t<TEnum>>(e2));
|
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) & static_cast<std::underlying_type_t<TEnum>>(e2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Operate e1 |= e2
|
||||||
|
*/
|
||||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||||
inline void Add(TEnum& e1, TEnum e2) {
|
inline void Add(TEnum& e1, TEnum e2) {
|
||||||
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) | static_cast<std::underlying_type_t<TEnum>>(e2));
|
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) | static_cast<std::underlying_type_t<TEnum>>(e2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return 'bool(e1 & e2)'
|
||||||
|
*/
|
||||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||||
inline bool Has(TEnum e, TEnum probe) {
|
inline bool Has(TEnum e, TEnum probe) {
|
||||||
return static_cast<bool>(static_cast<std::underlying_type_t<TEnum>>(e) & static_cast<std::underlying_type_t<TEnum>>(probe));
|
return static_cast<bool>(static_cast<std::underlying_type_t<TEnum>>(e) & static_cast<std::underlying_type_t<TEnum>>(probe));
|
||||||
|
@ -8,6 +8,37 @@ namespace LibCmo::XContainer {
|
|||||||
|
|
||||||
namespace NSXBitArray {
|
namespace NSXBitArray {
|
||||||
|
|
||||||
|
void Resize(XBitArray& ba, CKDWORD newsize) {
|
||||||
|
ba.resize(newsize, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Or(XBitArray& thisba, const XBitArray& thatba) {
|
||||||
|
if (thisba.size() < thatba.size()) {
|
||||||
|
Resize(thisba, static_cast<CKDWORD>(thatba.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < thisba.size(); ++i) {
|
||||||
|
thisba[i] = thisba[i] || thatba[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSet(const XBitArray& ba, CKDWORD n) {
|
||||||
|
if (n >= ba.size()) return false;
|
||||||
|
return ba[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(XBitArray& ba, CKDWORD n) {
|
||||||
|
if (n >= ba.size()) {
|
||||||
|
ba.resize(n + 1);
|
||||||
|
}
|
||||||
|
ba[n] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unset(XBitArray& ba, CKDWORD n) {
|
||||||
|
if (n >= ba.size()) return;
|
||||||
|
ba[n] = false;
|
||||||
|
}
|
||||||
|
|
||||||
template<bool _Cond>
|
template<bool _Cond>
|
||||||
bool GeneralGetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got) {
|
bool GeneralGetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got) {
|
||||||
CKDWORD counter = 0;
|
CKDWORD counter = 0;
|
||||||
@ -94,6 +125,21 @@ namespace LibCmo::XContainer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PreDeletedCheck(XList<CK2::CK_ID>& 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(XList<CK2::CK_ID>& 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 {
|
namespace NSXObjectPointerArray {
|
||||||
|
|
||||||
|
@ -82,13 +82,48 @@ namespace LibCmo::XContainer {
|
|||||||
namespace NSXBitArray {
|
namespace NSXBitArray {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the position of the n-th set(1) bit
|
* @brief Resize XBitArray to the new size. Initial value is false.
|
||||||
* @return false if not found.
|
* @param ba The XBitArray
|
||||||
|
* @param newsize New Size
|
||||||
|
*/
|
||||||
|
void Resize(XBitArray& ba, CKDWORD newsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Merge other XBitArray to this XBitArray with OR condition.
|
||||||
|
* This XBitArray will be resized at least equal with merged XBitArray if its size is lower than merged XBitArray
|
||||||
|
* @param thisba This XBitArray
|
||||||
|
* @param thatba Other XBitArray will be merged.
|
||||||
|
*/
|
||||||
|
void Or(XBitArray& thisba, const XBitArray& thatba);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether bit flag is set.
|
||||||
|
* @param ba The XBitArray
|
||||||
|
* @param n The check position.
|
||||||
|
* @return True if set. False if not set or out of range.
|
||||||
|
*/
|
||||||
|
bool IsSet(const XBitArray& ba, CKDWORD n);
|
||||||
|
/**
|
||||||
|
* @brief Set specified position to true in XBitArray. Auto resize if no space to set.
|
||||||
|
* @param ba The XBitArray
|
||||||
|
* @param n The set position.
|
||||||
|
*/
|
||||||
|
void Set(XBitArray& ba, CKDWORD n);
|
||||||
|
/**
|
||||||
|
* @brief Unset specified position to true in XBitArray. If out of range, simply return.
|
||||||
|
* @param ba The XBitArray
|
||||||
|
* @param n The unset position.
|
||||||
|
*/
|
||||||
|
void Unset(XBitArray& ba, CKDWORD n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the position of the n-th set(1) bit
|
||||||
|
* @return false if not found.
|
||||||
*/
|
*/
|
||||||
bool GetSetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got);
|
bool GetSetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got);
|
||||||
/**
|
/**
|
||||||
* @brief Returns the position of the n-th unset(0) bit
|
* @brief Returns the position of the n-th unset(0) bit
|
||||||
* @return false if not found.
|
* @return false if not found.
|
||||||
*/
|
*/
|
||||||
bool GetUnsetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got);
|
bool GetUnsetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got);
|
||||||
|
|
||||||
@ -127,6 +162,20 @@ namespace LibCmo::XContainer {
|
|||||||
*/
|
*/
|
||||||
void PostDeletedCheck(XObjectArray& objarray, CK2::CKContext* ctx);
|
void PostDeletedCheck(XObjectArray& objarray, CK2::CKContext* ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check Object pointer validation and remove invalid pointers before deletion.
|
||||||
|
* @param objarray
|
||||||
|
* @param ctx
|
||||||
|
*/
|
||||||
|
void PreDeletedCheck(XList<CK2::CK_ID>& 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::CK_ID>& objarray, CK2::CKContext* ctx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NSXObjectPointerArray {
|
namespace NSXObjectPointerArray {
|
||||||
|
Loading…
Reference in New Issue
Block a user