refactor (4/?)

This commit is contained in:
yyc12345 2023-08-25 21:57:22 +08:00
parent c8c2c6e20b
commit 4a787610f1
17 changed files with 323 additions and 265 deletions

View File

@ -13,8 +13,7 @@ namespace LibCmo::CK2 {
#pragma region Objects Management
CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name,
CK_OBJECTCREATION_OPTIONS options = CK_OBJECTCREATION_OPTIONS::CK_OBJECTCREATION_NONAMECHECK,
CK_CREATIONMODE* res = nullptr) {
CK_OBJECTCREATION_OPTIONS options, CK_CREATIONMODE* res) {
// todo: Process paramter options and res
// get description first

View File

@ -76,20 +76,20 @@ namespace LibCmo::CK2 {
~CKFileInfo() {}
LIBCMO_DEFAULT_COPY_MOVE(CKFileInfo);
CKDWORD ProductVersion; ///< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
CKDWORD ProductBuild; ///< Virtools Build Number.
CK_FILE_WRITEMODE FileWriteMode; ///< Options used to save this file. (CK_FILE_WRITEMODE)
CKDWORD FileVersion; ///< Version of file format when file was saved.
CKDWORD CKVersion; ///< Version of CK when file was saved.
CKDWORD FileSize; ///< Size of file in bytes.
CKDWORD ObjectCount; ///< Number of objects stored in the file.
CKDWORD ManagerCount; ///< Number of managers which saved data in the file.
CKDWORD MaxIDSaved; ///< Maximum Object identifier saved
CKDWORD Crc; ///< Crc of data
CKDWORD Hdr1PackSize; ///< Reserved
CKDWORD Hdr1UnPackSize; ///< Reserved
CKDWORD DataPackSize; ///< Reserved
CKDWORD DataUnPackSize; ///< Reserved
CKDWORD ProductVersion; /**< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) */
CKDWORD ProductBuild; /**< Virtools Build Number. */
CK_FILE_WRITEMODE FileWriteMode; /**< Options used to save this file. (CK_FILE_WRITEMODE) */
CKDWORD FileVersion; /**< Version of file format when file was saved. */
CKDWORD CKVersion; /**< Version of CK when file was saved. */
CKDWORD FileSize; /**< Size of file in bytes. */
CKDWORD ObjectCount; /**< Number of objects stored in the file. */
CKDWORD ManagerCount; /**< Number of managers which saved data in the file. */
CKDWORD MaxIDSaved; /**< Maximum Object identifier saved */
CKDWORD Crc; /**< Crc of data */
CKDWORD Hdr1PackSize; /**< The compressed size of Header section. */
CKDWORD Hdr1UnPackSize; /**< The uncompressed size of Header section. */
CKDWORD DataPackSize; /**< The compressed size of Data section. */
CKDWORD DataUnPackSize; /**< The uncompressed size of Data section. */
};
class CKFileObject {
@ -101,17 +101,17 @@ namespace LibCmo::CK2 {
CKFileObject& operator=(CKFileObject&&);
~CKFileObject();
CK_ID ObjectId; ///< ID of the object being load/saved (as it will be/was saved in the file)
CK_ID CreatedObjectId; ///< ID of the object being created
CK_CLASSID ObjectCid; ///< Class Identifier of the object
CKObject* ObjPtr; ///< A pointer to the object itself (as CreatedObject when loading)
TypeHelper::MKString Name; ///< Name of the Object
CKStateChunk* Data; ///< A CKStateChunk that contains object information
//CKINT PostPackSize; ///< When compressed chunk by chunk : size of Data after compression
//CKINT PrePackSize; ///< When compressed chunk by chunk : size of Data before compression
CK_FO_OPTIONS Options; ///< When loading an object it may be renamed , use to replace another object
CKINT FileIndex; ///< Position of the object data inside uncompressed file buffer
CKDWORD SaveFlags; ///< Flags used when this object was saved.
CK_ID ObjectId; /**< ID of the object being load/saved (as it will be/was saved in the file) */
CK_ID CreatedObjectId; /**< ID of the object being created */
CK_CLASSID ObjectCid; /**< Class Identifier of the object */
CKObject* ObjPtr; /**< A pointer to the object itself (as CreatedObject when loading) */
TypeHelper::MKString Name; /**< Name of the Object */
CKStateChunk* Data; /**< A CKStateChunk that contains object information */
//CKINT PostPackSize; /**< When compressed chunk by chunk : size of Data after compression */
//CKINT PrePackSize; /**< When compressed chunk by chunk : size of Data before compression */
CK_FO_OPTIONS Options; /**< When loading an object it may be renamed , use to replace another object */
CKINT FileIndex; /**< Position of the object data inside uncompressed file buffer */
CKDWORD SaveFlags; /**< Flags used when this object was saved. */
};
class CKFileManagerData {
@ -136,26 +136,32 @@ namespace LibCmo::CK2 {
CK_PLUGIN_TYPE m_PluginCategory;
XContainer::XArray<CKGUID> m_Guids;
XContainer::XBitArray ValidGuids;
//XContainer::XBitArray ValidGuids;
};
/**
@brief CKFile provides functions to save/load files in Virtools format.
@remark
+ Use CKFile just like a normal C++ class with passing CKCotext pointer.
+ Once created a CKFile can be used to save one or more objects to disk.
+ Only can load objects when this CKFile is empty. Use ClearData() to clear any existed CKFile.
+ In any case, CKFile can run Save(). So you can create a CKFile, add some obejcts and save it.
Or you can load a file by CKFile and add/modify something then save it.
*/
class CKFile {
class CKFileVisitor {
public:
CKFile(CKContext* ctx);
~CKFile();
LIBCMO_DISABLE_COPY_MOVE(CKFile);
CKFileVisitor(CKFileReader* reader);
CKFileVisitor(CKFileWriter* writer);
CKFileVisitor(const CKFileVisitor&);
CKFileVisitor(CKFileVisitor&&);
CKFileVisitor& operator=(const CKFileVisitor&);
CKFileVisitor& operator=(CKFileVisitor&&);
// ========== Reset CKFile ==========
void ClearData(void);
const CKFileObject* GetFileObjectByIndex(size_t index);
protected:
CKBOOL m_IsReader;
CKFileReader* m_Reader;
CKFileWriter* m_Writer;
CKContext* m_Ctx;
};
class CKFileReader {
friend class CKFileVisitor;
public:
CKFileReader(CKContext* ctx);
~CKFileReader();
LIBCMO_DISABLE_COPY_MOVE(CKFileReader);
// ========== Loading ==========
CKERROR ShallowLoad(CKSTRING u8_filename);
@ -165,6 +171,31 @@ namespace LibCmo::CK2 {
const XContainer::XArray<CKFileObject>& GetFileObjects();
const XContainer::XArray<XContainer::XString>& GetIncludedFiles();
protected:
CKBOOL m_Done;
CKINT m_SaveIDMax; /**< Maximum CK_ID found when saving or loading objects */
XContainer::XArray<CKFileObject> m_FileObjects; /**< List of objects being saved / loaded */
XContainer::XArray<CKFileManagerData> m_ManagersData; /**< Manager Data loaded */
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */
// XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; /**< List of index in the m_FileObjects table sorted by ClassID */
XContainer::XArray<XContainer::XString> m_IncludedFiles; /**< List of files that should be inserted in the CMO file. */
CKFileInfo m_FileInfo; /**< Headers summary */
CKERROR ReadFileHeader(CKBufferParser* ParserPtr);
CKERROR ReadFileData(CKBufferParser* ParserPtr);
CKContext* m_Ctx;
CKFileVisitor m_Visitor;
};
class CKFileWriter {
friend class CKFileVisitor;
public:
CKFileWriter(CKContext* ctx);
CKFileWriter(CKContext* ctx, CKFileReader* reader);
~CKFileWriter();
LIBCMO_DISABLE_COPY_MOVE(CKFileWriter);
// ========== Saving Preparing ==========
CKBOOL AddSavedObject(CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
CKBOOL AddSavedObjects(CKObjectArray* objarray, CKDWORD flags = CK_STATESAVE_ALL);
@ -173,41 +204,9 @@ namespace LibCmo::CK2 {
// ========== Saving ==========
CKERROR Save(CKSTRING u8_filename);
//CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
//CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags);
//CKERROR OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags);
//CKERROR ReadFileHeaders(CKBufferParser** ParserPtr);
//CKERROR ReadFileData(CKBufferParser** ParserPtr);
//CKERROR LoadFileData(void/*CKObjectArray list*/);
//CKERROR FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags);
CKINT m_SaveIDMax; // Maximum CK_ID found when saving or loading objects
XContainer::XArray<CKFileObject> m_FileObjects; // List of objects being saved / loaded
XContainer::XArray<CKFileManagerData> m_ManagersData; // Manager Data loaded
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; // Plugins dependencies for this file
// XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; // List of index in the m_FileObjects table sorted by ClassID
XContainer::XArray<XContainer::XString> m_IncludedFiles; // List of files that should be inserted in the CMO file.
CKFileInfo m_FileInfo; // Headers summary
//XContainer::XFileObjectsTable m_ObjectsHashTable;
//CKBOOL m_ReadFileDataDone;
//CKBOOL m_SceneSaved;
//XContainer::XIntArray m_DuplicateNameFounds; // A List of file object index for which a existing object with the same name has been
// // found, this list is build if the load option contains CK_LOAD_AUTOMATICMODE or CK_LOAD_DODIALOG
//XContainer::XBitArray m_AlreadySavedMask; // BitArray of IDs already saved {secret}
//XContainer::XBitArray m_AlreadyReferencedMask; // BitArray of IDs already referenced {secret}
//XContainer::XObjectPointerArray m_ReferencedObjects;
private:
// reader function and variables
CKERROR ReadFileHeader(CKBufferParser* ParserPtr);
CKERROR ReadFileData(CKBufferParser* ParserPtr);
// writer function and varibales
// shared function and variables
bool mCanLoad;
protected:
CKContext* m_Ctx;
CKFileVisitor m_Visitor;
};
}

View File

@ -64,6 +64,7 @@ namespace LibCmo::CK2 {
this->FileIndex = rhs.FileIndex;
this->SaveFlags = rhs.SaveFlags;
return *this;
}
CKFileObject::~CKFileObject() {
@ -107,6 +108,8 @@ namespace LibCmo::CK2 {
this->Data = rhs.Data;
rhs.Data = nullptr;
return *this;
}
CKFileManagerData::~CKFileManagerData() {
@ -115,36 +118,94 @@ namespace LibCmo::CK2 {
#pragma endregion
#pragma region CKFilePluginDependencies
#pragma region CKFileReader
CKFilePluginDependencies::CKFilePluginDependencies() :
m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() {}
CKFileReader::CKFileReader(CKContext* ctx) :
m_Ctx(ctx), m_Visitor(this),
m_Done(false),
m_SaveIDMax(0),
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
m_FileInfo() {}
CKFilePluginDependencies::CKFilePluginDependencies(const CKFilePluginDependencies& rhs) :
m_PluginCategory(rhs.m_PluginCategory), m_Guids(rhs.m_Guids) {}
CKFileReader::~CKFileReader() {}
CKFilePluginDependencies& CKFilePluginDependencies::operator=(const CKFilePluginDependencies& rhs) {
this->m_PluginCategory = rhs.m_PluginCategory;
this->m_Guids = rhs.m_Guids;
const XContainer::XArray<CKFileObject>& CKFileReader::GetFileObjects() {
return m_FileObjects;
}
const XContainer::XArray<XContainer::XString>& CKFileReader::GetIncludedFiles() {
return m_IncludedFiles;
}
#pragma endregion
#pragma region CKFileWriter
CKFileWriter::CKFileWriter(CKContext* ctx) :
m_Ctx(ctx), m_Visitor(this) {}
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader) :
m_Ctx(ctx), m_Visitor(this) {}
CKFileWriter::~CKFileWriter() {}
CKBOOL CKFileWriter::AddSavedObject(CKObject* obj, CKDWORD flags) {
return CKFALSE;
}
CKBOOL CKFileWriter::AddSavedObjects(CKObjectArray* objarray, CKDWORD flags) {
return CKFALSE;
}
CKBOOL CKFileWriter::AddSavedFile(CKSTRING u8FileName) {
return CKFALSE;
}
#pragma endregion
#pragma region CKFileVisitor
CKFileVisitor::CKFileVisitor(CKFileReader* reader) :
m_IsReader(CKTRUE), m_Reader(reader), m_Writer(nullptr) {
if (reader == nullptr) LIBPANIC("Reader is nullptr.");
}
CKFileVisitor::CKFileVisitor(CKFileWriter* writer) :
m_IsReader(false), m_Reader(nullptr), m_Writer(nullptr) {
if (writer == nullptr) LIBPANIC("Writer is nullptr.");
}
CKFileVisitor::CKFileVisitor(const CKFileVisitor& rhs) :
m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer) {}
CKFileVisitor::CKFileVisitor(CKFileVisitor&& rhs) :
m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer) {}
CKFileVisitor& CKFileVisitor::operator=(const CKFileVisitor& rhs) {
this->m_IsReader = rhs.m_IsReader;
this->m_Reader = rhs.m_Reader;
this->m_Writer = rhs.m_Writer;
return *this;
}
CKFilePluginDependencies::~CKFilePluginDependencies() {}
CKFileVisitor& CKFileVisitor::operator=(CKFileVisitor&& rhs) {
this->m_IsReader = rhs.m_IsReader;
this->m_Reader = rhs.m_Reader;
this->m_Writer = rhs.m_Writer;
#pragma endregion
#pragma region CKFile Misc
CKFile::CKFile(CKContext* ctx) :
m_Ctx(ctx) {
;
return *this;
}
CKFile::~CKFile() {}
const CKFileObject* CKFileVisitor::GetFileObjectByIndex(size_t index) {
if (m_IsReader) {
return &m_Reader->m_FileObjects[index];
} else {
return nullptr;
}
}
#pragma endregion
}

View File

@ -14,45 +14,34 @@ namespace LibCmo::CK2 {
* No need to support them.
*/
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename) {
// preset value
*out_doc = nullptr;
CKERROR CKFileReader::ShallowLoad(CKSTRING u8_filename) {
// check document status
if (this->m_Done) LIBPANIC("Can not load multiple times for single CKFileReader.")
// check file and open memory
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new(std::nothrow) VxMath::VxMemoryMappedFile(u8_filename));
if (mappedFile == nullptr) {
this->m_MinCtx->Printf("Out of memory when creating Memory File.");
return CKERROR::CKERR_OUTOFMEMORY;
}
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(u8_filename));
if (!mappedFile->IsValid()) {
this->m_MinCtx->Printf("Fail to create Memory File for \"%s\".", u8_filename);
this->m_Ctx->OutputToConsoleEx("Fail to create Memory File for \"%s\".", u8_filename);
return CKERROR::CKERR_INVALIDFILE;
}
// create document
std::unique_ptr<CKFileDocument> doc(new(std::nothrow) CKFileDocument());
if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
// create buffer and start loading
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
CKERROR err = this->ReadFileHeader(parser.get(), doc.get());
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
CKERROR err = this->ReadFileHeader(parser.get());
if (err != CKERROR::CKERR_OK) return err;
err = this->ReadFileData(parser.get(), doc.get());
err = this->ReadFileData(parser.get());
if (err != CKERROR::CKERR_OK) return err;
// unbind document and assign it
*out_doc = doc.release();
// other data will be free automatically
return CKERROR::CKERR_OK;
}
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr, CKFileDocument* doc) {
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
CKERROR CKFileReader::ReadFileHeader(CKBufferParser* ParserPtr) {
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
parser->SetCursor(ParserPtr->GetCursor());
std::string name_conv;
std::string name_conv, name_dest;
// ========== read header ==========
// check header size
@ -74,23 +63,23 @@ namespace LibCmo::CK2 {
}
// ========== assign value ==========
doc->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
doc->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
doc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
doc->m_FileInfo.CKVersion = rawHeader.CKVersion;
doc->m_FileInfo.FileVersion = rawHeader.FileVersion;
doc->m_FileInfo.FileSize = parser->GetSize();
doc->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
doc->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
doc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
doc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
doc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
doc->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
doc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
doc->m_FileInfo.Crc = rawHeader.Crc;
this->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
this->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
this->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
this->m_FileInfo.CKVersion = rawHeader.CKVersion;
this->m_FileInfo.FileVersion = rawHeader.FileVersion;
this->m_FileInfo.FileSize = static_cast<CKDWORD>(parser->GetSize());
this->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
this->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
this->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
this->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
this->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
this->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
this->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
this->m_FileInfo.Crc = rawHeader.Crc;
// ========== crc and body unpacker ==========
if (doc->m_FileInfo.FileVersion >= 8) {
if (this->m_FileInfo.FileVersion >= 8) {
// crc checker for file ver >= 8
// reset crc field of header
rawHeader.Crc = 0u;
@ -98,12 +87,12 @@ namespace LibCmo::CK2 {
// compute crc
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, sizeof(CKRawFileInfo), 0u);
parser->SetCursor(sizeof(CKRawFileInfo));
gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize, gotten_crc);
parser->MoveCursor(doc->m_FileInfo.Hdr1PackSize);
gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.DataPackSize, gotten_crc);
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);
if (gotten_crc != doc->m_FileInfo.Crc) {
this->m_MinCtx->Printf("Virtools file CRC error.");
if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR;
}
@ -111,13 +100,9 @@ namespace LibCmo::CK2 {
parser->SetCursor(sizeof(CKRawFileInfo));
// compare size to decide wheher use compress feature
void* decomp_buffer = CKUnPackData(doc->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize);
void* decomp_buffer = CKUnPackData(this->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_FileInfo.Hdr1PackSize);
if (decomp_buffer != nullptr) {
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.Hdr1UnPackSize, true));
if (parser == nullptr) {
delete[] reinterpret_cast<char*>(decomp_buffer);
return CKERROR::CKERR_OUTOFMEMORY;
}
parser = std::unique_ptr<CKBufferParser>(new CKBufferParser(decomp_buffer, this->m_FileInfo.Hdr1UnPackSize, true));
}
}
@ -125,12 +110,12 @@ namespace LibCmo::CK2 {
// file ver >= 7 have this features
{
// apply max id saved
doc->m_SaveIDMax = doc->m_FileInfo.MaxIDSaved;
this->m_SaveIDMax = this->m_FileInfo.MaxIDSaved;
// resize
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
this->m_FileObjects.resize(this->m_FileInfo.ObjectCount);
// read data
for (auto& fileobj : doc->m_FileObjects) {
for (auto& fileobj : this->m_FileObjects) {
// read basic fields
parser->Read(&(fileobj.ObjectId), sizeof(CK_ID));
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
@ -141,21 +126,22 @@ namespace LibCmo::CK2 {
if (namelen != 0) {
name_conv.resize(namelen);
parser->Read(name_conv.data(), namelen);
m_MinCtx->GetUtf8String(name_conv, fileobj.Name);
m_Ctx->GetUtf8String(name_conv, name_dest);
fileobj.Name = name_dest;
}
}
}
// ========== dep list read ==========
// file ver >= 8 have this feature
if (doc->m_FileInfo.FileVersion >= 8) {
if (this->m_FileInfo.FileVersion >= 8) {
// get size and resize
CKDWORD depSize;
parser->Read(&depSize, sizeof(CKDWORD));
doc->m_PluginDep.resize(depSize);
this->m_PluginsDep.resize(depSize);
CKDWORD guid_size;
for (auto& dep : doc->m_PluginDep) {
for (auto& dep : this->m_PluginsDep) {
// read category
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
// get size and resize
@ -171,7 +157,7 @@ namespace LibCmo::CK2 {
// ========== included file list read ==========
// file ver >= 8 have this feature
if (doc->m_FileInfo.FileVersion >= 8) {
if (this->m_FileInfo.FileVersion >= 8) {
// MARK: i don't knwo what is this!
int32_t hasIncludedFile;
parser->Read(&hasIncludedFile, sizeof(int32_t));
@ -180,7 +166,7 @@ namespace LibCmo::CK2 {
// read included file size and resize
CKDWORD includedFileCount;
parser->Read(&includedFileCount, sizeof(CKDWORD));
doc->m_IncludedFiles.resize(includedFileCount);
this->m_IncludedFiles.resize(includedFileCount);
hasIncludedFile -= 4;
}
@ -191,10 +177,10 @@ namespace LibCmo::CK2 {
}
// ========== sync main parser ==========
if (doc->m_FileInfo.FileVersion >= 8) {
if (this->m_FileInfo.FileVersion >= 8) {
// file ver >= 8, use header offset
// because it have compress feature
ParserPtr->SetCursor(doc->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
ParserPtr->SetCursor(this->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
} else {
// otherwise, sync with current parser.
ParserPtr->SetCursor(parser->GetCursor());
@ -203,7 +189,7 @@ namespace LibCmo::CK2 {
return CKERROR::CKERR_OK;
}
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr, CKFileDocument* doc) {
CKERROR CKFileReader::ReadFileData(CKBufferParser* ParserPtr) {
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
parser->SetCursor(ParserPtr->GetCursor());
@ -211,52 +197,47 @@ namespace LibCmo::CK2 {
std::string name_conv;
// ========== compress feature process ==========
if (EnumsHelper::FlagEnumHas(doc->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
EnumsHelper::FlagEnumHas(doc->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
if (EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
void* decomp_buffer = CKUnPackData(doc->m_FileInfo.DataUnPackSize, parser->GetPtr(), doc->m_FileInfo.DataPackSize);
void* decomp_buffer = CKUnPackData(this->m_FileInfo.DataUnPackSize, parser->GetPtr(), this->m_FileInfo.DataPackSize);
if (decomp_buffer != nullptr) {
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.DataUnPackSize, true));
if (parser == nullptr) {
delete[] reinterpret_cast<char*>(decomp_buffer);
return CKERROR::CKERR_OUTOFMEMORY;
}
parser = std::unique_ptr<CKBufferParser>(new CKBufferParser(decomp_buffer, this->m_FileInfo.DataUnPackSize, true));
}
}
// ========== old file crc and obj list read ==========
// only file ver < 8 run this
if (doc->m_FileInfo.FileVersion < 8) {
if (this->m_FileInfo.FileVersion < 8) {
// check crc
CKDWORD gotten_crc = CKComputeDataCRC(
parser->GetPtr(),
parser->GetSize() - parser->GetCursor(),
0u
);
if (gotten_crc != doc->m_FileInfo.Crc) {
this->m_MinCtx->Printf("Virtools file CRC error.");
if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR;
}
// MARK: why read again? especially for file ver == 7.
// get save id max
parser->Read(&doc->m_SaveIDMax, sizeof(int32_t));
parser->Read(&this->m_SaveIDMax, sizeof(int32_t));
// get object count and resize
parser->Read(&doc->m_FileInfo.ObjectCount, sizeof(CKDWORD));
if (doc->m_FileObjects.empty()) {
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
parser->Read(&this->m_FileInfo.ObjectCount, sizeof(CKDWORD));
if (this->m_FileObjects.empty()) {
this->m_FileObjects.resize(this->m_FileInfo.ObjectCount);
}
}
// ========== manager read ==========
// only file ver >= 6 have this
if (doc->m_FileInfo.ManagerCount != 0) {
doc->m_FileManagersData.resize(doc->m_FileInfo.ManagerCount);
if (this->m_FileInfo.ManagerCount != 0) {
this->m_ManagersData.resize(this->m_FileInfo.ManagerCount);
CKDWORD stateChunkLen = 0u;
bool stateChkParseSuccess = false;
for (auto& mgr : doc->m_FileManagersData) {
for (auto& mgr : this->m_ManagersData) {
// read guid
parser->Read(&(mgr.Manager), sizeof(CKGUID));
@ -269,25 +250,23 @@ namespace LibCmo::CK2 {
}
// read statechunk
mgr.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx);
if (mgr.Data != nullptr) {
mgr.Data = new CKStateChunk(&this->m_Visitor, this->m_Ctx);
stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
if (!stateChkParseSuccess) {
delete mgr.Data;
mgr.Data = nullptr;
}
}
parser->MoveCursor(stateChunkLen);
}
}
// ========== object read ==========
// only works file version >= 4. < 4 section has been removed.
if (doc->m_FileInfo.ObjectCount != 0) {
if (this->m_FileInfo.ObjectCount != 0) {
// new file reader section
CKDWORD stateChunkLen = 0u;
bool stateChkParseSuccess = false;
for (auto& obj : doc->m_FileObjects) {
for (auto& obj : this->m_FileObjects) {
// get statechunk len
parser->Read(&stateChunkLen, sizeof(CKDWORD));
// check state chunk len
@ -297,14 +276,12 @@ namespace LibCmo::CK2 {
}
// read state chunk
obj.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx);
if (obj.Data != nullptr) {
obj.Data = new CKStateChunk(&this->m_Visitor, this->m_Ctx);
stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
if (!stateChkParseSuccess) {
delete obj.Data;
obj.Data = nullptr;
}
}
parser->MoveCursor(stateChunkLen);
}
@ -314,11 +291,11 @@ namespace LibCmo::CK2 {
// before reading, we need switch back to original parser.
// and skip data chunk size
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
parser->MoveCursor(doc->m_FileInfo.DataPackSize);
parser->MoveCursor(this->m_FileInfo.DataPackSize);
// then we can read it.
if (doc->m_IncludedFiles.size() != 0) {
for (auto& file : doc->m_IncludedFiles) {
if (this->m_IncludedFiles.size() != 0) {
for (auto& file : this->m_IncludedFiles) {
// get file name length and resize it
CKDWORD filenamelen = 0u;
parser->Read(&filenamelen, sizeof(CKDWORD));
@ -327,7 +304,7 @@ namespace LibCmo::CK2 {
// read filename
if (filenamelen != 0) {
parser->Read(name_conv.data(), filenamelen);
m_MinCtx->GetUtf8String(name_conv, file);
m_Ctx->GetUtf8String(name_conv, file);
}
// read file body length
@ -335,7 +312,7 @@ namespace LibCmo::CK2 {
parser->Read(&filebodylen, sizeof(CKDWORD));
// read file body
FILE* fp = m_MinCtx->OpenTempFile(file.c_str(), false);
FILE* fp = m_Ctx->OpenTempFile(file.c_str(), false);
if (fp != nullptr) {
StreamHelper::CopyStream(parser->GetPtr(), fp, filebodylen);
fclose(fp);
@ -349,32 +326,26 @@ namespace LibCmo::CK2 {
return CKERROR::CKERR_OK;
}
CKERROR CKFile::DeepLoad(CKSTRING u8_filename, CKFileDocument** out_doc) {
CKERROR CKFileReader::DeepLoad(CKSTRING u8_filename) {
// ========== prepare work ==========
// preset value
*out_doc = nullptr;
CKERROR err = CKERROR::CKERR_OK;
// get shallow document first
CKFileDocument* rawShallowDoc = nullptr;
err = this->ShallowLoad(u8_filename, &rawShallowDoc);
if (rawShallowDoc == nullptr) return err;
// use unique ptr wrap it as a deep doc
std::unique_ptr<CKFileDocument> deepDoc(rawShallowDoc);
err = this->ShallowLoad(u8_filename);
if (err != CKERROR::CKERR_OK) return err;
// ========== create object first ==========
for (auto& obj : deepDoc->m_FileObjects) {
for (auto& obj : this->m_FileObjects) {
// todo: skip CK_LEVEL
// todo: resolve references
if (obj.Data == nullptr) continue;
// create object and assign created obj ckid
obj.ObjPtr = m_MinCtx->CreateCKObject(obj.ObjectId, obj.ObjectCid, obj.Name.c_str());
obj.ObjPtr = m_Ctx->CreateCKObject(obj.ObjectCid, obj.Name.c_str());
if (obj.ObjPtr == nullptr) {
obj.CreatedObject = 0u;
obj.CreatedObjectId = 0u;
} else {
obj.CreatedObject = obj.ObjPtr->m_ID;
obj.CreatedObjectId = obj.ObjPtr->GetID();
}
}
@ -386,13 +357,13 @@ namespace LibCmo::CK2 {
// todo...
// ========== analyze objects CKStateChunk ==========
for (auto& obj : deepDoc->m_FileObjects) {
for (auto& obj : this->m_FileObjects) {
if (obj.Data == nullptr || obj.ObjPtr == nullptr) continue;
// todo: special treat for CK_LEVEL
// try parsing data
obj.Data->StartRead();
bool success = obj.ObjPtr->Load(obj.Data, deepDoc.get());
bool success = obj.ObjPtr->Load(obj.Data, &this->m_Visitor);
obj.Data->StopRead();
if (success) {
// if success, clear CKStateChunk*
@ -400,15 +371,13 @@ namespace LibCmo::CK2 {
obj.Data = nullptr;
} else {
// if failed, delete it
m_MinCtx->DestroyCKObject(obj.ObjectId);
m_Ctx->DestroyCKObject(obj.ObjectId);
obj.ObjPtr = nullptr;
obj.CreatedObject = 0u;
obj.CreatedObjectId = 0u;
}
}
// ========== finalize work ==========
// detach and return
*out_doc = deepDoc.release();
return CKERROR::CKERR_OK;
}

View File

@ -2,6 +2,8 @@
namespace LibCmo::CK2 {
CKERROR CKFileWriter::Save(CKSTRING u8_filename) {
return CKERROR::CKERR_OK;
}
}

View File

@ -10,6 +10,8 @@
#include <algorithm>
#include <zlib.h>
#include "CKObjectImplements/CKObject.hpp"
namespace LibCmo::CK2 {
#pragma region Compression utilities
@ -68,7 +70,7 @@ namespace LibCmo::CK2 {
// find direct parent
auto finder = g_CKClassInfoId2Idx.find(desc.Parent);
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
CKClassDesc& parent = g_CKClassInfo[finder->second];
// if it is not self inheritance, call recursively
@ -80,7 +82,7 @@ namespace LibCmo::CK2 {
desc.Parents = parent.Parents;
// and set self as its parent
finder = g_CKClassInfoId2Idx.find(desc.Self);
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
desc.Parents[finder->second] = true;
// set derivation level
@ -105,7 +107,7 @@ namespace LibCmo::CK2 {
// iterate CKClassDesc::Parents and register it self to gotten parents
for (auto& item : g_CKClassInfo) {
auto finder = g_CKClassInfoId2Idx.find(item.Self);
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
size_t selfidx = finder->second;
for (size_t idx = 0; idx < classCount; ++idx) {
@ -154,10 +156,10 @@ namespace LibCmo::CK2 {
CKBOOL CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
// get corresponding index first
auto finder = g_CKClassInfoId2Idx.find(child);
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
size_t child_idx = finder->second;
finder = g_CKClassInfoId2Idx.find(parent);
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
size_t parent_idx = finder->second;
return g_CKClassInfo[child_idx].Parents[parent_idx];
@ -165,7 +167,7 @@ namespace LibCmo::CK2 {
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
auto finder = g_CKClassInfoId2Idx.find(child);
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
return g_CKClassInfo[finder->second].Parent;
}
@ -188,6 +190,10 @@ namespace LibCmo::CK2 {
CKERROR CKStartUp() {
// todo: add class type registrations
CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT,
[](CKContext* ctx, CK_ID id, CKSTRING name) -> CKObject* { return new CKObject(ctx, id, name); },
[](CKContext* ctx, CKObject* obj) -> void { delete obj; },
[]() -> CKSTRING { return "Basic Object"; });
/*
// register CKObjects
@ -218,6 +224,8 @@ namespace LibCmo::CK2 {
}
*/
CKBuildClassHierarchyTable();
return CKERROR::CKERR_OK;
}

View File

@ -69,7 +69,7 @@ namespace LibCmo::CK2 {
data for your manager.
@see CKStateChunk, LoadData
*/
virtual CKStateChunk* SaveData(CKFile* SavedFile) {
virtual CKStateChunk* SaveData(CKFileVisitor* SavedFile) {
return nullptr;
}
/**
@ -81,7 +81,7 @@ namespace LibCmo::CK2 {
+ During a load operation, each manager is automatically called if there was a chunk saved in the file with SaveData.
@see CKStateChunk, SaveData
*/
virtual CKERROR LoadData(CKStateChunk* chunk, CKFile* LoadedFile) {
virtual CKERROR LoadData(CKStateChunk* chunk, CKFileVisitor* LoadedFile) {
return CKERROR::CKERR_OK;
}

View File

@ -4,13 +4,13 @@
namespace LibCmo::CK2 {
void CKObject::PreSave(CKFile* file, CKDWORD flags) {}
void CKObject::PreSave(CKFileVisitor* file, CKDWORD flags) {}
CKStateChunk* CKObject::Save(CKFile* file, CKDWORD flags) {
CKStateChunk* CKObject::Save(CKFileVisitor* file, CKDWORD flags) {
return nullptr;
}
bool CKObject::Load(CKStateChunk* chunk, CKFile* file) {
bool CKObject::Load(CKStateChunk* chunk, CKFileVisitor* file) {
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
EnumsHelper::Rm(this->m_ObjectFlags,
EnumsHelper::Merge({ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE }));

View File

@ -39,9 +39,9 @@ namespace LibCmo::CK2 {
return CK_CLASSID::CKCID_OBJECT;
}
virtual void PreSave(CKFile* file, CKDWORD flags);
virtual CKStateChunk* Save(CKFile* file, CKDWORD flags);
virtual bool Load(CKStateChunk* chunk, CKFile* file);
virtual void PreSave(CKFileVisitor* file, CKDWORD flags);
virtual CKStateChunk* Save(CKFileVisitor* file, CKDWORD flags);
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file);
virtual void PostLoad();
private:

View File

@ -1,7 +1,6 @@
#include "VTUtils.hpp"
#include "CKStateChunk.hpp"
#include "CKMinContext.hpp"
#include "CKFile.hpp"
#include "CKContext.hpp"
namespace LibCmo::CK2 {
@ -16,21 +15,20 @@ namespace LibCmo::CK2 {
//{
// ;
//}
CKStateChunk::CKStateChunk(CKFileDocument* doc, CKMinContext* ctx) :
CKStateChunk::CKStateChunk(CKFileVisitor* visitor, CKContext* ctx) :
m_ClassId(CK_CLASSID::CKCID_OBJECT), m_DataDwSize(0u), m_pData(nullptr),
m_DataVersion(CK_STATECHUNK_DATAVERSION::CHUNKDATA_CURRENTVERSION), m_ChunkVersion(CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4),
m_Parser{ CKStateChunkStatus::IDLE, 0u, 0u, 0u },
m_ObjectList(), m_ChunkList(), m_ManagerList(),
m_BindDoc(doc), m_BindContext(ctx)
{
;
}
m_BindFile(visitor), m_BindContext(ctx)
{}
CKStateChunk::CKStateChunk(const CKStateChunk& rhs) :
m_ClassId(rhs.m_ClassId), m_DataVersion(rhs.m_DataVersion), m_ChunkVersion(rhs.m_ChunkVersion),
m_Parser(rhs.m_Parser),
m_ObjectList(rhs.m_ObjectList), m_ManagerList(rhs.m_ManagerList), m_ChunkList(rhs.m_ChunkList),
m_pData(nullptr), m_DataDwSize(rhs.m_DataDwSize),
m_BindDoc(rhs.m_BindDoc), m_BindContext(rhs.m_BindContext) {
m_BindFile(rhs.m_BindFile), m_BindContext(rhs.m_BindContext) {
// copy buffer
if (rhs.m_pData != nullptr) {
this->m_pData = new(std::nothrow) CKDWORD[rhs.m_DataDwSize];
@ -39,6 +37,7 @@ namespace LibCmo::CK2 {
}
}
}
CKStateChunk& CKStateChunk::operator=(const CKStateChunk& rhs) {
this->Clear();
@ -52,7 +51,7 @@ namespace LibCmo::CK2 {
this->m_ManagerList = rhs.m_ManagerList;
this->m_ChunkList = rhs.m_ChunkList;
this->m_BindDoc = rhs.m_BindDoc;
this->m_BindFile = rhs.m_BindFile;
this->m_BindContext = rhs.m_BindContext;
// copy buffer
@ -292,23 +291,23 @@ namespace LibCmo::CK2 {
std::memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize);
bufpos += this->m_DataDwSize;
}
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
// MARK: set ckfile = nullptr;
;
}
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
this->m_ObjectList.resize(dwbuf[bufpos]);
bufpos += 1u;
std::memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size());
bufpos += this->m_ObjectList.size();
}
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
this->m_ChunkList.resize(dwbuf[bufpos]);
bufpos += 1u;
std::memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size());
bufpos += this->m_ChunkList.size();
}
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
this->m_ManagerList.resize(dwbuf[bufpos]);
bufpos += 1u;
std::memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size());
@ -426,7 +425,7 @@ namespace LibCmo::CK2 {
return true;
} else {
// failed, report to context
m_BindContext->Printf("CKStateChunk read length error at %" PRICKdword ".", this->m_Parser.m_CurrentPos);
m_BindContext->OutputToConsoleEx("CKStateChunk read length error at %" PRIckDWORD ".", this->m_Parser.m_CurrentPos);
return false;
}
}
@ -464,13 +463,13 @@ namespace LibCmo::CK2 {
// new file
// if no doc associated, return directly
if (this->m_BindDoc == nullptr) {
if (this->m_BindFile == nullptr) {
*id = static_cast<CK_ID>(gotten_id);
return true;
}
// if it is positive, return corresponding value
if (gotten_id >= 0) {
*id = this->m_BindDoc->m_FileObjects[gotten_id].CreatedObject;
*id = this->m_BindFile->GetFileObjectByIndex(gotten_id)->CreatedObjectId;
return true;
}
@ -510,7 +509,7 @@ namespace LibCmo::CK2 {
if (!this->EnsureReadSpace(subChunkSize)) goto subchunk_defer;
// create statechunk
subchunk = new(std::nothrow) CKStateChunk(this->m_BindDoc, this->m_BindContext);
subchunk = new(std::nothrow) CKStateChunk(this->m_BindFile, this->m_BindContext);
if (subchunk == nullptr) goto subchunk_defer;
// start read data
@ -535,7 +534,7 @@ namespace LibCmo::CK2 {
// has bind file?
CKDWORD hasBindFile;
if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
if (hasBindFile == 1) subchunk->m_BindDoc = nullptr;
if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
// 3 list size
// manager only existed when ver > 4
@ -738,11 +737,11 @@ namespace LibCmo::CK2 {
}
// remap id
if (this->m_BindDoc != nullptr) {
if (this->m_BindFile != nullptr) {
if (cache < 0) {
id = 0u;
} else {
id = this->m_BindDoc->m_FileObjects[cache].CreatedObject;
id = this->m_BindFile->GetFileObjectByIndex(cache)->CreatedObjectId;
}
} else {
id = static_cast<CK_ID>(cache);

View File

@ -1,18 +1,17 @@
#pragma once
#include "CKDefines.hpp"
#include "CKEnums.hpp"
#include <type_traits>
#include <cinttypes>
#include "../VTAll.hpp"
namespace LibCmo::CK2 {
class CKStateChunk {
public:
//CKStateChunk();
CKStateChunk(CKFileDocument* doc, CKMinContext* ctx);
CKStateChunk(CKFileVisitor* visitor, CKContext* ctx);
CKStateChunk(const CKStateChunk&);
CKStateChunk(CKStateChunk&&);
CKStateChunk& operator=(const CKStateChunk&);
CKStateChunk& operator-(const CKStateChunk&&);
~CKStateChunk();
private:
@ -40,8 +39,8 @@ namespace LibCmo::CK2 {
std::vector<CKDWORD> m_ChunkList;
std::vector<CKDWORD> m_ManagerList;
CKFileDocument* m_BindDoc;
CKMinContext* m_BindContext;
CKFileVisitor* m_BindFile;
CKContext* m_BindContext;
#pragma region Buffer Related

View File

@ -161,6 +161,7 @@ namespace LibCmo::CK2 {
};
// ========== Type Definition ==========
// type define
using CKMUTSTRING = char*;
using CKSTRING = const char*;
@ -181,6 +182,12 @@ namespace LibCmo::CK2 {
using CKAttributeType = int32_t;
using CKAttributeCategory = int32_t;
// type print style define
#define PRIckBYTE PRIu8
#define PRIckDWORD PRIu32
#define PRIckWORD PRIu16
#define PRIckINT PRIi32
// ========== Class List ==========
// Objects and derivated classes
@ -269,7 +276,9 @@ namespace LibCmo::CK2 {
//--- Important classes
class CKContext;
class CKStateChunk;
class CKFile;
class CKFileReader;
class CKFileWriter;
class CKFileVisitor;
/**

View File

@ -2,6 +2,12 @@
namespace LibCmo {
void LibPanic(int line, const char* file, const char* errmsg) {
fprintf(stderr, "LIBCMO PANIC:%s (%s:L%d)\n",
errmsg ? errmsg : "", file, line);
std::abort();
}
namespace StreamHelper {
static constexpr const size_t CHUNK_SIZE = 10240;

View File

@ -68,6 +68,9 @@
namespace LibCmo {
[[noreturn]] void LibPanic(int line, const char* file, const char* errmsg);
#define LIBPANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg);
namespace TypeHelper {
/**
@ -88,11 +91,13 @@ namespace LibCmo {
MKString& operator=(const char* cstr) {
m_HasStr = cstr != nullptr;
m_Str = m_HasStr ? cstr : "";
return *this;
}
MKString(const std::string& cstr) : m_HasStr(true), m_Str(cstr) {}
MKString& operator=(const std::string& cstr) {
m_HasStr = true;
m_Str = cstr;
return *this;
}
MKString(const MKString& rhs) : m_HasStr(rhs.m_HasStr), m_Str(rhs.m_Str) {}
@ -102,11 +107,13 @@ namespace LibCmo {
MKString& operator=(const MKString& rhs) {
m_HasStr = rhs.m_HasStr;
m_Str = rhs.m_Str;
return *this;
}
MKString& operator=(MKString&& rhs) noexcept {
m_HasStr = rhs.m_HasStr;
m_Str = std::move(rhs.m_Str);
rhs.m_HasStr = false;
return *this;
}
const char* c_str() const {
@ -135,12 +142,12 @@ namespace LibCmo {
}
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
inline TEnum Rm(TEnum& e1, TEnum e2) {
inline void Rm(TEnum& e1, TEnum e2) {
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) & static_cast<std::underlying_type_t<TEnum>>(Inv(e2)));
}
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
inline TEnum Add(TEnum& e1, TEnum e2) {
inline void Add(TEnum& e1, TEnum e2) {
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) | static_cast<std::underlying_type_t<TEnum>>(e2));
}

View File

@ -1,5 +1,5 @@
#include "VxMemoryMappedFile.hpp"
#include "VTEncoding.hpp"
#include "../VTEncoding.hpp"
namespace LibCmo::VxMath {

View File

@ -1,6 +1,6 @@
#pragma once
#include "VTUtils.hpp"
#include "../VTAll.hpp"
#if defined(LIBCMO_OS_WIN32)
#include <Windows.h>
#else
@ -40,9 +40,9 @@ namespace LibCmo::VxMath {
VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete;
~VxMemoryMappedFile(void);
inline void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
inline size_t GetFileSize(void) { return this->m_cbFile; }
inline bool IsValid(void) { return this->m_bIsValid; }
void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
size_t GetFileSize(void) { return this->m_cbFile; }
bool IsValid(void) { return this->m_bIsValid; }
};
}

View File

@ -42,7 +42,7 @@ namespace LibCmo::VxMath {
Vx2DVector() : x(0.0f), y(0.0f) {}
Vx2DVector(float f) : x(f), y(f) {}
Vx2DVector(float _x, float _y, float _z) : x(_x), y(_y) {}
Vx2DVector(float _x, float _y) : x(_x), y(_y) {}
Vx2DVector(CK2::CKINT iX, CK2::CKINT iY) : x((float)iX), y((float)iY) {}
Vx2DVector(const float f[2]) : x(f[0]), y(f[1]) {}
};