refactor (4/?)
This commit is contained in:
parent
c8c2c6e20b
commit
4a787610f1
|
@ -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
|
||||
|
|
|
@ -76,20 +76,20 @@ namespace LibCmo::CK2 {
|
|||
~CKFileInfo() {}
|
||||
LIBCMO_DEFAULT_COPY_MOVE(CKFileInfo);
|
||||
|
||||
CKDWORD ProductVersion; ///< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
|
||||
CKDWORD ProductBuild; ///< Virtools Build Number.
|
||||
CK_FILE_WRITEMODE FileWriteMode; ///< Options used to save this file. (CK_FILE_WRITEMODE)
|
||||
CKDWORD FileVersion; ///< Version of file format when file was saved.
|
||||
CKDWORD CKVersion; ///< Version of CK when file was saved.
|
||||
CKDWORD FileSize; ///< Size of file in bytes.
|
||||
CKDWORD ObjectCount; ///< Number of objects stored in the file.
|
||||
CKDWORD ManagerCount; ///< Number of managers which saved data in the file.
|
||||
CKDWORD MaxIDSaved; ///< Maximum Object identifier saved
|
||||
CKDWORD Crc; ///< Crc of data
|
||||
CKDWORD Hdr1PackSize; ///< Reserved
|
||||
CKDWORD Hdr1UnPackSize; ///< Reserved
|
||||
CKDWORD DataPackSize; ///< Reserved
|
||||
CKDWORD DataUnPackSize; ///< Reserved
|
||||
CKDWORD ProductVersion; /**< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) */
|
||||
CKDWORD ProductBuild; /**< Virtools Build Number. */
|
||||
CK_FILE_WRITEMODE FileWriteMode; /**< Options used to save this file. (CK_FILE_WRITEMODE) */
|
||||
CKDWORD FileVersion; /**< Version of file format when file was saved. */
|
||||
CKDWORD CKVersion; /**< Version of CK when file was saved. */
|
||||
CKDWORD FileSize; /**< Size of file in bytes. */
|
||||
CKDWORD ObjectCount; /**< Number of objects stored in the file. */
|
||||
CKDWORD ManagerCount; /**< Number of managers which saved data in the file. */
|
||||
CKDWORD MaxIDSaved; /**< Maximum Object identifier saved */
|
||||
CKDWORD Crc; /**< Crc of data */
|
||||
CKDWORD Hdr1PackSize; /**< The compressed size of Header section. */
|
||||
CKDWORD Hdr1UnPackSize; /**< The uncompressed size of Header section. */
|
||||
CKDWORD DataPackSize; /**< The compressed size of Data section. */
|
||||
CKDWORD DataUnPackSize; /**< The uncompressed size of Data section. */
|
||||
};
|
||||
|
||||
class CKFileObject {
|
||||
|
@ -101,17 +101,17 @@ namespace LibCmo::CK2 {
|
|||
CKFileObject& operator=(CKFileObject&&);
|
||||
~CKFileObject();
|
||||
|
||||
CK_ID ObjectId; ///< ID of the object being load/saved (as it will be/was saved in the file)
|
||||
CK_ID CreatedObjectId; ///< ID of the object being created
|
||||
CK_CLASSID ObjectCid; ///< Class Identifier of the object
|
||||
CKObject* ObjPtr; ///< A pointer to the object itself (as CreatedObject when loading)
|
||||
TypeHelper::MKString Name; ///< Name of the Object
|
||||
CKStateChunk* Data; ///< A CKStateChunk that contains object information
|
||||
//CKINT PostPackSize; ///< When compressed chunk by chunk : size of Data after compression
|
||||
//CKINT PrePackSize; ///< When compressed chunk by chunk : size of Data before compression
|
||||
CK_FO_OPTIONS Options; ///< When loading an object it may be renamed , use to replace another object
|
||||
CKINT FileIndex; ///< Position of the object data inside uncompressed file buffer
|
||||
CKDWORD SaveFlags; ///< Flags used when this object was saved.
|
||||
CK_ID ObjectId; /**< ID of the object being load/saved (as it will be/was saved in the file) */
|
||||
CK_ID CreatedObjectId; /**< ID of the object being created */
|
||||
CK_CLASSID ObjectCid; /**< Class Identifier of the object */
|
||||
CKObject* ObjPtr; /**< A pointer to the object itself (as CreatedObject when loading) */
|
||||
TypeHelper::MKString Name; /**< Name of the Object */
|
||||
CKStateChunk* Data; /**< A CKStateChunk that contains object information */
|
||||
//CKINT PostPackSize; /**< When compressed chunk by chunk : size of Data after compression */
|
||||
//CKINT PrePackSize; /**< When compressed chunk by chunk : size of Data before compression */
|
||||
CK_FO_OPTIONS Options; /**< When loading an object it may be renamed , use to replace another object */
|
||||
CKINT FileIndex; /**< Position of the object data inside uncompressed file buffer */
|
||||
CKDWORD SaveFlags; /**< Flags used when this object was saved. */
|
||||
};
|
||||
|
||||
class CKFileManagerData {
|
||||
|
@ -136,26 +136,32 @@ namespace LibCmo::CK2 {
|
|||
|
||||
CK_PLUGIN_TYPE m_PluginCategory;
|
||||
XContainer::XArray<CKGUID> m_Guids;
|
||||
XContainer::XBitArray ValidGuids;
|
||||
//XContainer::XBitArray ValidGuids;
|
||||
};
|
||||
|
||||
/**
|
||||
@brief CKFile provides functions to save/load files in Virtools format.
|
||||
@remark
|
||||
+ Use CKFile just like a normal C++ class with passing CKCotext pointer.
|
||||
+ Once created a CKFile can be used to save one or more objects to disk.
|
||||
+ Only can load objects when this CKFile is empty. Use ClearData() to clear any existed CKFile.
|
||||
+ In any case, CKFile can run Save(). So you can create a CKFile, add some obejcts and save it.
|
||||
Or you can load a file by CKFile and add/modify something then save it.
|
||||
*/
|
||||
class CKFile {
|
||||
class CKFileVisitor {
|
||||
public:
|
||||
CKFile(CKContext* ctx);
|
||||
~CKFile();
|
||||
LIBCMO_DISABLE_COPY_MOVE(CKFile);
|
||||
CKFileVisitor(CKFileReader* reader);
|
||||
CKFileVisitor(CKFileWriter* writer);
|
||||
CKFileVisitor(const CKFileVisitor&);
|
||||
CKFileVisitor(CKFileVisitor&&);
|
||||
CKFileVisitor& operator=(const CKFileVisitor&);
|
||||
CKFileVisitor& operator=(CKFileVisitor&&);
|
||||
|
||||
// ========== Reset CKFile ==========
|
||||
void ClearData(void);
|
||||
const CKFileObject* GetFileObjectByIndex(size_t index);
|
||||
protected:
|
||||
CKBOOL m_IsReader;
|
||||
CKFileReader* m_Reader;
|
||||
CKFileWriter* m_Writer;
|
||||
CKContext* m_Ctx;
|
||||
};
|
||||
|
||||
class CKFileReader {
|
||||
friend class CKFileVisitor;
|
||||
public:
|
||||
CKFileReader(CKContext* ctx);
|
||||
~CKFileReader();
|
||||
LIBCMO_DISABLE_COPY_MOVE(CKFileReader);
|
||||
|
||||
// ========== Loading ==========
|
||||
CKERROR ShallowLoad(CKSTRING u8_filename);
|
||||
|
@ -165,6 +171,31 @@ namespace LibCmo::CK2 {
|
|||
const XContainer::XArray<CKFileObject>& GetFileObjects();
|
||||
const XContainer::XArray<XContainer::XString>& GetIncludedFiles();
|
||||
|
||||
protected:
|
||||
CKBOOL m_Done;
|
||||
CKINT m_SaveIDMax; /**< Maximum CK_ID found when saving or loading objects */
|
||||
XContainer::XArray<CKFileObject> m_FileObjects; /**< List of objects being saved / loaded */
|
||||
XContainer::XArray<CKFileManagerData> m_ManagersData; /**< Manager Data loaded */
|
||||
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */
|
||||
// XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; /**< List of index in the m_FileObjects table sorted by ClassID */
|
||||
XContainer::XArray<XContainer::XString> m_IncludedFiles; /**< List of files that should be inserted in the CMO file. */
|
||||
CKFileInfo m_FileInfo; /**< Headers summary */
|
||||
|
||||
CKERROR ReadFileHeader(CKBufferParser* ParserPtr);
|
||||
CKERROR ReadFileData(CKBufferParser* ParserPtr);
|
||||
|
||||
CKContext* m_Ctx;
|
||||
CKFileVisitor m_Visitor;
|
||||
};
|
||||
|
||||
class CKFileWriter {
|
||||
friend class CKFileVisitor;
|
||||
public:
|
||||
CKFileWriter(CKContext* ctx);
|
||||
CKFileWriter(CKContext* ctx, CKFileReader* reader);
|
||||
~CKFileWriter();
|
||||
LIBCMO_DISABLE_COPY_MOVE(CKFileWriter);
|
||||
|
||||
// ========== Saving Preparing ==========
|
||||
CKBOOL AddSavedObject(CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
|
||||
CKBOOL AddSavedObjects(CKObjectArray* objarray, CKDWORD flags = CK_STATESAVE_ALL);
|
||||
|
@ -173,41 +204,9 @@ namespace LibCmo::CK2 {
|
|||
// ========== Saving ==========
|
||||
CKERROR Save(CKSTRING u8_filename);
|
||||
|
||||
//CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
|
||||
//CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags);
|
||||
//CKERROR OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags);
|
||||
//CKERROR ReadFileHeaders(CKBufferParser** ParserPtr);
|
||||
//CKERROR ReadFileData(CKBufferParser** ParserPtr);
|
||||
//CKERROR LoadFileData(void/*CKObjectArray list*/);
|
||||
//CKERROR FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags);
|
||||
|
||||
CKINT m_SaveIDMax; // Maximum CK_ID found when saving or loading objects
|
||||
XContainer::XArray<CKFileObject> m_FileObjects; // List of objects being saved / loaded
|
||||
XContainer::XArray<CKFileManagerData> m_ManagersData; // Manager Data loaded
|
||||
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; // Plugins dependencies for this file
|
||||
// XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; // List of index in the m_FileObjects table sorted by ClassID
|
||||
XContainer::XArray<XContainer::XString> m_IncludedFiles; // List of files that should be inserted in the CMO file.
|
||||
CKFileInfo m_FileInfo; // Headers summary
|
||||
|
||||
//XContainer::XFileObjectsTable m_ObjectsHashTable;
|
||||
//CKBOOL m_ReadFileDataDone;
|
||||
//CKBOOL m_SceneSaved;
|
||||
//XContainer::XIntArray m_DuplicateNameFounds; // A List of file object index for which a existing object with the same name has been
|
||||
// // found, this list is build if the load option contains CK_LOAD_AUTOMATICMODE or CK_LOAD_DODIALOG
|
||||
//XContainer::XBitArray m_AlreadySavedMask; // BitArray of IDs already saved {secret}
|
||||
//XContainer::XBitArray m_AlreadyReferencedMask; // BitArray of IDs already referenced {secret}
|
||||
//XContainer::XObjectPointerArray m_ReferencedObjects;
|
||||
|
||||
private:
|
||||
// reader function and variables
|
||||
CKERROR ReadFileHeader(CKBufferParser* ParserPtr);
|
||||
CKERROR ReadFileData(CKBufferParser* ParserPtr);
|
||||
|
||||
// writer function and varibales
|
||||
|
||||
// shared function and variables
|
||||
bool mCanLoad;
|
||||
protected:
|
||||
CKContext* m_Ctx;
|
||||
CKFileVisitor m_Visitor;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace LibCmo::CK2 {
|
|||
this->FileIndex = rhs.FileIndex;
|
||||
this->SaveFlags = rhs.SaveFlags;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CKFileObject::~CKFileObject() {
|
||||
|
@ -107,6 +108,8 @@ namespace LibCmo::CK2 {
|
|||
|
||||
this->Data = rhs.Data;
|
||||
rhs.Data = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CKFileManagerData::~CKFileManagerData() {
|
||||
|
@ -115,36 +118,94 @@ namespace LibCmo::CK2 {
|
|||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKFilePluginDependencies
|
||||
#pragma region CKFileReader
|
||||
|
||||
CKFilePluginDependencies::CKFilePluginDependencies() :
|
||||
m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() {}
|
||||
CKFileReader::CKFileReader(CKContext* ctx) :
|
||||
m_Ctx(ctx), m_Visitor(this),
|
||||
m_Done(false),
|
||||
m_SaveIDMax(0),
|
||||
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
|
||||
m_FileInfo() {}
|
||||
|
||||
CKFilePluginDependencies::CKFilePluginDependencies(const CKFilePluginDependencies& rhs) :
|
||||
m_PluginCategory(rhs.m_PluginCategory), m_Guids(rhs.m_Guids) {}
|
||||
CKFileReader::~CKFileReader() {}
|
||||
|
||||
CKFilePluginDependencies& CKFilePluginDependencies::operator=(const CKFilePluginDependencies& rhs) {
|
||||
this->m_PluginCategory = rhs.m_PluginCategory;
|
||||
this->m_Guids = rhs.m_Guids;
|
||||
const XContainer::XArray<CKFileObject>& CKFileReader::GetFileObjects() {
|
||||
return m_FileObjects;
|
||||
}
|
||||
|
||||
const XContainer::XArray<XContainer::XString>& CKFileReader::GetIncludedFiles() {
|
||||
return m_IncludedFiles;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKFileWriter
|
||||
|
||||
CKFileWriter::CKFileWriter(CKContext* ctx) :
|
||||
m_Ctx(ctx), m_Visitor(this) {}
|
||||
|
||||
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader) :
|
||||
m_Ctx(ctx), m_Visitor(this) {}
|
||||
|
||||
CKFileWriter::~CKFileWriter() {}
|
||||
|
||||
CKBOOL CKFileWriter::AddSavedObject(CKObject* obj, CKDWORD flags) {
|
||||
return CKFALSE;
|
||||
}
|
||||
|
||||
CKBOOL CKFileWriter::AddSavedObjects(CKObjectArray* objarray, CKDWORD flags) {
|
||||
return CKFALSE;
|
||||
}
|
||||
|
||||
CKBOOL CKFileWriter::AddSavedFile(CKSTRING u8FileName) {
|
||||
return CKFALSE;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region CKFileVisitor
|
||||
|
||||
CKFileVisitor::CKFileVisitor(CKFileReader* reader) :
|
||||
m_IsReader(CKTRUE), m_Reader(reader), m_Writer(nullptr) {
|
||||
if (reader == nullptr) LIBPANIC("Reader is nullptr.");
|
||||
}
|
||||
|
||||
CKFileVisitor::CKFileVisitor(CKFileWriter* writer) :
|
||||
m_IsReader(false), m_Reader(nullptr), m_Writer(nullptr) {
|
||||
if (writer == nullptr) LIBPANIC("Writer is nullptr.");
|
||||
}
|
||||
|
||||
CKFileVisitor::CKFileVisitor(const CKFileVisitor& rhs) :
|
||||
m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer) {}
|
||||
|
||||
CKFileVisitor::CKFileVisitor(CKFileVisitor&& rhs) :
|
||||
m_IsReader(rhs.m_IsReader), m_Reader(rhs.m_Reader), m_Writer(rhs.m_Writer) {}
|
||||
|
||||
CKFileVisitor& CKFileVisitor::operator=(const CKFileVisitor& rhs) {
|
||||
this->m_IsReader = rhs.m_IsReader;
|
||||
this->m_Reader = rhs.m_Reader;
|
||||
this->m_Writer = rhs.m_Writer;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CKFilePluginDependencies::~CKFilePluginDependencies() {}
|
||||
CKFileVisitor& CKFileVisitor::operator=(CKFileVisitor&& rhs) {
|
||||
this->m_IsReader = rhs.m_IsReader;
|
||||
this->m_Reader = rhs.m_Reader;
|
||||
this->m_Writer = rhs.m_Writer;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKFile Misc
|
||||
|
||||
CKFile::CKFile(CKContext* ctx) :
|
||||
m_Ctx(ctx) {
|
||||
;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CKFile::~CKFile() {}
|
||||
|
||||
const CKFileObject* CKFileVisitor::GetFileObjectByIndex(size_t index) {
|
||||
if (m_IsReader) {
|
||||
return &m_Reader->m_FileObjects[index];
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,45 +14,34 @@ namespace LibCmo::CK2 {
|
|||
* No need to support them.
|
||||
*/
|
||||
|
||||
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename) {
|
||||
// preset value
|
||||
*out_doc = nullptr;
|
||||
CKERROR CKFileReader::ShallowLoad(CKSTRING u8_filename) {
|
||||
// check document status
|
||||
if (this->m_Done) LIBPANIC("Can not load multiple times for single CKFileReader.")
|
||||
|
||||
// check file and open memory
|
||||
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new(std::nothrow) VxMath::VxMemoryMappedFile(u8_filename));
|
||||
if (mappedFile == nullptr) {
|
||||
this->m_MinCtx->Printf("Out of memory when creating Memory File.");
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(u8_filename));
|
||||
if (!mappedFile->IsValid()) {
|
||||
this->m_MinCtx->Printf("Fail to create Memory File for \"%s\".", u8_filename);
|
||||
this->m_Ctx->OutputToConsoleEx("Fail to create Memory File for \"%s\".", u8_filename);
|
||||
return CKERROR::CKERR_INVALIDFILE;
|
||||
}
|
||||
|
||||
// create document
|
||||
std::unique_ptr<CKFileDocument> doc(new(std::nothrow) CKFileDocument());
|
||||
if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
|
||||
// create buffer and start loading
|
||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
|
||||
CKERROR err = this->ReadFileHeader(parser.get(), doc.get());
|
||||
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
|
||||
CKERROR err = this->ReadFileHeader(parser.get());
|
||||
if (err != CKERROR::CKERR_OK) return err;
|
||||
err = this->ReadFileData(parser.get(), doc.get());
|
||||
err = this->ReadFileData(parser.get());
|
||||
if (err != CKERROR::CKERR_OK) return err;
|
||||
|
||||
// unbind document and assign it
|
||||
*out_doc = doc.release();
|
||||
// other data will be free automatically
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr, CKFileDocument* doc) {
|
||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
CKERROR CKFileReader::ReadFileHeader(CKBufferParser* ParserPtr) {
|
||||
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||
parser->SetCursor(ParserPtr->GetCursor());
|
||||
|
||||
std::string name_conv;
|
||||
std::string name_conv, name_dest;
|
||||
|
||||
// ========== read header ==========
|
||||
// check header size
|
||||
|
@ -74,23 +63,23 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
|
||||
// ========== assign value ==========
|
||||
doc->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
|
||||
doc->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
|
||||
doc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
|
||||
doc->m_FileInfo.CKVersion = rawHeader.CKVersion;
|
||||
doc->m_FileInfo.FileVersion = rawHeader.FileVersion;
|
||||
doc->m_FileInfo.FileSize = parser->GetSize();
|
||||
doc->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
|
||||
doc->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
|
||||
doc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
|
||||
doc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
|
||||
doc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
|
||||
doc->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
|
||||
doc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
|
||||
doc->m_FileInfo.Crc = rawHeader.Crc;
|
||||
this->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
|
||||
this->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
|
||||
this->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
|
||||
this->m_FileInfo.CKVersion = rawHeader.CKVersion;
|
||||
this->m_FileInfo.FileVersion = rawHeader.FileVersion;
|
||||
this->m_FileInfo.FileSize = static_cast<CKDWORD>(parser->GetSize());
|
||||
this->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
|
||||
this->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
|
||||
this->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
|
||||
this->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
|
||||
this->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
|
||||
this->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
|
||||
this->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
|
||||
this->m_FileInfo.Crc = rawHeader.Crc;
|
||||
|
||||
// ========== crc and body unpacker ==========
|
||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// crc checker for file ver >= 8
|
||||
// reset crc field of header
|
||||
rawHeader.Crc = 0u;
|
||||
|
@ -98,12 +87,12 @@ namespace LibCmo::CK2 {
|
|||
// compute crc
|
||||
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, sizeof(CKRawFileInfo), 0u);
|
||||
parser->SetCursor(sizeof(CKRawFileInfo));
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize, gotten_crc);
|
||||
parser->MoveCursor(doc->m_FileInfo.Hdr1PackSize);
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.DataPackSize, gotten_crc);
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
|
||||
parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
|
||||
|
||||
if (gotten_crc != doc->m_FileInfo.Crc) {
|
||||
this->m_MinCtx->Printf("Virtools file CRC error.");
|
||||
if (gotten_crc != this->m_FileInfo.Crc) {
|
||||
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
|
||||
return CKERROR::CKERR_FILECRCERROR;
|
||||
}
|
||||
|
||||
|
@ -111,13 +100,9 @@ namespace LibCmo::CK2 {
|
|||
parser->SetCursor(sizeof(CKRawFileInfo));
|
||||
|
||||
// compare size to decide wheher use compress feature
|
||||
void* decomp_buffer = CKUnPackData(doc->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize);
|
||||
void* decomp_buffer = CKUnPackData(this->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_FileInfo.Hdr1PackSize);
|
||||
if (decomp_buffer != nullptr) {
|
||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.Hdr1UnPackSize, true));
|
||||
if (parser == nullptr) {
|
||||
delete[] reinterpret_cast<char*>(decomp_buffer);
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
parser = std::unique_ptr<CKBufferParser>(new CKBufferParser(decomp_buffer, this->m_FileInfo.Hdr1UnPackSize, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,12 +110,12 @@ namespace LibCmo::CK2 {
|
|||
// file ver >= 7 have this features
|
||||
{
|
||||
// apply max id saved
|
||||
doc->m_SaveIDMax = doc->m_FileInfo.MaxIDSaved;
|
||||
this->m_SaveIDMax = this->m_FileInfo.MaxIDSaved;
|
||||
// resize
|
||||
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
|
||||
this->m_FileObjects.resize(this->m_FileInfo.ObjectCount);
|
||||
|
||||
// read data
|
||||
for (auto& fileobj : doc->m_FileObjects) {
|
||||
for (auto& fileobj : this->m_FileObjects) {
|
||||
// read basic fields
|
||||
parser->Read(&(fileobj.ObjectId), sizeof(CK_ID));
|
||||
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
||||
|
@ -141,21 +126,22 @@ namespace LibCmo::CK2 {
|
|||
if (namelen != 0) {
|
||||
name_conv.resize(namelen);
|
||||
parser->Read(name_conv.data(), namelen);
|
||||
m_MinCtx->GetUtf8String(name_conv, fileobj.Name);
|
||||
m_Ctx->GetUtf8String(name_conv, name_dest);
|
||||
fileobj.Name = name_dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== dep list read ==========
|
||||
// file ver >= 8 have this feature
|
||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// get size and resize
|
||||
CKDWORD depSize;
|
||||
parser->Read(&depSize, sizeof(CKDWORD));
|
||||
doc->m_PluginDep.resize(depSize);
|
||||
this->m_PluginsDep.resize(depSize);
|
||||
|
||||
CKDWORD guid_size;
|
||||
for (auto& dep : doc->m_PluginDep) {
|
||||
for (auto& dep : this->m_PluginsDep) {
|
||||
// read category
|
||||
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
||||
// get size and resize
|
||||
|
@ -171,7 +157,7 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// ========== included file list read ==========
|
||||
// file ver >= 8 have this feature
|
||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// MARK: i don't knwo what is this!
|
||||
int32_t hasIncludedFile;
|
||||
parser->Read(&hasIncludedFile, sizeof(int32_t));
|
||||
|
@ -180,7 +166,7 @@ namespace LibCmo::CK2 {
|
|||
// read included file size and resize
|
||||
CKDWORD includedFileCount;
|
||||
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
||||
doc->m_IncludedFiles.resize(includedFileCount);
|
||||
this->m_IncludedFiles.resize(includedFileCount);
|
||||
|
||||
hasIncludedFile -= 4;
|
||||
}
|
||||
|
@ -191,10 +177,10 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
|
||||
// ========== sync main parser ==========
|
||||
if (doc->m_FileInfo.FileVersion >= 8) {
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// file ver >= 8, use header offset
|
||||
// because it have compress feature
|
||||
ParserPtr->SetCursor(doc->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
|
||||
ParserPtr->SetCursor(this->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
|
||||
} else {
|
||||
// otherwise, sync with current parser.
|
||||
ParserPtr->SetCursor(parser->GetCursor());
|
||||
|
@ -203,7 +189,7 @@ namespace LibCmo::CK2 {
|
|||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr, CKFileDocument* doc) {
|
||||
CKERROR CKFileReader::ReadFileData(CKBufferParser* ParserPtr) {
|
||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
parser->SetCursor(ParserPtr->GetCursor());
|
||||
|
@ -211,52 +197,47 @@ namespace LibCmo::CK2 {
|
|||
std::string name_conv;
|
||||
|
||||
// ========== compress feature process ==========
|
||||
if (EnumsHelper::FlagEnumHas(doc->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
||||
EnumsHelper::FlagEnumHas(doc->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
|
||||
if (EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
||||
EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
|
||||
|
||||
void* decomp_buffer = CKUnPackData(doc->m_FileInfo.DataUnPackSize, parser->GetPtr(), doc->m_FileInfo.DataPackSize);
|
||||
void* decomp_buffer = CKUnPackData(this->m_FileInfo.DataUnPackSize, parser->GetPtr(), this->m_FileInfo.DataPackSize);
|
||||
if (decomp_buffer != nullptr) {
|
||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.DataUnPackSize, true));
|
||||
|
||||
if (parser == nullptr) {
|
||||
delete[] reinterpret_cast<char*>(decomp_buffer);
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
parser = std::unique_ptr<CKBufferParser>(new CKBufferParser(decomp_buffer, this->m_FileInfo.DataUnPackSize, true));
|
||||
}
|
||||
}
|
||||
|
||||
// ========== old file crc and obj list read ==========
|
||||
// only file ver < 8 run this
|
||||
if (doc->m_FileInfo.FileVersion < 8) {
|
||||
if (this->m_FileInfo.FileVersion < 8) {
|
||||
// check crc
|
||||
CKDWORD gotten_crc = CKComputeDataCRC(
|
||||
parser->GetPtr(),
|
||||
parser->GetSize() - parser->GetCursor(),
|
||||
0u
|
||||
);
|
||||
if (gotten_crc != doc->m_FileInfo.Crc) {
|
||||
this->m_MinCtx->Printf("Virtools file CRC error.");
|
||||
if (gotten_crc != this->m_FileInfo.Crc) {
|
||||
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
|
||||
return CKERROR::CKERR_FILECRCERROR;
|
||||
}
|
||||
|
||||
// MARK: why read again? especially for file ver == 7.
|
||||
// get save id max
|
||||
parser->Read(&doc->m_SaveIDMax, sizeof(int32_t));
|
||||
parser->Read(&this->m_SaveIDMax, sizeof(int32_t));
|
||||
// get object count and resize
|
||||
parser->Read(&doc->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
||||
if (doc->m_FileObjects.empty()) {
|
||||
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
|
||||
parser->Read(&this->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
||||
if (this->m_FileObjects.empty()) {
|
||||
this->m_FileObjects.resize(this->m_FileInfo.ObjectCount);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== manager read ==========
|
||||
// only file ver >= 6 have this
|
||||
if (doc->m_FileInfo.ManagerCount != 0) {
|
||||
doc->m_FileManagersData.resize(doc->m_FileInfo.ManagerCount);
|
||||
if (this->m_FileInfo.ManagerCount != 0) {
|
||||
this->m_ManagersData.resize(this->m_FileInfo.ManagerCount);
|
||||
CKDWORD stateChunkLen = 0u;
|
||||
bool stateChkParseSuccess = false;
|
||||
|
||||
for (auto& mgr : doc->m_FileManagersData) {
|
||||
for (auto& mgr : this->m_ManagersData) {
|
||||
// read guid
|
||||
parser->Read(&(mgr.Manager), sizeof(CKGUID));
|
||||
|
||||
|
@ -269,25 +250,23 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
|
||||
// read statechunk
|
||||
mgr.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx);
|
||||
if (mgr.Data != nullptr) {
|
||||
mgr.Data = new CKStateChunk(&this->m_Visitor, this->m_Ctx);
|
||||
stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
|
||||
if (!stateChkParseSuccess) {
|
||||
delete mgr.Data;
|
||||
mgr.Data = nullptr;
|
||||
}
|
||||
}
|
||||
parser->MoveCursor(stateChunkLen);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== object read ==========
|
||||
// only works file version >= 4. < 4 section has been removed.
|
||||
if (doc->m_FileInfo.ObjectCount != 0) {
|
||||
if (this->m_FileInfo.ObjectCount != 0) {
|
||||
// new file reader section
|
||||
CKDWORD stateChunkLen = 0u;
|
||||
bool stateChkParseSuccess = false;
|
||||
for (auto& obj : doc->m_FileObjects) {
|
||||
for (auto& obj : this->m_FileObjects) {
|
||||
// get statechunk len
|
||||
parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
||||
// check state chunk len
|
||||
|
@ -297,14 +276,12 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
|
||||
// read state chunk
|
||||
obj.Data = new(std::nothrow) CKStateChunk(doc, this->m_MinCtx);
|
||||
if (obj.Data != nullptr) {
|
||||
obj.Data = new CKStateChunk(&this->m_Visitor, this->m_Ctx);
|
||||
stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
|
||||
if (!stateChkParseSuccess) {
|
||||
delete obj.Data;
|
||||
obj.Data = nullptr;
|
||||
}
|
||||
}
|
||||
parser->MoveCursor(stateChunkLen);
|
||||
|
||||
}
|
||||
|
@ -314,11 +291,11 @@ namespace LibCmo::CK2 {
|
|||
// before reading, we need switch back to original parser.
|
||||
// and skip data chunk size
|
||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||
parser->MoveCursor(doc->m_FileInfo.DataPackSize);
|
||||
parser->MoveCursor(this->m_FileInfo.DataPackSize);
|
||||
|
||||
// then we can read it.
|
||||
if (doc->m_IncludedFiles.size() != 0) {
|
||||
for (auto& file : doc->m_IncludedFiles) {
|
||||
if (this->m_IncludedFiles.size() != 0) {
|
||||
for (auto& file : this->m_IncludedFiles) {
|
||||
// get file name length and resize it
|
||||
CKDWORD filenamelen = 0u;
|
||||
parser->Read(&filenamelen, sizeof(CKDWORD));
|
||||
|
@ -327,7 +304,7 @@ namespace LibCmo::CK2 {
|
|||
// read filename
|
||||
if (filenamelen != 0) {
|
||||
parser->Read(name_conv.data(), filenamelen);
|
||||
m_MinCtx->GetUtf8String(name_conv, file);
|
||||
m_Ctx->GetUtf8String(name_conv, file);
|
||||
}
|
||||
|
||||
// read file body length
|
||||
|
@ -335,7 +312,7 @@ namespace LibCmo::CK2 {
|
|||
parser->Read(&filebodylen, sizeof(CKDWORD));
|
||||
|
||||
// read file body
|
||||
FILE* fp = m_MinCtx->OpenTempFile(file.c_str(), false);
|
||||
FILE* fp = m_Ctx->OpenTempFile(file.c_str(), false);
|
||||
if (fp != nullptr) {
|
||||
StreamHelper::CopyStream(parser->GetPtr(), fp, filebodylen);
|
||||
fclose(fp);
|
||||
|
@ -349,32 +326,26 @@ namespace LibCmo::CK2 {
|
|||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::DeepLoad(CKSTRING u8_filename, CKFileDocument** out_doc) {
|
||||
CKERROR CKFileReader::DeepLoad(CKSTRING u8_filename) {
|
||||
// ========== prepare work ==========
|
||||
// preset value
|
||||
*out_doc = nullptr;
|
||||
CKERROR err = CKERROR::CKERR_OK;
|
||||
|
||||
// get shallow document first
|
||||
CKFileDocument* rawShallowDoc = nullptr;
|
||||
err = this->ShallowLoad(u8_filename, &rawShallowDoc);
|
||||
if (rawShallowDoc == nullptr) return err;
|
||||
// use unique ptr wrap it as a deep doc
|
||||
std::unique_ptr<CKFileDocument> deepDoc(rawShallowDoc);
|
||||
err = this->ShallowLoad(u8_filename);
|
||||
if (err != CKERROR::CKERR_OK) return err;
|
||||
|
||||
// ========== create object first ==========
|
||||
for (auto& obj : deepDoc->m_FileObjects) {
|
||||
for (auto& obj : this->m_FileObjects) {
|
||||
// todo: skip CK_LEVEL
|
||||
// todo: resolve references
|
||||
if (obj.Data == nullptr) continue;
|
||||
|
||||
// create object and assign created obj ckid
|
||||
obj.ObjPtr = m_MinCtx->CreateCKObject(obj.ObjectId, obj.ObjectCid, obj.Name.c_str());
|
||||
obj.ObjPtr = m_Ctx->CreateCKObject(obj.ObjectCid, obj.Name.c_str());
|
||||
if (obj.ObjPtr == nullptr) {
|
||||
obj.CreatedObject = 0u;
|
||||
obj.CreatedObjectId = 0u;
|
||||
} else {
|
||||
obj.CreatedObject = obj.ObjPtr->m_ID;
|
||||
obj.CreatedObjectId = obj.ObjPtr->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,13 +357,13 @@ namespace LibCmo::CK2 {
|
|||
// todo...
|
||||
|
||||
// ========== analyze objects CKStateChunk ==========
|
||||
for (auto& obj : deepDoc->m_FileObjects) {
|
||||
for (auto& obj : this->m_FileObjects) {
|
||||
if (obj.Data == nullptr || obj.ObjPtr == nullptr) continue;
|
||||
|
||||
// todo: special treat for CK_LEVEL
|
||||
// try parsing data
|
||||
obj.Data->StartRead();
|
||||
bool success = obj.ObjPtr->Load(obj.Data, deepDoc.get());
|
||||
bool success = obj.ObjPtr->Load(obj.Data, &this->m_Visitor);
|
||||
obj.Data->StopRead();
|
||||
if (success) {
|
||||
// if success, clear CKStateChunk*
|
||||
|
@ -400,15 +371,13 @@ namespace LibCmo::CK2 {
|
|||
obj.Data = nullptr;
|
||||
} else {
|
||||
// if failed, delete it
|
||||
m_MinCtx->DestroyCKObject(obj.ObjectId);
|
||||
m_Ctx->DestroyCKObject(obj.ObjectId);
|
||||
obj.ObjPtr = nullptr;
|
||||
obj.CreatedObject = 0u;
|
||||
obj.CreatedObjectId = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== finalize work ==========
|
||||
// detach and return
|
||||
*out_doc = deepDoc.release();
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
|
||||
CKERROR CKFileWriter::Save(CKSTRING u8_filename) {
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
#include <algorithm>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "CKObjectImplements/CKObject.hpp"
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
#pragma region Compression utilities
|
||||
|
@ -68,7 +70,7 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// find direct parent
|
||||
auto finder = g_CKClassInfoId2Idx.find(desc.Parent);
|
||||
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
|
||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
||||
CKClassDesc& parent = g_CKClassInfo[finder->second];
|
||||
|
||||
// if it is not self inheritance, call recursively
|
||||
|
@ -80,7 +82,7 @@ namespace LibCmo::CK2 {
|
|||
desc.Parents = parent.Parents;
|
||||
// and set self as its parent
|
||||
finder = g_CKClassInfoId2Idx.find(desc.Self);
|
||||
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
|
||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
||||
desc.Parents[finder->second] = true;
|
||||
|
||||
// set derivation level
|
||||
|
@ -105,7 +107,7 @@ namespace LibCmo::CK2 {
|
|||
// iterate CKClassDesc::Parents and register it self to gotten parents
|
||||
for (auto& item : g_CKClassInfo) {
|
||||
auto finder = g_CKClassInfoId2Idx.find(item.Self);
|
||||
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
|
||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
||||
size_t selfidx = finder->second;
|
||||
|
||||
for (size_t idx = 0; idx < classCount; ++idx) {
|
||||
|
@ -154,10 +156,10 @@ namespace LibCmo::CK2 {
|
|||
CKBOOL CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
||||
// get corresponding index first
|
||||
auto finder = g_CKClassInfoId2Idx.find(child);
|
||||
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
|
||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
||||
size_t child_idx = finder->second;
|
||||
finder = g_CKClassInfoId2Idx.find(parent);
|
||||
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
|
||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
||||
size_t parent_idx = finder->second;
|
||||
|
||||
return g_CKClassInfo[child_idx].Parents[parent_idx];
|
||||
|
@ -165,7 +167,7 @@ namespace LibCmo::CK2 {
|
|||
|
||||
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
||||
auto finder = g_CKClassInfoId2Idx.find(child);
|
||||
if (finder == g_CKClassInfoId2Idx.end()) std::abort();
|
||||
if (finder == g_CKClassInfoId2Idx.end()) LIBPANIC("No such CK_CLASSID.");
|
||||
return g_CKClassInfo[finder->second].Parent;
|
||||
}
|
||||
|
||||
|
@ -188,6 +190,10 @@ namespace LibCmo::CK2 {
|
|||
|
||||
CKERROR CKStartUp() {
|
||||
// todo: add class type registrations
|
||||
CKClassRegister(CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT,
|
||||
[](CKContext* ctx, CK_ID id, CKSTRING name) -> CKObject* { return new CKObject(ctx, id, name); },
|
||||
[](CKContext* ctx, CKObject* obj) -> void { delete obj; },
|
||||
[]() -> CKSTRING { return "Basic Object"; });
|
||||
|
||||
/*
|
||||
// register CKObjects
|
||||
|
@ -218,6 +224,8 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
*/
|
||||
|
||||
CKBuildClassHierarchyTable();
|
||||
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "VTUtils.hpp"
|
||||
#include "CKStateChunk.hpp"
|
||||
#include "CKMinContext.hpp"
|
||||
#include "CKFile.hpp"
|
||||
#include "CKContext.hpp"
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
|
@ -16,21 +15,20 @@ namespace LibCmo::CK2 {
|
|||
//{
|
||||
// ;
|
||||
//}
|
||||
CKStateChunk::CKStateChunk(CKFileDocument* doc, CKMinContext* ctx) :
|
||||
CKStateChunk::CKStateChunk(CKFileVisitor* visitor, CKContext* ctx) :
|
||||
m_ClassId(CK_CLASSID::CKCID_OBJECT), m_DataDwSize(0u), m_pData(nullptr),
|
||||
m_DataVersion(CK_STATECHUNK_DATAVERSION::CHUNKDATA_CURRENTVERSION), m_ChunkVersion(CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4),
|
||||
m_Parser{ CKStateChunkStatus::IDLE, 0u, 0u, 0u },
|
||||
m_ObjectList(), m_ChunkList(), m_ManagerList(),
|
||||
m_BindDoc(doc), m_BindContext(ctx)
|
||||
{
|
||||
;
|
||||
}
|
||||
m_BindFile(visitor), m_BindContext(ctx)
|
||||
{}
|
||||
|
||||
CKStateChunk::CKStateChunk(const CKStateChunk& rhs) :
|
||||
m_ClassId(rhs.m_ClassId), m_DataVersion(rhs.m_DataVersion), m_ChunkVersion(rhs.m_ChunkVersion),
|
||||
m_Parser(rhs.m_Parser),
|
||||
m_ObjectList(rhs.m_ObjectList), m_ManagerList(rhs.m_ManagerList), m_ChunkList(rhs.m_ChunkList),
|
||||
m_pData(nullptr), m_DataDwSize(rhs.m_DataDwSize),
|
||||
m_BindDoc(rhs.m_BindDoc), m_BindContext(rhs.m_BindContext) {
|
||||
m_BindFile(rhs.m_BindFile), m_BindContext(rhs.m_BindContext) {
|
||||
// copy buffer
|
||||
if (rhs.m_pData != nullptr) {
|
||||
this->m_pData = new(std::nothrow) CKDWORD[rhs.m_DataDwSize];
|
||||
|
@ -39,6 +37,7 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
CKStateChunk& CKStateChunk::operator=(const CKStateChunk& rhs) {
|
||||
this->Clear();
|
||||
|
||||
|
@ -52,7 +51,7 @@ namespace LibCmo::CK2 {
|
|||
this->m_ManagerList = rhs.m_ManagerList;
|
||||
this->m_ChunkList = rhs.m_ChunkList;
|
||||
|
||||
this->m_BindDoc = rhs.m_BindDoc;
|
||||
this->m_BindFile = rhs.m_BindFile;
|
||||
this->m_BindContext = rhs.m_BindContext;
|
||||
|
||||
// copy buffer
|
||||
|
@ -292,23 +291,23 @@ namespace LibCmo::CK2 {
|
|||
std::memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize);
|
||||
bufpos += this->m_DataDwSize;
|
||||
}
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
|
||||
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
|
||||
// MARK: set ckfile = nullptr;
|
||||
;
|
||||
}
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
|
||||
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
|
||||
this->m_ObjectList.resize(dwbuf[bufpos]);
|
||||
bufpos += 1u;
|
||||
std::memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size());
|
||||
bufpos += this->m_ObjectList.size();
|
||||
}
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
|
||||
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
|
||||
this->m_ChunkList.resize(dwbuf[bufpos]);
|
||||
bufpos += 1u;
|
||||
std::memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size());
|
||||
bufpos += this->m_ChunkList.size();
|
||||
}
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
|
||||
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
|
||||
this->m_ManagerList.resize(dwbuf[bufpos]);
|
||||
bufpos += 1u;
|
||||
std::memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size());
|
||||
|
@ -426,7 +425,7 @@ namespace LibCmo::CK2 {
|
|||
return true;
|
||||
} else {
|
||||
// failed, report to context
|
||||
m_BindContext->Printf("CKStateChunk read length error at %" PRICKdword ".", this->m_Parser.m_CurrentPos);
|
||||
m_BindContext->OutputToConsoleEx("CKStateChunk read length error at %" PRIckDWORD ".", this->m_Parser.m_CurrentPos);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -464,13 +463,13 @@ namespace LibCmo::CK2 {
|
|||
// new file
|
||||
|
||||
// if no doc associated, return directly
|
||||
if (this->m_BindDoc == nullptr) {
|
||||
if (this->m_BindFile == nullptr) {
|
||||
*id = static_cast<CK_ID>(gotten_id);
|
||||
return true;
|
||||
}
|
||||
// if it is positive, return corresponding value
|
||||
if (gotten_id >= 0) {
|
||||
*id = this->m_BindDoc->m_FileObjects[gotten_id].CreatedObject;
|
||||
*id = this->m_BindFile->GetFileObjectByIndex(gotten_id)->CreatedObjectId;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -510,7 +509,7 @@ namespace LibCmo::CK2 {
|
|||
if (!this->EnsureReadSpace(subChunkSize)) goto subchunk_defer;
|
||||
|
||||
// create statechunk
|
||||
subchunk = new(std::nothrow) CKStateChunk(this->m_BindDoc, this->m_BindContext);
|
||||
subchunk = new(std::nothrow) CKStateChunk(this->m_BindFile, this->m_BindContext);
|
||||
if (subchunk == nullptr) goto subchunk_defer;
|
||||
|
||||
// start read data
|
||||
|
@ -535,7 +534,7 @@ namespace LibCmo::CK2 {
|
|||
// has bind file?
|
||||
CKDWORD hasBindFile;
|
||||
if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
|
||||
if (hasBindFile == 1) subchunk->m_BindDoc = nullptr;
|
||||
if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
|
||||
|
||||
// 3 list size
|
||||
// manager only existed when ver > 4
|
||||
|
@ -738,11 +737,11 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
|
||||
// remap id
|
||||
if (this->m_BindDoc != nullptr) {
|
||||
if (this->m_BindFile != nullptr) {
|
||||
if (cache < 0) {
|
||||
id = 0u;
|
||||
} else {
|
||||
id = this->m_BindDoc->m_FileObjects[cache].CreatedObject;
|
||||
id = this->m_BindFile->GetFileObjectByIndex(cache)->CreatedObjectId;
|
||||
}
|
||||
} else {
|
||||
id = static_cast<CK_ID>(cache);
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "CKDefines.hpp"
|
||||
#include "CKEnums.hpp"
|
||||
#include <type_traits>
|
||||
#include <cinttypes>
|
||||
#include "../VTAll.hpp"
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
class CKStateChunk {
|
||||
public:
|
||||
//CKStateChunk();
|
||||
CKStateChunk(CKFileDocument* doc, CKMinContext* ctx);
|
||||
CKStateChunk(CKFileVisitor* visitor, CKContext* ctx);
|
||||
CKStateChunk(const CKStateChunk&);
|
||||
CKStateChunk(CKStateChunk&&);
|
||||
CKStateChunk& operator=(const CKStateChunk&);
|
||||
CKStateChunk& operator-(const CKStateChunk&&);
|
||||
~CKStateChunk();
|
||||
|
||||
private:
|
||||
|
@ -40,8 +39,8 @@ namespace LibCmo::CK2 {
|
|||
std::vector<CKDWORD> m_ChunkList;
|
||||
std::vector<CKDWORD> m_ManagerList;
|
||||
|
||||
CKFileDocument* m_BindDoc;
|
||||
CKMinContext* m_BindContext;
|
||||
CKFileVisitor* m_BindFile;
|
||||
CKContext* m_BindContext;
|
||||
|
||||
#pragma region Buffer Related
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -68,6 +68,9 @@
|
|||
|
||||
namespace LibCmo {
|
||||
|
||||
[[noreturn]] void LibPanic(int line, const char* file, const char* errmsg);
|
||||
#define LIBPANIC(msg) LibCmo::LibPanic(__LINE__, __FILE__, msg);
|
||||
|
||||
namespace TypeHelper {
|
||||
|
||||
/**
|
||||
|
@ -88,11 +91,13 @@ namespace LibCmo {
|
|||
MKString& operator=(const char* cstr) {
|
||||
m_HasStr = cstr != nullptr;
|
||||
m_Str = m_HasStr ? cstr : "";
|
||||
return *this;
|
||||
}
|
||||
MKString(const std::string& cstr) : m_HasStr(true), m_Str(cstr) {}
|
||||
MKString& operator=(const std::string& cstr) {
|
||||
m_HasStr = true;
|
||||
m_Str = cstr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MKString(const MKString& rhs) : m_HasStr(rhs.m_HasStr), m_Str(rhs.m_Str) {}
|
||||
|
@ -102,11 +107,13 @@ namespace LibCmo {
|
|||
MKString& operator=(const MKString& rhs) {
|
||||
m_HasStr = rhs.m_HasStr;
|
||||
m_Str = rhs.m_Str;
|
||||
return *this;
|
||||
}
|
||||
MKString& operator=(MKString&& rhs) noexcept {
|
||||
m_HasStr = rhs.m_HasStr;
|
||||
m_Str = std::move(rhs.m_Str);
|
||||
rhs.m_HasStr = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
|
@ -135,12 +142,12 @@ namespace LibCmo {
|
|||
}
|
||||
|
||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||
inline TEnum Rm(TEnum& e1, TEnum e2) {
|
||||
inline void Rm(TEnum& e1, TEnum e2) {
|
||||
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) & static_cast<std::underlying_type_t<TEnum>>(Inv(e2)));
|
||||
}
|
||||
|
||||
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
||||
inline TEnum Add(TEnum& e1, TEnum e2) {
|
||||
inline void Add(TEnum& e1, TEnum e2) {
|
||||
e1 = static_cast<TEnum>(static_cast<std::underlying_type_t<TEnum>>(e1) | static_cast<std::underlying_type_t<TEnum>>(e2));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "VxMemoryMappedFile.hpp"
|
||||
#include "VTEncoding.hpp"
|
||||
#include "../VTEncoding.hpp"
|
||||
|
||||
namespace LibCmo::VxMath {
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "VTUtils.hpp"
|
||||
#include "../VTAll.hpp"
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
|
@ -40,9 +40,9 @@ namespace LibCmo::VxMath {
|
|||
VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete;
|
||||
~VxMemoryMappedFile(void);
|
||||
|
||||
inline void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
|
||||
inline size_t GetFileSize(void) { return this->m_cbFile; }
|
||||
inline bool IsValid(void) { return this->m_bIsValid; }
|
||||
void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
|
||||
size_t GetFileSize(void) { return this->m_cbFile; }
|
||||
bool IsValid(void) { return this->m_bIsValid; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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]) {}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user