From 4a787610f189bc7c4c23ec76226a6a57224c3709 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 25 Aug 2023 21:57:22 +0800 Subject: [PATCH] refactor (4/?) --- LibCmo/CK2/CKContext.cpp | 3 +- LibCmo/CK2/CKFile.hpp | 149 +++++++------ LibCmo/CK2/CKFileOthers.cpp | 99 +++++++-- LibCmo/CK2/CKFileReader.cpp | 205 ++++++++---------- LibCmo/CK2/CKFileWriter.cpp | 4 +- LibCmo/CK2/CKGlobals.cpp | 20 +- .../CK2/CKManagerImplements/CKBaseManager.hpp | 4 +- LibCmo/CK2/CKObjectImplements/CKObject.cpp | 6 +- LibCmo/CK2/CKObjectImplements/CKObject.hpp | 6 +- LibCmo/CK2/CKStateChunk.cpp | 39 ++-- LibCmo/CK2/CKStateChunk.hpp | 13 +- LibCmo/CK2/CKTypes.hpp | 11 +- LibCmo/VTUtils.cpp | 6 + LibCmo/VTUtils.hpp | 11 +- LibCmo/VxMath/VxMemoryMappedFile.cpp | 2 +- LibCmo/VxMath/VxMemoryMappedFile.hpp | 8 +- LibCmo/VxMath/VxTypes.hpp | 2 +- 17 files changed, 323 insertions(+), 265 deletions(-) diff --git a/LibCmo/CK2/CKContext.cpp b/LibCmo/CK2/CKContext.cpp index c52e727..30a084b 100644 --- a/LibCmo/CK2/CKContext.cpp +++ b/LibCmo/CK2/CKContext.cpp @@ -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 diff --git a/LibCmo/CK2/CKFile.hpp b/LibCmo/CK2/CKFile.hpp index 65ddb6a..54bc3bf 100644 --- a/LibCmo/CK2/CKFile.hpp +++ b/LibCmo/CK2/CKFile.hpp @@ -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 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& GetFileObjects(); const XContainer::XArray& GetIncludedFiles(); + protected: + CKBOOL m_Done; + CKINT m_SaveIDMax; /**< Maximum CK_ID found when saving or loading objects */ + XContainer::XArray m_FileObjects; /**< List of objects being saved / loaded */ + XContainer::XArray m_ManagersData; /**< Manager Data loaded */ + XContainer::XArray m_PluginsDep; /**< Plugins dependencies for this file */ + // XContainer::XClassArray m_IndexByClassId; /**< List of index in the m_FileObjects table sorted by ClassID */ + XContainer::XArray 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 m_FileObjects; // List of objects being saved / loaded - XContainer::XArray m_ManagersData; // Manager Data loaded - XContainer::XArray m_PluginsDep; // Plugins dependencies for this file - // XContainer::XClassArray m_IndexByClassId; // List of index in the m_FileObjects table sorted by ClassID - XContainer::XArray 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; }; } diff --git a/LibCmo/CK2/CKFileOthers.cpp b/LibCmo/CK2/CKFileOthers.cpp index a44ba47..201926f 100644 --- a/LibCmo/CK2/CKFileOthers.cpp +++ b/LibCmo/CK2/CKFileOthers.cpp @@ -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& CKFileReader::GetFileObjects() { + return m_FileObjects; + } + + const XContainer::XArray& 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 - } diff --git a/LibCmo/CK2/CKFileReader.cpp b/LibCmo/CK2/CKFileReader.cpp index 045c960..4724ac0 100644 --- a/LibCmo/CK2/CKFileReader.cpp +++ b/LibCmo/CK2/CKFileReader.cpp @@ -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 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 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 doc(new(std::nothrow) CKFileDocument()); - if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY; - // create buffer and start loading - std::unique_ptr parser(new(std::nothrow) CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false)); - CKERROR err = this->ReadFileHeader(parser.get(), doc.get()); + std::unique_ptr 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 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 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(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(rawHeader.FileWriteMode); + this->m_FileInfo.CKVersion = rawHeader.CKVersion; + this->m_FileInfo.FileVersion = rawHeader.FileVersion; + this->m_FileInfo.FileSize = static_cast(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(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.Hdr1UnPackSize, true)); - if (parser == nullptr) { - delete[] reinterpret_cast(decomp_buffer); - return CKERROR::CKERR_OUTOFMEMORY; - } + parser = std::unique_ptr(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 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(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.DataUnPackSize, true)); - - if (parser == nullptr) { - delete[] reinterpret_cast(decomp_buffer); - return CKERROR::CKERR_OUTOFMEMORY; - } + parser = std::unique_ptr(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,13 +250,11 @@ namespace LibCmo::CK2 { } // read statechunk - mgr.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx); - if (mgr.Data != nullptr) { - stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr()); - if (!stateChkParseSuccess) { - delete mgr.Data; - 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); } @@ -283,11 +262,11 @@ namespace LibCmo::CK2 { // ========== 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,13 +276,11 @@ namespace LibCmo::CK2 { } // read state chunk - obj.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx); - if (obj.Data != nullptr) { - stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr()); - if (!stateChkParseSuccess) { - delete obj.Data; - 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(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 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; } diff --git a/LibCmo/CK2/CKFileWriter.cpp b/LibCmo/CK2/CKFileWriter.cpp index 3fcfb90..c2dd28a 100644 --- a/LibCmo/CK2/CKFileWriter.cpp +++ b/LibCmo/CK2/CKFileWriter.cpp @@ -2,6 +2,8 @@ namespace LibCmo::CK2 { - + CKERROR CKFileWriter::Save(CKSTRING u8_filename) { + return CKERROR::CKERR_OK; + } } \ No newline at end of file diff --git a/LibCmo/CK2/CKGlobals.cpp b/LibCmo/CK2/CKGlobals.cpp index 3f6640d..dead4b3 100644 --- a/LibCmo/CK2/CKGlobals.cpp +++ b/LibCmo/CK2/CKGlobals.cpp @@ -10,6 +10,8 @@ #include #include +#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; } diff --git a/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp b/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp index f032c3e..da93fcd 100644 --- a/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp +++ b/LibCmo/CK2/CKManagerImplements/CKBaseManager.hpp @@ -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; } diff --git a/LibCmo/CK2/CKObjectImplements/CKObject.cpp b/LibCmo/CK2/CKObjectImplements/CKObject.cpp index 35bd0f1..fc4ce6d 100644 --- a/LibCmo/CK2/CKObjectImplements/CKObject.cpp +++ b/LibCmo/CK2/CKObjectImplements/CKObject.cpp @@ -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 })); diff --git a/LibCmo/CK2/CKObjectImplements/CKObject.hpp b/LibCmo/CK2/CKObjectImplements/CKObject.hpp index 6506382..d6f31fe 100644 --- a/LibCmo/CK2/CKObjectImplements/CKObject.hpp +++ b/LibCmo/CK2/CKObjectImplements/CKObject.hpp @@ -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: diff --git a/LibCmo/CK2/CKStateChunk.cpp b/LibCmo/CK2/CKStateChunk.cpp index cc86abb..5771a44 100644 --- a/LibCmo/CK2/CKStateChunk.cpp +++ b/LibCmo/CK2/CKStateChunk.cpp @@ -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(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(cache); diff --git a/LibCmo/CK2/CKStateChunk.hpp b/LibCmo/CK2/CKStateChunk.hpp index 1cacfa4..edd22c0 100644 --- a/LibCmo/CK2/CKStateChunk.hpp +++ b/LibCmo/CK2/CKStateChunk.hpp @@ -1,18 +1,17 @@ #pragma once -#include "CKDefines.hpp" -#include "CKEnums.hpp" -#include -#include +#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 m_ChunkList; std::vector m_ManagerList; - CKFileDocument* m_BindDoc; - CKMinContext* m_BindContext; + CKFileVisitor* m_BindFile; + CKContext* m_BindContext; #pragma region Buffer Related diff --git a/LibCmo/CK2/CKTypes.hpp b/LibCmo/CK2/CKTypes.hpp index 79d9f41..9ced99a 100644 --- a/LibCmo/CK2/CKTypes.hpp +++ b/LibCmo/CK2/CKTypes.hpp @@ -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; /** diff --git a/LibCmo/VTUtils.cpp b/LibCmo/VTUtils.cpp index fba3145..963e093 100644 --- a/LibCmo/VTUtils.cpp +++ b/LibCmo/VTUtils.cpp @@ -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; diff --git a/LibCmo/VTUtils.hpp b/LibCmo/VTUtils.hpp index 8156e0b..e709a63 100644 --- a/LibCmo/VTUtils.hpp +++ b/LibCmo/VTUtils.hpp @@ -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, int> = 0> - inline TEnum Rm(TEnum& e1, TEnum e2) { + inline void Rm(TEnum& e1, TEnum e2) { e1 = static_cast(static_cast>(e1) & static_cast>(Inv(e2))); } template, int> = 0> - inline TEnum Add(TEnum& e1, TEnum e2) { + inline void Add(TEnum& e1, TEnum e2) { e1 = static_cast(static_cast>(e1) | static_cast>(e2)); } diff --git a/LibCmo/VxMath/VxMemoryMappedFile.cpp b/LibCmo/VxMath/VxMemoryMappedFile.cpp index 49feb82..5904d18 100644 --- a/LibCmo/VxMath/VxMemoryMappedFile.cpp +++ b/LibCmo/VxMath/VxMemoryMappedFile.cpp @@ -1,5 +1,5 @@ #include "VxMemoryMappedFile.hpp" -#include "VTEncoding.hpp" +#include "../VTEncoding.hpp" namespace LibCmo::VxMath { diff --git a/LibCmo/VxMath/VxMemoryMappedFile.hpp b/LibCmo/VxMath/VxMemoryMappedFile.hpp index 6559f7d..2be7bf2 100644 --- a/LibCmo/VxMath/VxMemoryMappedFile.hpp +++ b/LibCmo/VxMath/VxMemoryMappedFile.hpp @@ -1,6 +1,6 @@ #pragma once -#include "VTUtils.hpp" +#include "../VTAll.hpp" #if defined(LIBCMO_OS_WIN32) #include #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; } }; } diff --git a/LibCmo/VxMath/VxTypes.hpp b/LibCmo/VxMath/VxTypes.hpp index f85906b..e76887d 100644 --- a/LibCmo/VxMath/VxTypes.hpp +++ b/LibCmo/VxMath/VxTypes.hpp @@ -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]) {} };