finish half writing function
This commit is contained in:
parent
f0657b1656
commit
bac9f2ae25
|
@ -99,7 +99,7 @@ namespace LibCmo::CK2 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MgrImpls::CKBaseManager* CKContext::GetManager(int index) {
|
MgrImpls::CKBaseManager* CKContext::GetManager(CKINT index) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,12 +188,18 @@ namespace LibCmo::CK2 {
|
||||||
EncodingHelper::SetStdPathFromU8Path(this->m_TempFolder, u8_temp);
|
EncodingHelper::SetStdPathFromU8Path(this->m_TempFolder, u8_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* CKContext::OpenTempFile(CKSTRING u8_filename, CKBOOL is_read) {
|
FILE* CKContext::OpenTempFile(CKSTRING u8_filename, CKSTRING u8_mode) {
|
||||||
std::filesystem::path stdfilename;
|
std::filesystem::path stdfilename;
|
||||||
EncodingHelper::SetStdPathFromU8Path(stdfilename, u8_filename);
|
EncodingHelper::SetStdPathFromU8Path(stdfilename, u8_filename);
|
||||||
|
|
||||||
auto realfile = this->m_TempFolder / stdfilename;
|
auto realfile = this->m_TempFolder / stdfilename;
|
||||||
return EncodingHelper::OpenStdPathFile(realfile, is_read);
|
return EncodingHelper::StdPathFOpen(realfile, u8_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* CKContext::OpenFile(CKSTRING u8_filename, CKSTRING u8_mode) {
|
||||||
|
std::filesystem::path stdfilename;
|
||||||
|
EncodingHelper::SetStdPathFromU8Path(stdfilename, u8_filename);
|
||||||
|
return EncodingHelper::StdPathFOpen(stdfilename, u8_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace LibCmo::CK2 {
|
||||||
// ========== Common Managers Functions ==========
|
// ========== Common Managers Functions ==========
|
||||||
|
|
||||||
CKINT GetManagerCount();
|
CKINT GetManagerCount();
|
||||||
MgrImpls::CKBaseManager* GetManager(int index);
|
MgrImpls::CKBaseManager* GetManager(CKINT index);
|
||||||
|
|
||||||
// ========== File Save/Load Options ==========
|
// ========== File Save/Load Options ==========
|
||||||
|
|
||||||
|
@ -79,7 +79,8 @@ namespace LibCmo::CK2 {
|
||||||
// ========== Temp IO utilities ==========
|
// ========== Temp IO utilities ==========
|
||||||
|
|
||||||
void SetTempPath(CKSTRING u8_temp);
|
void SetTempPath(CKSTRING u8_temp);
|
||||||
FILE* OpenTempFile(CKSTRING u8_filename, CKBOOL is_read);
|
FILE* OpenTempFile(CKSTRING u8_filename, CKSTRING u8_mode);
|
||||||
|
FILE* OpenFile(CKSTRING u8_filename, CKSTRING u8_mode);
|
||||||
|
|
||||||
// ========== Print utilities ==========
|
// ========== Print utilities ==========
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,19 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
/**
|
||||||
|
* @brief The identifier of Virtools file.
|
||||||
|
*/
|
||||||
|
constexpr const char CKNEMOFI[] = "Nemo Fi";
|
||||||
/**
|
/**
|
||||||
* @brief Current Version of CK Engine (Day/Month/Year)
|
* @brief Current Version of CK Engine (Day/Month/Year)
|
||||||
*/
|
*/
|
||||||
constexpr const CKDWORD CKVERSION = 0x05082002u;
|
constexpr const CKDWORD CKVERSION = 0x13022002u;
|
||||||
/**
|
/**
|
||||||
* @brief Current Version of Dev
|
* @brief Current Version of Dev
|
||||||
*/
|
*/
|
||||||
constexpr const CKDWORD DEVVERSION = 0x02050000u;
|
constexpr const CKDWORD DEVVERSION = 0x02010001u;
|
||||||
|
constexpr const CKDWORD DEVBUILD = 0u;
|
||||||
constexpr const CKGUID VIRTOOLS_GUID = CKGUID(0x56495254u, 0x4f4f4c53u);
|
constexpr const CKGUID VIRTOOLS_GUID = CKGUID(0x56495254u, 0x4f4f4c53u);
|
||||||
|
|
||||||
// ========== Class registration utilities ==========
|
// ========== Class registration utilities ==========
|
||||||
|
|
|
@ -121,6 +121,7 @@ namespace LibCmo::CK2 {
|
||||||
ObjImpls::CKObject* ObjPtr; /**< A pointer to the object itself (as CreatedObject when loading) */
|
ObjImpls::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 */
|
||||||
|
CKDWORD PackSize; /**< The CKStateChunk data size */
|
||||||
//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 */
|
||||||
|
@ -233,11 +234,14 @@ namespace LibCmo::CK2 {
|
||||||
*/
|
*/
|
||||||
CKBOOL m_IsCopyFromReader;
|
CKBOOL m_IsCopyFromReader;
|
||||||
|
|
||||||
|
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<CKFileObject> m_FileObjects; /**< List of objects being saved / loaded */
|
||||||
XContainer::XArray<CKFileManagerData> m_ManagersData; /**< Manager Data loaded */
|
XContainer::XArray<CKFileManagerData> m_ManagersData; /**< Manager Data loaded */
|
||||||
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */
|
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */
|
||||||
XContainer::XArray<XContainer::XString> m_IncludedFiles; /**< List of files that should be inserted in the CMO file. */
|
XContainer::XArray<XContainer::XString> m_IncludedFiles; /**< List of files that should be inserted in the CMO file. */
|
||||||
CKFileInfo m_FileInfo; /**< Headers summary */
|
//CKFileInfo m_FileInfo; /**< Headers summary */
|
||||||
|
|
||||||
|
CKERROR PrepareFile(CKSTRING filename);
|
||||||
|
|
||||||
CKContext* m_Ctx;
|
CKContext* m_Ctx;
|
||||||
CKFileVisitor m_Visitor;
|
CKFileVisitor m_Visitor;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "CKFile.hpp"
|
#include "CKFile.hpp"
|
||||||
#include "CKStateChunk.hpp"
|
#include "CKStateChunk.hpp"
|
||||||
|
#include "ObjImpls/CKObject.hpp"
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
@ -13,12 +14,12 @@ namespace LibCmo::CK2 {
|
||||||
CKFileObject::CKFileObject() :
|
CKFileObject::CKFileObject() :
|
||||||
ObjectId(0u), CreatedObjectId(0u), ObjectCid(CK_CLASSID::CKCID_OBJECT),
|
ObjectId(0u), CreatedObjectId(0u), ObjectCid(CK_CLASSID::CKCID_OBJECT),
|
||||||
ObjPtr(nullptr), Name(), Data(nullptr), Options(CK_FO_OPTIONS::CK_FO_DEFAULT),
|
ObjPtr(nullptr), Name(), Data(nullptr), Options(CK_FO_OPTIONS::CK_FO_DEFAULT),
|
||||||
FileIndex(0u), SaveFlags(CK_STATESAVE_ALL) {}
|
FileIndex(0u), SaveFlags(CK_STATESAVE_ALL), PackSize(0u) {}
|
||||||
|
|
||||||
CKFileObject::CKFileObject(const CKFileObject& rhs) :
|
CKFileObject::CKFileObject(const CKFileObject& rhs) :
|
||||||
ObjectId(rhs.ObjectId), CreatedObjectId(rhs.CreatedObjectId), ObjectCid(rhs.ObjectCid),
|
ObjectId(rhs.ObjectId), CreatedObjectId(rhs.CreatedObjectId), ObjectCid(rhs.ObjectCid),
|
||||||
ObjPtr(rhs.ObjPtr), Name(rhs.Name), Data(rhs.Data), Options(rhs.Options),
|
ObjPtr(rhs.ObjPtr), Name(rhs.Name), Data(rhs.Data), Options(rhs.Options),
|
||||||
FileIndex(rhs.FileIndex), SaveFlags(rhs.SaveFlags) {
|
FileIndex(rhs.FileIndex), SaveFlags(rhs.SaveFlags), PackSize(rhs.PackSize) {
|
||||||
if (this->Data != nullptr) {
|
if (this->Data != nullptr) {
|
||||||
this->Data = new CKStateChunk(*(rhs.Data));
|
this->Data = new CKStateChunk(*(rhs.Data));
|
||||||
}
|
}
|
||||||
|
@ -27,7 +28,7 @@ namespace LibCmo::CK2 {
|
||||||
CKFileObject::CKFileObject(CKFileObject&& rhs) :
|
CKFileObject::CKFileObject(CKFileObject&& rhs) :
|
||||||
ObjectId(rhs.ObjectId), CreatedObjectId(rhs.CreatedObjectId), ObjectCid(rhs.ObjectCid),
|
ObjectId(rhs.ObjectId), CreatedObjectId(rhs.CreatedObjectId), ObjectCid(rhs.ObjectCid),
|
||||||
ObjPtr(rhs.ObjPtr), Name(rhs.Name), Data(rhs.Data), Options(rhs.Options),
|
ObjPtr(rhs.ObjPtr), Name(rhs.Name), Data(rhs.Data), Options(rhs.Options),
|
||||||
FileIndex(rhs.FileIndex), SaveFlags(rhs.SaveFlags) {
|
FileIndex(rhs.FileIndex), SaveFlags(rhs.SaveFlags), PackSize(rhs.PackSize) {
|
||||||
rhs.Data = nullptr;
|
rhs.Data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ namespace LibCmo::CK2 {
|
||||||
this->Data = new CKStateChunk(*(rhs.Data));
|
this->Data = new CKStateChunk(*(rhs.Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->PackSize = rhs.PackSize;
|
||||||
this->Options = rhs.Options;
|
this->Options = rhs.Options;
|
||||||
this->FileIndex = rhs.FileIndex;
|
this->FileIndex = rhs.FileIndex;
|
||||||
this->SaveFlags = rhs.SaveFlags;
|
this->SaveFlags = rhs.SaveFlags;
|
||||||
|
@ -59,7 +61,8 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
this->Data = rhs.Data;
|
this->Data = rhs.Data;
|
||||||
rhs.Data = nullptr;
|
rhs.Data = nullptr;
|
||||||
|
|
||||||
|
this->PackSize = rhs.PackSize;
|
||||||
this->Options = rhs.Options;
|
this->Options = rhs.Options;
|
||||||
this->FileIndex = rhs.FileIndex;
|
this->FileIndex = rhs.FileIndex;
|
||||||
this->SaveFlags = rhs.SaveFlags;
|
this->SaveFlags = rhs.SaveFlags;
|
||||||
|
@ -160,16 +163,19 @@ namespace LibCmo::CK2 {
|
||||||
CKFileWriter::CKFileWriter(CKContext* ctx) :
|
CKFileWriter::CKFileWriter(CKContext* ctx) :
|
||||||
m_Ctx(ctx), m_Visitor(this),
|
m_Ctx(ctx), m_Visitor(this),
|
||||||
m_Done(false), m_IsCopyFromReader(false),
|
m_Done(false), m_IsCopyFromReader(false),
|
||||||
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
|
m_SaveIDMax(0),
|
||||||
m_FileInfo()
|
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader) :
|
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader) :
|
||||||
m_Ctx(ctx), m_Visitor(this),
|
m_Ctx(ctx), m_Visitor(this),
|
||||||
m_Done(false), m_IsCopyFromReader(true),
|
m_Done(false), m_IsCopyFromReader(true),
|
||||||
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
|
m_SaveIDMax(0),
|
||||||
m_FileInfo()
|
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles()
|
||||||
{
|
{
|
||||||
|
// sync save id max
|
||||||
|
this->m_SaveIDMax = reader->GetSaveIdMax();
|
||||||
|
|
||||||
// copy objects
|
// copy objects
|
||||||
for (const auto& item : reader->GetFileObjects()) {
|
for (const auto& item : reader->GetFileObjects()) {
|
||||||
CKFileObject obj;
|
CKFileObject obj;
|
||||||
|
@ -182,8 +188,11 @@ namespace LibCmo::CK2 {
|
||||||
obj.Data = new CKStateChunk(*item.Data);
|
obj.Data = new CKStateChunk(*item.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy save flag
|
// copy other data
|
||||||
|
obj.ObjectId = item.ObjectId;
|
||||||
|
obj.ObjectCid = item.ObjectCid;
|
||||||
obj.SaveFlags = item.SaveFlags;
|
obj.SaveFlags = item.SaveFlags;
|
||||||
|
obj.Name = item.Name;
|
||||||
|
|
||||||
// insert
|
// insert
|
||||||
m_FileObjects.emplace_back(std::move(obj));
|
m_FileObjects.emplace_back(std::move(obj));
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CKERROR CKFileReader::ShallowLoad(CKSTRING u8_filename) {
|
CKERROR CKFileReader::ShallowLoad(CKSTRING u8_filename) {
|
||||||
// check document status
|
// check document status
|
||||||
if (this->m_Done) LIBPANIC("Can not load multiple times for single CKFileReader.")
|
if (this->m_Done) CKERROR::CKERR_CANCELLED;
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -46,7 +46,7 @@ namespace LibCmo::CK2 {
|
||||||
// ========== read header ==========
|
// ========== read header ==========
|
||||||
// check header size
|
// check header size
|
||||||
if (parser->GetSize() < sizeof(CKRawFileInfo)) return CKERROR::CKERR_INVALIDFILE;
|
if (parser->GetSize() < sizeof(CKRawFileInfo)) return CKERROR::CKERR_INVALIDFILE;
|
||||||
if (std::memcmp(parser->GetPtr(), "Nemo Fi", sizeof(CKRawFileInfo::NeMo))) return CKERROR::CKERR_INVALIDFILE;
|
if (std::memcmp(parser->GetPtr(), CKNEMOFI, sizeof(CKRawFileInfo::NeMo))) return CKERROR::CKERR_INVALIDFILE;
|
||||||
// read header
|
// read header
|
||||||
CKRawFileInfo rawHeader;
|
CKRawFileInfo rawHeader;
|
||||||
parser->Read(&rawHeader, sizeof(CKRawFileInfo));
|
parser->Read(&rawHeader, sizeof(CKRawFileInfo));
|
||||||
|
@ -168,7 +168,7 @@ namespace LibCmo::CK2 {
|
||||||
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
||||||
this->m_IncludedFiles.resize(includedFileCount);
|
this->m_IncludedFiles.resize(includedFileCount);
|
||||||
|
|
||||||
hasIncludedFile -= 4;
|
hasIncludedFile -= sizeof(CKDWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: backward pos
|
// MARK: backward pos
|
||||||
|
@ -263,13 +263,12 @@ namespace LibCmo::CK2 {
|
||||||
// only works file version >= 4. < 4 section has been removed.
|
// only works file version >= 4. < 4 section has been removed.
|
||||||
if (this->m_FileInfo.ObjectCount != 0) {
|
if (this->m_FileInfo.ObjectCount != 0) {
|
||||||
// new file reader section
|
// new file reader section
|
||||||
CKDWORD stateChunkLen = 0u;
|
|
||||||
bool stateChkParseSuccess = false;
|
bool stateChkParseSuccess = false;
|
||||||
for (auto& obj : this->m_FileObjects) {
|
for (auto& obj : this->m_FileObjects) {
|
||||||
// get statechunk len
|
// get statechunk len
|
||||||
parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
parser->Read(&obj.PackSize, sizeof(CKDWORD));
|
||||||
// check state chunk len
|
// check state chunk len
|
||||||
if (stateChunkLen == 0) {
|
if (obj.PackSize == 0) {
|
||||||
obj.Data = nullptr;
|
obj.Data = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -281,7 +280,7 @@ namespace LibCmo::CK2 {
|
||||||
delete obj.Data;
|
delete obj.Data;
|
||||||
obj.Data = nullptr;
|
obj.Data = nullptr;
|
||||||
}
|
}
|
||||||
parser->MoveCursor(stateChunkLen);
|
parser->MoveCursor(obj.PackSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,7 +310,7 @@ namespace LibCmo::CK2 {
|
||||||
parser->Read(&filebodylen, sizeof(CKDWORD));
|
parser->Read(&filebodylen, sizeof(CKDWORD));
|
||||||
|
|
||||||
// read file body
|
// read file body
|
||||||
FILE* fp = m_Ctx->OpenTempFile(file.c_str(), false);
|
FILE* fp = m_Ctx->OpenTempFile(file.c_str(), "wb");
|
||||||
if (fp != nullptr) {
|
if (fp != nullptr) {
|
||||||
StreamHelper::CopyStream(parser->GetPtr(), fp, filebodylen);
|
StreamHelper::CopyStream(parser->GetPtr(), fp, filebodylen);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@ -326,6 +325,9 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
CKERROR CKFileReader::DeepLoad(CKSTRING u8_filename) {
|
CKERROR CKFileReader::DeepLoad(CKSTRING u8_filename) {
|
||||||
|
// check document status
|
||||||
|
if (this->m_Done) CKERROR::CKERR_CANCELLED;
|
||||||
|
|
||||||
// ========== prepare work ==========
|
// ========== prepare work ==========
|
||||||
CKERROR err = CKERROR::CKERR_OK;
|
CKERROR err = CKERROR::CKERR_OK;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,212 @@
|
||||||
#include "CKFile.hpp"
|
#include "CKFile.hpp"
|
||||||
|
#include "CKContext.hpp"
|
||||||
|
#include "CKStateChunk.hpp"
|
||||||
|
#include "ObjImpls/CKObject.hpp"
|
||||||
|
#include "MgrImpls/CKBaseManager.hpp"
|
||||||
|
#include "../VxMath/VxMemoryMappedFile.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
CKERROR CKFileWriter::Save(CKSTRING u8_filename) {
|
CKERROR CKFileWriter::Save(CKSTRING u8_filename) {
|
||||||
return CKERROR::CKERR_OK;
|
// check document status
|
||||||
|
if (this->m_Done) CKERROR::CKERR_CANCELLED;
|
||||||
|
|
||||||
|
// try detect filename legality
|
||||||
|
CKERROR err = PrepareFile(u8_filename);
|
||||||
|
if (err != CKERROR::CKERR_OK) return err;
|
||||||
|
|
||||||
|
// ========== Prepare Stage ==========
|
||||||
|
// todo: add TOBEDELETED flag for all Referenced objects's m_ObjectFlags
|
||||||
|
|
||||||
|
// MARK: ignore the notification to all CKBehavior based objects.
|
||||||
|
|
||||||
|
// ========== StateChunk convertion ==========
|
||||||
|
|
||||||
|
// iterate all objects and transform it into CKStateChunk
|
||||||
|
// MARK: Drop the support of collecting the sum of InterfaceChunk's size.
|
||||||
|
// because it is useless.
|
||||||
|
for (auto& obj : m_FileObjects) {
|
||||||
|
// if there is a chunk, skip
|
||||||
|
if (obj.Data != nullptr) continue;
|
||||||
|
|
||||||
|
obj.Data = new CKStateChunk(&m_Visitor, m_Ctx);
|
||||||
|
obj.Data->StartWrite();
|
||||||
|
bool suc = obj.ObjPtr->Save(obj.Data, &m_Visitor, obj.SaveFlags);
|
||||||
|
obj.Data->StopWrite();
|
||||||
|
if (!suc) {
|
||||||
|
// fail to parse
|
||||||
|
delete obj.Data;
|
||||||
|
obj.Data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate manager
|
||||||
|
// if copied from reader. skip
|
||||||
|
if (!m_IsCopyFromReader) {
|
||||||
|
CKINT mgrcount = m_Ctx->GetManagerCount();
|
||||||
|
CKINT availablemgr = 0;
|
||||||
|
|
||||||
|
// place manager
|
||||||
|
// if no data, skip it
|
||||||
|
m_ManagersData.resize(mgrcount);
|
||||||
|
for (CKINT i = 0; i < mgrcount; ++i) {
|
||||||
|
MgrImpls::CKBaseManager* mgr = m_Ctx->GetManager(i);
|
||||||
|
|
||||||
|
m_ManagersData[availablemgr].Manager = mgr->GetGuid();
|
||||||
|
|
||||||
|
m_ManagersData[availablemgr].Data = new CKStateChunk(&m_Visitor, m_Ctx);
|
||||||
|
m_ManagersData[availablemgr].Data->StartWrite();
|
||||||
|
bool suc = mgr->SaveData(m_ManagersData[availablemgr].Data, &m_Visitor);
|
||||||
|
m_ManagersData[availablemgr].Data->StopWrite();
|
||||||
|
if (!suc) {
|
||||||
|
delete m_ManagersData[availablemgr].Data;
|
||||||
|
m_ManagersData[availablemgr].Data = nullptr;
|
||||||
|
} else {
|
||||||
|
++availablemgr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// resize to the new size which erase all skipped manager
|
||||||
|
m_ManagersData.resize(availablemgr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// if copied from reader, skip plugin dep
|
||||||
|
if (!m_IsCopyFromReader) {
|
||||||
|
// todo: finish plugin dep filling
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: skip include file filling.
|
||||||
|
// we order user manually fill it.
|
||||||
|
|
||||||
|
// ========== Size Calc ==========
|
||||||
|
// iterate 3 list to get each parts' size
|
||||||
|
CKDWORD sumDataObjSize = 0,
|
||||||
|
sumHdrObjSize = 0;
|
||||||
|
for (auto& obj : m_FileObjects) {
|
||||||
|
// += 4DWORD(ObjId, ObjCid, FileIndex, NameLen) + Name size
|
||||||
|
sumHdrObjSize += 4 * sizeof(CKDWORD) + obj.Name.size();
|
||||||
|
|
||||||
|
if (obj.Data == nullptr) {
|
||||||
|
obj.PackSize = 0;
|
||||||
|
} else {
|
||||||
|
obj.PackSize = obj.Data->ConvertToBuffer(nullptr);
|
||||||
|
}
|
||||||
|
// += chunk size + chunk
|
||||||
|
sumDataObjSize += obj.PackSize + sizeof(CKDWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
CKDWORD sumDataMgrSize = 0;
|
||||||
|
for (auto& mgr : m_ManagersData) {
|
||||||
|
CKDWORD chunksize;
|
||||||
|
if (mgr.Data == nullptr) {
|
||||||
|
chunksize = 0;
|
||||||
|
} else {
|
||||||
|
chunksize = mgr.Data->ConvertToBuffer(nullptr);
|
||||||
|
}
|
||||||
|
// += GUID(2 DWORD) + chunk size + chunk
|
||||||
|
sumDataMgrSize += chunksize + 3 * sizeof(CKDWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// += Plugin Dep list size
|
||||||
|
CKDWORD sumHdrPlgSize = sizeof(CKDWORD);
|
||||||
|
for (auto& plg : m_PluginsDep) {
|
||||||
|
// += GUID list + (dep category + GUID list size)
|
||||||
|
sumHdrPlgSize += sizeof(CKGUID) * plg.m_Guids.size() + 2 * sizeof(CKDWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
CKDWORD sumHdrIncludedFiles = sizeof(int32_t) + sizeof(CKDWORD);
|
||||||
|
|
||||||
|
// calc the whole size
|
||||||
|
CKDWORD sumHdrSize = sumHdrObjSize + sumHdrPlgSize + sumHdrIncludedFiles;
|
||||||
|
CKDWORD sumDataSize = sumDataObjSize + sumDataMgrSize;
|
||||||
|
|
||||||
|
// compute file index for all object
|
||||||
|
if (!m_FileObjects.empty()) {
|
||||||
|
// set base for first one
|
||||||
|
m_FileObjects[0].FileIndex = sumHdrSize + sumDataMgrSize + sizeof(CKRawFileInfo);
|
||||||
|
// calc the remains
|
||||||
|
for (size_t i = 1; i < m_FileObjects.size(); ++i) {
|
||||||
|
// prev obj PackSize + prev obj FileIndex + prev obj chunk size
|
||||||
|
m_FileObjects[i].FileIndex = m_FileObjects[i - 1].FileIndex + m_FileObjects[i - 1].PackSize + sizeof(CKDWORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Construct File Header ==========
|
||||||
|
CKRawFileInfo rawHeader;
|
||||||
|
std::memcpy(&rawHeader.NeMo, CKNEMOFI, sizeof(CKRawFileInfo::NeMo));
|
||||||
|
rawHeader.Crc = 0;
|
||||||
|
rawHeader.Zero = 0;
|
||||||
|
rawHeader.CKVersion = CKVERSION;
|
||||||
|
rawHeader.FileVersion = 8;
|
||||||
|
rawHeader.FileWriteMode = static_cast<CKDWORD>(m_Ctx->GetFileWriteMode());
|
||||||
|
rawHeader.ObjectCount = static_cast<CKDWORD>(m_FileObjects.size());
|
||||||
|
rawHeader.ManagerCount = static_cast<CKDWORD>(m_ManagersData.size());
|
||||||
|
rawHeader.Hdr1UnPackSize = sumHdrSize;
|
||||||
|
rawHeader.DataUnPackSize = sumDataSize;
|
||||||
|
rawHeader.Hdr1PackSize = sumHdrSize;
|
||||||
|
rawHeader.DataPackSize = sumDataSize;
|
||||||
|
rawHeader.ProductVersion = DEVVERSION;
|
||||||
|
rawHeader.ProductBuild = DEVBUILD;
|
||||||
|
rawHeader.MaxIDSaved = m_SaveIDMax;
|
||||||
|
// crc will filled later
|
||||||
|
|
||||||
|
// create a encoding conversion helper string
|
||||||
|
std::string name_conv;
|
||||||
|
|
||||||
|
// ========== Writing header ==========
|
||||||
|
// create a buffer
|
||||||
|
std::unique_ptr<CKBufferParser> hdrparser(new CKBufferParser(sumHdrSize));
|
||||||
|
|
||||||
|
// write obj
|
||||||
|
for (auto& obj : m_FileObjects) {
|
||||||
|
|
||||||
|
// todo: remove TOBEDELETED for referenced objects' m_ObjectFlags
|
||||||
|
|
||||||
|
hdrparser->Write(&obj.ObjectId, sizeof(CK_ID));
|
||||||
|
hdrparser->Write(&obj.ObjectCid, sizeof(CK_CLASSID));
|
||||||
|
hdrparser->Write(&obj.FileIndex, sizeof(CKDWORD));
|
||||||
|
|
||||||
|
if (obj.Name.c_str() != nullptr) {
|
||||||
|
m_Ctx->GetNativeString(obj.Name.string(), name_conv);
|
||||||
|
CKDWORD namelen = static_cast<CKDWORD>(name_conv.size());
|
||||||
|
hdrparser->Write(&namelen, sizeof(CKDWORD));
|
||||||
|
hdrparser->Write(name_conv.data(), namelen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write plugin dep
|
||||||
|
{
|
||||||
|
CKDWORD depsize = static_cast<CKDWORD>(m_PluginsDep.size());
|
||||||
|
hdrparser->Write(&depsize, sizeof(CKDWORD));
|
||||||
|
|
||||||
|
for (auto& dep : m_PluginsDep) {
|
||||||
|
hdrparser->Write(&dep.m_PluginCategory, sizeof(CK_PLUGIN_TYPE));
|
||||||
|
|
||||||
|
CKDWORD guidsize = static_cast<CKDWORD>(dep.m_Guids.size());
|
||||||
|
hdrparser->Write(&guidsize, sizeof(CKDWORD));
|
||||||
|
|
||||||
|
hdrparser->Write(dep.m_Guids.data(), sizeof(CKGUID) * guidsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CKERROR CKFileWriter::PrepareFile(CKSTRING filename) {
|
||||||
|
// check nullptr
|
||||||
|
if (filename == nullptr) return CKERROR::CKERR_INVALIDFILE;
|
||||||
|
|
||||||
|
// try open file to check whether we can write it.
|
||||||
|
CKERROR err;
|
||||||
|
FILE* tryfile = m_Ctx->OpenFile(filename, "ab");
|
||||||
|
if (tryfile == nullptr) {
|
||||||
|
err = CKERROR::CKERR_CANTWRITETOFILE;
|
||||||
|
} else {
|
||||||
|
err = CKERROR::CKERR_OK;
|
||||||
|
std::fclose(tryfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -46,10 +46,12 @@ namespace LibCmo::CK2 {
|
||||||
CKDWORD CKComputeDataCRC(const void* data, CKINT size, CKDWORD PreviousCRC = 0);
|
CKDWORD CKComputeDataCRC(const void* data, CKINT size, CKDWORD PreviousCRC = 0);
|
||||||
|
|
||||||
// ========== CKClass Registration ==========
|
// ========== CKClass Registration ==========
|
||||||
|
|
||||||
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
|
||||||
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
|
||||||
|
|
||||||
// ========== Class Hierarchy Management ==========
|
// ========== Class Hierarchy Management ==========
|
||||||
|
|
||||||
CKINT CKGetClassCount();
|
CKINT CKGetClassCount();
|
||||||
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
||||||
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
||||||
|
|
|
@ -69,8 +69,8 @@ namespace LibCmo::CK2::MgrImpls {
|
||||||
data for your manager.
|
data for your manager.
|
||||||
@see CKStateChunk, LoadData
|
@see CKStateChunk, LoadData
|
||||||
*/
|
*/
|
||||||
virtual CKStateChunk* SaveData(CKFileVisitor* SavedFile) {
|
virtual bool SaveData(CKStateChunk* chunk, CKFileVisitor* SavedFile) {
|
||||||
return nullptr;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@brief Called to load manager data.
|
@brief Called to load manager data.
|
||||||
|
|
|
@ -6,8 +6,8 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
void CKObject::PreSave(CKFileVisitor* file, CKDWORD flags) {}
|
void CKObject::PreSave(CKFileVisitor* file, CKDWORD flags) {}
|
||||||
|
|
||||||
CKStateChunk* CKObject::Save(CKFileVisitor* file, CKDWORD flags) {
|
bool CKObject::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {
|
||||||
return nullptr;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKObject::Load(CKStateChunk* chunk, CKFileVisitor* file) {
|
bool CKObject::Load(CKStateChunk* chunk, CKFileVisitor* file) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void PreSave(CKFileVisitor* file, CKDWORD flags);
|
virtual void PreSave(CKFileVisitor* file, CKDWORD flags);
|
||||||
virtual CKStateChunk* Save(CKFileVisitor* file, CKDWORD flags);
|
virtual bool Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags);
|
||||||
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file);
|
virtual bool Load(CKStateChunk* chunk, CKFileVisitor* file);
|
||||||
virtual void PostLoad();
|
virtual void PostLoad();
|
||||||
|
|
||||||
|
|
|
@ -187,9 +187,15 @@ namespace LibCmo::EncodingHelper {
|
||||||
stdpath = u8_path;
|
stdpath = u8_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read) {
|
FILE* StdPathFOpen(std::filesystem::path& std_filepath, const char* u8_mode) {
|
||||||
return _wfopen(u8_filepath.wstring().c_str(), is_read ? L"rb" : L"wb");
|
std::wstring wmode;
|
||||||
|
if (CharToWchar(u8_mode, wmode, CP_UTF8)) {
|
||||||
|
return _wfopen(std_filepath.wstring().c_str(), wmode.c_str());
|
||||||
|
} else {
|
||||||
|
// fallback
|
||||||
|
return std::fopen(std_filepath.string().c_str(), u8_mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -237,8 +243,8 @@ namespace LibCmo::EncodingHelper {
|
||||||
stdpath = u8_path;
|
stdpath = u8_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read) {
|
FILE* StdPathFOpen(std::filesystem::path& std_filepath, const char* u8_mode) {
|
||||||
return fopen(u8_filepath.string().c_str(), is_read ? "rb" : "wb");
|
return std::fopen(u8_filepath.string().c_str(), u8_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace LibCmo::EncodingHelper {
|
||||||
bool GetNativeVirtoolsName(const std::string& u8_name, std::string& native_name, const ENCODING_TOKEN& token);
|
bool GetNativeVirtoolsName(const std::string& u8_name, std::string& native_name, const ENCODING_TOKEN& token);
|
||||||
|
|
||||||
void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path);
|
void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path);
|
||||||
FILE* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read);
|
FILE* StdPathFOpen(std::filesystem::path& std_filepath, const char* u8_mode);
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,9 @@ namespace LibCmo {
|
||||||
const char* c_str() const {
|
const char* c_str() const {
|
||||||
return m_HasStr ? m_Str.c_str() : nullptr;
|
return m_HasStr ? m_Str.c_str() : nullptr;
|
||||||
}
|
}
|
||||||
|
const std::string& string() const {
|
||||||
|
return m_Str;
|
||||||
|
}
|
||||||
const size_t size() const {
|
const size_t size() const {
|
||||||
return m_HasStr ? m_Str.size() : 0u;
|
return m_HasStr ? m_Str.size() : 0u;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user