refactor (4/?)
This commit is contained in:
parent
c8c2c6e20b
commit
4a787610f1
|
@ -13,8 +13,7 @@ namespace LibCmo::CK2 {
|
||||||
#pragma region Objects Management
|
#pragma region Objects Management
|
||||||
|
|
||||||
CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name,
|
CKObject* CKContext::CreateCKObject(CK_CLASSID cls, CKSTRING name,
|
||||||
CK_OBJECTCREATION_OPTIONS options = CK_OBJECTCREATION_OPTIONS::CK_OBJECTCREATION_NONAMECHECK,
|
CK_OBJECTCREATION_OPTIONS options, CK_CREATIONMODE* res) {
|
||||||
CK_CREATIONMODE* res = nullptr) {
|
|
||||||
// todo: Process paramter options and res
|
// todo: Process paramter options and res
|
||||||
|
|
||||||
// get description first
|
// get description first
|
||||||
|
|
|
@ -76,20 +76,20 @@ namespace LibCmo::CK2 {
|
||||||
~CKFileInfo() {}
|
~CKFileInfo() {}
|
||||||
LIBCMO_DEFAULT_COPY_MOVE(CKFileInfo);
|
LIBCMO_DEFAULT_COPY_MOVE(CKFileInfo);
|
||||||
|
|
||||||
CKDWORD ProductVersion; ///< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
|
CKDWORD ProductVersion; /**< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) */
|
||||||
CKDWORD ProductBuild; ///< Virtools Build Number.
|
CKDWORD ProductBuild; /**< Virtools Build Number. */
|
||||||
CK_FILE_WRITEMODE FileWriteMode; ///< Options used to save this file. (CK_FILE_WRITEMODE)
|
CK_FILE_WRITEMODE FileWriteMode; /**< Options used to save this file. (CK_FILE_WRITEMODE) */
|
||||||
CKDWORD FileVersion; ///< Version of file format when file was saved.
|
CKDWORD FileVersion; /**< Version of file format when file was saved. */
|
||||||
CKDWORD CKVersion; ///< Version of CK when file was saved.
|
CKDWORD CKVersion; /**< Version of CK when file was saved. */
|
||||||
CKDWORD FileSize; ///< Size of file in bytes.
|
CKDWORD FileSize; /**< Size of file in bytes. */
|
||||||
CKDWORD ObjectCount; ///< Number of objects stored in the file.
|
CKDWORD ObjectCount; /**< Number of objects stored in the file. */
|
||||||
CKDWORD ManagerCount; ///< Number of managers which saved data in the file.
|
CKDWORD ManagerCount; /**< Number of managers which saved data in the file. */
|
||||||
CKDWORD MaxIDSaved; ///< Maximum Object identifier saved
|
CKDWORD MaxIDSaved; /**< Maximum Object identifier saved */
|
||||||
CKDWORD Crc; ///< Crc of data
|
CKDWORD Crc; /**< Crc of data */
|
||||||
CKDWORD Hdr1PackSize; ///< Reserved
|
CKDWORD Hdr1PackSize; /**< The compressed size of Header section. */
|
||||||
CKDWORD Hdr1UnPackSize; ///< Reserved
|
CKDWORD Hdr1UnPackSize; /**< The uncompressed size of Header section. */
|
||||||
CKDWORD DataPackSize; ///< Reserved
|
CKDWORD DataPackSize; /**< The compressed size of Data section. */
|
||||||
CKDWORD DataUnPackSize; ///< Reserved
|
CKDWORD DataUnPackSize; /**< The uncompressed size of Data section. */
|
||||||
};
|
};
|
||||||
|
|
||||||
class CKFileObject {
|
class CKFileObject {
|
||||||
|
@ -101,17 +101,17 @@ namespace LibCmo::CK2 {
|
||||||
CKFileObject& operator=(CKFileObject&&);
|
CKFileObject& operator=(CKFileObject&&);
|
||||||
~CKFileObject();
|
~CKFileObject();
|
||||||
|
|
||||||
CK_ID ObjectId; ///< ID of the object being load/saved (as it will be/was saved in the file)
|
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_ID CreatedObjectId; /**< ID of the object being created */
|
||||||
CK_CLASSID ObjectCid; ///< Class Identifier of the object
|
CK_CLASSID ObjectCid; /**< Class Identifier of the object */
|
||||||
CKObject* ObjPtr; ///< A pointer to the object itself (as CreatedObject when loading)
|
CKObject* ObjPtr; /**< A pointer to the object itself (as CreatedObject when loading) */
|
||||||
TypeHelper::MKString Name; ///< Name of the Object
|
TypeHelper::MKString Name; /**< Name of the Object */
|
||||||
CKStateChunk* Data; ///< A CKStateChunk that contains object information
|
CKStateChunk* Data; /**< A CKStateChunk that contains object information */
|
||||||
//CKINT PostPackSize; ///< When compressed chunk by chunk : size of Data after compression
|
//CKINT PostPackSize; /**< When compressed chunk by chunk : size of Data after compression */
|
||||||
//CKINT PrePackSize; ///< When compressed chunk by chunk : size of Data before 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
|
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
|
CKINT FileIndex; /**< Position of the object data inside uncompressed file buffer */
|
||||||
CKDWORD SaveFlags; ///< Flags used when this object was saved.
|
CKDWORD SaveFlags; /**< Flags used when this object was saved. */
|
||||||
};
|
};
|
||||||
|
|
||||||
class CKFileManagerData {
|
class CKFileManagerData {
|
||||||
|
@ -136,26 +136,32 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CK_PLUGIN_TYPE m_PluginCategory;
|
CK_PLUGIN_TYPE m_PluginCategory;
|
||||||
XContainer::XArray<CKGUID> m_Guids;
|
XContainer::XArray<CKGUID> m_Guids;
|
||||||
XContainer::XBitArray ValidGuids;
|
//XContainer::XBitArray ValidGuids;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
class CKFileVisitor {
|
||||||
@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 {
|
|
||||||
public:
|
public:
|
||||||
CKFile(CKContext* ctx);
|
CKFileVisitor(CKFileReader* reader);
|
||||||
~CKFile();
|
CKFileVisitor(CKFileWriter* writer);
|
||||||
LIBCMO_DISABLE_COPY_MOVE(CKFile);
|
CKFileVisitor(const CKFileVisitor&);
|
||||||
|
CKFileVisitor(CKFileVisitor&&);
|
||||||
|
CKFileVisitor& operator=(const CKFileVisitor&);
|
||||||
|
CKFileVisitor& operator=(CKFileVisitor&&);
|
||||||
|
|
||||||
// ========== Reset CKFile ==========
|
const CKFileObject* GetFileObjectByIndex(size_t index);
|
||||||
void ClearData(void);
|
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 ==========
|
// ========== Loading ==========
|
||||||
CKERROR ShallowLoad(CKSTRING u8_filename);
|
CKERROR ShallowLoad(CKSTRING u8_filename);
|
||||||
|
@ -165,6 +171,31 @@ namespace LibCmo::CK2 {
|
||||||
const XContainer::XArray<CKFileObject>& GetFileObjects();
|
const XContainer::XArray<CKFileObject>& GetFileObjects();
|
||||||
const XContainer::XArray<XContainer::XString>& GetIncludedFiles();
|
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 ==========
|
// ========== Saving Preparing ==========
|
||||||
CKBOOL AddSavedObject(CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
|
CKBOOL AddSavedObject(CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
|
||||||
CKBOOL AddSavedObjects(CKObjectArray* objarray, CKDWORD flags = CK_STATESAVE_ALL);
|
CKBOOL AddSavedObjects(CKObjectArray* objarray, CKDWORD flags = CK_STATESAVE_ALL);
|
||||||
|
@ -173,41 +204,9 @@ namespace LibCmo::CK2 {
|
||||||
// ========== Saving ==========
|
// ========== Saving ==========
|
||||||
CKERROR Save(CKSTRING u8_filename);
|
CKERROR Save(CKSTRING u8_filename);
|
||||||
|
|
||||||
//CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
|
protected:
|
||||||
//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;
|
|
||||||
CKContext* m_Ctx;
|
CKContext* m_Ctx;
|
||||||
|
CKFileVisitor m_Visitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace LibCmo::CK2 {
|
||||||
this->FileIndex = rhs.FileIndex;
|
this->FileIndex = rhs.FileIndex;
|
||||||
this->SaveFlags = rhs.SaveFlags;
|
this->SaveFlags = rhs.SaveFlags;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKFileObject::~CKFileObject() {
|
CKFileObject::~CKFileObject() {
|
||||||
|
@ -107,6 +108,8 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
this->Data = rhs.Data;
|
this->Data = rhs.Data;
|
||||||
rhs.Data = nullptr;
|
rhs.Data = nullptr;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKFileManagerData::~CKFileManagerData() {
|
CKFileManagerData::~CKFileManagerData() {
|
||||||
|
@ -115,36 +118,94 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region CKFilePluginDependencies
|
#pragma region CKFileReader
|
||||||
|
|
||||||
CKFilePluginDependencies::CKFilePluginDependencies() :
|
CKFileReader::CKFileReader(CKContext* ctx) :
|
||||||
m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() {}
|
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) :
|
CKFileReader::~CKFileReader() {}
|
||||||
m_PluginCategory(rhs.m_PluginCategory), m_Guids(rhs.m_Guids) {}
|
|
||||||
|
|
||||||
CKFilePluginDependencies& CKFilePluginDependencies::operator=(const CKFilePluginDependencies& rhs) {
|
const XContainer::XArray<CKFileObject>& CKFileReader::GetFileObjects() {
|
||||||
this->m_PluginCategory = rhs.m_PluginCategory;
|
return m_FileObjects;
|
||||||
this->m_Guids = rhs.m_Guids;
|
}
|
||||||
|
|
||||||
|
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;
|
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
|
return *this;
|
||||||
|
|
||||||
#pragma region CKFile Misc
|
|
||||||
|
|
||||||
CKFile::CKFile(CKContext* ctx) :
|
|
||||||
m_Ctx(ctx) {
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CKFile::~CKFile() {}
|
const CKFileObject* CKFileVisitor::GetFileObjectByIndex(size_t index) {
|
||||||
|
if (m_IsReader) {
|
||||||
|
return &m_Reader->m_FileObjects[index];
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,45 +14,34 @@ namespace LibCmo::CK2 {
|
||||||
* No need to support them.
|
* No need to support them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename) {
|
CKERROR CKFileReader::ShallowLoad(CKSTRING u8_filename) {
|
||||||
// preset value
|
// check document status
|
||||||
*out_doc = nullptr;
|
if (this->m_Done) LIBPANIC("Can not load multiple times for single CKFileReader.")
|
||||||
|
|
||||||
// check file and open memory
|
// check file and open memory
|
||||||
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||||
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new(std::nothrow) VxMath::VxMemoryMappedFile(u8_filename));
|
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(u8_filename));
|
||||||
if (mappedFile == nullptr) {
|
|
||||||
this->m_MinCtx->Printf("Out of memory when creating Memory File.");
|
|
||||||
return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
if (!mappedFile->IsValid()) {
|
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;
|
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
|
// create buffer and start loading
|
||||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
|
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
|
||||||
CKERROR err = this->ReadFileHeader(parser.get(), doc.get());
|
CKERROR err = this->ReadFileHeader(parser.get());
|
||||||
if (err != CKERROR::CKERR_OK) return err;
|
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;
|
if (err != CKERROR::CKERR_OK) return err;
|
||||||
|
|
||||||
// unbind document and assign it
|
|
||||||
*out_doc = doc.release();
|
|
||||||
// other data will be free automatically
|
// other data will be free automatically
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr, CKFileDocument* doc) {
|
CKERROR CKFileReader::ReadFileHeader(CKBufferParser* ParserPtr) {
|
||||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||||
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
parser->SetCursor(ParserPtr->GetCursor());
|
parser->SetCursor(ParserPtr->GetCursor());
|
||||||
|
|
||||||
std::string name_conv;
|
std::string name_conv, name_dest;
|
||||||
|
|
||||||
// ========== read header ==========
|
// ========== read header ==========
|
||||||
// check header size
|
// check header size
|
||||||
|
@ -74,23 +63,23 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== assign value ==========
|
// ========== assign value ==========
|
||||||
doc->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
|
this->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
|
||||||
doc->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
|
this->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
|
||||||
doc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
|
this->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
|
||||||
doc->m_FileInfo.CKVersion = rawHeader.CKVersion;
|
this->m_FileInfo.CKVersion = rawHeader.CKVersion;
|
||||||
doc->m_FileInfo.FileVersion = rawHeader.FileVersion;
|
this->m_FileInfo.FileVersion = rawHeader.FileVersion;
|
||||||
doc->m_FileInfo.FileSize = parser->GetSize();
|
this->m_FileInfo.FileSize = static_cast<CKDWORD>(parser->GetSize());
|
||||||
doc->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
|
this->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
|
||||||
doc->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
|
this->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
|
||||||
doc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
|
this->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
|
||||||
doc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
|
this->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
|
||||||
doc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
|
this->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
|
||||||
doc->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
|
this->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
|
||||||
doc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
|
this->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
|
||||||
doc->m_FileInfo.Crc = rawHeader.Crc;
|
this->m_FileInfo.Crc = rawHeader.Crc;
|
||||||
|
|
||||||
// ========== crc and body unpacker ==========
|
// ========== crc and body unpacker ==========
|
||||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
if (this->m_FileInfo.FileVersion >= 8) {
|
||||||
// crc checker for file ver >= 8
|
// crc checker for file ver >= 8
|
||||||
// reset crc field of header
|
// reset crc field of header
|
||||||
rawHeader.Crc = 0u;
|
rawHeader.Crc = 0u;
|
||||||
|
@ -98,12 +87,12 @@ namespace LibCmo::CK2 {
|
||||||
// compute crc
|
// compute crc
|
||||||
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, sizeof(CKRawFileInfo), 0u);
|
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, sizeof(CKRawFileInfo), 0u);
|
||||||
parser->SetCursor(sizeof(CKRawFileInfo));
|
parser->SetCursor(sizeof(CKRawFileInfo));
|
||||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize, gotten_crc);
|
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
|
||||||
parser->MoveCursor(doc->m_FileInfo.Hdr1PackSize);
|
parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
||||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.DataPackSize, gotten_crc);
|
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
|
||||||
|
|
||||||
if (gotten_crc != doc->m_FileInfo.Crc) {
|
if (gotten_crc != this->m_FileInfo.Crc) {
|
||||||
this->m_MinCtx->Printf("Virtools file CRC error.");
|
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
|
||||||
return CKERROR::CKERR_FILECRCERROR;
|
return CKERROR::CKERR_FILECRCERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,13 +100,9 @@ namespace LibCmo::CK2 {
|
||||||
parser->SetCursor(sizeof(CKRawFileInfo));
|
parser->SetCursor(sizeof(CKRawFileInfo));
|
||||||
|
|
||||||
// compare size to decide wheher use compress feature
|
// 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) {
|
if (decomp_buffer != nullptr) {
|
||||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.Hdr1UnPackSize, true));
|
parser = std::unique_ptr<CKBufferParser>(new CKBufferParser(decomp_buffer, this->m_FileInfo.Hdr1UnPackSize, true));
|
||||||
if (parser == nullptr) {
|
|
||||||
delete[] reinterpret_cast<char*>(decomp_buffer);
|
|
||||||
return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,12 +110,12 @@ namespace LibCmo::CK2 {
|
||||||
// file ver >= 7 have this features
|
// file ver >= 7 have this features
|
||||||
{
|
{
|
||||||
// apply max id saved
|
// apply max id saved
|
||||||
doc->m_SaveIDMax = doc->m_FileInfo.MaxIDSaved;
|
this->m_SaveIDMax = this->m_FileInfo.MaxIDSaved;
|
||||||
// resize
|
// resize
|
||||||
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
|
this->m_FileObjects.resize(this->m_FileInfo.ObjectCount);
|
||||||
|
|
||||||
// read data
|
// read data
|
||||||
for (auto& fileobj : doc->m_FileObjects) {
|
for (auto& fileobj : this->m_FileObjects) {
|
||||||
// read basic fields
|
// read basic fields
|
||||||
parser->Read(&(fileobj.ObjectId), sizeof(CK_ID));
|
parser->Read(&(fileobj.ObjectId), sizeof(CK_ID));
|
||||||
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
||||||
|
@ -141,21 +126,22 @@ namespace LibCmo::CK2 {
|
||||||
if (namelen != 0) {
|
if (namelen != 0) {
|
||||||
name_conv.resize(namelen);
|
name_conv.resize(namelen);
|
||||||
parser->Read(name_conv.data(), 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 ==========
|
// ========== dep list read ==========
|
||||||
// file ver >= 8 have this feature
|
// file ver >= 8 have this feature
|
||||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
if (this->m_FileInfo.FileVersion >= 8) {
|
||||||
// get size and resize
|
// get size and resize
|
||||||
CKDWORD depSize;
|
CKDWORD depSize;
|
||||||
parser->Read(&depSize, sizeof(CKDWORD));
|
parser->Read(&depSize, sizeof(CKDWORD));
|
||||||
doc->m_PluginDep.resize(depSize);
|
this->m_PluginsDep.resize(depSize);
|
||||||
|
|
||||||
CKDWORD guid_size;
|
CKDWORD guid_size;
|
||||||
for (auto& dep : doc->m_PluginDep) {
|
for (auto& dep : this->m_PluginsDep) {
|
||||||
// read category
|
// read category
|
||||||
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
||||||
// get size and resize
|
// get size and resize
|
||||||
|
@ -171,7 +157,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
// ========== included file list read ==========
|
// ========== included file list read ==========
|
||||||
// file ver >= 8 have this feature
|
// 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!
|
// MARK: i don't knwo what is this!
|
||||||
int32_t hasIncludedFile;
|
int32_t hasIncludedFile;
|
||||||
parser->Read(&hasIncludedFile, sizeof(int32_t));
|
parser->Read(&hasIncludedFile, sizeof(int32_t));
|
||||||
|
@ -180,7 +166,7 @@ namespace LibCmo::CK2 {
|
||||||
// read included file size and resize
|
// read included file size and resize
|
||||||
CKDWORD includedFileCount;
|
CKDWORD includedFileCount;
|
||||||
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
||||||
doc->m_IncludedFiles.resize(includedFileCount);
|
this->m_IncludedFiles.resize(includedFileCount);
|
||||||
|
|
||||||
hasIncludedFile -= 4;
|
hasIncludedFile -= 4;
|
||||||
}
|
}
|
||||||
|
@ -191,10 +177,10 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== sync main parser ==========
|
// ========== sync main parser ==========
|
||||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
if (this->m_FileInfo.FileVersion >= 8) {
|
||||||
// file ver >= 8, use header offset
|
// file ver >= 8, use header offset
|
||||||
// because it have compress feature
|
// because it have compress feature
|
||||||
ParserPtr->SetCursor(doc->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
|
ParserPtr->SetCursor(this->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
|
||||||
} else {
|
} else {
|
||||||
// otherwise, sync with current parser.
|
// otherwise, sync with current parser.
|
||||||
ParserPtr->SetCursor(parser->GetCursor());
|
ParserPtr->SetCursor(parser->GetCursor());
|
||||||
|
@ -203,7 +189,7 @@ namespace LibCmo::CK2 {
|
||||||
return CKERROR::CKERR_OK;
|
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));
|
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());
|
||||||
|
@ -211,52 +197,47 @@ namespace LibCmo::CK2 {
|
||||||
std::string name_conv;
|
std::string name_conv;
|
||||||
|
|
||||||
// ========== compress feature process ==========
|
// ========== compress feature process ==========
|
||||||
if (EnumsHelper::FlagEnumHas(doc->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
if (EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
||||||
EnumsHelper::FlagEnumHas(doc->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
|
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) {
|
if (decomp_buffer != nullptr) {
|
||||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.DataUnPackSize, true));
|
parser = std::unique_ptr<CKBufferParser>(new CKBufferParser(decomp_buffer, this->m_FileInfo.DataUnPackSize, true));
|
||||||
|
|
||||||
if (parser == nullptr) {
|
|
||||||
delete[] reinterpret_cast<char*>(decomp_buffer);
|
|
||||||
return CKERROR::CKERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== old file crc and obj list read ==========
|
// ========== old file crc and obj list read ==========
|
||||||
// only file ver < 8 run this
|
// only file ver < 8 run this
|
||||||
if (doc->m_FileInfo.FileVersion < 8) {
|
if (this->m_FileInfo.FileVersion < 8) {
|
||||||
// check crc
|
// check crc
|
||||||
CKDWORD gotten_crc = CKComputeDataCRC(
|
CKDWORD gotten_crc = CKComputeDataCRC(
|
||||||
parser->GetPtr(),
|
parser->GetPtr(),
|
||||||
parser->GetSize() - parser->GetCursor(),
|
parser->GetSize() - parser->GetCursor(),
|
||||||
0u
|
0u
|
||||||
);
|
);
|
||||||
if (gotten_crc != doc->m_FileInfo.Crc) {
|
if (gotten_crc != this->m_FileInfo.Crc) {
|
||||||
this->m_MinCtx->Printf("Virtools file CRC error.");
|
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
|
||||||
return CKERROR::CKERR_FILECRCERROR;
|
return CKERROR::CKERR_FILECRCERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: why read again? especially for file ver == 7.
|
// MARK: why read again? especially for file ver == 7.
|
||||||
// get save id max
|
// 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
|
// get object count and resize
|
||||||
parser->Read(&doc->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
parser->Read(&this->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
||||||
if (doc->m_FileObjects.empty()) {
|
if (this->m_FileObjects.empty()) {
|
||||||
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
|
this->m_FileObjects.resize(this->m_FileInfo.ObjectCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== manager read ==========
|
// ========== manager read ==========
|
||||||
// only file ver >= 6 have this
|
// only file ver >= 6 have this
|
||||||
if (doc->m_FileInfo.ManagerCount != 0) {
|
if (this->m_FileInfo.ManagerCount != 0) {
|
||||||
doc->m_FileManagersData.resize(doc->m_FileInfo.ManagerCount);
|
this->m_ManagersData.resize(this->m_FileInfo.ManagerCount);
|
||||||
CKDWORD stateChunkLen = 0u;
|
CKDWORD stateChunkLen = 0u;
|
||||||
bool stateChkParseSuccess = false;
|
bool stateChkParseSuccess = false;
|
||||||
|
|
||||||
for (auto& mgr : doc->m_FileManagersData) {
|
for (auto& mgr : this->m_ManagersData) {
|
||||||
// read guid
|
// read guid
|
||||||
parser->Read(&(mgr.Manager), sizeof(CKGUID));
|
parser->Read(&(mgr.Manager), sizeof(CKGUID));
|
||||||
|
|
||||||
|
@ -269,25 +250,23 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read statechunk
|
// read statechunk
|
||||||
mgr.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx);
|
mgr.Data = new CKStateChunk(&this->m_Visitor, this->m_Ctx);
|
||||||
if (mgr.Data != nullptr) {
|
|
||||||
stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
|
stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
|
||||||
if (!stateChkParseSuccess) {
|
if (!stateChkParseSuccess) {
|
||||||
delete mgr.Data;
|
delete mgr.Data;
|
||||||
mgr.Data = nullptr;
|
mgr.Data = nullptr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
parser->MoveCursor(stateChunkLen);
|
parser->MoveCursor(stateChunkLen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== object read ==========
|
// ========== object read ==========
|
||||||
// only works file version >= 4. < 4 section has been removed.
|
// 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
|
// new file reader section
|
||||||
CKDWORD stateChunkLen = 0u;
|
CKDWORD stateChunkLen = 0u;
|
||||||
bool stateChkParseSuccess = false;
|
bool stateChkParseSuccess = false;
|
||||||
for (auto& obj : doc->m_FileObjects) {
|
for (auto& obj : this->m_FileObjects) {
|
||||||
// get statechunk len
|
// get statechunk len
|
||||||
parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
||||||
// check state chunk len
|
// check state chunk len
|
||||||
|
@ -297,14 +276,12 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read state chunk
|
// read state chunk
|
||||||
obj.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx);
|
obj.Data = new CKStateChunk(&this->m_Visitor, this->m_Ctx);
|
||||||
if (obj.Data != nullptr) {
|
|
||||||
stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
|
stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
|
||||||
if (!stateChkParseSuccess) {
|
if (!stateChkParseSuccess) {
|
||||||
delete obj.Data;
|
delete obj.Data;
|
||||||
obj.Data = nullptr;
|
obj.Data = nullptr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
parser->MoveCursor(stateChunkLen);
|
parser->MoveCursor(stateChunkLen);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -314,11 +291,11 @@ namespace LibCmo::CK2 {
|
||||||
// before reading, we need switch back to original parser.
|
// before reading, we need switch back to original parser.
|
||||||
// and skip data chunk size
|
// and skip data chunk size
|
||||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
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.
|
// then we can read it.
|
||||||
if (doc->m_IncludedFiles.size() != 0) {
|
if (this->m_IncludedFiles.size() != 0) {
|
||||||
for (auto& file : doc->m_IncludedFiles) {
|
for (auto& file : this->m_IncludedFiles) {
|
||||||
// get file name length and resize it
|
// get file name length and resize it
|
||||||
CKDWORD filenamelen = 0u;
|
CKDWORD filenamelen = 0u;
|
||||||
parser->Read(&filenamelen, sizeof(CKDWORD));
|
parser->Read(&filenamelen, sizeof(CKDWORD));
|
||||||
|
@ -327,7 +304,7 @@ namespace LibCmo::CK2 {
|
||||||
// read filename
|
// read filename
|
||||||
if (filenamelen != 0) {
|
if (filenamelen != 0) {
|
||||||
parser->Read(name_conv.data(), filenamelen);
|
parser->Read(name_conv.data(), filenamelen);
|
||||||
m_MinCtx->GetUtf8String(name_conv, file);
|
m_Ctx->GetUtf8String(name_conv, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read file body length
|
// read file body length
|
||||||
|
@ -335,7 +312,7 @@ namespace LibCmo::CK2 {
|
||||||
parser->Read(&filebodylen, sizeof(CKDWORD));
|
parser->Read(&filebodylen, sizeof(CKDWORD));
|
||||||
|
|
||||||
// read file body
|
// read file body
|
||||||
FILE* fp = m_MinCtx->OpenTempFile(file.c_str(), false);
|
FILE* fp = m_Ctx->OpenTempFile(file.c_str(), false);
|
||||||
if (fp != nullptr) {
|
if (fp != nullptr) {
|
||||||
StreamHelper::CopyStream(parser->GetPtr(), fp, filebodylen);
|
StreamHelper::CopyStream(parser->GetPtr(), fp, filebodylen);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@ -349,32 +326,26 @@ namespace LibCmo::CK2 {
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKFile::DeepLoad(CKSTRING u8_filename, CKFileDocument** out_doc) {
|
CKERROR CKFileReader::DeepLoad(CKSTRING u8_filename) {
|
||||||
// ========== prepare work ==========
|
// ========== prepare work ==========
|
||||||
// preset value
|
|
||||||
*out_doc = nullptr;
|
|
||||||
CKERROR err = CKERROR::CKERR_OK;
|
CKERROR err = CKERROR::CKERR_OK;
|
||||||
|
|
||||||
// get shallow document first
|
// get shallow document first
|
||||||
CKFileDocument* rawShallowDoc = nullptr;
|
err = this->ShallowLoad(u8_filename);
|
||||||
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);
|
|
||||||
if (err != CKERROR::CKERR_OK) return err;
|
if (err != CKERROR::CKERR_OK) return err;
|
||||||
|
|
||||||
// ========== create object first ==========
|
// ========== create object first ==========
|
||||||
for (auto& obj : deepDoc->m_FileObjects) {
|
for (auto& obj : this->m_FileObjects) {
|
||||||
// todo: skip CK_LEVEL
|
// todo: skip CK_LEVEL
|
||||||
// todo: resolve references
|
// todo: resolve references
|
||||||
if (obj.Data == nullptr) continue;
|
if (obj.Data == nullptr) continue;
|
||||||
|
|
||||||
// create object and assign created obj ckid
|
// 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) {
|
if (obj.ObjPtr == nullptr) {
|
||||||
obj.CreatedObject = 0u;
|
obj.CreatedObjectId = 0u;
|
||||||
} else {
|
} else {
|
||||||
obj.CreatedObject = obj.ObjPtr->m_ID;
|
obj.CreatedObjectId = obj.ObjPtr->GetID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,13 +357,13 @@ namespace LibCmo::CK2 {
|
||||||
// todo...
|
// todo...
|
||||||
|
|
||||||
// ========== analyze objects CKStateChunk ==========
|
// ========== analyze objects CKStateChunk ==========
|
||||||
for (auto& obj : deepDoc->m_FileObjects) {
|
for (auto& obj : this->m_FileObjects) {
|
||||||
if (obj.Data == nullptr || obj.ObjPtr == nullptr) continue;
|
if (obj.Data == nullptr || obj.ObjPtr == 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();
|
||||||
bool success = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
bool success = obj.ObjPtr->Load(obj.Data, &this->m_Visitor);
|
||||||
obj.Data->StopRead();
|
obj.Data->StopRead();
|
||||||
if (success) {
|
if (success) {
|
||||||
// if success, clear CKStateChunk*
|
// if success, clear CKStateChunk*
|
||||||
|
@ -400,15 +371,13 @@ namespace LibCmo::CK2 {
|
||||||
obj.Data = nullptr;
|
obj.Data = nullptr;
|
||||||
} else {
|
} else {
|
||||||
// if failed, delete it
|
// if failed, delete it
|
||||||
m_MinCtx->DestroyCKObject(obj.ObjectId);
|
m_Ctx->DestroyCKObject(obj.ObjectId);
|
||||||
obj.ObjPtr = nullptr;
|
obj.ObjPtr = nullptr;
|
||||||
obj.CreatedObject = 0u;
|
obj.CreatedObjectId = 0u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== finalize work ==========
|
// ========== finalize work ==========
|
||||||
// detach and return
|
|
||||||
*out_doc = deepDoc.release();
|
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
|
CKERROR CKFileWriter::Save(CKSTRING u8_filename) {
|
||||||
|
return CKERROR::CKERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,6 +10,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "CKObjectImplements/CKObject.hpp"
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma region Compression utilities
|
#pragma region Compression utilities
|
||||||
|
@ -68,7 +70,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
// find direct parent
|
// find direct parent
|
||||||
auto finder = g_CKClassInfoId2Idx.find(desc.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];
|
CKClassDesc& parent = g_CKClassInfo[finder->second];
|
||||||
|
|
||||||
// if it is not self inheritance, call recursively
|
// if it is not self inheritance, call recursively
|
||||||
|
@ -80,7 +82,7 @@ namespace LibCmo::CK2 {
|
||||||
desc.Parents = parent.Parents;
|
desc.Parents = parent.Parents;
|
||||||
// and set self as its parent
|
// and set self as its parent
|
||||||
finder = g_CKClassInfoId2Idx.find(desc.Self);
|
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;
|
desc.Parents[finder->second] = true;
|
||||||
|
|
||||||
// set derivation level
|
// set derivation level
|
||||||
|
@ -105,7 +107,7 @@ namespace LibCmo::CK2 {
|
||||||
// iterate CKClassDesc::Parents and register it self to gotten parents
|
// iterate CKClassDesc::Parents and register it self to gotten parents
|
||||||
for (auto& item : g_CKClassInfo) {
|
for (auto& item : g_CKClassInfo) {
|
||||||
auto finder = g_CKClassInfoId2Idx.find(item.Self);
|
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;
|
size_t selfidx = finder->second;
|
||||||
|
|
||||||
for (size_t idx = 0; idx < classCount; ++idx) {
|
for (size_t idx = 0; idx < classCount; ++idx) {
|
||||||
|
@ -154,10 +156,10 @@ namespace LibCmo::CK2 {
|
||||||
CKBOOL CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
CKBOOL CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
||||||
// get corresponding index first
|
// get corresponding index first
|
||||||
auto finder = g_CKClassInfoId2Idx.find(child);
|
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;
|
size_t child_idx = finder->second;
|
||||||
finder = g_CKClassInfoId2Idx.find(parent);
|
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;
|
size_t parent_idx = finder->second;
|
||||||
|
|
||||||
return g_CKClassInfo[child_idx].Parents[parent_idx];
|
return g_CKClassInfo[child_idx].Parents[parent_idx];
|
||||||
|
@ -165,7 +167,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
||||||
auto finder = g_CKClassInfoId2Idx.find(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;
|
return g_CKClassInfo[finder->second].Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +190,10 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CKERROR CKStartUp() {
|
CKERROR CKStartUp() {
|
||||||
// todo: add class type registrations
|
// 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
|
// register CKObjects
|
||||||
|
@ -218,6 +224,8 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
CKBuildClassHierarchyTable();
|
||||||
|
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace LibCmo::CK2 {
|
||||||
data for your manager.
|
data for your manager.
|
||||||
@see CKStateChunk, LoadData
|
@see CKStateChunk, LoadData
|
||||||
*/
|
*/
|
||||||
virtual CKStateChunk* SaveData(CKFile* SavedFile) {
|
virtual CKStateChunk* SaveData(CKFileVisitor* SavedFile) {
|
||||||
return nullptr;
|
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.
|
+ During a load operation, each manager is automatically called if there was a chunk saved in the file with SaveData.
|
||||||
@see CKStateChunk, SaveData
|
@see CKStateChunk, SaveData
|
||||||
*/
|
*/
|
||||||
virtual CKERROR LoadData(CKStateChunk* chunk, CKFile* LoadedFile) {
|
virtual CKERROR LoadData(CKStateChunk* chunk, CKFileVisitor* LoadedFile) {
|
||||||
return CKERROR::CKERR_OK;
|
return CKERROR::CKERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
namespace LibCmo::CK2 {
|
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;
|
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)) {
|
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
|
||||||
EnumsHelper::Rm(this->m_ObjectFlags,
|
EnumsHelper::Rm(this->m_ObjectFlags,
|
||||||
EnumsHelper::Merge({ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE }));
|
EnumsHelper::Merge({ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE }));
|
||||||
|
|
|
@ -39,9 +39,9 @@ namespace LibCmo::CK2 {
|
||||||
return CK_CLASSID::CKCID_OBJECT;
|
return CK_CLASSID::CKCID_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void PreSave(CKFile* file, CKDWORD flags);
|
virtual void PreSave(CKFileVisitor* file, CKDWORD flags);
|
||||||
virtual CKStateChunk* Save(CKFile* file, CKDWORD flags);
|
virtual CKStateChunk* Save(CKFileVisitor* file, CKDWORD flags);
|
||||||
virtual bool Load(CKStateChunk* chunk, CKFile* file);
|
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file);
|
||||||
virtual void PostLoad();
|
virtual void PostLoad();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "VTUtils.hpp"
|
|
||||||
#include "CKStateChunk.hpp"
|
#include "CKStateChunk.hpp"
|
||||||
#include "CKMinContext.hpp"
|
|
||||||
#include "CKFile.hpp"
|
#include "CKFile.hpp"
|
||||||
|
#include "CKContext.hpp"
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
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_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_DataVersion(CK_STATECHUNK_DATAVERSION::CHUNKDATA_CURRENTVERSION), m_ChunkVersion(CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4),
|
||||||
m_Parser{ CKStateChunkStatus::IDLE, 0u, 0u, 0u },
|
m_Parser{ CKStateChunkStatus::IDLE, 0u, 0u, 0u },
|
||||||
m_ObjectList(), m_ChunkList(), m_ManagerList(),
|
m_ObjectList(), m_ChunkList(), m_ManagerList(),
|
||||||
m_BindDoc(doc), m_BindContext(ctx)
|
m_BindFile(visitor), m_BindContext(ctx)
|
||||||
{
|
{}
|
||||||
;
|
|
||||||
}
|
|
||||||
CKStateChunk::CKStateChunk(const CKStateChunk& rhs) :
|
CKStateChunk::CKStateChunk(const CKStateChunk& rhs) :
|
||||||
m_ClassId(rhs.m_ClassId), m_DataVersion(rhs.m_DataVersion), m_ChunkVersion(rhs.m_ChunkVersion),
|
m_ClassId(rhs.m_ClassId), m_DataVersion(rhs.m_DataVersion), m_ChunkVersion(rhs.m_ChunkVersion),
|
||||||
m_Parser(rhs.m_Parser),
|
m_Parser(rhs.m_Parser),
|
||||||
m_ObjectList(rhs.m_ObjectList), m_ManagerList(rhs.m_ManagerList), m_ChunkList(rhs.m_ChunkList),
|
m_ObjectList(rhs.m_ObjectList), m_ManagerList(rhs.m_ManagerList), m_ChunkList(rhs.m_ChunkList),
|
||||||
m_pData(nullptr), m_DataDwSize(rhs.m_DataDwSize),
|
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
|
// copy buffer
|
||||||
if (rhs.m_pData != nullptr) {
|
if (rhs.m_pData != nullptr) {
|
||||||
this->m_pData = new(std::nothrow) CKDWORD[rhs.m_DataDwSize];
|
this->m_pData = new(std::nothrow) CKDWORD[rhs.m_DataDwSize];
|
||||||
|
@ -39,6 +37,7 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CKStateChunk& CKStateChunk::operator=(const CKStateChunk& rhs) {
|
CKStateChunk& CKStateChunk::operator=(const CKStateChunk& rhs) {
|
||||||
this->Clear();
|
this->Clear();
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ namespace LibCmo::CK2 {
|
||||||
this->m_ManagerList = rhs.m_ManagerList;
|
this->m_ManagerList = rhs.m_ManagerList;
|
||||||
this->m_ChunkList = rhs.m_ChunkList;
|
this->m_ChunkList = rhs.m_ChunkList;
|
||||||
|
|
||||||
this->m_BindDoc = rhs.m_BindDoc;
|
this->m_BindFile = rhs.m_BindFile;
|
||||||
this->m_BindContext = rhs.m_BindContext;
|
this->m_BindContext = rhs.m_BindContext;
|
||||||
|
|
||||||
// copy buffer
|
// copy buffer
|
||||||
|
@ -292,23 +291,23 @@ namespace LibCmo::CK2 {
|
||||||
std::memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize);
|
std::memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize);
|
||||||
bufpos += 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;
|
// 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]);
|
this->m_ObjectList.resize(dwbuf[bufpos]);
|
||||||
bufpos += 1u;
|
bufpos += 1u;
|
||||||
std::memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size());
|
std::memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size());
|
||||||
bufpos += 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]);
|
this->m_ChunkList.resize(dwbuf[bufpos]);
|
||||||
bufpos += 1u;
|
bufpos += 1u;
|
||||||
std::memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size());
|
std::memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size());
|
||||||
bufpos += 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]);
|
this->m_ManagerList.resize(dwbuf[bufpos]);
|
||||||
bufpos += 1u;
|
bufpos += 1u;
|
||||||
std::memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size());
|
std::memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size());
|
||||||
|
@ -426,7 +425,7 @@ namespace LibCmo::CK2 {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// failed, report to context
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,13 +463,13 @@ namespace LibCmo::CK2 {
|
||||||
// new file
|
// new file
|
||||||
|
|
||||||
// if no doc associated, return directly
|
// if no doc associated, return directly
|
||||||
if (this->m_BindDoc == nullptr) {
|
if (this->m_BindFile == nullptr) {
|
||||||
*id = static_cast<CK_ID>(gotten_id);
|
*id = static_cast<CK_ID>(gotten_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// if it is positive, return corresponding value
|
// if it is positive, return corresponding value
|
||||||
if (gotten_id >= 0) {
|
if (gotten_id >= 0) {
|
||||||
*id = this->m_BindDoc->m_FileObjects[gotten_id].CreatedObject;
|
*id = this->m_BindFile->GetFileObjectByIndex(gotten_id)->CreatedObjectId;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +509,7 @@ namespace LibCmo::CK2 {
|
||||||
if (!this->EnsureReadSpace(subChunkSize)) goto subchunk_defer;
|
if (!this->EnsureReadSpace(subChunkSize)) goto subchunk_defer;
|
||||||
|
|
||||||
// create statechunk
|
// 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;
|
if (subchunk == nullptr) goto subchunk_defer;
|
||||||
|
|
||||||
// start read data
|
// start read data
|
||||||
|
@ -535,7 +534,7 @@ namespace LibCmo::CK2 {
|
||||||
// has bind file?
|
// has bind file?
|
||||||
CKDWORD hasBindFile;
|
CKDWORD hasBindFile;
|
||||||
if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
|
if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
|
||||||
if (hasBindFile == 1) subchunk->m_BindDoc = nullptr;
|
if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
|
||||||
|
|
||||||
// 3 list size
|
// 3 list size
|
||||||
// manager only existed when ver > 4
|
// manager only existed when ver > 4
|
||||||
|
@ -738,11 +737,11 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remap id
|
// remap id
|
||||||
if (this->m_BindDoc != nullptr) {
|
if (this->m_BindFile != nullptr) {
|
||||||
if (cache < 0) {
|
if (cache < 0) {
|
||||||
id = 0u;
|
id = 0u;
|
||||||
} else {
|
} else {
|
||||||
id = this->m_BindDoc->m_FileObjects[cache].CreatedObject;
|
id = this->m_BindFile->GetFileObjectByIndex(cache)->CreatedObjectId;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
id = static_cast<CK_ID>(cache);
|
id = static_cast<CK_ID>(cache);
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CKDefines.hpp"
|
#include "../VTAll.hpp"
|
||||||
#include "CKEnums.hpp"
|
|
||||||
#include <type_traits>
|
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
class CKStateChunk {
|
class CKStateChunk {
|
||||||
public:
|
public:
|
||||||
//CKStateChunk();
|
//CKStateChunk();
|
||||||
CKStateChunk(CKFileDocument* doc, CKMinContext* ctx);
|
CKStateChunk(CKFileVisitor* visitor, CKContext* ctx);
|
||||||
CKStateChunk(const CKStateChunk&);
|
CKStateChunk(const CKStateChunk&);
|
||||||
|
CKStateChunk(CKStateChunk&&);
|
||||||
CKStateChunk& operator=(const CKStateChunk&);
|
CKStateChunk& operator=(const CKStateChunk&);
|
||||||
|
CKStateChunk& operator-(const CKStateChunk&&);
|
||||||
~CKStateChunk();
|
~CKStateChunk();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -40,8 +39,8 @@ namespace LibCmo::CK2 {
|
||||||
std::vector<CKDWORD> m_ChunkList;
|
std::vector<CKDWORD> m_ChunkList;
|
||||||
std::vector<CKDWORD> m_ManagerList;
|
std::vector<CKDWORD> m_ManagerList;
|
||||||
|
|
||||||
CKFileDocument* m_BindDoc;
|
CKFileVisitor* m_BindFile;
|
||||||
CKMinContext* m_BindContext;
|
CKContext* m_BindContext;
|
||||||
|
|
||||||
#pragma region Buffer Related
|
#pragma region Buffer Related
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@ namespace LibCmo::CK2 {
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== Type Definition ==========
|
// ========== Type Definition ==========
|
||||||
|
// type define
|
||||||
|
|
||||||
using CKMUTSTRING = char*;
|
using CKMUTSTRING = char*;
|
||||||
using CKSTRING = const char*;
|
using CKSTRING = const char*;
|
||||||
|
@ -181,6 +182,12 @@ namespace LibCmo::CK2 {
|
||||||
using CKAttributeType = int32_t;
|
using CKAttributeType = int32_t;
|
||||||
using CKAttributeCategory = int32_t;
|
using CKAttributeCategory = int32_t;
|
||||||
|
|
||||||
|
// type print style define
|
||||||
|
#define PRIckBYTE PRIu8
|
||||||
|
#define PRIckDWORD PRIu32
|
||||||
|
#define PRIckWORD PRIu16
|
||||||
|
#define PRIckINT PRIi32
|
||||||
|
|
||||||
// ========== Class List ==========
|
// ========== Class List ==========
|
||||||
// Objects and derivated classes
|
// Objects and derivated classes
|
||||||
|
|
||||||
|
@ -269,7 +276,9 @@ namespace LibCmo::CK2 {
|
||||||
//--- Important classes
|
//--- Important classes
|
||||||
class CKContext;
|
class CKContext;
|
||||||
class CKStateChunk;
|
class CKStateChunk;
|
||||||
class CKFile;
|
class CKFileReader;
|
||||||
|
class CKFileWriter;
|
||||||
|
class CKFileVisitor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
namespace LibCmo {
|
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 {
|
namespace StreamHelper {
|
||||||
|
|
||||||
static constexpr const size_t CHUNK_SIZE = 10240;
|
static constexpr const size_t CHUNK_SIZE = 10240;
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
|
|
||||||
namespace LibCmo {
|
namespace LibCmo {
|
||||||
|
|
||||||
|
[[noreturn]] void LibPanic(int line, const char* file, const char* errmsg);
|
||||||
|
#define LIBPANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg);
|
||||||
|
|
||||||
namespace TypeHelper {
|
namespace TypeHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,11 +91,13 @@ namespace LibCmo {
|
||||||
MKString& operator=(const char* cstr) {
|
MKString& operator=(const char* cstr) {
|
||||||
m_HasStr = cstr != nullptr;
|
m_HasStr = cstr != nullptr;
|
||||||
m_Str = m_HasStr ? cstr : "";
|
m_Str = m_HasStr ? cstr : "";
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
MKString(const std::string& cstr) : m_HasStr(true), m_Str(cstr) {}
|
MKString(const std::string& cstr) : m_HasStr(true), m_Str(cstr) {}
|
||||||
MKString& operator=(const std::string& cstr) {
|
MKString& operator=(const std::string& cstr) {
|
||||||
m_HasStr = true;
|
m_HasStr = true;
|
||||||
m_Str = cstr;
|
m_Str = cstr;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MKString(const MKString& rhs) : m_HasStr(rhs.m_HasStr), m_Str(rhs.m_Str) {}
|
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) {
|
MKString& operator=(const MKString& rhs) {
|
||||||
m_HasStr = rhs.m_HasStr;
|
m_HasStr = rhs.m_HasStr;
|
||||||
m_Str = rhs.m_Str;
|
m_Str = rhs.m_Str;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
MKString& operator=(MKString&& rhs) noexcept {
|
MKString& operator=(MKString&& rhs) noexcept {
|
||||||
m_HasStr = rhs.m_HasStr;
|
m_HasStr = rhs.m_HasStr;
|
||||||
m_Str = std::move(rhs.m_Str);
|
m_Str = std::move(rhs.m_Str);
|
||||||
rhs.m_HasStr = false;
|
rhs.m_HasStr = false;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() const {
|
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>
|
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)));
|
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>
|
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));
|
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) | static_cast<std::underlying_type_t<TEnum>>(e2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "VxMemoryMappedFile.hpp"
|
#include "VxMemoryMappedFile.hpp"
|
||||||
#include "VTEncoding.hpp"
|
#include "../VTEncoding.hpp"
|
||||||
|
|
||||||
namespace LibCmo::VxMath {
|
namespace LibCmo::VxMath {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "VTUtils.hpp"
|
#include "../VTAll.hpp"
|
||||||
#if defined(LIBCMO_OS_WIN32)
|
#if defined(LIBCMO_OS_WIN32)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#else
|
#else
|
||||||
|
@ -40,9 +40,9 @@ namespace LibCmo::VxMath {
|
||||||
VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete;
|
VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete;
|
||||||
~VxMemoryMappedFile(void);
|
~VxMemoryMappedFile(void);
|
||||||
|
|
||||||
inline void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
|
void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
|
||||||
inline size_t GetFileSize(void) { return this->m_cbFile; }
|
size_t GetFileSize(void) { return this->m_cbFile; }
|
||||||
inline bool IsValid(void) { return this->m_bIsValid; }
|
bool IsValid(void) { return this->m_bIsValid; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace LibCmo::VxMath {
|
||||||
|
|
||||||
Vx2DVector() : x(0.0f), y(0.0f) {}
|
Vx2DVector() : x(0.0f), y(0.0f) {}
|
||||||
Vx2DVector(float f) : x(f), y(f) {}
|
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(CK2::CKINT iX, CK2::CKINT iY) : x((float)iX), y((float)iY) {}
|
||||||
Vx2DVector(const float f[2]) : x(f[0]), y(f[1]) {}
|
Vx2DVector(const float f[2]) : x(f[0]), y(f[1]) {}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user