almost finish CKGroup

This commit is contained in:
yyc12345 2023-09-01 12:19:06 +08:00
parent 3755a2e148
commit fd69914a25
15 changed files with 310 additions and 88 deletions

View File

@ -1,5 +1,6 @@
#include "CKContext.hpp" #include "CKContext.hpp"
#include "ObjImpls/CKObject.hpp" #include "ObjImpls/CKObject.hpp"
#include "../XContainer/XBitArray.hpp"
#include <cstdarg> #include <cstdarg>
namespace LibCmo::CK2 { namespace LibCmo::CK2 {
@ -10,6 +11,29 @@ namespace LibCmo::CK2 {
static char g_UniqueFolder[] = "LibCmo"; static char g_UniqueFolder[] = "LibCmo";
#endif #endif
#pragma region Ctor Dtor
CKContext::CKContext() :
m_ObjectsList(), m_ReturnedObjectIds(),
m_GroupGlobalIndex(), m_SceneGlobalIndex(),
m_CompressionLevel(5), m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED),
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);
}
CKContext::~CKContext() {
DestroyAllCKObjects();
}
#pragma endregion
#pragma region Objects Management #pragma region Objects Management
ObjImpls::CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name, ObjImpls::CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name,
@ -78,6 +102,45 @@ namespace LibCmo::CK2 {
} }
CKDWORD CKContext::AllocateGroupGlobalIndex() {
// try find first non-true position
CKDWORD index;
if (!XContainer::XBitArrayPatch::GetSetBitPosition(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] = true;
return index;
}
CKDWORD CKContext::AllocateSceneGlobalIndex() {
// same as group
CKDWORD index;
if (!XContainer::XBitArrayPatch::GetSetBitPosition(m_SceneGlobalIndex, 0, index)) {
index = static_cast<CKDWORD>(m_SceneGlobalIndex.size());
m_SceneGlobalIndex.resize(m_SceneGlobalIndex.size() + 1);
}
m_SceneGlobalIndex[index] = true;
return index;
}
void CKContext::FreeGroupGlobalIndex(CKDWORD id) {
// check position
if (id >= m_GroupGlobalIndex.size()) return;
// set value
m_GroupGlobalIndex[id] = false;
}
void CKContext::FreeSceneGlobalIndex(CKDWORD id) {
// same as group
if (id >= m_SceneGlobalIndex.size()) return;
m_SceneGlobalIndex[id] = false;
}
void CKContext::DestroyAllCKObjects() { void CKContext::DestroyAllCKObjects() {
// free all created objects // free all created objects
for (auto& ptr : m_ObjectsList) { for (auto& ptr : m_ObjectsList) {
@ -89,6 +152,10 @@ namespace LibCmo::CK2 {
m_ReturnedObjectIds.clear(); m_ReturnedObjectIds.clear();
// empty object list // empty object list
m_ObjectsList.clear(); m_ObjectsList.clear();
// clear group and scene global index at the same time
m_SceneGlobalIndex.clear();
m_GroupGlobalIndex.clear();
} }
#pragma endregion #pragma endregion
@ -128,29 +195,6 @@ namespace LibCmo::CK2 {
#pragma endregion #pragma endregion
#pragma region Ctor Dtor
CKContext::CKContext() :
m_ObjectsList(), m_ReturnedObjectIds(),
m_CompressionLevel(5), m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED),
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);
}
CKContext::~CKContext() {
DestroyAllCKObjects();
}
#pragma endregion
#pragma region Output utilities #pragma region Output utilities
void CKContext::OutputToConsole(CKSTRING str) { void CKContext::OutputToConsole(CKSTRING str) {

View File

@ -42,6 +42,12 @@ namespace LibCmo::CK2 {
CK_CREATIONMODE* res = nullptr); CK_CREATIONMODE* res = nullptr);
ObjImpls::CKObject* GetCKObject(CK_ID id); ObjImpls::CKObject* GetCKObject(CK_ID id);
void DestroyCKObject(CK_ID id); void DestroyCKObject(CK_ID id);
CKDWORD AllocateGroupGlobalIndex();
CKDWORD AllocateSceneGlobalIndex();
void FreeGroupGlobalIndex(CKDWORD id);
void FreeSceneGlobalIndex(CKDWORD id);
void DestroyAllCKObjects(); void DestroyAllCKObjects();
// ========== Object Access ========== // ========== Object Access ==========
@ -94,6 +100,9 @@ namespace LibCmo::CK2 {
XContainer::XArray<ObjImpls::CKObject*> m_ObjectsList; XContainer::XArray<ObjImpls::CKObject*> m_ObjectsList;
std::deque<CK_ID> m_ReturnedObjectIds; std::deque<CK_ID> m_ReturnedObjectIds;
XContainer::XBitArray m_GroupGlobalIndex;
XContainer::XBitArray m_SceneGlobalIndex;
// ========== File Save/Load Options ========== // ========== File Save/Load Options ==========
CKINT m_CompressionLevel; CKINT m_CompressionLevel;
CK_FILE_WRITEMODE m_FileWriteMode; CK_FILE_WRITEMODE m_FileWriteMode;

View File

@ -34,6 +34,7 @@ namespace LibCmo::CK2 {
//using CKClassDependenciesCountFct = std::function<CKINT(CKINT)>; //using CKClassDependenciesCountFct = std::function<CKINT(CKINT)>;
struct CKClassDesc { struct CKClassDesc {
bool IsValid; /**< True if this CKClassDesc is a valid one. Because CK_CLASSID may not be consecutive. */
bool Done; bool Done;
// Initialized upon class registration // Initialized upon class registration
CK_CLASSID Self; CK_CLASSID Self;
@ -62,6 +63,7 @@ namespace LibCmo::CK2 {
//XContainer::XSArray<CK_CLASSID> ToNotify; // List of ClassID to notify when an object of this class is deleted (inverse of ToBeNotify) //XContainer::XSArray<CK_CLASSID> ToNotify; // List of ClassID to notify when an object of this class is deleted (inverse of ToBeNotify)
CKClassDesc() : CKClassDesc() :
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), CreationFct(nullptr), ReleaseFct(nullptr), NameFct(nullptr),

View File

@ -11,6 +11,9 @@
#include <zlib.h> #include <zlib.h>
#include "ObjImpls/CKObject.hpp" #include "ObjImpls/CKObject.hpp"
#include "ObjImpls/CKSceneObject.hpp"
#include "ObjImpls/CKBeObject.hpp"
#include "ObjImpls/CKGroup.hpp"
namespace LibCmo::CK2 { namespace LibCmo::CK2 {
@ -61,17 +64,23 @@ namespace LibCmo::CK2 {
#pragma region CKClass Registration #pragma region CKClass Registration
static XContainer::XArray<CKClassDesc> g_CKClassInfo; static XContainer::XArray<CKClassDesc> g_CKClassInfo;
static std::map<CK_CLASSID, size_t> g_CKClassInfoId2Idx;
static CK_CLASSID g_CKClassInfoMaxID = static_cast<CK_CLASSID>(0); CK_CLASSID CKClassGetNewIdentifier() {
size_t classsize = g_CKClassInfo.size();
if (classsize < static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID)) {
return CK_CLASSID::CKCID_MAXCLASSID;
} else {
return static_cast<CK_CLASSID>(classsize);
}
}
static void ComputeParentsTable(CKClassDesc& desc) { static void ComputeParentsTable(CKClassDesc& desc) {
// if it has done, do not process it again. // if it has done, do not process it again.
if (desc.Done) return; if (desc.Done) return;
// find direct parent // find direct parent
auto finder = g_CKClassInfoId2Idx.find(desc.Parent); CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID."); if (!parent.IsValid) LIBPANIC("No such CK_CLASSID.");
CKClassDesc& parent = g_CKClassInfo[finder->second];
// if it is not self inheritance, call recursively // if it is not self inheritance, call recursively
if (desc.Self != desc.Parent) { if (desc.Self != desc.Parent) {
@ -81,9 +90,7 @@ namespace LibCmo::CK2 {
// copy parent's parents // copy parent's parents
desc.Parents = parent.Parents; desc.Parents = parent.Parents;
// and set self as its parent // and set self as its parent
finder = g_CKClassInfoId2Idx.find(desc.Self); desc.Parents[static_cast<size_t>(desc.Self)] = true;
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
desc.Parents[finder->second] = true;
// set derivation level // set derivation level
desc.DerivationLevel = parent.DerivationLevel + 1; desc.DerivationLevel = parent.DerivationLevel + 1;
@ -95,26 +102,30 @@ namespace LibCmo::CK2 {
// set Done to false and resize all XBitArray // set Done to false and resize all XBitArray
size_t classCount = g_CKClassInfo.size(); size_t classCount = g_CKClassInfo.size();
for (auto& item : g_CKClassInfo) { for (auto& item : g_CKClassInfo) {
if (!item.IsValid) continue;
item.Done = false; item.Done = false;
item.Parents.resize(classCount, false); item.Parents.resize(classCount, false);
item.Children.resize(classCount, false); item.Children.resize(classCount, false);
} }
// compute parents // compute parents
for (auto& item : g_CKClassInfo) { for (auto& item : g_CKClassInfo) {
if (!item.IsValid) continue;
ComputeParentsTable(item); ComputeParentsTable(item);
} }
// compute children by parents table // compute children by parents table
// iterate CKClassDesc::Parents and register it self to gotten parents // iterate CKClassDesc::Parents and register it self to gotten parents
for (auto& item : g_CKClassInfo) { for (auto& item : g_CKClassInfo) {
auto finder = g_CKClassInfoId2Idx.find(item.Self); if (!item.IsValid) continue;
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
size_t selfidx = finder->second;
for (size_t idx = 0; idx < classCount; ++idx) { for (size_t idx = 0; idx < classCount; ++idx) {
if (!g_CKClassInfo[idx].IsValid) continue;
// if this idx is its parent, // if this idx is its parent,
// add self to parent. // add self to parent.
if (item.Parents[idx]) { if (item.Parents[idx]) {
g_CKClassInfo[idx].Children[selfidx] = true; g_CKClassInfo[idx].Children[static_cast<size_t>(item.Self)] = true;
} }
} }
} }
@ -122,54 +133,60 @@ namespace LibCmo::CK2 {
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid, void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) { CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct) {
// resize class desc array
size_t intcid = static_cast<size_t>(cid);
if (intcid >= g_CKClassInfo.size()) {
g_CKClassInfo.resize(intcid + 1);
}
// emplace desc
CKClassDesc desc; CKClassDesc desc;
desc.IsValid = true;
desc.Self = cid; desc.Self = cid;
desc.Parent = parentCid; desc.Parent = parentCid;
desc.CreationFct = createFct; desc.CreationFct = createFct;
desc.ReleaseFct = relFct; desc.ReleaseFct = relFct;
desc.NameFct = nameFct; desc.NameFct = nameFct;
g_CKClassInfoId2Idx.emplace(cid, g_CKClassInfo.size()); g_CKClassInfo[intcid] = std::move(desc);
g_CKClassInfo.emplace_back(std::move(desc));
g_CKClassInfoMaxID = std::max(g_CKClassInfoMaxID, cid);
} }
#pragma endregion #pragma endregion
#pragma region Class Hierarchy Management #pragma region Class Hierarchy Management
CKINT CKGetClassCount() { static bool GetClassIdIndex(CK_CLASSID cid, size_t& intcid) {
return static_cast<CKINT>(g_CKClassInfo.size()); intcid = static_cast<size_t>(cid);
if (intcid >= g_CKClassInfo.size()) return false;
if (!g_CKClassInfo[intcid].IsValid) return false;
return true;
}
CKDWORD CKGetClassCount() {
return static_cast<CKDWORD>(g_CKClassInfo.size());
} }
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) { const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) {
auto finder = g_CKClassInfoId2Idx.find(cid); size_t intcid;
if (finder == g_CKClassInfoId2Idx.end()) return nullptr; if (!GetClassIdIndex(cid, intcid)) return nullptr;
return g_CKClassInfo.data() + finder->second; return &g_CKClassInfo[intcid];
} }
CKSTRING CKClassIDToString(CK_CLASSID cid) { CKSTRING CKClassIDToString(CK_CLASSID cid) {
auto finder = g_CKClassInfoId2Idx.find(cid); const CKClassDesc* desc = CKGetClassDesc(cid);
if (finder == g_CKClassInfoId2Idx.end() || g_CKClassInfo[finder->second].NameFct == nullptr) return "Invalid Class Identifier"; if (desc == nullptr) return "Undefined Type";
return g_CKClassInfo[finder->second].NameFct(); else return desc->NameFct();
} }
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) { bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
// get corresponding index first size_t intchild, intparent;
// if we can't find it, return false anyway. if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) return false;
auto finder = g_CKClassInfoId2Idx.find(child); return g_CKClassInfo[intchild].Parents[intparent];
if (finder == g_CKClassInfoId2Idx.end()) return false;
size_t child_idx = finder->second;
finder = g_CKClassInfoId2Idx.find(parent);
if (finder == g_CKClassInfoId2Idx.end()) return false;
size_t parent_idx = finder->second;
return g_CKClassInfo[child_idx].Parents[parent_idx];
} }
CK_CLASSID CKGetParentClassID(CK_CLASSID child) { CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
auto finder = g_CKClassInfoId2Idx.find(child); const CKClassDesc* desc = CKGetClassDesc(child);
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID."); if (desc == nullptr) return CK_CLASSID::CKCID_OBJECT;
return g_CKClassInfo[finder->second].Parent; return desc->Parent;
} }
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2) { CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2) {
@ -190,11 +207,28 @@ namespace LibCmo::CK2 {
#pragma region Initializations functions #pragma region Initializations functions
CKERROR CKStartUp() { CKERROR CKStartUp() {
// reserve class info array.
g_CKClassInfo.reserve(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
// todo: add class type registrations // todo: add class type registrations
CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT, #define EasyClassReg(clsname, cid, parentCid, strName) \
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new ObjImpls::CKObject(ctx, id, name); }, CKClassRegister(cid, parentCid, \
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, [](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
[]() -> CKSTRING { return "Basic Object"; }); [](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
[]() -> CKSTRING { return strName; });
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::CKBeObject, CK_CLASSID::CKCID_BEOBJECT, CK_CLASSID::CKCID_SCENEOBJECT, "Behavioral Object");
EasyClassReg(ObjImpls::CKGroup, CK_CLASSID::CKCID_GROUP, CK_CLASSID::CKCID_BEOBJECT, "Group");
//CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT,
// [](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new ObjImpls::CKObject(ctx, id, name); },
// [](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; },
// []() -> CKSTRING { return "Basic Object"; });
#undef EasyClassReg
/* /*
// register CKObjects // register CKObjects
@ -233,8 +267,6 @@ namespace LibCmo::CK2 {
CKERROR CKShutdown() { CKERROR CKShutdown() {
// free class indo // free class indo
g_CKClassInfo.clear(); g_CKClassInfo.clear();
g_CKClassInfoId2Idx.clear();
g_CKClassInfoMaxID = static_cast<CK_CLASSID>(0);
return CKERROR::CKERR_OK; return CKERROR::CKERR_OK;
} }

View File

@ -54,12 +54,13 @@ namespace LibCmo::CK2 {
// ========== CKClass Registration ========== // ========== CKClass Registration ==========
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); CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
// ========== Class Hierarchy Management ========== // ========== Class Hierarchy Management ==========
CKINT CKGetClassCount(); CKDWORD CKGetClassCount();
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid); const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
CKSTRING CKClassIDToString(CK_CLASSID cid); CKSTRING CKClassIDToString(CK_CLASSID cid);

View File

@ -22,4 +22,9 @@ namespace LibCmo::CK2::ObjImpls {
return false; return false;
} }
void CKBeObject::CKGroup_SetGroups(CKDWORD pos, bool val) {
if (pos >= m_Groups.size()) m_Groups.resize(pos + 1);
m_Groups[pos] = val;
}
} }

View File

@ -22,6 +22,7 @@ namespace LibCmo::CK2::ObjImpls {
//virtual void PostLoad() override; //virtual void PostLoad() override;
bool IsInGroup(CKGroup* group); bool IsInGroup(CKGroup* group);
void CKGroup_SetGroups(CKDWORD pos, bool val);
protected: protected:
XContainer::XBitArray m_Groups; XContainer::XBitArray m_Groups;

View File

@ -1,27 +1,92 @@
#include "CKSceneObject.hpp"
#include "../CKStateChunk.hpp"
#include "CKGroup.hpp" #include "CKGroup.hpp"
#include "../CKStateChunk.hpp"
#include "../CKContext.hpp"
#include <algorithm>
namespace LibCmo::CK2::ObjImpls { namespace LibCmo::CK2::ObjImpls {
CKGroup::CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) :
CKBeObject(ctx, ckid, name),
m_ObjectArray(),
m_GroupIndex(m_Context->AllocateGroupGlobalIndex()) {}
CKGroup::~CKGroup() {
m_Context->FreeGroupGlobalIndex(m_GroupIndex);
}
bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) { bool CKGroup::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {
return false; bool suc = CKBeObject::Save(chunk, file, flags);
if (!suc) return false;
return true;
} }
bool CKGroup::Load(CKStateChunk* chunk, CKFileVisitor* file) { bool CKGroup::Load(CKStateChunk* chunk, CKFileVisitor* file) {
return false; bool suc = CKBeObject::Load(chunk, file);
if (!suc) return false;
return true;
} }
CKDWORD CKGroup::GetGroupIndex() { CKDWORD CKGroup::GetGroupIndex() {
return m_GroupIndex; return m_GroupIndex;
} }
CKObject* CKGroup::GetObject(CKDWORD pos) { CKERROR CKGroup::AddObject(CKBeObject* o) {
return nullptr; if (o == nullptr || o == this || !CKIsChildClassOf(o->GetClassID(), CK_CLASSID::CKCID_BEOBJECT)) {
return CKERROR::CKERR_INVALIDPARAMETER;
}
if (o->IsInGroup(this)) {
return CKERROR::CKERR_ALREADYPRESENT;
}
// set object
o->CKGroup_SetGroups(m_GroupIndex, true);
// set self
m_ObjectArray.emplace_back(o);
return CKERROR::CKERR_OK;
}
CKBeObject* CKGroup::RemoveObject(CKDWORD pos) {
// check pos
if (pos >= m_ObjectArray.size()) return nullptr;
auto it = m_ObjectArray.begin() + pos;
CKBeObject* obj = static_cast<CKBeObject*>(*it);
// set object
obj->CKGroup_SetGroups(m_GroupIndex, false);
// remove self
m_ObjectArray.erase(it);
return obj;
}
void CKGroup::RemoveObject(CKBeObject* obj) {
// find first
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);
// remove self
m_ObjectArray.erase(finder);
}
}
void CKGroup::Clear() {
for (auto& beobj : m_ObjectArray) {
// set object
static_cast<CKBeObject*>(beobj)->CKGroup_SetGroups(m_GroupIndex, false);
}
m_ObjectArray.clear();
}
CKBeObject* CKGroup::GetObject(CKDWORD pos) {
if (pos >= m_ObjectArray.size()) return nullptr;
else return static_cast<CKBeObject*>(m_ObjectArray[pos]);
} }
CKDWORD CKGroup::GetObjectCount() { CKDWORD CKGroup::GetObjectCount() {
return CKDWORD(); return static_cast<CKDWORD>(m_ObjectArray.size());
} }
} }

View File

@ -7,14 +7,8 @@ namespace LibCmo::CK2::ObjImpls {
class CKGroup : public CKBeObject { class CKGroup : public CKBeObject {
public: public:
CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name) : CKGroup(CKContext* ctx, CK_ID ckid, CKSTRING name);
CKBeObject(ctx, ckid, name), virtual ~CKGroup();
m_ObjectArray(),
m_GroupIndex() // todo: allocate group id
{}
virtual ~CKGroup() {
// todo: free allocated group id
}
LIBCMO_DISABLE_COPY_MOVE(CKGroup); LIBCMO_DISABLE_COPY_MOVE(CKGroup);
virtual CK_CLASSID GetClassID(void) override { virtual CK_CLASSID GetClassID(void) override {
@ -29,20 +23,14 @@ namespace LibCmo::CK2::ObjImpls {
// ===== Insert ===== // ===== Insert =====
CKERROR AddObject(CKBeObject *o); CKERROR AddObject(CKBeObject *o);
CKERROR AddObjectFront(CKBeObject *o);
CKERROR InsertObjectAt(CKBeObject *o, CKDWORD pos);
// ===== Remove ===== // ===== Remove =====
CKBeObject* RemoveObject(CKDWORD pos); CKBeObject* RemoveObject(CKDWORD pos);
void RemoveObject(CKBeObject *obj); void RemoveObject(CKBeObject *obj);
void Clear(); void Clear();
// ===== Order =====
void MoveObjectUp(CKBeObject *o);
void MoveObjectDown(CKBeObject *o);
// ===== Access ===== // ===== Access =====
CKObject* GetObject(CKDWORD pos); CKBeObject* GetObject(CKDWORD pos);
CKDWORD GetObjectCount(); CKDWORD GetObjectCount();
protected: protected:

View File

@ -189,6 +189,7 @@
<ClCompile Include="CK2\CKStateChunk.cpp" /> <ClCompile Include="CK2\CKStateChunk.cpp" />
<ClCompile Include="VTUtils.cpp" /> <ClCompile Include="VTUtils.cpp" />
<ClCompile Include="VxMath\VxMemoryMappedFile.cpp" /> <ClCompile Include="VxMath\VxMemoryMappedFile.cpp" />
<ClCompile Include="XContainer\XBitArray.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="CK2\CKDefines.hpp" /> <ClInclude Include="CK2\CKDefines.hpp" />
@ -209,6 +210,7 @@
<ClInclude Include="VTUtils.hpp" /> <ClInclude Include="VTUtils.hpp" />
<ClInclude Include="VxMath\VxMemoryMappedFile.hpp" /> <ClInclude Include="VxMath\VxMemoryMappedFile.hpp" />
<ClInclude Include="VxMath\VxTypes.hpp" /> <ClInclude Include="VxMath\VxTypes.hpp" />
<ClInclude Include="XContainer\XBitArray.hpp" />
<ClInclude Include="XContainer\XTypes.hpp" /> <ClInclude Include="XContainer\XTypes.hpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -87,6 +87,9 @@
<ClCompile Include="CK2\ObjImpls\CKGroup.cpp"> <ClCompile Include="CK2\ObjImpls\CKGroup.cpp">
<Filter>Sources\CK2\ObjImpls</Filter> <Filter>Sources\CK2\ObjImpls</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="XContainer\XBitArray.cpp">
<Filter>Sources\XContainer</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="VTUtils.hpp"> <ClInclude Include="VTUtils.hpp">
@ -146,5 +149,8 @@
<ClInclude Include="CK2\ObjImpls\CKGroup.hpp"> <ClInclude Include="CK2\ObjImpls\CKGroup.hpp">
<Filter>Headers\CK2\ObjImpls</Filter> <Filter>Headers\CK2\ObjImpls</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="XContainer\XBitArray.hpp">
<Filter>Headers\XContainer</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,30 @@
#include "XBitArray.hpp"
namespace LibCmo::XContainer::XBitArrayPatch {
template<bool _Cond>
bool GeneralGetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got) {
CK2::CKDWORD counter = 0;
for (size_t i = 0; i < ba.size(); ++i) {
if (ba[i] == _Cond) {
if (counter == n) {
got = static_cast<CK2::CKDWORD>(i);
return true;
} else {
++counter;
}
}
}
return false;
}
bool GetSetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got) {
return GeneralGetBitPosition<true>(ba, n, got);
}
bool GetUnsetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got) {
return GeneralGetBitPosition<false>(ba, n, got);
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "XTypes.hpp"
namespace LibCmo::XContainer::XBitArrayPatch {
/**
* @brief Returns the position of the n-th set(1) bit
* @return false if not found.
*/
bool GetSetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got);
/**
* @brief Returns the position of the n-th unset(0) bit
* @return false if not found.
*/
bool GetUnsetBitPosition(XBitArray& ba, CK2::CKDWORD n, CK2::CKDWORD& got);
}

View File

@ -167,14 +167,28 @@ namespace Unvirt::StructFormatter {
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject* obj) { void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject* obj) {
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKObject\n")), stdout); fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKObject\n")), stdout);
if (obj == nullptr) {
fputs(UNVIRT_TERMCOL_LIGHT_RED(("No Data\n")), stdout);
return;
}
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout); fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
} }
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) { void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) {
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKBaseManager\n")), stdout); fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKBaseManager\n")), stdout);
if (mgr == nullptr) {
fputs(UNVIRT_TERMCOL_LIGHT_RED(("No Data\n")), stdout);
return;
}
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout); fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
} }
void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) { void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) {
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout); fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout);
if (chunk == nullptr) {
fputs(UNVIRT_TERMCOL_LIGHT_RED(("No Data\n")), stdout);
return;
}
// hack const state chunk // hack const state chunk
LibCmo::CK2::CKStateChunk* operchunk = const_cast<LibCmo::CK2::CKStateChunk*>(chunk); LibCmo::CK2::CKStateChunk* operchunk = const_cast<LibCmo::CK2::CKStateChunk*>(chunk);

View File

@ -127,6 +127,7 @@ namespace Unvirt::Context {
m_Help = root->RootHelp(); m_Help = root->RootHelp();
// create context // create context
LibCmo::CK2::CKStartUp();
m_Ctx = new LibCmo::CK2::CKContext(); m_Ctx = new LibCmo::CK2::CKContext();
m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1)); m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1));
} }
@ -134,6 +135,11 @@ namespace Unvirt::Context {
UnvirtContext::~UnvirtContext() { UnvirtContext::~UnvirtContext() {
if (m_Help != nullptr) if (m_Help != nullptr)
delete m_Help; delete m_Help;
// free context
ClearDocument();
delete m_Ctx;
LibCmo::CK2::CKShutdown();
} }
bool UnvirtContext::HasOpenedFile() { bool UnvirtContext::HasOpenedFile() {