diff --git a/LibCmo/CK2/CKContext.cpp b/LibCmo/CK2/CKContext.cpp index fbbf903..3f0764c 100644 --- a/LibCmo/CK2/CKContext.cpp +++ b/LibCmo/CK2/CKContext.cpp @@ -185,21 +185,17 @@ namespace LibCmo::CK2 { #pragma region Temp IO utilities void CKContext::SetTempPath(CKSTRING u8_temp) { - EncodingHelper::SetStdPathFromU8Path(this->m_TempFolder, u8_temp); + EncodingHelper::U8PathToStdPath(this->m_TempFolder, u8_temp); } - FILE* CKContext::OpenTempFile(CKSTRING u8_filename, CKSTRING u8_mode) { + std::string CKContext::GetTempFilePath(CKSTRING u8_filename) { std::filesystem::path stdfilename; - EncodingHelper::SetStdPathFromU8Path(stdfilename, u8_filename); - + EncodingHelper::U8PathToStdPath(stdfilename, u8_filename); auto realfile = this->m_TempFolder / stdfilename; - 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); + std::string result; + EncodingHelper::StdPathToU8Path(result, realfile); + return result; } #pragma endregion diff --git a/LibCmo/CK2/CKContext.hpp b/LibCmo/CK2/CKContext.hpp index e941c54..882ae25 100644 --- a/LibCmo/CK2/CKContext.hpp +++ b/LibCmo/CK2/CKContext.hpp @@ -79,8 +79,7 @@ namespace LibCmo::CK2 { // ========== Temp IO utilities ========== void SetTempPath(CKSTRING u8_temp); - FILE* OpenTempFile(CKSTRING u8_filename, CKSTRING u8_mode); - FILE* OpenFile(CKSTRING u8_filename, CKSTRING u8_mode); + std::string GetTempFilePath(CKSTRING u8_filename); // ========== Print utilities ========== diff --git a/LibCmo/CK2/CKFileReader.cpp b/LibCmo/CK2/CKFileReader.cpp index 84f52aa..33e89fd 100644 --- a/LibCmo/CK2/CKFileReader.cpp +++ b/LibCmo/CK2/CKFileReader.cpp @@ -68,7 +68,7 @@ namespace LibCmo::CK2 { this->m_FileInfo.FileWriteMode = static_cast(rawHeader.FileWriteMode); this->m_FileInfo.CKVersion = rawHeader.CKVersion; this->m_FileInfo.FileVersion = rawHeader.FileVersion; - this->m_FileInfo.FileSize = static_cast(parser->GetSize()); + this->m_FileInfo.FileSize = parser->GetSize(); this->m_FileInfo.ManagerCount = rawHeader.ManagerCount; this->m_FileInfo.ObjectCount = rawHeader.ObjectCount; this->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved; @@ -291,6 +291,7 @@ namespace LibCmo::CK2 { // before reading, we need switch back to original parser. // and skip data chunk size parser = std::unique_ptr(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false)); + parser->SetCursor(ParserPtr->GetCursor()); parser->MoveCursor(this->m_FileInfo.DataPackSize); // then we can read it. @@ -312,10 +313,13 @@ namespace LibCmo::CK2 { parser->Read(&filebodylen, sizeof(CKDWORD)); // read file body - FILE* fp = m_Ctx->OpenTempFile(file.c_str(), "wb"); + std::string tempfilename = m_Ctx->GetTempFilePath(file.c_str()); + FILE* fp = EncodingHelper::U8FOpen(tempfilename.c_str(), "wb"); if (fp != nullptr) { std::fwrite(parser->GetPtr(), sizeof(char), filebodylen, fp); std::fclose(fp); + } else { + m_Ctx->OutputToConsoleEx("Fail to open temp file: %s", tempfilename.c_str()); } // move to next diff --git a/LibCmo/CK2/CKFileWriter.cpp b/LibCmo/CK2/CKFileWriter.cpp index 600ef4c..0057bb5 100644 --- a/LibCmo/CK2/CKFileWriter.cpp +++ b/LibCmo/CK2/CKFileWriter.cpp @@ -213,7 +213,7 @@ namespace LibCmo::CK2 { EnumsHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) { CKDWORD comp_buf_size = 0; - void* comp_buffer = CKPackData(hdrparser->GetBase(), static_cast(hdrparser->GetSize()), comp_buf_size, m_Ctx->GetCompressionLevel()); + void* comp_buffer = CKPackData(hdrparser->GetBase(), hdrparser->GetSize(), comp_buf_size, m_Ctx->GetCompressionLevel()); if (comp_buffer != nullptr) { hdrparser = std::unique_ptr(new CKBufferParser(comp_buffer, comp_buf_size, true)); rawHeader.Hdr1PackSize = comp_buf_size; @@ -260,7 +260,7 @@ namespace LibCmo::CK2 { EnumsHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) { CKDWORD comp_buf_size = 0; - void* comp_buffer = CKPackData(datparser->GetBase(), static_cast(datparser->GetSize()), comp_buf_size, m_Ctx->GetCompressionLevel()); + void* comp_buffer = CKPackData(datparser->GetBase(), datparser->GetSize(), comp_buf_size, m_Ctx->GetCompressionLevel()); if (comp_buffer != nullptr) { datparser = std::unique_ptr(new CKBufferParser(comp_buffer, comp_buf_size, true)); rawHeader.DataPackSize = comp_buf_size; @@ -296,7 +296,7 @@ namespace LibCmo::CK2 { // ========== Open File & Write Essential Data ========== // open file and test - FILE* fs = m_Ctx->OpenFile(u8_filename, "wb"); + FILE* fs = EncodingHelper::U8FOpen(u8_filename, "wb"); if (fs == nullptr) return CKERROR::CKERR_CANTWRITETOFILE; // write small header + header + data std::fwrite(&rawHeader, sizeof(CKRawFileInfo), 1, fs); @@ -315,15 +315,22 @@ namespace LibCmo::CK2 { std::fwrite(name_conv.data(), sizeof(char), filenamelen, fs); // try mapping file. - std::unique_ptr mappedFile(new VxMath::VxMemoryMappedFile(fentry.c_str())); - - // write file length - CKDWORD filebodylen = static_cast(mappedFile->IsValid() ? mappedFile->GetFileSize() : 0); - std::fwrite(&filebodylen, sizeof(CKDWORD), 1, fs); - - // write file body + std::string tempfilename = m_Ctx->GetTempFilePath(fentry.c_str()); + std::unique_ptr mappedFile(new VxMath::VxMemoryMappedFile(tempfilename.c_str())); if (mappedFile->IsValid()) { + // write file length + CKDWORD filebodylen = mappedFile->GetFileSize(); + std::fwrite(&filebodylen, sizeof(CKDWORD), 1, fs); + + // write file body std::fwrite(mappedFile->GetBase(), sizeof(char), filebodylen, fs); + } else { + // write zero file length + CKDWORD filebodylen = 0; + std::fwrite(&filebodylen, sizeof(CKDWORD), 1, fs); + + // report error + m_Ctx->OutputToConsoleEx("Fail to open temp file: %s", tempfilename.c_str()); } // release mapped file @@ -343,7 +350,7 @@ namespace LibCmo::CK2 { // try open file to check whether we can write it. CKERROR err; - FILE* tryfile = m_Ctx->OpenFile(filename, "ab"); + FILE* tryfile = EncodingHelper::U8FOpen(filename, "ab"); if (tryfile == nullptr) { err = CKERROR::CKERR_CANTWRITETOFILE; } else { diff --git a/LibCmo/VTEncoding.cpp b/LibCmo/VTEncoding.cpp index fba59bb..0c2b619 100644 --- a/LibCmo/VTEncoding.cpp +++ b/LibCmo/VTEncoding.cpp @@ -178,7 +178,7 @@ namespace LibCmo::EncodingHelper { return CharToChar(u8_name, native_name, CP_UTF8, *token); } - void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path) { + void U8PathToStdPath(std::filesystem::path& stdpath, const char* u8_path) { std::wstring intermediary; if (CharToWchar(u8_path, intermediary, CP_UTF8)) { stdpath = intermediary.c_str(); @@ -187,14 +187,24 @@ namespace LibCmo::EncodingHelper { stdpath = u8_path; } } + + void StdPathToU8Path(std::string& u8path, std::filesystem::path& stdpath) { + if (!WcharToChar(stdpath.wstring(), u8path, CP_UTF8)) { + // fallback + u8path = stdpath.string(); + } + } - FILE* StdPathFOpen(std::filesystem::path& std_filepath, const char* u8_mode) { - std::wstring wmode; - if (CharToWchar(u8_mode, wmode, CP_UTF8)) { - return _wfopen(std_filepath.wstring().c_str(), wmode.c_str()); + FILE* U8FOpen(const char* u8_filepath, const char* u8_mode) { + std::wstring wmode, wpath; + bool suc = CharToWchar(u8_mode, wmode, CP_UTF8); + suc = suc && CharToWchar(u8_filepath, wpath, CP_UTF8); + + if (suc) { + return _wfopen(wpath.c_str(), wmode.c_str()); } else { // fallback - return std::fopen(std_filepath.string().c_str(), u8_mode); + return std::fopen(u8_filepath, u8_mode); } } @@ -239,12 +249,16 @@ namespace LibCmo::EncodingHelper { return DoIconv(token->FromUtf8, u8_name, native_name); } - void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path) { + void U8PathToStdPath(std::filesystem::path& stdpath, const char* u8_path) { stdpath = u8_path; } - FILE* StdPathFOpen(std::filesystem::path& std_filepath, const char* u8_mode) { - return std::fopen(u8_filepath.string().c_str(), u8_mode); + void StdPathToU8Path(std::string& u8path, std::filesystem::path& stdpath) { + u8path = stdpath.string(); + } + + FILE* U8FOpen(const char* u8_filepath, const char* u8_mode) { + return std::fopen(u8_filepath, u8_mode); } diff --git a/LibCmo/VTEncoding.hpp b/LibCmo/VTEncoding.hpp index 193217e..91d986f 100644 --- a/LibCmo/VTEncoding.hpp +++ b/LibCmo/VTEncoding.hpp @@ -71,8 +71,9 @@ namespace LibCmo::EncodingHelper { bool GetUtf8VirtoolsName(const std::string& native_name, std::string& u8_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); - FILE* StdPathFOpen(std::filesystem::path& std_filepath, const char* u8_mode); + void U8PathToStdPath(std::filesystem::path& stdpath, const char* u8_path); + void StdPathToU8Path(std::string& u8path, std::filesystem::path& stdpath); + FILE* U8FOpen(const char* u8_filepath, const char* u8_mode); #pragma endregion diff --git a/LibCmo/VxMath/VxMemoryMappedFile.cpp b/LibCmo/VxMath/VxMemoryMappedFile.cpp index 5904d18..50259db 100644 --- a/LibCmo/VxMath/VxMemoryMappedFile.cpp +++ b/LibCmo/VxMath/VxMemoryMappedFile.cpp @@ -16,7 +16,7 @@ namespace LibCmo::VxMath { // save file path #if defined(LIBCMO_OS_WIN32) - EncodingHelper::SetStdPathFromU8Path(m_szFilePath, u8_filepath); + EncodingHelper::U8PathToStdPath(m_szFilePath, u8_filepath); #else this->m_szFilePath = u8_filepath; #endif