2023-09-16 18:31:25 +08:00
|
|
|
#include "XTypes.hpp"
|
2023-09-16 22:38:21 +08:00
|
|
|
#include "../CK2/CKContext.hpp"
|
|
|
|
#include "../CK2/MgrImpls/CKObjectManager.hpp"
|
|
|
|
#include "../CK2/ObjImpls/CKObject.hpp"
|
|
|
|
#include <type_traits>
|
2023-09-19 22:32:07 +08:00
|
|
|
#include <algorithm>
|
2023-09-16 18:31:25 +08:00
|
|
|
|
|
|
|
namespace LibCmo::XContainer {
|
|
|
|
|
|
|
|
namespace NSXBitArray {
|
|
|
|
|
2023-09-17 12:39:21 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-09-16 18:31:25 +08:00
|
|
|
template<bool _Cond>
|
2024-08-19 10:43:30 +08:00
|
|
|
static bool GeneralGetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got) {
|
2023-09-16 18:31:25 +08:00
|
|
|
CKDWORD counter = 0;
|
|
|
|
for (size_t i = 0; i < ba.size(); ++i) {
|
|
|
|
if (ba[i] == _Cond) {
|
|
|
|
if (counter == n) {
|
|
|
|
got = static_cast<CKDWORD>(i);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
++counter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GetSetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got) {
|
|
|
|
return GeneralGetBitPosition<true>(ba, n, got);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GetUnsetBitPosition(const XBitArray& ba, CKDWORD n, CKDWORD& got) {
|
|
|
|
return GeneralGetBitPosition<false>(ba, n, got);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace NSXString {
|
|
|
|
|
|
|
|
CKSTRING ToCKSTRING(const XString& strl) {
|
|
|
|
if (strl.empty()) return nullptr;
|
|
|
|
else return strl.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FromCKSTRING(XString& strl, CKSTRING s) {
|
|
|
|
if (s == nullptr) strl.clear();
|
|
|
|
else strl = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-09-16 22:38:21 +08:00
|
|
|
template<class _Ty>
|
2024-08-19 10:43:30 +08:00
|
|
|
static constexpr bool GeneralXArrayCheck_TypeCheck() {
|
2023-09-16 22:38:21 +08:00
|
|
|
return std::is_same_v<_Ty, CK2::CK_ID> || std::is_same_v<_Ty, CK2::ObjImpls::CKObject*>;
|
|
|
|
}
|
|
|
|
template<class _Ty, bool _IsPre>
|
2024-08-19 10:43:30 +08:00
|
|
|
static bool GeneralXArrayCheck_ItemCheck(const _Ty& item, CK2::CKContext* ctx) {
|
2023-09-16 22:38:21 +08:00
|
|
|
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;
|
|
|
|
}
|
2023-09-20 15:25:43 +08:00
|
|
|
if (obj->IsToBeDeleted()) return false;
|
2023-09-16 22:38:21 +08:00
|
|
|
} 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);
|
|
|
|
});
|
|
|
|
}
|
2023-09-17 12:39:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
2023-09-16 22:38:21 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
namespace NSXObjectPointerArray {
|
|
|
|
|
2023-09-22 14:48:45 +08:00
|
|
|
bool AddIfNotHere(XObjectPointerArray& objarray, CK2::ObjImpls::CKObject* obj) {
|
2023-09-19 22:32:07 +08:00
|
|
|
auto finder = std::find(objarray.begin(), objarray.end(), obj);
|
|
|
|
if (finder == objarray.end()) {
|
|
|
|
objarray.emplace_back(obj);
|
2023-09-20 10:49:32 +08:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
2023-09-19 22:32:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-16 22:38:21 +08:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-09-16 18:31:25 +08:00
|
|
|
}
|