update shit
This commit is contained in:
parent
11d05615ba
commit
599456a587
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,9 @@
|
||||||
*.vmo
|
*.vmo
|
||||||
CodeGen/dest/*.txt
|
CodeGen/dest/*.txt
|
||||||
PyCmoOld/
|
PyCmoOld/
|
||||||
|
|
||||||
out/
|
out/
|
||||||
|
temp/
|
||||||
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
|
|
@ -68,20 +68,12 @@ namespace LibCmo {
|
||||||
class CKMinContext;
|
class CKMinContext;
|
||||||
class CKStateChunk;
|
class CKStateChunk;
|
||||||
class CKFile;
|
class CKFile;
|
||||||
namespace CKFileData {
|
class CKFileDocument;
|
||||||
class ShallowDocument;
|
|
||||||
class DeepDocument;
|
|
||||||
class HybridDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
// useful struct define
|
// useful struct define
|
||||||
struct CKGUID {
|
struct CKGUID {
|
||||||
union {
|
CKDWORD d1, d2;
|
||||||
struct {
|
|
||||||
CKDWORD d1, d2;
|
|
||||||
};
|
|
||||||
CKDWORD d[2];
|
|
||||||
};
|
|
||||||
constexpr CKGUID(CKDWORD gd1 = 0, CKDWORD gd2 = 0) : d1(gd1), d2(gd2) {}
|
constexpr CKGUID(CKDWORD gd1 = 0, CKDWORD gd2 = 0) : d1(gd1), d2(gd2) {}
|
||||||
CKGUID(const CKGUID& rhs) : d1(rhs.d1), d2(rhs.d2) {}
|
CKGUID(const CKGUID& rhs) : d1(rhs.d1), d2(rhs.d2) {}
|
||||||
CKGUID& operator=(const CKGUID& rhs) {
|
CKGUID& operator=(const CKGUID& rhs) {
|
||||||
|
@ -136,12 +128,7 @@ namespace LibCmo {
|
||||||
class VxMemoryMappedFile;
|
class VxMemoryMappedFile;
|
||||||
|
|
||||||
struct VxVector {
|
struct VxVector {
|
||||||
union {
|
float x, y, z;
|
||||||
struct {
|
|
||||||
float x, y, z;
|
|
||||||
};
|
|
||||||
float v[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
VxVector() : x(0.0f), y(0.0f), z(0.0f) { ; }
|
VxVector() : x(0.0f), y(0.0f), z(0.0f) { ; }
|
||||||
VxVector(float f) : x(f), y(f), z(f) { ; }
|
VxVector(float f) : x(f), y(f), z(f) { ; }
|
||||||
|
@ -150,12 +137,7 @@ namespace LibCmo {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VxQuaternion {
|
struct VxQuaternion {
|
||||||
union {
|
float x, y, z, w;
|
||||||
struct {
|
|
||||||
float x, y, z, w;
|
|
||||||
};
|
|
||||||
float v[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
VxQuaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f) { ; }
|
VxQuaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f) { ; }
|
||||||
VxQuaternion(float X, float Y, float Z, float W) : x(X), y(Y), z(Z), w(W) { ; }
|
VxQuaternion(float X, float Y, float Z, float W) : x(X), y(Y), z(Z), w(W) { ; }
|
||||||
|
|
|
@ -64,13 +64,15 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CKFileObject::CKFileObject() :
|
CKFileObject::CKFileObject() :
|
||||||
ObjectId(0u), ObjectCid(CK_CLASSID::CKCID_OBJECT), Name(),
|
ObjectId(0u), ObjectCid(CK_CLASSID::CKCID_OBJECT), Name(),
|
||||||
Data(nullptr), FileIndex(0u) {
|
ObjPtr(nullptr), Data(nullptr), FileIndex(0u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CKFileObject::CKFileObject(const CKFileObject& rhs) :
|
CKFileObject::CKFileObject(const CKFileObject& rhs) :
|
||||||
ObjectId(rhs.ObjectId), ObjectCid(rhs.ObjectCid), Name(rhs.Name),
|
ObjectId(rhs.ObjectId), ObjectCid(rhs.ObjectCid), Name(rhs.Name),
|
||||||
Data(rhs.Data), FileIndex(rhs.FileIndex) {
|
ObjPtr(rhs.ObjPtr), Data(rhs.Data), FileIndex(rhs.FileIndex) {
|
||||||
|
|
||||||
|
// CKObject is managed by CKMinContext, so we just copy its pointer.
|
||||||
|
// however, we need copy CKStateChunk.
|
||||||
if (this->Data != nullptr) {
|
if (this->Data != nullptr) {
|
||||||
this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data));
|
this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data));
|
||||||
}
|
}
|
||||||
|
@ -83,6 +85,10 @@ namespace LibCmo::CK2 {
|
||||||
this->Name = rhs.Name;
|
this->Name = rhs.Name;
|
||||||
this->FileIndex = rhs.FileIndex;
|
this->FileIndex = rhs.FileIndex;
|
||||||
|
|
||||||
|
// CKObject is managed by CKMinContext, so we just copy its pointer.
|
||||||
|
this->ObjPtr = rhs.ObjPtr;
|
||||||
|
|
||||||
|
// however, we need copy CKStateChunk.
|
||||||
this->Data = rhs.Data;
|
this->Data = rhs.Data;
|
||||||
if (this->Data != nullptr) {
|
if (this->Data != nullptr) {
|
||||||
this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data));
|
this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data));
|
||||||
|
@ -100,11 +106,11 @@ namespace LibCmo::CK2 {
|
||||||
#pragma region CKFileManagerData
|
#pragma region CKFileManagerData
|
||||||
|
|
||||||
CKFileManagerData::CKFileManagerData() :
|
CKFileManagerData::CKFileManagerData() :
|
||||||
Data(nullptr), Manager(0u, 0u) {
|
MgrPtr(nullptr), Data(nullptr), Manager(0u, 0u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CKFileManagerData::CKFileManagerData(const CKFileManagerData& rhs) :
|
CKFileManagerData::CKFileManagerData(const CKFileManagerData& rhs) :
|
||||||
Data(rhs.Data), Manager(rhs.Manager) {
|
MgrPtr(rhs.MgrPtr), Data(rhs.Data), Manager(rhs.Manager) {
|
||||||
|
|
||||||
if (this->Data != nullptr) {
|
if (this->Data != nullptr) {
|
||||||
this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data));
|
this->Data = new(std::nothrow) CKStateChunk(*(rhs.Data));
|
||||||
|
@ -114,6 +120,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CKFileManagerData& CKFileManagerData::operator=(const CKFileManagerData& rhs) {
|
CKFileManagerData& CKFileManagerData::operator=(const CKFileManagerData& rhs) {
|
||||||
this->Manager = rhs.Manager;
|
this->Manager = rhs.Manager;
|
||||||
|
this->MgrPtr = rhs.MgrPtr;
|
||||||
|
|
||||||
this->Data = rhs.Data;
|
this->Data = rhs.Data;
|
||||||
if (this->Data != nullptr) {
|
if (this->Data != nullptr) {
|
||||||
|
@ -151,34 +158,18 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
namespace CKFileData {
|
|
||||||
|
|
||||||
#pragma region ShallowDocument
|
#pragma region ShallowDocument
|
||||||
|
|
||||||
ShallowDocument::ShallowDocument() {
|
CKFileDocument::CKFileDocument() {
|
||||||
/*this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));*/
|
/*this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
ShallowDocument::~ShallowDocument() {
|
CKFileDocument::~CKFileDocument() {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region DeepDocument
|
|
||||||
|
|
||||||
DeepDocument::DeepDocument() {
|
|
||||||
/*this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));*/
|
|
||||||
}
|
|
||||||
|
|
||||||
DeepDocument::~DeepDocument() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region CKFile Misc
|
#pragma region CKFile Misc
|
||||||
|
|
||||||
CKFile::CKFile(CKMinContext* ctx) :
|
CKFile::CKFile(CKMinContext* ctx) :
|
||||||
|
|
|
@ -88,11 +88,12 @@ namespace LibCmo::CK2 {
|
||||||
CKFileObject& operator=(const CKFileObject&);
|
CKFileObject& operator=(const CKFileObject&);
|
||||||
~CKFileObject();
|
~CKFileObject();
|
||||||
|
|
||||||
CK_ID ObjectId;
|
CK_ID ObjectId; // ID of the object being load/saved (as it will be/was saved in the file)
|
||||||
CK_CLASSID ObjectCid;
|
CK_CLASSID ObjectCid; // Class Identifier of the object
|
||||||
std::string Name;
|
CKObjectImplements::CKObject* ObjPtr; // A pointer to the object itself (as CreatedObject when loading)
|
||||||
CKStateChunk* Data;
|
std::string Name; // Name of the Object
|
||||||
CKDWORD FileIndex;
|
CKStateChunk* Data; // A CKStateChunk that contains object information
|
||||||
|
CKDWORD FileIndex; // Position of the object data inside uncompressed file buffer
|
||||||
private:
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -104,6 +105,7 @@ namespace LibCmo::CK2 {
|
||||||
CKFileManagerData& operator=(const CKFileManagerData&);
|
CKFileManagerData& operator=(const CKFileManagerData&);
|
||||||
~CKFileManagerData();
|
~CKFileManagerData();
|
||||||
|
|
||||||
|
CKManagerImplements::CKBaseManager* MgrPtr;
|
||||||
CKStateChunk* Data;
|
CKStateChunk* Data;
|
||||||
CKGUID Manager;
|
CKGUID Manager;
|
||||||
private:
|
private:
|
||||||
|
@ -123,56 +125,22 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace CKFileData {
|
class CKFileDocument {
|
||||||
class ShallowDocument {
|
public:
|
||||||
public:
|
CKFileDocument();
|
||||||
ShallowDocument();
|
~CKFileDocument();
|
||||||
ShallowDocument(const ShallowDocument&) = delete;
|
|
||||||
ShallowDocument& operator=(const ShallowDocument&) = delete;
|
|
||||||
~ShallowDocument();
|
|
||||||
|
|
||||||
int32_t m_SaveIDMax;
|
int32_t m_SaveIDMax;
|
||||||
CKFileInfo m_FileInfo;
|
CKFileInfo m_FileInfo;
|
||||||
|
|
||||||
XArray<CKFileObject> m_FileObjects;
|
XArray<CKFileObject> m_FileObjects;
|
||||||
XArray<CKFileManagerData> m_FileManagersData;
|
XArray<CKFileManagerData> m_FileManagersData;
|
||||||
XClassArray<CKFilePluginDependencies> m_PluginDep;
|
XClassArray<CKFilePluginDependencies> m_PluginDep;
|
||||||
/*XClassArray<XIntArray> m_IndexByClassId;*/
|
/*XClassArray<XIntArray> m_IndexByClassId;*/
|
||||||
XClassArray<XString> m_IncludedFiles;
|
XClassArray<XString> m_IncludedFiles;
|
||||||
|
private:
|
||||||
|
|
||||||
private:
|
};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeepDocument {
|
|
||||||
public:
|
|
||||||
DeepDocument();
|
|
||||||
DeepDocument(const DeepDocument&) = delete;
|
|
||||||
DeepDocument& operator=(const DeepDocument&) = delete;
|
|
||||||
~DeepDocument();
|
|
||||||
|
|
||||||
int32_t m_SaveIDMax;
|
|
||||||
CKFileInfo m_FileInfo;
|
|
||||||
|
|
||||||
XArray<CKObjectImplements::CKObject*> m_Objects;
|
|
||||||
/*XClassArray<XIntArray> m_IndexByClassId;*/
|
|
||||||
XClassArray<XString> m_IncludedFiles;
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class HybridDocument {
|
|
||||||
public:
|
|
||||||
HybridDocument();
|
|
||||||
HybridDocument(const HybridDocument&) = delete;
|
|
||||||
HybridDocument& operator=(const HybridDocument&) = delete;
|
|
||||||
~HybridDocument();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class CKFile {
|
class CKFile {
|
||||||
public:
|
public:
|
||||||
|
@ -183,16 +151,10 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
void ClearData(void);
|
void ClearData(void);
|
||||||
|
|
||||||
CKERROR ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc);
|
CKERROR ShallowLoad(CKSTRING u8_filename, CKFileDocument** out_doc);
|
||||||
CKERROR DeepLoad(CKSTRING u8_filename, CKFileData::DeepDocument** out_doc);
|
CKERROR DeepLoad(CKSTRING u8_filename, CKFileDocument** out_doc);
|
||||||
|
|
||||||
CKERROR ShallowSave(CKSTRING u8_filename, CKFileData::ShallowDocument* in_doc);
|
CKERROR Save(CKSTRING u8_filename, CKFileDocument* in_doc);
|
||||||
CKERROR DeepSave(CKSTRING u8_filename, CKFileData::DeepDocument* out_doc);
|
|
||||||
CKERROR HybridSave(CKSTRING u8_filename, CKFileData::HybridDocument* out_doc);
|
|
||||||
|
|
||||||
CKERROR DestroyDocument(CKFileData::ShallowDocument* in_doc);
|
|
||||||
CKERROR DestroyDocument(CKFileData::DeepDocument* in_doc);
|
|
||||||
CKERROR DestroyDocument(CKFileData::HybridDocument* in_doc);
|
|
||||||
|
|
||||||
//CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
|
//CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
|
||||||
//CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags);
|
//CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags);
|
||||||
|
@ -218,8 +180,8 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// reader function and variables
|
// reader function and variables
|
||||||
CKERROR ReadFileHeader(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc);
|
CKERROR ReadFileHeader(CKBufferParser* ParserPtr, CKFileDocument* doc);
|
||||||
CKERROR ReadFileData(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc);
|
CKERROR ReadFileData(CKBufferParser* ParserPtr, CKFileDocument* doc);
|
||||||
|
|
||||||
// writer function and varibales
|
// writer function and varibales
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace LibCmo::CK2 {
|
||||||
* No need to support them.
|
* No need to support them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc) {
|
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileDocument** out_doc) {
|
||||||
// preset value
|
// preset value
|
||||||
*out_doc = nullptr;
|
*out_doc = nullptr;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create document
|
// create document
|
||||||
std::unique_ptr<CKFileData::ShallowDocument> doc(new(std::nothrow) CKFileData::ShallowDocument());
|
std::unique_ptr<CKFileDocument> doc(new(std::nothrow) CKFileDocument());
|
||||||
if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||||
|
|
||||||
// create buffer and start loading
|
// create buffer and start loading
|
||||||
|
@ -48,7 +48,7 @@ namespace LibCmo::CK2 {
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc) {
|
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr, CKFileDocument* doc) {
|
||||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||||
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||||
parser->SetCursor(ParserPtr->GetCursor());
|
parser->SetCursor(ParserPtr->GetCursor());
|
||||||
|
@ -149,7 +149,6 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
// ========== dep list read ==========
|
// ========== dep list read ==========
|
||||||
// file ver >= 8 have this feature
|
// file ver >= 8 have this feature
|
||||||
bool noDepLost = true;
|
|
||||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
if (doc->m_FileInfo.FileVersion >= 8) {
|
||||||
// get size and resize
|
// get size and resize
|
||||||
CKDWORD depSize;
|
CKDWORD depSize;
|
||||||
|
@ -205,7 +204,7 @@ namespace LibCmo::CK2 {
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc) {
|
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr, CKFileDocument* doc) {
|
||||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||||
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||||
parser->SetCursor(ParserPtr->GetCursor());
|
parser->SetCursor(ParserPtr->GetCursor());
|
||||||
|
@ -351,32 +350,27 @@ namespace LibCmo::CK2 {
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKFile::DeepLoad(CKSTRING u8_filename, CKFileData::DeepDocument** out_doc) {
|
CKERROR CKFile::DeepLoad(CKSTRING u8_filename, CKFileDocument** out_doc) {
|
||||||
// ========== prepare work ==========
|
// ========== prepare work ==========
|
||||||
// preset value
|
// preset value
|
||||||
*out_doc = nullptr;
|
*out_doc = nullptr;
|
||||||
|
CKERROR err = CKERROR::CKERR_OK;
|
||||||
|
|
||||||
// get shallow document first
|
// get shallow document first
|
||||||
CKFileData::ShallowDocument* rawShallowDoc = nullptr;
|
CKFileDocument* rawShallowDoc = nullptr;
|
||||||
CKERROR err = this->ShallowLoad(u8_filename, &rawShallowDoc);
|
err = this->ShallowLoad(u8_filename, &rawShallowDoc);
|
||||||
if (rawShallowDoc == nullptr) return err;
|
if (rawShallowDoc == nullptr) return err;
|
||||||
std::unique_ptr<CKFileData::ShallowDocument> shallowDoc(rawShallowDoc);
|
// use unique ptr wrap it as a deep doc
|
||||||
|
std::unique_ptr<CKFileDocument> deepDoc(rawShallowDoc);
|
||||||
if (err != CKERROR::CKERR_OK) return err;
|
if (err != CKERROR::CKERR_OK) return err;
|
||||||
|
|
||||||
// create deep document
|
|
||||||
std::unique_ptr<CKFileData::DeepDocument> deepDoc(new(std::nothrow) CKFileData::DeepDocument());
|
|
||||||
if (deepDoc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
|
|
||||||
// ========== create object first ==========
|
// ========== create object first ==========
|
||||||
size_t index = 0u;
|
for (auto& obj : deepDoc->m_FileObjects) {
|
||||||
std::vector<CKObjectImplements::CKObject*> createdObjs(shallowDoc->m_FileObjects.size(), nullptr);
|
|
||||||
for (index = 0u; index < shallowDoc->m_FileObjects.size(); ++index) {
|
|
||||||
// todo: skip CK_LEVEL
|
// todo: skip CK_LEVEL
|
||||||
// todo: resolve references
|
// todo: resolve references
|
||||||
const auto& obj = shallowDoc->m_FileObjects[index];
|
|
||||||
if (obj.Data == nullptr) continue;
|
if (obj.Data == nullptr) continue;
|
||||||
|
|
||||||
createdObjs[index] = m_MinCtx->CreateCKObject(obj.ObjectId, obj.ObjectCid, obj.Name.c_str());
|
obj.ObjPtr = m_MinCtx->CreateCKObject(obj.ObjectId, obj.ObjectCid, obj.Name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== CKStateChunk remap ==========
|
// ========== CKStateChunk remap ==========
|
||||||
|
@ -387,523 +381,29 @@ namespace LibCmo::CK2 {
|
||||||
// todo...
|
// todo...
|
||||||
|
|
||||||
// ========== analyze objects CKStateChunk ==========
|
// ========== analyze objects CKStateChunk ==========
|
||||||
for (index = 0u; index < shallowDoc->m_FileObjects.size(); ++index) {
|
for (auto& obj : deepDoc->m_FileObjects) {
|
||||||
const auto& obj = shallowDoc->m_FileObjects[index];
|
if (obj.Data == nullptr || obj.ObjPtr == nullptr) continue;
|
||||||
if (obj.Data == nullptr || createdObjs[index] == nullptr) continue;
|
|
||||||
|
|
||||||
// todo: special treat for CK_LEVEL
|
// todo: special treat for CK_LEVEL
|
||||||
// try parsing data
|
// try parsing data
|
||||||
obj.Data->StartRead();
|
obj.Data->StartRead();
|
||||||
CKERROR err = createdObjs[index]->Load(obj.Data, shallowDoc.get());
|
err = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
||||||
obj.Data->StopRead();
|
obj.Data->StopRead();
|
||||||
if (err != CKERROR::CKERR_OK) {
|
if (err != CKERROR::CKERR_OK) {
|
||||||
delete (createdObjs[index]);
|
// if failed, delete it
|
||||||
createdObjs[index] = nullptr;
|
m_MinCtx->DestroyCKObject(obj.ObjectId);
|
||||||
|
obj.ObjPtr = nullptr;
|
||||||
} else {
|
} else {
|
||||||
// add into result
|
// if success, clear CKStateChunk*
|
||||||
deepDoc->m_Objects.push_back(createdObjs[index]);
|
delete obj.Data;
|
||||||
|
obj.Data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== finalize work ==========
|
// ========== finalize work ==========
|
||||||
// copy misc structure
|
|
||||||
deepDoc->m_IncludedFiles = shallowDoc->m_IncludedFiles;
|
|
||||||
deepDoc->m_SaveIDMax = shallowDoc->m_SaveIDMax;
|
|
||||||
deepDoc->m_FileInfo = shallowDoc->m_FileInfo;
|
|
||||||
// detach and return
|
// detach and return
|
||||||
*out_doc = deepDoc.release();
|
*out_doc = deepDoc.release();
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//CKERROR CKFile::Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags) {
|
|
||||||
// CKERROR result = this->OpenFile(u8_filename, flags);
|
|
||||||
// if (result == CKERROR::CKERR_OK || result == CKERROR::CKERR_PLUGINSMISSING) {
|
|
||||||
// result = this->LoadFileData();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return result;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//CKERROR CKFile::OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags) {
|
|
||||||
// this->ClearData();
|
|
||||||
// if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
|
||||||
|
|
||||||
// this->m_FileName = u8_filename;
|
|
||||||
// this->m_MappedFile = new(std::nothrow) VxMemoryMappedFile(this->m_FileName.c_str());
|
|
||||||
// if (this->m_MappedFile == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
// if (!this->m_MappedFile->IsValid()) return CKERROR::CKERR_INVALIDFILE;
|
|
||||||
|
|
||||||
// // MARK: CKContext::SetLastCmoLoaded
|
|
||||||
// return this->OpenMemory(this->m_MappedFile->GetBase(), this->m_MappedFile->GetFileSize(), flags);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//CKERROR CKFile::OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags) {
|
|
||||||
// if (MemoryBuffer == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
|
||||||
// // compare magic words
|
|
||||||
// if (BufferSize < 0x20 || memcmp(MemoryBuffer, "Nemo", 4u)) return CKERROR::CKERR_INVALIDFILE;
|
|
||||||
|
|
||||||
// this->m_Parser = new(std::nothrow) CKBufferParser(MemoryBuffer, BufferSize, false);
|
|
||||||
// if (this->m_Parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
// // MARK: eliminate check of m_Parser->m_ReaderBegin
|
|
||||||
|
|
||||||
// // MARK: dword_2405F6C0 = 0;
|
|
||||||
// this->m_Flags = Flags;
|
|
||||||
// this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
|
||||||
// return this->ReadFileHeaders(&(this->m_Parser));
|
|
||||||
//}
|
|
||||||
|
|
||||||
//CKERROR CKFile::ReadFileHeaders(CKBufferParser** ParserPtr) {
|
|
||||||
// CKBufferParser* parser = *ParserPtr;
|
|
||||||
// this->m_IncludedFiles.clear();
|
|
||||||
|
|
||||||
// // ========== read header1 ==========
|
|
||||||
// CKDWORD fhdr1[8];
|
|
||||||
// CKDWORD fhdr2[8];
|
|
||||||
// if (parser->GetSize() < sizeof(fhdr1)) return CKERROR::CKERR_INVALIDFILE;
|
|
||||||
// parser->Read(fhdr1, sizeof(fhdr1));
|
|
||||||
|
|
||||||
// if (fhdr1[5]) { // it seems that there is a ZERO checker?
|
|
||||||
// memset(fhdr1, 0, sizeof(fhdr1));
|
|
||||||
// }
|
|
||||||
// // check outdated
|
|
||||||
// if (fhdr1[4] > 9) return CKERROR::CKERR_OBSOLETEVIRTOOLS;
|
|
||||||
|
|
||||||
// // ========== read header2 ==========
|
|
||||||
// // file ver < 5 do not have second header
|
|
||||||
// if (fhdr1[4] < 5) {
|
|
||||||
// memset(fhdr2, 0, sizeof(fhdr2));
|
|
||||||
// } else {
|
|
||||||
// if (parser->GetSize() < sizeof(fhdr1) + sizeof(fhdr2)) return CKERROR::CKERR_INVALIDFILE;
|
|
||||||
// parser->Read(fhdr2, sizeof(fhdr2));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // forcely reset too big product ver
|
|
||||||
// if (fhdr2[5] >= 12) {
|
|
||||||
// fhdr2[5] = 0;
|
|
||||||
// fhdr2[6] = 0x1010000;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== assign value ==========
|
|
||||||
// this->m_FileInfo.ProductVersion = fhdr2[5];
|
|
||||||
// this->m_FileInfo.ProductBuild = fhdr2[6];
|
|
||||||
// this->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(fhdr1[6]);
|
|
||||||
// this->m_FileInfo.CKVersion = fhdr1[3];
|
|
||||||
// this->m_FileInfo.FileVersion = fhdr1[4];
|
|
||||||
// this->m_FileInfo.FileSize = parser->GetSize();
|
|
||||||
// this->m_FileInfo.ManagerCount = fhdr2[2];
|
|
||||||
// this->m_FileInfo.ObjectCount = fhdr2[3];
|
|
||||||
// this->m_FileInfo.MaxIDSaved = fhdr2[4];
|
|
||||||
// this->m_FileInfo.Hdr1PackSize = fhdr1[7];
|
|
||||||
// this->m_FileInfo.Hdr1UnPackSize = fhdr2[7];
|
|
||||||
// this->m_FileInfo.DataPackSize = fhdr2[0];
|
|
||||||
// this->m_FileInfo.DataUnPackSize = fhdr2[1];
|
|
||||||
// this->m_FileInfo.Crc = fhdr1[2];
|
|
||||||
|
|
||||||
// // ========== crc and body unpacker ==========
|
|
||||||
// if (this->m_FileInfo.FileVersion >= 8) {
|
|
||||||
// // crc checker for file ver >= 8
|
|
||||||
// // reset crc field of header
|
|
||||||
// fhdr1[2] = 0;
|
|
||||||
|
|
||||||
// // compute crc
|
|
||||||
// CKDWORD gotten_crc = CKComputeDataCRC(&fhdr1, sizeof(fhdr1), 0u);
|
|
||||||
// parser->SetCursor(sizeof(fhdr1));
|
|
||||||
// gotten_crc = CKComputeDataCRC(parser->GetPtr(), sizeof(fhdr2), gotten_crc);
|
|
||||||
// parser->MoveCursor(sizeof(fhdr2));
|
|
||||||
// gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
|
|
||||||
// parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
|
||||||
// gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
|
|
||||||
// parser->SetCursor(sizeof(fhdr1) + sizeof(fhdr2));
|
|
||||||
|
|
||||||
// if (gotten_crc != this->m_FileInfo.Crc) return CKERROR::CKERR_FILECRCERROR;
|
|
||||||
|
|
||||||
// // compare size to decide wheher use compress feature
|
|
||||||
// void* decomp_buffer = CKUnPackData(this->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_FileInfo.Hdr1PackSize);
|
|
||||||
// if (decomp_buffer != nullptr) {
|
|
||||||
// parser = new(std::nothrow) CKBufferParser(decomp_buffer, this->m_FileInfo.Hdr1UnPackSize, true);
|
|
||||||
// if (parser == nullptr) {
|
|
||||||
// delete[] decomp_buffer;
|
|
||||||
// return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== object list read ==========
|
|
||||||
// // file ver >= 7 have this features
|
|
||||||
// if (this->m_FileInfo.FileVersion >= 7) {
|
|
||||||
// // apply max id saved
|
|
||||||
// this->m_SaveIDMax = this->m_FileInfo.MaxIDSaved;
|
|
||||||
// // resize
|
|
||||||
// this->m_FileObject.resize(this->m_FileInfo.ObjectCount);
|
|
||||||
|
|
||||||
// // read data
|
|
||||||
// for (auto& fileobj : this->m_FileObject) {
|
|
||||||
// // setup useless fields
|
|
||||||
// fileobj.ObjPtr = nullptr;
|
|
||||||
// fileobj.Data = nullptr;
|
|
||||||
|
|
||||||
// // read basic fields
|
|
||||||
// parser->Read(&(fileobj.Object), sizeof(CK_ID));
|
|
||||||
// parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
|
||||||
// parser->Read(&(fileobj.FileIndex), sizeof(CKDWORD));
|
|
||||||
|
|
||||||
// CKDWORD namelen;
|
|
||||||
// parser->Read(&namelen, sizeof(CKDWORD));
|
|
||||||
// if (namelen != 0) {
|
|
||||||
// fileobj.Name.resize(namelen);
|
|
||||||
// parser->Read(fileobj.Name.data(), namelen);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== dep list read ==========
|
|
||||||
// // file ver >= 8 have this feature
|
|
||||||
// bool noDepLost = true;
|
|
||||||
// if (this->m_FileInfo.FileVersion >= 8) {
|
|
||||||
// // get size and resize
|
|
||||||
// CKDWORD depSize;
|
|
||||||
// parser->Read(&depSize, sizeof(CKDWORD));
|
|
||||||
// this->m_PluginDep.resize(depSize);
|
|
||||||
|
|
||||||
// CKDWORD guid_size;
|
|
||||||
// for (auto& dep : this->m_PluginDep) {
|
|
||||||
// // read category
|
|
||||||
// parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
|
||||||
// // get size and resize
|
|
||||||
// parser->Read(&guid_size, sizeof(CKDWORD));
|
|
||||||
// dep.m_Guids.resize(guid_size);
|
|
||||||
// dep.ValidGuids.resize(guid_size);
|
|
||||||
// // read data
|
|
||||||
// if (guid_size != 0) {
|
|
||||||
// parser->Read(dep.m_Guids.data(), sizeof(CKGUID) * guid_size);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // extra load flag
|
|
||||||
// if (EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_CHECKDEPENDENCIES)) {
|
|
||||||
// for (size_t i = 0u; i < dep.m_Guids.size(); ++i) {
|
|
||||||
// // MARK: CKPluginManager::FindComponent
|
|
||||||
// bool plgEntryIsNull = true;
|
|
||||||
// if (plgEntryIsNull) {
|
|
||||||
// noDepLost = false;
|
|
||||||
// dep.ValidGuids[i] = false;
|
|
||||||
// } else {
|
|
||||||
// dep.ValidGuids[i] = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== included file list read ==========
|
|
||||||
// // file ver >= 8 have this feature
|
|
||||||
// if (this->m_FileInfo.FileVersion >= 8) {
|
|
||||||
// // MARK: i don't knwo what is this!
|
|
||||||
// int32_t hasIncludedFile;
|
|
||||||
// parser->Read(&hasIncludedFile, sizeof(int32_t));
|
|
||||||
|
|
||||||
// if (hasIncludedFile > 0) {
|
|
||||||
// // read included file size and resize
|
|
||||||
// CKDWORD includedFileCount;
|
|
||||||
// parser->Read(&includedFileCount, sizeof(CKDWORD));
|
|
||||||
// this->m_IncludedFiles.resize(includedFileCount);
|
|
||||||
|
|
||||||
// hasIncludedFile -= 4;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // backward pos
|
|
||||||
// parser->SetCursor(hasIncludedFile);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== read data ==========
|
|
||||||
// // restore old parser if needed
|
|
||||||
// if (parser != *ParserPtr) {
|
|
||||||
// delete parser;
|
|
||||||
// parser = *ParserPtr;
|
|
||||||
// parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MARK: dword_2405F6BC, dword_2405F6B8 set
|
|
||||||
|
|
||||||
// if (!(EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_CHECKDEPENDENCIES) &&
|
|
||||||
// this->m_FileInfo.FileVersion < 8)) {
|
|
||||||
// // we have read all header. return result
|
|
||||||
// return noDepLost ? CKERROR::CKERR_OK : CKERROR::CKERR_PLUGINSMISSING;
|
|
||||||
// } // however, if we need check dep, and, we have not read dep list. continue read them.
|
|
||||||
|
|
||||||
// return CKERROR::CKERR_OK;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//CKERROR CKFile::ReadFileData(CKBufferParser** ParserPtr) {
|
|
||||||
// CKBufferParser* parser = *ParserPtr;
|
|
||||||
// CKBufferParser* parserSrc = *ParserPtr;
|
|
||||||
|
|
||||||
// // ========== compress feature process ==========
|
|
||||||
// if (EnumHelper::FlagEnumHas(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
|
||||||
// EnumHelper::FlagEnumHas(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
|
|
||||||
// void* decomp_buffer = CKUnPackData(this->m_FileInfo.DataUnPackSize, parser->GetPtr(), this->m_FileInfo.DataPackSize);
|
|
||||||
// parser->MoveCursor(this->m_FileInfo.DataPackSize);
|
|
||||||
|
|
||||||
// if (decomp_buffer != nullptr) {
|
|
||||||
// parser = new(std::nothrow) CKBufferParser(decomp_buffer, this->m_FileInfo.DataUnPackSize, true);
|
|
||||||
// if (parser == nullptr) {
|
|
||||||
// delete[] decomp_buffer;
|
|
||||||
// return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // sync to args
|
|
||||||
// *ParserPtr = parser;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== old file crc and obj list read ==========
|
|
||||||
// // only file ver < 8 run this
|
|
||||||
// if (this->m_FileInfo.FileVersion < 8) {
|
|
||||||
// // very very old flag
|
|
||||||
// if (this->m_FileInfo.FileVersion < 2) {
|
|
||||||
// ;
|
|
||||||
// // MARK: dword_2405F6C0 setter
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // check crc
|
|
||||||
// CKDWORD gotten_crc = CKComputeDataCRC(
|
|
||||||
// parser->GetPtr(),
|
|
||||||
// parser->GetSize() - parser->GetCursor(),
|
|
||||||
// 0u
|
|
||||||
// );
|
|
||||||
// if (gotten_crc != this->m_FileInfo.Crc) {
|
|
||||||
// // MARK: report crc error
|
|
||||||
// return CKERROR::CKERR_FILECRCERROR;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // get save id max
|
|
||||||
// parser->Read(&this->m_SaveIDMax, sizeof(int32_t));
|
|
||||||
// // get object count and resize
|
|
||||||
// parser->Read(&this->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
|
||||||
// if (this->m_FileObject.empty()) {
|
|
||||||
// this->m_FileObject.resize(this->m_FileInfo.ObjectCount);
|
|
||||||
// // MARK: ZeroMemory removed. i think it is not necessary.
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== manager read ==========
|
|
||||||
// // only file ver >= 6 have this
|
|
||||||
// if (this->m_FileInfo.FileVersion >= 6 && this->m_FileInfo.ManagerCount != 0) {
|
|
||||||
// this->m_ManagersData.resize(this->m_FileInfo.ManagerCount);
|
|
||||||
// CKDWORD stateChunkLen = 0u;
|
|
||||||
// bool stateChkParseSuccess = false;
|
|
||||||
|
|
||||||
// for (auto& mgr : this->m_ManagersData) {
|
|
||||||
// // read guid
|
|
||||||
// parser->Read(&(mgr.Manager), sizeof(CKGUID));
|
|
||||||
|
|
||||||
// // read statechunk len
|
|
||||||
// parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
|
||||||
// // check len
|
|
||||||
// if (stateChunkLen == 0) {
|
|
||||||
// mgr.Data = nullptr;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// // read statechunk
|
|
||||||
// mgr.Data = new(std::nothrow) CKStateChunk();
|
|
||||||
// if (mgr.Data != nullptr) {
|
|
||||||
// stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
|
|
||||||
// if (!stateChkParseSuccess) {
|
|
||||||
// delete mgr.Data;
|
|
||||||
// mgr.Data = nullptr;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// parser->MoveCursor(stateChunkLen);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== object read ==========
|
|
||||||
// if (this->m_FileInfo.ObjectCount != 0) {
|
|
||||||
// if (this->m_FileInfo.FileVersion >= 4) {
|
|
||||||
// // new file reader section
|
|
||||||
// CKDWORD stateChunkLen = 0u;
|
|
||||||
// bool stateChkParseSuccess = false;
|
|
||||||
// for (auto& obj : this->m_FileObject) {
|
|
||||||
// if (this->m_FileInfo.FileVersion < 7) {
|
|
||||||
// // it seems that file ver < 7, ck id was stored first.
|
|
||||||
// parser->Read(&(obj.Object), sizeof(CK_ID));
|
|
||||||
// }
|
|
||||||
// // get statechunk len
|
|
||||||
// parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
|
||||||
|
|
||||||
// // if only load behavior and current loaded obj is not behavior, give up.
|
|
||||||
// // >= 7 is corresponding with obj header version requirement
|
|
||||||
// // so don't worry about this
|
|
||||||
// if (EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_ONLYBEHAVIORS) &&
|
|
||||||
// this->m_FileInfo.FileVersion >= 7 &&
|
|
||||||
// obj.ObjectCid != CK_CLASSID::CKCID_BEHAVIOR) {
|
|
||||||
// // move cursor for next one.
|
|
||||||
// parser->MoveCursor(stateChunkLen);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // check state chunk len
|
|
||||||
// if (stateChunkLen == 0) {
|
|
||||||
// obj.Data = nullptr;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// // read state chunk
|
|
||||||
// obj.Data = new(std::nothrow) CKStateChunk();
|
|
||||||
// if (obj.Data != nullptr) {
|
|
||||||
// stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
|
|
||||||
// if (!stateChkParseSuccess) {
|
|
||||||
// delete obj.Data;
|
|
||||||
// obj.Data = nullptr;
|
|
||||||
// } else {
|
|
||||||
// // get data size and fill some fields
|
|
||||||
// obj.PostPackSize = obj.Data->GetDataSize();
|
|
||||||
// obj.PrePackSize = obj.PostPackSize;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// parser->MoveCursor(stateChunkLen);
|
|
||||||
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// // old file read section
|
|
||||||
// for (auto& obj : this->m_FileObject) {
|
|
||||||
// // read CK_ID
|
|
||||||
// parser->Read(&(obj.Object), sizeof(CK_ID));
|
|
||||||
// // get data len
|
|
||||||
// CKDWORD dataLen = 0u;
|
|
||||||
// parser->Read(&dataLen, sizeof(CKDWORD));
|
|
||||||
|
|
||||||
// // check state chunk len
|
|
||||||
// if (dataLen == 0) {
|
|
||||||
// obj.Data = nullptr;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MARK: set dword_2405F6C0
|
|
||||||
//
|
|
||||||
// // read class id
|
|
||||||
// CK_CLASSID clsid = CK_CLASSID::CKCID_OBJECT;
|
|
||||||
// parser->Read(&clsid, sizeof(CK_CLASSID));
|
|
||||||
// if (static_cast<uint32_t>(clsid) == UINT32_C(0)) {
|
|
||||||
// // invalid cid;
|
|
||||||
// return CKERROR::CKERR_INVALIDFILE;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // read save flags
|
|
||||||
// parser->Read(&obj.SaveFlags, sizeof(CK_FILE_WRITEMODE));
|
|
||||||
|
|
||||||
// // read statechunk len
|
|
||||||
// CKDWORD oldBufLen = 0u;
|
|
||||||
// parser->Read(&oldBufLen, sizeof(CKDWORD));
|
|
||||||
|
|
||||||
// // setup state chunk and order parse it
|
|
||||||
// obj.Data = new(std::nothrow) CKStateChunk(clsid);
|
|
||||||
// if (obj.Data != nullptr) {
|
|
||||||
// if (!obj.Data->ConvertFromOldBuffer(parser->GetPtr(), oldBufLen, dataLen, obj.SaveFlags)) {
|
|
||||||
// delete obj.Data;
|
|
||||||
// obj.Data = nullptr;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // move to next
|
|
||||||
// parser->MoveCursor(oldBufLen);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MARK: remove a weird assign: parserSrc = v46; it seems useless.
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== object name get ==========
|
|
||||||
// // only file ver < 7 need get it from statechunk
|
|
||||||
// if (this->m_FileInfo.FileVersion < 7) {
|
|
||||||
// for (auto& obj : this->m_FileObject) {
|
|
||||||
// if (obj.Data != nullptr) {
|
|
||||||
// // TODO: CK_STATESAVE_NAME
|
|
||||||
// if (obj.Data->SeekIdentifier(1u)) {
|
|
||||||
// obj.Data->ReadString(obj.Name);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== included file get ==========
|
|
||||||
// // WARN: we use "parserSrc" to read, not "parser"!!!
|
|
||||||
// for (size_t i = 0; i < this->m_IncludedFiles.size(); ++i) {
|
|
||||||
// // get file name length and resize it
|
|
||||||
// CKDWORD filenamelen = 0u;
|
|
||||||
// parserSrc->Read(&filenamelen, sizeof(CKDWORD));
|
|
||||||
// std::string filename;
|
|
||||||
// filename.resize(filenamelen);
|
|
||||||
|
|
||||||
// // read filename
|
|
||||||
// if (filenamelen != 0) {
|
|
||||||
// parserSrc->Read(filename.data(), filenamelen);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // todo: construct temp folder path
|
|
||||||
// // and regulate file name
|
|
||||||
|
|
||||||
// // read file body length
|
|
||||||
// CKDWORD filebodylen = 0u;
|
|
||||||
// parserSrc->Read(&filebodylen, sizeof(CKDWORD));
|
|
||||||
|
|
||||||
// // todo: read file body
|
|
||||||
// parserSrc->MoveCursor(filebodylen);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ========== free parser ==========
|
|
||||||
// if (parserSrc != parser && parserSrc != nullptr) {
|
|
||||||
// // WARN: we should free parserSrc! not free parser
|
|
||||||
// // because "parser" has synced with ParserPtr and will be freed from outside.
|
|
||||||
// delete parserSrc;
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return CKERROR::CKERR_OK;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//CKERROR CKFile::LoadFileData(void/*CKObjectArray list*/) {
|
|
||||||
// if (!this->m_Parser && !this->m_ReadFileDataDone) {
|
|
||||||
// return CKERROR::CKERR_INVALIDFILE;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MARK: sub_240372EA, ctx + 193 = 1
|
|
||||||
|
|
||||||
// // if file data has not been read. read it
|
|
||||||
// CKERROR err = CKERROR::CKERR_OK;
|
|
||||||
// CKBufferParser** ParserPtr = &this->m_Parser;
|
|
||||||
// if (!this->m_ReadFileDataDone) {
|
|
||||||
// err = this->ReadFileData(ParserPtr);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MARK: i assume FinishLoading do not calling mapped file anymore
|
|
||||||
// // free file data
|
|
||||||
// if (*ParserPtr != nullptr) {
|
|
||||||
// delete *ParserPtr;
|
|
||||||
// *ParserPtr = nullptr;
|
|
||||||
// }
|
|
||||||
// if (this->m_MappedFile != nullptr) {
|
|
||||||
// delete this->m_MappedFile;
|
|
||||||
// this->m_MappedFile = nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // if no error, do finish loading
|
|
||||||
// if (err == CKERROR::CKERR_OK) {
|
|
||||||
// this->FinishLoading(this->m_Flags);
|
|
||||||
|
|
||||||
// // MARK: dword_2405F6C0 old vt ver output
|
|
||||||
// }
|
|
||||||
// // MARK: CKContext::SetAutomaticLoadMode
|
|
||||||
// // MARK:CKContext::SetUserLoadCallback
|
|
||||||
|
|
||||||
// // MARK: sub_24037360
|
|
||||||
// // MARK: ctx + 193 = 0
|
|
||||||
|
|
||||||
// return err;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//CKERROR CKFile::FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags) {
|
|
||||||
// return CKERROR::CKERR_OK;
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ namespace LibCmo::CK2::CKManagerImplements {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKBaseManager::LoadData(CKStateChunk* statechunk, CKFileData::ShallowDocument* doc) {
|
CKERROR CKBaseManager::LoadData(CKStateChunk* statechunk, CKFileDocument* doc) {
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
CKStateChunk* CKBaseManager::SaveData(CKFileData::ShallowDocument* doc) {
|
CKStateChunk* CKBaseManager::SaveData(CKFileDocument* doc) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace LibCmo::CK2::CKManagerImplements {
|
||||||
CKBaseManager& operator=(const CKBaseManager&) = delete;
|
CKBaseManager& operator=(const CKBaseManager&) = delete;
|
||||||
virtual ~CKBaseManager();
|
virtual ~CKBaseManager();
|
||||||
|
|
||||||
virtual CKERROR LoadData(CKStateChunk* statechunk, CKFileData::ShallowDocument* doc);
|
virtual CKERROR LoadData(CKStateChunk* statechunk, CKFileDocument* doc);
|
||||||
virtual CKStateChunk* SaveData(CKFileData::ShallowDocument* doc);
|
virtual CKStateChunk* SaveData(CKFileDocument* doc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,11 @@ namespace LibCmo::CK2 {
|
||||||
std::filesystem::create_directory(m_TempFolder);
|
std::filesystem::create_directory(m_TempFolder);
|
||||||
}
|
}
|
||||||
CKMinContext::~CKMinContext() {
|
CKMinContext::~CKMinContext() {
|
||||||
|
// free all created objects
|
||||||
|
for (const auto& [key, value] : this->m_ObjectsList) {
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
// todo: free all created managers
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace LibCmo::CK2::CKObjectImplements {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKObject::Load(CKStateChunk* chunk, const CKFileData::ShallowDocument* doc) {
|
CKERROR CKObject::Load(CKStateChunk* chunk, const CKFileDocument* doc) {
|
||||||
if (chunk->SeekIdentifier(Identifiers::CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
|
if (chunk->SeekIdentifier(Identifiers::CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
|
||||||
EnumsHelper::FlagEnumRm(this->m_ObjectFlags,
|
EnumsHelper::FlagEnumRm(this->m_ObjectFlags,
|
||||||
{ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE,
|
{ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE,
|
||||||
|
@ -45,7 +45,7 @@ namespace LibCmo::CK2::CKObjectImplements {
|
||||||
|
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
CKStateChunk* CKObject::Save(CKFileData::ShallowDocument* doc) {
|
CKStateChunk* CKObject::Save(const CKFileDocument* doc) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ namespace LibCmo::CK2::CKObjectImplements {
|
||||||
void SetObjectFlags(CK_OBJECT_FLAGS flags) { this->m_ObjectFlags = flags; }
|
void SetObjectFlags(CK_OBJECT_FLAGS flags) { this->m_ObjectFlags = flags; }
|
||||||
|
|
||||||
virtual CK_CLASSID GetClassID(void) { return CK_CLASSID::CKCID_OBJECT; }
|
virtual CK_CLASSID GetClassID(void) { return CK_CLASSID::CKCID_OBJECT; }
|
||||||
virtual CKERROR Load(CKStateChunk* chunk, const CKFileData::ShallowDocument* doc);
|
virtual CKERROR Load(CKStateChunk* chunk, const CKFileDocument* doc);
|
||||||
virtual CKStateChunk* Save(CKFileData::ShallowDocument* doc);
|
virtual CKStateChunk* Save(const CKFileDocument* doc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CKSceneObject : public CKObject {
|
class CKSceneObject : public CKObject {
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace LibCmo::CK2 {
|
||||||
if (EnsureReadSpace(static_cast<CKDWORD>(size))) {
|
if (EnsureReadSpace(static_cast<CKDWORD>(size))) {
|
||||||
std::memcpy(data, this->m_pData + this->m_Parser.m_CurrentPos, size);
|
std::memcpy(data, this->m_pData + this->m_Parser.m_CurrentPos, size);
|
||||||
|
|
||||||
} return CKERROR::CKERR_OUTOFMEMORY;
|
} else return CKERROR::CKERR_OUTOFMEMORY;
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
|
|
@ -29,11 +29,11 @@ namespace LibCmo::EncodingHelper {
|
||||||
int count, write_result;
|
int count, write_result;
|
||||||
|
|
||||||
//converter to CHAR
|
//converter to CHAR
|
||||||
count = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
|
count = WideCharToMultiByte(codepage, 0, src, -1, NULL, 0, NULL, NULL);
|
||||||
if (count <= 0) return false;
|
if (count <= 0) return false;
|
||||||
|
|
||||||
dest.resize(count);
|
dest.resize(count);
|
||||||
write_result = WideCharToMultiByte(CP_UTF8, 0, src, -1, dest.data(), count, NULL, NULL);
|
write_result = WideCharToMultiByte(codepage, 0, src, -1, dest.data(), count, NULL, NULL);
|
||||||
if (write_result <= 0) return false;
|
if (write_result <= 0) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -50,7 +50,7 @@ namespace LibCmo::EncodingHelper {
|
||||||
if (wcount <= 0) return false;
|
if (wcount <= 0) return false;
|
||||||
|
|
||||||
dest.resize(wcount);
|
dest.resize(wcount);
|
||||||
write_result = MultiByteToWideChar(CP_UTF8, 0, src, -1, dest.data(), wcount);
|
write_result = MultiByteToWideChar(codepage, 0, src, -1, dest.data(), wcount);
|
||||||
if (write_result <= 0) return false;
|
if (write_result <= 0) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -71,9 +71,9 @@ namespace LibCmo::EncodingHelper {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static constexpr const IconvInc = 16;
|
static constexpr const size_t IconvInc = 16;
|
||||||
bool DoIconv(const char* enc_from, const char* enc_to,
|
|
||||||
std::string& str_from, std::string& str_to) {
|
bool DoIconv(const char* enc_from, const char* enc_to, std::string& str_from, std::string& str_to) {
|
||||||
iconv_t cd;
|
iconv_t cd;
|
||||||
char *inbuf = nullptr, *outbuf = nullptr;
|
char *inbuf = nullptr, *outbuf = nullptr;
|
||||||
size_t inbytesleft, outbytesleft, nchars, result_len;
|
size_t inbytesleft, outbytesleft, nchars, result_len;
|
||||||
|
@ -199,7 +199,7 @@ namespace LibCmo::EncodingHelper {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static const char UTF8_SYMBOL[] = "UTF-8";
|
static constexpr const char UTF8_SYMBOL[] = "UTF-8";
|
||||||
|
|
||||||
ENCODING_TOKEN CreateEncodingToken(std::string& token_string) {
|
ENCODING_TOKEN CreateEncodingToken(std::string& token_string) {
|
||||||
ENCODING_TOKEN token = new(std::nothrow) char[token_string.size() + 1];
|
ENCODING_TOKEN token = new(std::nothrow) char[token_string.size() + 1];
|
||||||
|
|
|
@ -1,78 +1,243 @@
|
||||||
#include "CmdHelper.hpp"
|
#include "CmdHelper.hpp"
|
||||||
#include "TerminalHelper.hpp"
|
#include "TerminalHelper.hpp"
|
||||||
#include "VTUtils.hpp"
|
|
||||||
#include "VTEncoding.hpp"
|
#include <CKMinContext.hpp>
|
||||||
|
#include <CKFile.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
/*
|
namespace Unvirt::CmdHelper {
|
||||||
|
|
||||||
namespace Unvirt {
|
|
||||||
namespace CmdHelper {
|
|
||||||
|
|
||||||
#pragma region CmdSplitter
|
#pragma region CmdSplitter
|
||||||
|
|
||||||
CmdSplitter::CmdSplitter() :
|
CmdSplitter::CmdSplitter() :
|
||||||
mCmdChar(0), mBuffer(nullptr), mResult(nullptr),
|
mCmdChar(0), mBuffer(nullptr), mResult(nullptr),
|
||||||
mState(StateType::NORMAL), mPreState(StateType::NORMAL) {
|
mState(StateType::NORMAL), mPreState(StateType::NORMAL) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
CmdSplitter::~CmdSplitter() {
|
CmdSplitter::~CmdSplitter() {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
|
const std::deque<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
|
||||||
// set up variables
|
// set up variables
|
||||||
std::vector<std::string> result;
|
std::deque<std::string> result;
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
mBuffer = &buffer;
|
mBuffer = &buffer;
|
||||||
mResult = &result;
|
mResult = &result;
|
||||||
mState = mPreState = StateType::SPACE;
|
mState = mPreState = StateType::SPACE;
|
||||||
|
|
||||||
// split
|
// split
|
||||||
for (auto it = u8cmd.begin(); it != u8cmd.end(); ++it) {
|
for (auto it = u8cmd.begin(); it != u8cmd.end(); ++it) {
|
||||||
mCmdChar = (*it);
|
mCmdChar = (*it);
|
||||||
|
|
||||||
switch (mState) {
|
|
||||||
case StateType::SPACE:
|
|
||||||
ProcSpace();
|
|
||||||
break;
|
|
||||||
case StateType::SINGLE:
|
|
||||||
ProcSingle();
|
|
||||||
break;
|
|
||||||
case StateType::DOUBLE:
|
|
||||||
ProcDouble();
|
|
||||||
break;
|
|
||||||
case StateType::ESCAPE:
|
|
||||||
ProcEscape();
|
|
||||||
break;
|
|
||||||
case StateType::NORMAL:
|
|
||||||
ProcNormal();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// final proc
|
|
||||||
switch (mState) {
|
switch (mState) {
|
||||||
case StateType::SPACE:
|
case StateType::SPACE:
|
||||||
break;
|
ProcSpace();
|
||||||
case StateType::NORMAL:
|
|
||||||
// push the last one
|
|
||||||
mResult->push_back(*mBuffer);
|
|
||||||
break;
|
break;
|
||||||
case StateType::SINGLE:
|
case StateType::SINGLE:
|
||||||
|
ProcSingle();
|
||||||
|
break;
|
||||||
case StateType::DOUBLE:
|
case StateType::DOUBLE:
|
||||||
|
ProcDouble();
|
||||||
|
break;
|
||||||
case StateType::ESCAPE:
|
case StateType::ESCAPE:
|
||||||
// error
|
ProcEscape();
|
||||||
result.clear();
|
break;
|
||||||
|
case StateType::NORMAL:
|
||||||
|
ProcNormal();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return value
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// final proc
|
||||||
|
switch (mState) {
|
||||||
|
case StateType::SPACE:
|
||||||
|
break;
|
||||||
|
case StateType::NORMAL:
|
||||||
|
// push the last one
|
||||||
|
mResult->push_back(*mBuffer);
|
||||||
|
break;
|
||||||
|
case StateType::SINGLE:
|
||||||
|
case StateType::DOUBLE:
|
||||||
|
case StateType::ESCAPE:
|
||||||
|
// error
|
||||||
|
result.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return value
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region ArgParser
|
||||||
|
|
||||||
|
bool ArgParser::ParseInt(const std::vector<std::string>& cmd, const size_t expected_index, int32_t& result) {
|
||||||
|
if (expected_index >= cmd.size()) {
|
||||||
|
result = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* pend = nullptr;
|
||||||
|
errno = 0;
|
||||||
|
int64_t v = std::strtoll(cmd[expected_index].c_str(), &pend, 10);
|
||||||
|
|
||||||
|
if (pend == cmd[expected_index].c_str() || errno == ERANGE) {
|
||||||
|
result = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = static_cast<int>(v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArgParser::ParseString(const std::vector<std::string>& cmd, const size_t expected_index, std::string& result) {
|
||||||
|
if (expected_index >= cmd.size()) {
|
||||||
|
result.clear();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
result = cmd[expected_index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArgParser::ParseSwitch(const std::vector<std::string>& cmd, const size_t expected_index, const std::vector<std::string>& switches, std::string& gotten) {
|
||||||
|
if (expected_index >= cmd.size()) {
|
||||||
|
gotten.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& sw : switches) {
|
||||||
|
if (cmd[expected_index] == sw) {
|
||||||
|
gotten = cmd[expected_index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gotten.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region InteractiveCmd
|
||||||
|
|
||||||
|
InteractiveCmd::InteractiveCmd() :
|
||||||
|
m_CmdSplitter(), m_ExitRunFlag(false),
|
||||||
|
m_Ctx(nullptr), m_Doc(nullptr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
InteractiveCmd::~InteractiveCmd() {
|
||||||
|
if (m_Doc != nullptr) delete m_Doc;
|
||||||
|
if (m_Ctx != nullptr) delete m_Ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractiveCmd::Run(void) {
|
||||||
|
std::string u8cmd;
|
||||||
|
|
||||||
|
m_ExitRunFlag = false;
|
||||||
|
while (!m_ExitRunFlag) {
|
||||||
|
// get command
|
||||||
|
GetCmdLine(u8cmd);
|
||||||
|
|
||||||
|
// split cmd and parse it
|
||||||
|
auto cmds = m_CmdSplitter.Convert(u8cmd);
|
||||||
|
|
||||||
|
// get sub command
|
||||||
|
if (cmds.size() < 1u) {
|
||||||
|
this->PrintCommonError("No command specified!");
|
||||||
|
this->PrintHelp();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string subcmd(cmds.front());
|
||||||
|
cmds.pop_front();
|
||||||
|
|
||||||
|
// dispatch command
|
||||||
|
bool success = true;
|
||||||
|
if (subcmd == "load") success = this->ProcLoad(cmds);
|
||||||
|
else if (subcmd == "unload") success = this->ProcUnLoad(cmds);
|
||||||
|
else if (subcmd == "info") success = this->ProcInfo(cmds);
|
||||||
|
else if (subcmd == "ls") success = this->ProcLs(cmds);
|
||||||
|
else {
|
||||||
|
this->PrintCommonError("No such command \"\".", subcmd.c_str());
|
||||||
|
this->PrintHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) this->PrintHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractiveCmd::GetCmdLine(std::string& u8cmd) {
|
||||||
|
#if defined(LIBCMO_OS_WIN32)
|
||||||
|
std::wstring wcmd;
|
||||||
|
std::getline(std::wcin, wcmd);
|
||||||
|
LibCmo::EncodingHelper::WcharToChar(wcmd, u8cmd, CP_UTF8);
|
||||||
|
#else
|
||||||
|
std::getline(std::cin, u8cmd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InteractiveCmd::HasOpenedFile(void) {
|
||||||
|
return (m_Ctx != nullptr || m_Doc != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractiveCmd::PrintHelp(void) {
|
||||||
|
FILE* f = stdout;
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Subcommands: \n")), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractiveCmd::PrintArgParseError(const std::deque<std::string>& cmd, size_t pos) {
|
||||||
|
if (pos >= cmd.size()) {
|
||||||
|
fprintf(stdout, UNVIRT_TERMCOL_LIGHT_RED(("Lost argument at position %zu.\n")), pos);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, UNVIRT_TERMCOL_LIGHT_RED(("Unexpected argument \"%s\".\n")), cmd[pos].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// arg error always print help
|
||||||
|
this->PrintHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractiveCmd::PrintCommonError(const char* u8_fmt, ...) {
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, u8_fmt);
|
||||||
|
std::fputs(UNVIRT_TERMCOLHDR_LIGHT_RED, stdout);
|
||||||
|
std::vfprintf(stdout, u8_fmt, argptr);
|
||||||
|
std::fputs(UNVIRT_TERMCOLTAIL, stdout);
|
||||||
|
va_end(argptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Command Processors
|
||||||
|
|
||||||
|
bool InteractiveCmd::ProcLoad(const std::deque<std::string>& cmd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InteractiveCmd::ProcUnLoad(const std::deque<std::string>& cmd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InteractiveCmd::ProcInfo(const std::deque<std::string>& cmd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InteractiveCmd::ProcLs(const std::deque<std::string>& cmd) {
|
||||||
|
static const std::vector<std::string> c_AllowedSwitches {
|
||||||
|
"obj", "mgr"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
#pragma region OptionsDescription
|
#pragma region OptionsDescription
|
||||||
|
|
||||||
OptionsDescription::OptionsDescription() :
|
OptionsDescription::OptionsDescription() :
|
||||||
|
@ -444,7 +609,7 @@ namespace Unvirt {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,256 +1,290 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <VTUtils.h>
|
||||||
|
#include <CKDefines.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <deque>
|
||||||
#include <stdexcept>
|
|
||||||
#include "VTUtils.hpp"
|
|
||||||
|
|
||||||
/*
|
namespace Unvirt::CmdHelper {
|
||||||
|
|
||||||
namespace Unvirt {
|
class CmdSplitter {
|
||||||
namespace CmdHelper {
|
public:
|
||||||
|
CmdSplitter();
|
||||||
|
CmdSplitter(const CmdSplitter&) = delete;
|
||||||
|
CmdSplitter& operator=(const CmdSplitter&) = delete;
|
||||||
|
~CmdSplitter();
|
||||||
|
|
||||||
class CmdSplitter {
|
const std::deque<std::string> Convert(const std::string& u8cmd);
|
||||||
public:
|
private:
|
||||||
CmdSplitter();
|
char mCmdChar;
|
||||||
CmdSplitter(const CmdSplitter&) = delete;
|
std::string* mBuffer;
|
||||||
CmdSplitter& operator=(const CmdSplitter&) = delete;
|
std::deque<std::string>* mResult;
|
||||||
~CmdSplitter();
|
|
||||||
|
|
||||||
const std::vector<std::string> Convert(const std::string& u8cmd);
|
enum class StateType : int {
|
||||||
private:
|
SPACE,
|
||||||
char mCmdChar;
|
SINGLE,
|
||||||
std::string* mBuffer;
|
DOUBLE,
|
||||||
std::vector<std::string>* mResult;
|
ESCAPE,
|
||||||
|
NORMAL
|
||||||
|
};
|
||||||
|
StateType mState, mPreState;
|
||||||
|
|
||||||
enum class StateType : int {
|
inline void ProcSpace(void) {
|
||||||
SPACE,
|
switch (mCmdChar) {
|
||||||
SINGLE,
|
case '\'':
|
||||||
DOUBLE,
|
mState = StateType::SINGLE;
|
||||||
ESCAPE,
|
break;
|
||||||
NORMAL
|
case '"':
|
||||||
};
|
mState = StateType::DOUBLE;
|
||||||
StateType mState, mPreState;
|
break;
|
||||||
|
case '\\':
|
||||||
inline void ProcSpace(void) {
|
mState = StateType::ESCAPE;
|
||||||
switch (mCmdChar) {
|
mPreState = StateType::NORMAL;
|
||||||
case '\'':
|
break;
|
||||||
mState = StateType::SINGLE;
|
case ' ':
|
||||||
break;
|
break; // skip blank
|
||||||
case '"':
|
default:
|
||||||
mState = StateType::DOUBLE;
|
mBuffer->push_back(mCmdChar);
|
||||||
break;
|
mState = StateType::NORMAL;
|
||||||
case '\\':
|
break;
|
||||||
mState = StateType::ESCAPE;
|
|
||||||
mPreState = StateType::NORMAL;
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
break; // skip blank
|
|
||||||
default:
|
|
||||||
mBuffer->push_back(mCmdChar);
|
|
||||||
mState = StateType::NORMAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
inline void ProcSingle(void) {
|
}
|
||||||
switch (mCmdChar) {
|
inline void ProcSingle(void) {
|
||||||
case '\'':
|
switch (mCmdChar) {
|
||||||
mState = StateType::NORMAL;
|
case '\'':
|
||||||
break;
|
mState = StateType::NORMAL;
|
||||||
case '"':
|
break;
|
||||||
mBuffer->push_back('"');
|
case '"':
|
||||||
break;
|
mBuffer->push_back('"');
|
||||||
case '\\':
|
break;
|
||||||
mState = StateType::ESCAPE;
|
case '\\':
|
||||||
mPreState = StateType::SINGLE;
|
mState = StateType::ESCAPE;
|
||||||
break;
|
mPreState = StateType::SINGLE;
|
||||||
case ' ':
|
break;
|
||||||
mBuffer->push_back(' ');
|
case ' ':
|
||||||
break;
|
mBuffer->push_back(' ');
|
||||||
default:
|
break;
|
||||||
mBuffer->push_back(mCmdChar);
|
default:
|
||||||
break;
|
mBuffer->push_back(mCmdChar);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
inline void ProcDouble(void) {
|
}
|
||||||
switch (mCmdChar) {
|
inline void ProcDouble(void) {
|
||||||
case '\'':
|
switch (mCmdChar) {
|
||||||
mBuffer->push_back('\'');
|
case '\'':
|
||||||
break;
|
mBuffer->push_back('\'');
|
||||||
case '"':
|
break;
|
||||||
mState = StateType::NORMAL;
|
case '"':
|
||||||
break;
|
mState = StateType::NORMAL;
|
||||||
case '\\':
|
break;
|
||||||
mState = StateType::ESCAPE;
|
case '\\':
|
||||||
mPreState = StateType::DOUBLE;
|
mState = StateType::ESCAPE;
|
||||||
break;
|
mPreState = StateType::DOUBLE;
|
||||||
case ' ':
|
break;
|
||||||
mBuffer->push_back(' ');
|
case ' ':
|
||||||
break;
|
mBuffer->push_back(' ');
|
||||||
default:
|
break;
|
||||||
mBuffer->push_back(mCmdChar);
|
default:
|
||||||
break;
|
mBuffer->push_back(mCmdChar);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
inline void ProcEscape(void) {
|
}
|
||||||
// add itself
|
inline void ProcEscape(void) {
|
||||||
mBuffer->push_back(mCmdChar);
|
// add itself
|
||||||
// restore state
|
mBuffer->push_back(mCmdChar);
|
||||||
mState = mPreState;
|
// restore state
|
||||||
|
mState = mPreState;
|
||||||
|
}
|
||||||
|
inline void ProcNormal(void) {
|
||||||
|
switch (mCmdChar) {
|
||||||
|
case '\'':
|
||||||
|
mBuffer->push_back('\'');
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
mBuffer->push_back('"');
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
mState = StateType::ESCAPE;
|
||||||
|
mPreState = StateType::NORMAL;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
mResult->push_back(*mBuffer);
|
||||||
|
mBuffer->clear();
|
||||||
|
mState = StateType::SPACE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mBuffer->push_back(mCmdChar);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
inline void ProcNormal(void) {
|
}
|
||||||
switch (mCmdChar) {
|
};
|
||||||
case '\'':
|
|
||||||
mBuffer->push_back('\'');
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
mBuffer->push_back('"');
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
mState = StateType::ESCAPE;
|
|
||||||
mPreState = StateType::NORMAL;
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
mResult->push_back(*mBuffer);
|
|
||||||
mBuffer->clear();
|
|
||||||
mState = StateType::SPACE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mBuffer->push_back(mCmdChar);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CmdArgType {
|
class ArgParser {
|
||||||
NONE,
|
public:
|
||||||
STRING,
|
ArgParser() {}
|
||||||
INT
|
ArgParser(const ArgParser&) = delete;
|
||||||
};
|
ArgParser& operator=(const ArgParser&) = delete;
|
||||||
|
~ArgParser() {}
|
||||||
|
|
||||||
struct OptionDescription {
|
static bool ParseInt(const std::vector<std::string>& cmd, const size_t expected_index, int32_t& result);
|
||||||
std::string mLongName;
|
static bool ParseString(const std::vector<std::string>& cmd, const size_t expected_index, std::string& result);
|
||||||
char mShortName;
|
static bool ParseSwitch(const std::vector<std::string>& cmd, const size_t expected_index, const std::vector<std::string>& switches, std::string& gotten);
|
||||||
CmdArgType mType;
|
};
|
||||||
std::string mDescription;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OptionsDescription {
|
class InteractiveCmd {
|
||||||
public:
|
public:
|
||||||
OptionsDescription();
|
InteractiveCmd();
|
||||||
OptionsDescription(const OptionsDescription&) = delete;
|
InteractiveCmd(const InteractiveCmd&) = delete;
|
||||||
OptionsDescription& operator=(const OptionsDescription&) = delete;
|
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
||||||
~OptionsDescription();
|
~InteractiveCmd();
|
||||||
|
|
||||||
/// <summary>
|
void Run(void);
|
||||||
/// Add an option
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fullname">The long name of this option. Should NOT be blank or NULL.</param>
|
|
||||||
/// <param name="shortname">A single char for the short name of this option. Leave ZERO to omit this.</param>
|
|
||||||
/// <param name="type">The value type of this option. Set to CmdArgType::NONE to indicate this is a switch (no value).</param>
|
|
||||||
/// <param name="sescription">The description of this option. This can be NULL.</param>
|
|
||||||
void AddOption(const char* fullname, char shortname, CmdArgType type, const char* sescription);
|
|
||||||
void AddPositionalOption(const char* corresponding_longname);
|
|
||||||
|
|
||||||
OptionDescription* GetDescByLongName(const std::string& longname);
|
private:
|
||||||
OptionDescription* GetDescByShortName(char shortname);
|
void GetCmdLine(std::string& u8cmd);
|
||||||
OptionDescription* GetDescByPosition(size_t pos);
|
bool HasOpenedFile(void);
|
||||||
|
void PrintHelp(void);
|
||||||
|
void PrintArgParseError(const std::deque<std::string>& cmd, size_t pos);
|
||||||
|
void PrintCommonError(const char* u8_fmt, ...);
|
||||||
|
|
||||||
void PrintHelp(FILE* f);
|
bool ProcLoad(const std::deque<std::string>& cmd);
|
||||||
private:
|
bool ProcUnLoad(const std::deque<std::string>& cmd);
|
||||||
std::unordered_map<std::string, OptionDescription> mLongNameDict;
|
bool ProcInfo(const std::deque<std::string>& cmd);
|
||||||
std::unordered_map<char, std::string> mShortNameMapping;
|
bool ProcLs(const std::deque<std::string>& cmd);
|
||||||
std::vector<std::string> mPositionalArgMapping;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AnyVariable {
|
bool m_ExitRunFlag;
|
||||||
size_t mDataBasicSize;
|
CmdSplitter m_CmdSplitter;
|
||||||
void* mData;
|
LibCmo::CK2::CKMinContext* m_Ctx;
|
||||||
};
|
LibCmo::CK2::CKFileDocument* m_Doc;
|
||||||
|
};
|
||||||
|
|
||||||
class VariablesMap {
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, AnyVariable> mDataPair;
|
|
||||||
|
|
||||||
public:
|
/*
|
||||||
VariablesMap();
|
|
||||||
VariablesMap(const VariablesMap&) = delete;
|
|
||||||
VariablesMap& operator=(const VariablesMap&) = delete;
|
|
||||||
~VariablesMap();
|
|
||||||
|
|
||||||
void Clear(void);
|
enum class CmdArgType {
|
||||||
/// <summary>
|
NONE,
|
||||||
/// Add option key value pair.
|
STRING,
|
||||||
/// </summary>
|
INT
|
||||||
/// <param name="name"></param>
|
};
|
||||||
/// <param name="t"></param>
|
|
||||||
/// <param name="val"></param>
|
|
||||||
/// <returns>return false when this opt is existed.</returns>
|
|
||||||
bool AddPair(const std::string& name, CmdArgType t, const std::string& val);
|
|
||||||
bool Contain(const char* opt) {
|
|
||||||
if (opt == nullptr) throw std::invalid_argument("Invalid Option Name.");
|
|
||||||
return mDataPair.contains(opt);
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
T* GetData(const char* opt) {
|
|
||||||
if (opt == nullptr) throw std::invalid_argument("Invalid Option Name.");
|
|
||||||
const auto search = mDataPair.find(opt);
|
|
||||||
if (search == mDataPair.end()) return nullptr;
|
|
||||||
|
|
||||||
if (sizeof(T) > search->second.mDataBasicSize) throw std::invalid_argument("Memory Violation.");
|
struct OptionDescription {
|
||||||
return reinterpret_cast<T*>(search->second.mData);
|
std::string mLongName;
|
||||||
}
|
char mShortName;
|
||||||
};
|
CmdArgType mType;
|
||||||
|
std::string mDescription;
|
||||||
|
};
|
||||||
|
|
||||||
struct CmdRegisteryEntry {
|
class OptionsDescription {
|
||||||
std::string mSubCmdDesc;
|
public:
|
||||||
OptionsDescription mOptDesc;
|
OptionsDescription();
|
||||||
std::function<void(OptionsDescription&, VariablesMap&)> mBindProc;
|
OptionsDescription(const OptionsDescription&) = delete;
|
||||||
};
|
OptionsDescription& operator=(const OptionsDescription&) = delete;
|
||||||
|
~OptionsDescription();
|
||||||
|
|
||||||
class ExecEnvironment {
|
/// <summary>
|
||||||
public:
|
/// Add an option
|
||||||
ExecEnvironment();
|
/// </summary>
|
||||||
ExecEnvironment(const ExecEnvironment&) = delete;
|
/// <param name="fullname">The long name of this option. Should NOT be blank or NULL.</param>
|
||||||
ExecEnvironment& operator=(const ExecEnvironment&) = delete;
|
/// <param name="shortname">A single char for the short name of this option. Leave ZERO to omit this.</param>
|
||||||
~ExecEnvironment();
|
/// <param name="type">The value type of this option. Set to CmdArgType::NONE to indicate this is a switch (no value).</param>
|
||||||
|
/// <param name="sescription">The description of this option. This can be NULL.</param>
|
||||||
|
void AddOption(const char* fullname, char shortname, CmdArgType type, const char* sescription);
|
||||||
|
void AddPositionalOption(const char* corresponding_longname);
|
||||||
|
|
||||||
void ProcLoad(OptionsDescription&, VariablesMap&);
|
OptionDescription* GetDescByLongName(const std::string& longname);
|
||||||
void ProcInfo(OptionsDescription&, VariablesMap&);
|
OptionDescription* GetDescByShortName(char shortname);
|
||||||
void ProcClear(OptionsDescription&, VariablesMap&);
|
OptionDescription* GetDescByPosition(size_t pos);
|
||||||
void ProcExportSql(OptionsDescription&, VariablesMap&);
|
|
||||||
private:
|
|
||||||
LibCmo::CKFile* mVtFile;
|
|
||||||
LibCmo::Utils::VirtoolsContext* mVtFileEnv;
|
|
||||||
};
|
|
||||||
|
|
||||||
class InteractiveCmd {
|
void PrintHelp(FILE* f);
|
||||||
public:
|
private:
|
||||||
InteractiveCmd();
|
std::unordered_map<std::string, OptionDescription> mLongNameDict;
|
||||||
InteractiveCmd(const InteractiveCmd&) = delete;
|
std::unordered_map<char, std::string> mShortNameMapping;
|
||||||
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
std::vector<std::string> mPositionalArgMapping;
|
||||||
~InteractiveCmd();
|
};
|
||||||
|
|
||||||
void Run(void);
|
struct AnyVariable {
|
||||||
|
size_t mDataBasicSize;
|
||||||
|
void* mData;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
class VariablesMap {
|
||||||
void GetCmdLine(std::string& u8cmd);
|
private:
|
||||||
void CmdParser(const std::vector<std::string>& args);
|
std::unordered_map<std::string, AnyVariable> mDataPair;
|
||||||
void PrintHelp(FILE* f);
|
|
||||||
|
|
||||||
void ProcExit(OptionsDescription&, VariablesMap&);
|
public:
|
||||||
|
VariablesMap();
|
||||||
|
VariablesMap(const VariablesMap&) = delete;
|
||||||
|
VariablesMap& operator=(const VariablesMap&) = delete;
|
||||||
|
~VariablesMap();
|
||||||
|
|
||||||
std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher;
|
void Clear(void);
|
||||||
CmdSplitter mCmdSplitter;
|
/// <summary>
|
||||||
ExecEnvironment mExecEnv;
|
/// Add option key value pair.
|
||||||
VariablesMap mVm;
|
/// </summary>
|
||||||
std::string mBlank;
|
/// <param name="name"></param>
|
||||||
bool mExitRunFlag;
|
/// <param name="t"></param>
|
||||||
};
|
/// <param name="val"></param>
|
||||||
|
/// <returns>return false when this opt is existed.</returns>
|
||||||
|
bool AddPair(const std::string& name, CmdArgType t, const std::string& val);
|
||||||
|
bool Contain(const char* opt) {
|
||||||
|
if (opt == nullptr) throw std::invalid_argument("Invalid Option Name.");
|
||||||
|
return mDataPair.contains(opt);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
T* GetData(const char* opt) {
|
||||||
|
if (opt == nullptr) throw std::invalid_argument("Invalid Option Name.");
|
||||||
|
const auto search = mDataPair.find(opt);
|
||||||
|
if (search == mDataPair.end()) return nullptr;
|
||||||
|
|
||||||
}
|
if (sizeof(T) > search->second.mDataBasicSize) throw std::invalid_argument("Memory Violation.");
|
||||||
}
|
return reinterpret_cast<T*>(search->second.mData);
|
||||||
*/
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CmdRegisteryEntry {
|
||||||
|
std::string mSubCmdDesc;
|
||||||
|
OptionsDescription mOptDesc;
|
||||||
|
std::function<void(OptionsDescription&, VariablesMap&)> mBindProc;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExecEnvironment {
|
||||||
|
public:
|
||||||
|
ExecEnvironment();
|
||||||
|
ExecEnvironment(const ExecEnvironment&) = delete;
|
||||||
|
ExecEnvironment& operator=(const ExecEnvironment&) = delete;
|
||||||
|
~ExecEnvironment();
|
||||||
|
|
||||||
|
void ProcLoad(OptionsDescription&, VariablesMap&);
|
||||||
|
void ProcInfo(OptionsDescription&, VariablesMap&);
|
||||||
|
void ProcClear(OptionsDescription&, VariablesMap&);
|
||||||
|
void ProcExportSql(OptionsDescription&, VariablesMap&);
|
||||||
|
private:
|
||||||
|
LibCmo::CKFile* mVtFile;
|
||||||
|
LibCmo::Utils::VirtoolsContext* mVtFileEnv;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InteractiveCmd {
|
||||||
|
public:
|
||||||
|
InteractiveCmd();
|
||||||
|
InteractiveCmd(const InteractiveCmd&) = delete;
|
||||||
|
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
||||||
|
~InteractiveCmd();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetCmdLine(std::string& u8cmd);
|
||||||
|
void CmdParser(const std::vector<std::string>& args);
|
||||||
|
void PrintHelp(FILE* f);
|
||||||
|
|
||||||
|
void ProcExit(OptionsDescription&, VariablesMap&);
|
||||||
|
|
||||||
|
std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher;
|
||||||
|
CmdSplitter mCmdSplitter;
|
||||||
|
ExecEnvironment mExecEnv;
|
||||||
|
VariablesMap mVm;
|
||||||
|
std::string mBlank;
|
||||||
|
bool mExitRunFlag;
|
||||||
|
};
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
|
@ -6,6 +6,28 @@ namespace Unvirt{
|
||||||
#define UNVIRT_REMOVE_PARENS_IMPL(...) __VA_ARGS__
|
#define UNVIRT_REMOVE_PARENS_IMPL(...) __VA_ARGS__
|
||||||
#define UNVIRT_REMOVE_PARENS(T) UNVIRT_REMOVE_PARENS_IMPL T
|
#define UNVIRT_REMOVE_PARENS(T) UNVIRT_REMOVE_PARENS_IMPL T
|
||||||
|
|
||||||
|
|
||||||
|
#define UNVIRT_TERMCOLHDR_BLACK "\033[30m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_RED "\033[31m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_GREEN "\033[32m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_YELLOW "\033[33m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_BLUE "\033[34m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_MAGENTA "\033[35m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_CYAN "\033[36m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_WHITE "\033[37m"
|
||||||
|
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_BLACK "\033[90m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_RED "\033[91m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_GREEN "\033[92m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_YELLOW "\033[93m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_BLUE "\033[94m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_MAGENTA "\033[95m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_CYAN "\033[96m"
|
||||||
|
#define UNVIRT_TERMCOLHDR_LIGHT_WHITE "\033[97m"
|
||||||
|
|
||||||
|
#define UNVIRT_TERMCOLTAIL "\033[97m"
|
||||||
|
|
||||||
|
|
||||||
#define UNVIRT_TERMCOL_BLACK(T) "\033[30m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
#define UNVIRT_TERMCOL_BLACK(T) "\033[30m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
||||||
#define UNVIRT_TERMCOL_RED(T) "\033[31m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
#define UNVIRT_TERMCOL_RED(T) "\033[31m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
||||||
#define UNVIRT_TERMCOL_GREEN(T) "\033[32m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
#define UNVIRT_TERMCOL_GREEN(T) "\033[32m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
||||||
|
|
|
@ -17,8 +17,8 @@ int main(int argc, char* argv[]) {
|
||||||
vtctx.SetEncoding("850");
|
vtctx.SetEncoding("850");
|
||||||
|
|
||||||
LibCmo::CK2::CKFile vtfile(&vtctx);
|
LibCmo::CK2::CKFile vtfile(&vtctx);
|
||||||
LibCmo::CK2::CKFileData::DeepDocument* doc;
|
LibCmo::CK2::CKFileDocument* doc;
|
||||||
LibCmo::CK2::CKERROR err = vtfile.DeepLoad("Level_01.NMO", &doc);
|
LibCmo::CK2::CKERROR err = vtfile.DeepLoad("Level_02.NMO", &doc);
|
||||||
|
|
||||||
if (doc)
|
if (doc)
|
||||||
Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo);
|
Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo);
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
@ -136,7 +136,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
@ -154,7 +154,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user