fully remove dassault garbage code

This commit is contained in:
yyc12345 2023-02-25 22:58:28 +08:00
parent d32ed302d1
commit bf7c669ce6
15 changed files with 505 additions and 147 deletions

View File

@ -3,25 +3,6 @@
namespace LibCmo { namespace LibCmo {
#pragma region CKMinContext
CKMinContext::CKMinContext() {
}
CKMinContext::~CKMinContext() {
}
void CKMinContext::Printf(CKSTRING fmt, ...) {
va_list argptr;
va_start(argptr, fmt);
vfprintf(stdout, fmt, argptr);
va_end(argptr);
}
#pragma endregion
#pragma region CKBufferParser #pragma region CKBufferParser
CKBufferParser::CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) : CKBufferParser::CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) :
@ -36,6 +17,16 @@ namespace LibCmo {
#pragma endregion #pragma endregion
#pragma region CKFileInfo
CKFileInfo::CKFileInfo() {
}
CKFileInfo::~CKFileInfo() {
}
#pragma endregion
#pragma region CKFileObject #pragma region CKFileObject
LibCmo::CKFileObject::CKFileObject() : LibCmo::CKFileObject::CKFileObject() :
@ -49,6 +40,25 @@ namespace LibCmo {
#pragma endregion #pragma endregion
#pragma region CKFileManagerData
CKFileManagerData::CKFileManagerData() {
}
CKFileManagerData::~CKFileManagerData() {
}
#pragma endregion
#pragma region CKFilePluginDependencies
CKFilePluginDependencies::CKFilePluginDependencies() {
}
CKFilePluginDependencies::~CKFilePluginDependencies() {
}
#pragma endregion
#pragma region ShallowDocument #pragma region ShallowDocument
@ -74,12 +84,10 @@ namespace LibCmo {
#pragma endregion #pragma endregion
#pragma region CKFile Misc #pragma region CKFile Misc
CKFile::CKFile(CKMinContext* ctx) : CKFile::CKFile(CKMinContext* ctx) :
m_MappedFile(nullptr), m_FileName(), m_FileName(), m_MinCtx(ctx) {
m_MinCtx(ctx) {
; ;
} }
@ -87,7 +95,6 @@ namespace LibCmo {
} }
#pragma endregion #pragma endregion

View File

@ -5,25 +5,10 @@
#include "VxMemoryMappedFile.hpp" #include "VxMemoryMappedFile.hpp"
#include "CKStateChunk.hpp" #include "CKStateChunk.hpp"
#include "VTObjects.hpp" #include "CKMinContext.hpp"
namespace LibCmo { namespace LibCmo {
class CKMinContext {
public:
CKMinContext();
CKMinContext(const CKMinContext&) = delete;
CKMinContext& operator=(const CKMinContext&) = delete;
~CKMinContext();
void Printf(CKSTRING fmt, ...);
private:
std::string NameEncoding;
std::string TempFolder;
};
class CKBufferParser { class CKBufferParser {
private: private:
char* m_MemBegin; char* m_MemBegin;
@ -103,16 +88,14 @@ namespace LibCmo {
class CKFileObject { class CKFileObject {
public: public:
CKFileObject(); CKFileObject();
CKFileObject(const CKFileObject&) = delete; //CKFileObject(const CKFileObject&) = delete;
CKFileObject& operator=(const CKFileObject&) = delete; //CKFileObject& operator=(const CKFileObject&) = delete;
~CKFileObject(); ~CKFileObject();
CK_ID ObjectId; CK_ID ObjectId;
CK_CLASSID ObjectCid; CK_CLASSID ObjectCid;
std::string Name; std::string Name;
CKStateChunk* Data; CKStateChunk* Data;
CKDWORD PostPackSize;
CKDWORD PrePackSize;
CKDWORD FileIndex; CKDWORD FileIndex;
private: private:
@ -121,8 +104,8 @@ namespace LibCmo {
class CKFileManagerData { class CKFileManagerData {
public: public:
CKFileManagerData(); CKFileManagerData();
CKFileManagerData(const CKFileManagerData&) = delete; //CKFileManagerData(const CKFileManagerData&) = delete;
CKFileManagerData& operator=(const CKFileManagerData&) = delete; //CKFileManagerData& operator=(const CKFileManagerData&) = delete;
~CKFileManagerData(); ~CKFileManagerData();
CKStateChunk* Data; CKStateChunk* Data;
@ -134,8 +117,8 @@ namespace LibCmo {
class CKFilePluginDependencies { class CKFilePluginDependencies {
public: public:
CKFilePluginDependencies(); CKFilePluginDependencies();
CKFilePluginDependencies(const CKFilePluginDependencies&) = delete; //CKFilePluginDependencies(const CKFilePluginDependencies&) = delete;
CKFilePluginDependencies& operator=(const CKFilePluginDependencies&) = delete; //CKFilePluginDependencies& operator=(const CKFilePluginDependencies&) = delete;
~CKFilePluginDependencies(); ~CKFilePluginDependencies();
CK_PLUGIN_TYPE m_PluginCategory; CK_PLUGIN_TYPE m_PluginCategory;
@ -239,19 +222,13 @@ namespace LibCmo {
private: private:
// reader function and variables // reader function and variables
CKERROR PrepareLoad(CKSTRING u8_filename); CKERROR ReadFileHeader(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc);
CKERROR ReadFileHeader(CKBufferParser* ParserPtr); CKERROR ReadFileData(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc);
CKERROR ReadFileData(CKBufferParser* ParserPtr);
CKFileData::ShallowDocument* m_ShallowDoc;
CKFileData::DeepDocument* m_DeepDoc;
// writer function and varibales // writer function and varibales
// shared function and variables // shared function and variables
std::string m_FileName; std::string m_FileName;
VxMemoryMappedFile* m_MappedFile;
CKMinContext* m_MinCtx; CKMinContext* m_MinCtx;
}; };

View File

@ -11,47 +11,45 @@ namespace LibCmo {
* No need to support them. * No need to support them.
*/ */
CKERROR CKFile::PrepareLoad(CKSTRING u8_filename) { CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc) {
// assign file name // preset value
this->m_FileName = u8_filename; *out_doc = nullptr;
// create mapped file
this->m_MappedFile = new(std::nothrow) VxMemoryMappedFile(this->m_FileName.c_str()); // check file and open memory
if (this->m_MappedFile == nullptr) { if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
std::unique_ptr<VxMemoryMappedFile> mappedFile(new(std::nothrow) VxMemoryMappedFile(u8_filename));
if (mappedFile == nullptr) {
this->m_MinCtx->Printf("Out of memory when creating Memory File."); this->m_MinCtx->Printf("Out of memory when creating Memory File.");
return CKERROR::CKERR_OUTOFMEMORY; return CKERROR::CKERR_OUTOFMEMORY;
} }
if (!this->m_MappedFile->IsValid()) { if (!mappedFile->IsValid()) {
this->m_MinCtx->Printf("Fail to create Memory File for \"%s\".", this->m_FileName.c_str()); this->m_MinCtx->Printf("Fail to create Memory File for \"%s\".", this->m_FileName.c_str());
return CKERROR::CKERR_INVALIDFILE; return CKERROR::CKERR_INVALIDFILE;
} }
return CKERROR::CKERR_OK;
}
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc) {
// check file and open memory
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
CKERROR err = PrepareLoad(u8_filename);
if (err != CKERROR::CKERR_OK) return err;
// create document // create document
this->m_ShallowDoc = new(std::nothrow) CKFileData::ShallowDocument(); std::unique_ptr<CKFileData::ShallowDocument> doc(new(std::nothrow) CKFileData::ShallowDocument());
if (this->m_ShallowDoc == nullptr) return CKERROR::CKERR_OUTOFMEMORY; if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
// create buffer and start loading // create buffer and start loading
CKBufferParser parser(this->m_MappedFile->GetBase(), this->m_MappedFile->GetFileSize(), false); std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
err = this->ReadFileHeader(&parser); CKERROR err = this->ReadFileHeader(parser.get(), doc.get());
if (err != CKERROR::CKERR_OK) return err; if (err != CKERROR::CKERR_OK) return err;
err = this->ReadFileData(&parser); err = this->ReadFileData(parser.get(), doc.get());
if (err != CKERROR::CKERR_OK) return err; if (err != CKERROR::CKERR_OK) return err;
// free all data // unbind document and assign it
this->ClearData(); *out_doc = doc.release();
// other data will be free automatically
return CKERROR::CKERR_OK; return CKERROR::CKERR_OK;
} }
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr) { CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc) {
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;
parser->SetCursor(ParserPtr->GetCursor());
std::string name_conv;
// ========== read header ========== // ========== read header ==========
// check header size // check header size
@ -73,23 +71,23 @@ namespace LibCmo {
} }
// ========== assign value ========== // ========== assign value ==========
this->m_ShallowDoc->m_FileInfo.ProductVersion = rawHeader.ProductVersion; doc->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
this->m_ShallowDoc->m_FileInfo.ProductBuild = rawHeader.ProductBuild; doc->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
this->m_ShallowDoc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode); doc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
this->m_ShallowDoc->m_FileInfo.CKVersion = rawHeader.CKVersion; doc->m_FileInfo.CKVersion = rawHeader.CKVersion;
this->m_ShallowDoc->m_FileInfo.FileVersion = rawHeader.FileVersion; doc->m_FileInfo.FileVersion = rawHeader.FileVersion;
this->m_ShallowDoc->m_FileInfo.FileSize = parser->GetSize(); doc->m_FileInfo.FileSize = parser->GetSize();
this->m_ShallowDoc->m_FileInfo.ManagerCount = rawHeader.ManagerCount; doc->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
this->m_ShallowDoc->m_FileInfo.ObjectCount = rawHeader.ObjectCount; doc->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
this->m_ShallowDoc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved; doc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
this->m_ShallowDoc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u; doc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u; doc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
this->m_ShallowDoc->m_FileInfo.DataPackSize = rawHeader.DataPackSize; doc->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
this->m_ShallowDoc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize; doc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
this->m_ShallowDoc->m_FileInfo.Crc = rawHeader.Crc; doc->m_FileInfo.Crc = rawHeader.Crc;
// ========== crc and body unpacker ========== // ========== crc and body unpacker ==========
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) { if (doc->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;
@ -97,19 +95,22 @@ namespace LibCmo {
// 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(), this->m_ShallowDoc->m_FileInfo.Hdr1PackSize, gotten_crc); gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize, gotten_crc);
parser->MoveCursor(this->m_ShallowDoc->m_FileInfo.Hdr1PackSize); parser->MoveCursor(doc->m_FileInfo.Hdr1PackSize);
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.DataPackSize, gotten_crc); gotten_crc = CKComputeDataCRC(parser->GetPtr(), doc->m_FileInfo.DataPackSize, gotten_crc);
if (gotten_crc != this->m_ShallowDoc->m_FileInfo.Crc) return CKERROR::CKERR_FILECRCERROR; if (gotten_crc != doc->m_FileInfo.Crc) {
this->m_MinCtx->Printf("Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR;
}
// reset cursor // reset cursor
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(this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.Hdr1PackSize); void* decomp_buffer = CKUnPackData(doc->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), doc->m_FileInfo.Hdr1PackSize);
if (decomp_buffer != nullptr) { if (decomp_buffer != nullptr) {
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize, true)); parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, doc->m_FileInfo.Hdr1UnPackSize, true));
if (parser == nullptr) { if (parser == nullptr) {
delete[] decomp_buffer; delete[] decomp_buffer;
return CKERROR::CKERR_OUTOFMEMORY; return CKERROR::CKERR_OUTOFMEMORY;
@ -119,14 +120,14 @@ namespace LibCmo {
// ========== object list read ========== // ========== object list read ==========
// file ver >= 7 have this features // file ver >= 7 have this features
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 7) { {
// apply max id saved // apply max id saved
this->m_ShallowDoc->m_SaveIDMax = this->m_ShallowDoc->m_FileInfo.MaxIDSaved; doc->m_SaveIDMax = doc->m_FileInfo.MaxIDSaved;
// resize // resize
this->m_ShallowDoc->m_FileObjects.resize(this->m_ShallowDoc->m_FileInfo.ObjectCount); doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
// read data // read data
for (auto& fileobj : this->m_ShallowDoc->m_FileObjects) { for (auto& fileobj : doc->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));
@ -135,8 +136,9 @@ namespace LibCmo {
CKDWORD namelen; CKDWORD namelen;
parser->Read(&namelen, sizeof(CKDWORD)); parser->Read(&namelen, sizeof(CKDWORD));
if (namelen != 0) { if (namelen != 0) {
fileobj.Name.resize(namelen); name_conv.resize(namelen);
parser->Read(fileobj.Name.data(), namelen); parser->Read(name_conv.data(), namelen);
m_MinCtx->GetUtf8ObjectName(name_conv, fileobj.Name);
} }
} }
} }
@ -144,14 +146,14 @@ namespace LibCmo {
// ========== dep list read ========== // ========== dep list read ==========
// file ver >= 8 have this feature // file ver >= 8 have this feature
bool noDepLost = true; bool noDepLost = true;
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) { if (doc->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));
this->m_ShallowDoc->m_PluginDep.resize(depSize); doc->m_PluginDep.resize(depSize);
CKDWORD guid_size; CKDWORD guid_size;
for (auto& dep : this->m_ShallowDoc->m_PluginDep) { for (auto& dep : doc->m_PluginDep) {
// 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
@ -167,7 +169,7 @@ namespace LibCmo {
// ========== included file list read ========== // ========== included file list read ==========
// file ver >= 8 have this feature // file ver >= 8 have this feature
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) { if (doc->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));
@ -176,20 +178,173 @@ namespace LibCmo {
// 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));
this->m_ShallowDoc->m_IncludedFiles.resize(includedFileCount); doc->m_IncludedFiles.resize(includedFileCount);
hasIncludedFile -= 4; hasIncludedFile -= 4;
} }
// backward pos // MARK: backward pos
parser->SetCursor(hasIncludedFile); // backward with 0?
parser->MoveCursor(hasIncludedFile);
}
// ========== sync main parser ==========
if (doc->m_FileInfo.FileVersion >= 8) {
// file ver >= 8, use header offset
// because it have compress feature
ParserPtr->SetCursor(doc->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
} else {
// otherwise, sync with current parser.
ParserPtr->SetCursor(parser->GetCursor());
} }
return CKERROR::CKERR_OK; return CKERROR::CKERR_OK;
} }
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr) { CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc) {
return CKERROR(); 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());
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)) {
void* decomp_buffer = CKUnPackData(doc->m_FileInfo.DataUnPackSize, parser->GetPtr(), doc->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[] decomp_buffer;
return CKERROR::CKERR_OUTOFMEMORY;
}
}
}
// ========== old file crc and obj list read ==========
// only file ver < 8 run this
if (doc->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.");
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));
// 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);
}
}
// ========== manager read ==========
// only file ver >= 6 have this
if (doc->m_FileInfo.ManagerCount != 0) {
doc->m_FileManagersData.resize(doc->m_FileInfo.ManagerCount);
CKDWORD stateChunkLen = 0u;
bool stateChkParseSuccess = false;
for (auto& mgr : doc->m_FileManagersData) {
// read guid
parser->Read(&(mgr.Manager), sizeof(CKGUID));
// read statechunk len
parser->Read(&stateChunkLen, sizeof(CKDWORD));
// check len
if (stateChunkLen == 0) {
mgr.Data = nullptr;
continue;
}
// read statechunk
mgr.Data = new(std::nothrow) CKStateChunk();
if (mgr.Data != nullptr) {
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) {
// new file reader section
CKDWORD stateChunkLen = 0u;
bool stateChkParseSuccess = false;
for (auto& obj : doc->m_FileObjects) {
// get statechunk len
parser->Read(&stateChunkLen, sizeof(CKDWORD));
// check state chunk len
if (stateChunkLen == 0) {
obj.Data = nullptr;
continue;
}
// read state chunk
obj.Data = new(std::nothrow) CKStateChunk();
if (obj.Data != nullptr) {
stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
if (!stateChkParseSuccess) {
delete obj.Data;
obj.Data = nullptr;
}
}
parser->MoveCursor(stateChunkLen);
}
}
// ========== included file get ==========
// 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);
// then we can read it.
if (doc->m_IncludedFiles.size() != 0) {
for (auto& file : doc->m_IncludedFiles) {
// get file name length and resize it
CKDWORD filenamelen = 0u;
parser->Read(&filenamelen, sizeof(CKDWORD));
name_conv.resize(filenamelen);
// read filename
if (filenamelen != 0) {
parser->Read(name_conv.data(), filenamelen);
m_MinCtx->GetUtf8ObjectName(name_conv, file);
}
// read file body length
CKDWORD filebodylen = 0u;
parser->Read(&filebodylen, sizeof(CKDWORD));
// read file body
FILE* fp = m_MinCtx->OpenTempFile(file.c_str(), false);
if (fp != nullptr) {
Utils::CopyStream(parser->GetPtr(), fp, filebodylen);
fclose(fp);
}
// move to next
parser->MoveCursor(filebodylen);
}
}
return CKERROR::CKERR_OK;
} }
//CKERROR CKFile::Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags) { //CKERROR CKFile::Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags) {

63
LibCmo/CKMinContext.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "VTUtils.hpp"
#include "CKMinContext.hpp"
namespace LibCmo {
#if defined(LIBCMO_OS_WIN32)
static wchar_t g_UniqueFolder[] = L"LibCmo";
#else
static char g_UniqueFolder[] = "LibCmo";
#endif
CKMinContext::CKMinContext() :
NameEncoding(), NameEncodingToken(Encoding::ENCODING_TOKEN_DEFAULT),
TempFolder()
{
// preset for temp folder
TempFolder = std::filesystem::temp_directory_path();
TempFolder /= g_UniqueFolder;
std::filesystem::create_directory(TempFolder);
}
CKMinContext::~CKMinContext() {
}
void CKMinContext::Printf(CKSTRING fmt, ...) {
va_list argptr;
va_start(argptr, fmt);
vfprintf(stdout, fmt, argptr);
va_end(argptr);
}
void CKMinContext::GetUtf8ObjectName(std::string& native_name, std::string& u8_name) {
Encoding::GetUtf8VirtoolsName(native_name, u8_name, this->NameEncodingToken);
}
void CKMinContext::GetNativeObjectName(std::string& u8_name, std::string& native_name) {
Encoding::GetNativeVirtoolsName(u8_name, native_name, this->NameEncodingToken);
}
void CKMinContext::SetEncoding(CKSTRING encoding) {
this->NameEncoding = encoding;
this->RefetchEncodingToken();
}
void CKMinContext::SetTempPath(CKSTRING u8_temp) {
Encoding::SetStdPathFromU8Path(this->TempFolder, u8_temp);
}
FILE* CKMinContext::OpenTempFile(CKSTRING u8_filename, bool is_read) {
std::filesystem::path stdfilename;
Encoding::SetStdPathFromU8Path(stdfilename, u8_filename);
auto realfile = this->TempFolder / stdfilename;
return Encoding::OpenStdPathFile(realfile, is_read);
}
void CKMinContext::RefetchEncodingToken(void) {
Encoding::DestroyEncodingToken(this->NameEncodingToken);
this->NameEncodingToken = Encoding::CreateEncodingToken(this->NameEncoding);
}
}

41
LibCmo/CKMinContext.hpp Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include "CKDefines.hpp"
#include "CKEnums.hpp"
#include "VTEncoding.hpp"
#include <filesystem>
namespace LibCmo {
// forward decl to rm recursive reference
namespace ObjsImpl { class CKObject; }
class CKMinContext {
public:
CKMinContext();
CKMinContext(const CKMinContext&) = delete;
CKMinContext& operator=(const CKMinContext&) = delete;
~CKMinContext();
void Printf(CKSTRING fmt, ...);
ObjsImpl::CKObject* CreateObject(CK_ID id, CKSTRING name);
void DestroyObject(ObjsImpl::CKObject* obj);
void GetUtf8ObjectName(std::string& native_name, std::string& u8_name);
void GetNativeObjectName(std::string& u8_name, std::string& native_name);
void SetEncoding(CKSTRING encoding);
void SetTempPath(CKSTRING u8_temp);
FILE* OpenTempFile(CKSTRING u8_filename, bool is_read);
private:
void RefetchEncodingToken(void);
std::string NameEncoding;
Encoding::ENCODING_TOKEN NameEncodingToken;
std::filesystem::path TempFolder;
};
}

View File

@ -174,10 +174,12 @@
<ClCompile Include="CKFile.cpp" /> <ClCompile Include="CKFile.cpp" />
<ClCompile Include="CKFileWriter.cpp" /> <ClCompile Include="CKFileWriter.cpp" />
<ClCompile Include="CKGlobals.cpp" /> <ClCompile Include="CKGlobals.cpp" />
<ClCompile Include="CKMinContext.cpp" />
<ClCompile Include="ObjsImpl\CKObject.cpp" /> <ClCompile Include="ObjsImpl\CKObject.cpp" />
<ClCompile Include="VTEncoding.cpp" /> <ClCompile Include="VTEncoding.cpp" />
<ClCompile Include="CKFileReader.cpp" /> <ClCompile Include="CKFileReader.cpp" />
<ClCompile Include="CKStateChunk.cpp" /> <ClCompile Include="CKStateChunk.cpp" />
<ClCompile Include="VTUtils.cpp" />
<ClCompile Include="VxMemoryMappedFile.cpp" /> <ClCompile Include="VxMemoryMappedFile.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -185,6 +187,7 @@
<ClInclude Include="CKEnums.hpp" /> <ClInclude Include="CKEnums.hpp" />
<ClInclude Include="CKFile.hpp" /> <ClInclude Include="CKFile.hpp" />
<ClInclude Include="CKGlobals.hpp" /> <ClInclude Include="CKGlobals.hpp" />
<ClInclude Include="CKMinContext.hpp" />
<ClInclude Include="CKStateChunk.hpp" /> <ClInclude Include="CKStateChunk.hpp" />
<ClInclude Include="VTEncoding.hpp" /> <ClInclude Include="VTEncoding.hpp" />
<ClInclude Include="VTObjects.hpp" /> <ClInclude Include="VTObjects.hpp" />

View File

@ -42,6 +42,12 @@
<ClCompile Include="CKFile.cpp"> <ClCompile Include="CKFile.cpp">
<Filter>Sources</Filter> <Filter>Sources</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="CKMinContext.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="VTUtils.cpp">
<Filter>Sources</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="VTUtils.hpp"> <ClInclude Include="VTUtils.hpp">
@ -71,5 +77,8 @@
<ClInclude Include="VxMemoryMappedFile.hpp"> <ClInclude Include="VxMemoryMappedFile.hpp">
<Filter>Headers</Filter> <Filter>Headers</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="CKMinContext.hpp">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -60,6 +60,16 @@ namespace LibCmo {
return CharToWchar(src.c_str(), dest, codepage); return CharToWchar(src.c_str(), dest, codepage);
} }
bool CharToChar(const char* src, std::string& dest, UINT src_codepage, UINT dest_codepage) {
std::wstring intermediary;
if (!CharToWchar(src, intermediary, src_codepage)) return false;
if (!WcharToChar(intermediary, dest, dest_codepage)) return false;
return true;
}
bool CharToChar(std::string& src, std::string& dest, UINT src_codepage, UINT dest_codepage) {
return CharToChar(src.c_str(), dest, src_codepage, dest_codepage);
}
#else #else
//todo: linux implementation //todo: linux implementation
@ -72,34 +82,65 @@ namespace LibCmo {
#if defined(LIBCMO_OS_WIN32) #if defined(LIBCMO_OS_WIN32)
void GetUtf8VirtoolsName(std::string& native_name, std::string& u8_name, const char* u8_encoding_spec) { const ENCODING_TOKEN ENCODING_TOKEN_DEFAULT = nullptr;
// switch encoding spec
UINT codepage = CP_ACP; ENCODING_TOKEN CreateEncodingToken(std::string& token_string) {
if (!GetWindowsCodePage(u8_encoding_spec, &codepage)) { ENCODING_TOKEN token = new(std::nothrow) UINT();
if (token == nullptr) return ENCODING_TOKEN_DEFAULT;
if (!GetWindowsCodePage(token_string.c_str(), token)) {
*token = CP_ACP;
}
return token;
}
void DestroyEncodingToken(ENCODING_TOKEN token) {
if (token != ENCODING_TOKEN_DEFAULT) {
delete token;
}
}
void GetUtf8VirtoolsName(std::string& native_name, std::string& u8_name, ENCODING_TOKEN token) {
if (token == ENCODING_TOKEN_DEFAULT) {
u8_name = native_name.c_str(); u8_name = native_name.c_str();
return; return;
} }
// do convert // convert with fallback
if (!CharToChar(native_name, u8_name, *token, CP_UTF8)) {
u8_name = native_name.c_str();
}
}
void GetNativeVirtoolsName(std::string& u8_name, std::string& native_name, ENCODING_TOKEN token) {
if (token == ENCODING_TOKEN_DEFAULT) {
native_name = u8_name.c_str();
return;
}
// convert with fallback
if (!CharToChar(u8_name, native_name, CP_UTF8, *token)) {
native_name = u8_name.c_str();
}
}
void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path) {
std::wstring intermediary; std::wstring intermediary;
if (!CharToWchar(native_name, intermediary, codepage)) { if (CharToWchar(u8_path, intermediary, CP_UTF8)) {
u8_name = native_name.c_str(); stdpath = intermediary.c_str();
return; } else {
// fallback
stdpath = u8_path;
} }
if (!WcharToChar(intermediary, u8_name, CP_UTF8)) {
u8_name = native_name.c_str();
return;
} }
return; FILE* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read) {
} return _wfopen(u8_filepath.wstring().c_str(), is_read ? L"rb" : L"wb");
void GetWcharStdin(std::string& u8_input, std::wstring& wc_input) {
// just redirect to prev func
CharToWchar(u8_input, wc_input, CP_UTF8);
} }
#else #else
const ENCODING_TOKEN ENCODING_TOKEN_DEFAULT = nullptr;
//todo: linux implementation //todo: linux implementation
#endif #endif

View File

@ -2,6 +2,7 @@
#include "VTUtils.hpp" #include "VTUtils.hpp"
#include <string> #include <string>
#include <filesystem>
#if defined(LIBCMO_OS_WIN32) #if defined(LIBCMO_OS_WIN32)
#include <Windows.h> #include <Windows.h>
@ -25,6 +26,9 @@ namespace LibCmo {
bool CharToWchar(const char* src, std::wstring& dest, UINT codepage); bool CharToWchar(const char* src, std::wstring& dest, UINT codepage);
bool CharToWchar(std::string& src, std::wstring& dest, UINT codepage); bool CharToWchar(std::string& src, std::wstring& dest, UINT codepage);
bool CharToChar(const char* src, std::string& dest, UINT src_codepage, UINT dest_codepage);
bool CharToChar(std::string& src, std::string& dest, UINT src_codepage, UINT dest_codepage);
#else #else
#error NO IMPLEMENTATION FOR LINUX ENCODING! #error NO IMPLEMENTATION FOR LINUX ENCODING!
#endif #endif
@ -35,9 +39,31 @@ namespace LibCmo {
#if defined(LIBCMO_OS_WIN32) #if defined(LIBCMO_OS_WIN32)
void GetUtf8VirtoolsName(std::string& native_name, std::string& u8_name, const char* u8_encoding_spec); /// <summary>
/// Token is the ticket for using encoding functions.
/// It should be created by "GenerateEncodingToken" and free by "DestroyEncodingToken".
/// </summary>
using ENCODING_TOKEN = UINT*;
extern const ENCODING_TOKEN ENCODING_TOKEN_DEFAULT;
ENCODING_TOKEN CreateEncodingToken(std::string& token_string);
void DestroyEncodingToken(ENCODING_TOKEN token);
void GetUtf8VirtoolsName(std::string& native_name, std::string& u8_name, ENCODING_TOKEN token);
void GetNativeVirtoolsName(std::string& u8_name, std::string& native_name, ENCODING_TOKEN token);
void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path);
FILE* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read);
#else #else
/// <summary>
/// Token is the ticket for using encoding functions.
/// It should be created by "GenerateEncodingToken" and free by "DestroyEncodingToken".
/// </summary>
using ENCODING_TOKEN = char*;
extern const ENCODING_TOKEN ENCODING_TOKEN_DEFAULT;
#error NO IMPLEMENTATION FOR LINUX ENCODING! #error NO IMPLEMENTATION FOR LINUX ENCODING!
#endif #endif

24
LibCmo/VTUtils.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "VTUtils.hpp"
namespace LibCmo {
namespace Utils {
static constexpr const size_t CHUNK_SIZE = 10240;
void CopyStream(const void* src, FILE* dest, size_t len) {
fwrite(src, sizeof(char), len, dest);
}
void CopyStream(FILE* src, void* dest, size_t len) {
size_t expected_size = 0u;
char* p = reinterpret_cast<char*>(dest);
while (len != 0) {
expected_size = len < CHUNK_SIZE ? len : CHUNK_SIZE;
fread(p, sizeof(char), expected_size, src);
p += expected_size;
len -= expected_size;
}
}
}
}

View File

@ -41,10 +41,13 @@
#define LIBCMO_OS_WIN32 #define LIBCMO_OS_WIN32
#endif #endif
#include <cstdio>
namespace LibCmo { namespace LibCmo {
namespace Utils { namespace Utils {
void CopyStream(const void* src, FILE* dest, size_t len);
void CopyStream(FILE* src, void* dest, size_t len);
} }
} }

View File

@ -16,7 +16,7 @@ namespace LibCmo {
// save file path // save file path
#if defined(LIBCMO_OS_WIN32) #if defined(LIBCMO_OS_WIN32)
Encoding::CharToWchar(u8_filepath, this->m_szFilePath, CP_UTF8); Encoding::SetStdPathFromU8Path(m_szFilePath, u8_filepath);
#else #else
this->m_szFilePath = u8_filepath; this->m_szFilePath = u8_filepath;
#endif #endif
@ -26,7 +26,7 @@ namespace LibCmo {
// open file // open file
this->m_hFile = CreateFileW( this->m_hFile = CreateFileW(
this->m_szFilePath.c_str(), this->m_szFilePath.wstring().c_str(),
GENERIC_READ, GENERIC_READ,
0, // do not share 0, // do not share
NULL, // no security NULL, // no security

View File

@ -8,23 +8,25 @@
#endif #endif
#include <string> #include <string>
#include <filesystem>
namespace LibCmo { namespace LibCmo {
class VxMemoryMappedFile { class VxMemoryMappedFile {
private: private:
#if defined(LIBCMO_OS_WIN32) #if defined(LIBCMO_OS_WIN32)
std::wstring m_szFilePath;
HANDLE m_hFile; HANDLE m_hFile;
DWORD m_dwFileSizeLow, m_dwFileSizeHigh; DWORD m_dwFileSizeLow, m_dwFileSizeHigh;
HANDLE m_hFileMapping; HANDLE m_hFileMapping;
LPVOID m_hFileMapView; LPVOID m_hFileMapView;
#else #else
std::string m_szFilePath;
#error NO IMPLEMENTATION FOR LINUX MMAP! #error NO IMPLEMENTATION FOR LINUX MMAP!
#endif #endif
std::filesystem::path m_szFilePath;
void* m_pMemoryMappedFileBase; void* m_pMemoryMappedFileBase;
size_t m_cbFile; size_t m_cbFile;
bool m_bIsValid; bool m_bIsValid;

View File

@ -11,8 +11,11 @@ namespace Unvirt {
std::string container; std::string container;
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileInfo\n")), fout); fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileInfo\n")), fout);
fprintf(fout, "Version (File / CK): %" PRIu32 " / 0x%08" PRIX32 "\n", fprintf(fout, "Version (File / CK): %" PRIu32 " / %02" PRIX32 "/%02" PRIX32 "/%04" PRIX32 "\n",
fileinfo.FileVersion, fileinfo.CKVersion fileinfo.FileVersion,
(fileinfo.CKVersion >> 24) & 0xFF,
(fileinfo.CKVersion >> 16) & 0xFF,
(fileinfo.CKVersion >> 0) & 0xFFFF
); );
LibCmo::CKDWORD product_series[4]{ LibCmo::CKDWORD product_series[4]{

View File

@ -10,10 +10,14 @@ int main(int argc, char* argv[]) {
Unvirt::TerminalHelper::EnsureTerminalEncoding(); Unvirt::TerminalHelper::EnsureTerminalEncoding();
LibCmo::CKMinContext vtctx; LibCmo::CKMinContext vtctx;
vtctx.SetTempPath("Temp");
vtctx.SetEncoding("850");
LibCmo::CKFile vtfile(&vtctx); LibCmo::CKFile vtfile(&vtctx);
LibCmo::CKFileData::ShallowDocument* doc; LibCmo::CKFileData::ShallowDocument* doc;
LibCmo::CKERROR err = vtfile.ShallowLoad("Language.old.nmo", &doc); LibCmo::CKERROR err = vtfile.ShallowLoad("combining behaviors.cmo", &doc);
if (doc)
Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo); Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo);
return 0; return 0;