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 {
#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
CKBufferParser::CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) :
@ -36,6 +17,16 @@ namespace LibCmo {
#pragma endregion
#pragma region CKFileInfo
CKFileInfo::CKFileInfo() {
}
CKFileInfo::~CKFileInfo() {
}
#pragma endregion
#pragma region CKFileObject
LibCmo::CKFileObject::CKFileObject() :
@ -49,6 +40,25 @@ namespace LibCmo {
#pragma endregion
#pragma region CKFileManagerData
CKFileManagerData::CKFileManagerData() {
}
CKFileManagerData::~CKFileManagerData() {
}
#pragma endregion
#pragma region CKFilePluginDependencies
CKFilePluginDependencies::CKFilePluginDependencies() {
}
CKFilePluginDependencies::~CKFilePluginDependencies() {
}
#pragma endregion
#pragma region ShallowDocument
@ -74,12 +84,10 @@ namespace LibCmo {
#pragma endregion
#pragma region CKFile Misc
CKFile::CKFile(CKMinContext* ctx) :
m_MappedFile(nullptr), m_FileName(),
m_MinCtx(ctx) {
m_FileName(), m_MinCtx(ctx) {
;
}
@ -87,7 +95,6 @@ namespace LibCmo {
}
#pragma endregion

View File

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

View File

@ -11,47 +11,45 @@ namespace LibCmo {
* No need to support them.
*/
CKERROR CKFile::PrepareLoad(CKSTRING u8_filename) {
// assign file name
this->m_FileName = u8_filename;
// create mapped file
this->m_MappedFile = new(std::nothrow) VxMemoryMappedFile(this->m_FileName.c_str());
if (this->m_MappedFile == nullptr) {
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc) {
// preset value
*out_doc = nullptr;
// check file and open memory
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.");
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());
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
this->m_ShallowDoc = new(std::nothrow) CKFileData::ShallowDocument();
if (this->m_ShallowDoc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
std::unique_ptr<CKFileData::ShallowDocument> doc(new(std::nothrow) CKFileData::ShallowDocument());
if (doc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
// create buffer and start loading
CKBufferParser parser(this->m_MappedFile->GetBase(), this->m_MappedFile->GetFileSize(), false);
err = this->ReadFileHeader(&parser);
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(mappedFile->GetBase(), mappedFile->GetFileSize(), false));
CKERROR err = this->ReadFileHeader(parser.get(), doc.get());
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;
// free all data
this->ClearData();
// unbind document and assign it
*out_doc = doc.release();
// other data will be free automatically
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));
if (parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
parser->SetCursor(ParserPtr->GetCursor());
std::string name_conv;
// ========== read header ==========
// check header size
@ -73,23 +71,23 @@ namespace LibCmo {
}
// ========== assign value ==========
this->m_ShallowDoc->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
this->m_ShallowDoc->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
this->m_ShallowDoc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
this->m_ShallowDoc->m_FileInfo.CKVersion = rawHeader.CKVersion;
this->m_ShallowDoc->m_FileInfo.FileVersion = rawHeader.FileVersion;
this->m_ShallowDoc->m_FileInfo.FileSize = parser->GetSize();
this->m_ShallowDoc->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
this->m_ShallowDoc->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
this->m_ShallowDoc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
this->m_ShallowDoc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
this->m_ShallowDoc->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
this->m_ShallowDoc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
this->m_ShallowDoc->m_FileInfo.Crc = rawHeader.Crc;
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;
// ========== crc and body unpacker ==========
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) {
if (doc->m_FileInfo.FileVersion >= 8) {
// crc checker for file ver >= 8
// reset crc field of header
rawHeader.Crc = 0u;
@ -97,19 +95,22 @@ namespace LibCmo {
// compute crc
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, sizeof(CKRawFileInfo), 0u);
parser->SetCursor(sizeof(CKRawFileInfo));
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.Hdr1PackSize, gotten_crc);
parser->MoveCursor(this->m_ShallowDoc->m_FileInfo.Hdr1PackSize);
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.DataPackSize, gotten_crc);
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);
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
parser->SetCursor(sizeof(CKRawFileInfo));
// 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) {
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) {
delete[] decomp_buffer;
return CKERROR::CKERR_OUTOFMEMORY;
@ -119,14 +120,14 @@ namespace LibCmo {
// ========== object list read ==========
// file ver >= 7 have this features
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 7) {
{
// apply max id saved
this->m_ShallowDoc->m_SaveIDMax = this->m_ShallowDoc->m_FileInfo.MaxIDSaved;
doc->m_SaveIDMax = doc->m_FileInfo.MaxIDSaved;
// resize
this->m_ShallowDoc->m_FileObjects.resize(this->m_ShallowDoc->m_FileInfo.ObjectCount);
doc->m_FileObjects.resize(doc->m_FileInfo.ObjectCount);
// read data
for (auto& fileobj : this->m_ShallowDoc->m_FileObjects) {
for (auto& fileobj : doc->m_FileObjects) {
// read basic fields
parser->Read(&(fileobj.ObjectId), sizeof(CK_ID));
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
@ -135,8 +136,9 @@ namespace LibCmo {
CKDWORD namelen;
parser->Read(&namelen, sizeof(CKDWORD));
if (namelen != 0) {
fileobj.Name.resize(namelen);
parser->Read(fileobj.Name.data(), namelen);
name_conv.resize(namelen);
parser->Read(name_conv.data(), namelen);
m_MinCtx->GetUtf8ObjectName(name_conv, fileobj.Name);
}
}
}
@ -144,14 +146,14 @@ namespace LibCmo {
// ========== dep list read ==========
// file ver >= 8 have this feature
bool noDepLost = true;
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) {
if (doc->m_FileInfo.FileVersion >= 8) {
// get size and resize
CKDWORD depSize;
parser->Read(&depSize, sizeof(CKDWORD));
this->m_ShallowDoc->m_PluginDep.resize(depSize);
doc->m_PluginDep.resize(depSize);
CKDWORD guid_size;
for (auto& dep : this->m_ShallowDoc->m_PluginDep) {
for (auto& dep : doc->m_PluginDep) {
// read category
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
// get size and resize
@ -167,7 +169,7 @@ namespace LibCmo {
// ========== included file list read ==========
// 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!
int32_t hasIncludedFile;
parser->Read(&hasIncludedFile, sizeof(int32_t));
@ -176,20 +178,173 @@ namespace LibCmo {
// read included file size and resize
CKDWORD includedFileCount;
parser->Read(&includedFileCount, sizeof(CKDWORD));
this->m_ShallowDoc->m_IncludedFiles.resize(includedFileCount);
doc->m_IncludedFiles.resize(includedFileCount);
hasIncludedFile -= 4;
}
// backward pos
parser->SetCursor(hasIncludedFile);
// MARK: backward pos
// 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;
}
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr) {
return CKERROR();
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr, CKFileData::ShallowDocument* doc) {
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) {

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

View File

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

View File

@ -60,6 +60,16 @@ namespace LibCmo {
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
//todo: linux implementation
@ -72,34 +82,65 @@ namespace LibCmo {
#if defined(LIBCMO_OS_WIN32)
void GetUtf8VirtoolsName(std::string& native_name, std::string& u8_name, const char* u8_encoding_spec) {
// switch encoding spec
UINT codepage = CP_ACP;
if (!GetWindowsCodePage(u8_encoding_spec, &codepage)) {
const ENCODING_TOKEN ENCODING_TOKEN_DEFAULT = nullptr;
ENCODING_TOKEN CreateEncodingToken(std::string& token_string) {
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();
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;
if (!CharToWchar(native_name, intermediary, codepage)) {
u8_name = native_name.c_str();
return;
if (CharToWchar(u8_path, intermediary, CP_UTF8)) {
stdpath = intermediary.c_str();
} else {
// fallback
stdpath = u8_path;
}
if (!WcharToChar(intermediary, u8_name, CP_UTF8)) {
u8_name = native_name.c_str();
return;
}
return;
}
void GetWcharStdin(std::string& u8_input, std::wstring& wc_input) {
// just redirect to prev func
CharToWchar(u8_input, wc_input, CP_UTF8);
FILE* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read) {
return _wfopen(u8_filepath.wstring().c_str(), is_read ? L"rb" : L"wb");
}
#else
const ENCODING_TOKEN ENCODING_TOKEN_DEFAULT = nullptr;
//todo: linux implementation
#endif

View File

@ -2,6 +2,7 @@
#include "VTUtils.hpp"
#include <string>
#include <filesystem>
#if defined(LIBCMO_OS_WIN32)
#include <Windows.h>
@ -25,6 +26,9 @@ namespace LibCmo {
bool CharToWchar(const char* 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
#error NO IMPLEMENTATION FOR LINUX ENCODING!
#endif
@ -35,9 +39,31 @@ namespace LibCmo {
#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
/// <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!
#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
#endif
#include <cstdio>
namespace LibCmo {
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
#if defined(LIBCMO_OS_WIN32)
Encoding::CharToWchar(u8_filepath, this->m_szFilePath, CP_UTF8);
Encoding::SetStdPathFromU8Path(m_szFilePath, u8_filepath);
#else
this->m_szFilePath = u8_filepath;
#endif
@ -26,7 +26,7 @@ namespace LibCmo {
// open file
this->m_hFile = CreateFileW(
this->m_szFilePath.c_str(),
this->m_szFilePath.wstring().c_str(),
GENERIC_READ,
0, // do not share
NULL, // no security

View File

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

View File

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

View File

@ -10,10 +10,14 @@ int main(int argc, char* argv[]) {
Unvirt::TerminalHelper::EnsureTerminalEncoding();
LibCmo::CKMinContext vtctx;
vtctx.SetTempPath("Temp");
vtctx.SetEncoding("850");
LibCmo::CKFile vtfile(&vtctx);
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);
return 0;