From 2a6cd48ac9c2b755ee11dcb38bf2ffd40909e47d Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Tue, 14 Feb 2023 16:28:37 +0800 Subject: [PATCH] finish migration from py to c++ --- PyCmo/PyCmo.py | 2 +- Unvirt/AccessibleValue.cpp | 21 ++++--- Unvirt/CmdHelper.cpp | 113 +++++++++++++++++++++++++++++----- Unvirt/CmdHelper.hpp | 21 +++++-- Unvirt/StringHelper.cpp | 2 +- Unvirt/StructFormatter.cpp | 61 ++++++++++++++++++ Unvirt/StructFormatter.hpp | 11 ++++ Unvirt/Unvirt.cpp | 9 +-- Unvirt/Unvirt.vcxproj | 2 + Unvirt/Unvirt.vcxproj.filters | 6 ++ 10 files changed, 207 insertions(+), 41 deletions(-) create mode 100644 Unvirt/StructFormatter.cpp create mode 100644 Unvirt/StructFormatter.hpp diff --git a/PyCmo/PyCmo.py b/PyCmo/PyCmo.py index 0bb6ec9..4a44cda 100644 --- a/PyCmo/PyCmo.py +++ b/PyCmo/PyCmo.py @@ -1,7 +1,7 @@ import VTReader, VTStruct, VTConstants ckFile = VTStruct.CKFile() -VTReader.CKFileReader.Load(ckFile, "D:\\libcmo21\\PyCmo\\Language.nmo", VTConstants.CK_LOAD_FLAGS(VTConstants.CK_LOAD_FLAGS.CK_LOAD_DEFAULT)) +VTReader.CKFileReader.Load(ckFile, "D:\\libcmo21\\PyCmo\\Language.old.nmo", VTConstants.CK_LOAD_FLAGS(VTConstants.CK_LOAD_FLAGS.CK_LOAD_DEFAULT)) print(ckFile) print(str(ckFile.m_FileObjects)) diff --git a/Unvirt/AccessibleValue.cpp b/Unvirt/AccessibleValue.cpp index 0f9cc5b..31da055 100644 --- a/Unvirt/AccessibleValue.cpp +++ b/Unvirt/AccessibleValue.cpp @@ -231,30 +231,31 @@ namespace Unvirt { void GetAccessibleFileSize(std::string& strl, uint64_t size) { static double denominator = (double)0b1111111111; + uint64_t probe = size; // check bytes - if ((size >> 10) == UINT64_C(0)) { - StringHelper::StdstringPrintf(strl, "%" PRIu64 "Bytes", size); + if ((probe >> 10) == UINT64_C(0)) { + StringHelper::StdstringPrintf(strl, "%" PRIu64 "Bytes", probe); return; } - size >>= 10; + probe >>= 10; // check kb - if ((size >> 10) == UINT64_C(0)) { - StringHelper::StdstringPrintf(strl, "%.2lfKiB", size / denominator); + if ((probe >> 10) == UINT64_C(0)) { + StringHelper::StdstringPrintf(strl, "%.2lfKiB", size / static_cast(UINT64_C(1) << 10)); return; } - size >>= 10; + probe >>= 10; // check mb - if ((size >> 10) == UINT64_C(0)) { - StringHelper::StdstringPrintf(strl, "%.2lfMiB", size / denominator); + if ((probe >> 10) == UINT64_C(0)) { + StringHelper::StdstringPrintf(strl, "%.2lfMiB", size / static_cast(UINT64_C(1) << 20)); return; } - size >>= 10; + probe >>= 10; // otherwise gb - StringHelper::StdstringPrintf(strl, "%.2lfGiB", size / denominator); + StringHelper::StdstringPrintf(strl, "%.2lfGiB", size / static_cast(UINT64_C(1) << 30)); return; } diff --git a/Unvirt/CmdHelper.cpp b/Unvirt/CmdHelper.cpp index fe2efed..15d7dc4 100644 --- a/Unvirt/CmdHelper.cpp +++ b/Unvirt/CmdHelper.cpp @@ -1,5 +1,10 @@ #include "CmdHelper.hpp" #include "TerminalHelper.hpp" +#include "VTUtils.hpp" +#include "VTEncoding.hpp" +#include + +/* namespace Unvirt { namespace CmdHelper { @@ -15,7 +20,7 @@ namespace Unvirt { ; } - std::vector CmdSplitter::Convert(const std::string& u8cmd) { + const std::vector CmdSplitter::Convert(const std::string& u8cmd) { // set up variables std::vector result; std::string buffer; @@ -129,7 +134,7 @@ namespace Unvirt { if (search == mShortNameMapping.end()) return nullptr; return GetDescByLongName((*search).second); } - OptionDescription* OptionsDescription::GetDescByPosition(int pos) { + OptionDescription* OptionsDescription::GetDescByPosition(size_t pos) { if (pos >= mPositionalArgMapping.size()) return nullptr; return GetDescByLongName(mPositionalArgMapping[pos]); } @@ -167,7 +172,7 @@ namespace Unvirt { mDataPair.clear(); } - bool VariablesMap::AddPair(std::string& name, CmdArgType t, std::string& val) { + bool VariablesMap::AddPair(const std::string& name, CmdArgType t, const std::string& val) { if (mDataPair.contains(name)) return false; AnyVariable var; @@ -206,41 +211,75 @@ namespace Unvirt { } mDataPair.emplace(name, std::move(var)); + return true; } #pragma endregion #pragma region ExecEnvironment - ExecEnvironment::ExecEnvironment() { + ExecEnvironment::ExecEnvironment() : + mVtFile(nullptr), mVtFileEnv(nullptr) { + ; } ExecEnvironment::~ExecEnvironment() { + if (mVtFile != nullptr) delete mVtFile; + if (mVtFileEnv != nullptr) delete mVtFileEnv; } void ExecEnvironment::ProcLoad(OptionsDescription& od, VariablesMap& vm) { + if (mVtFile != nullptr || mVtFileEnv != nullptr) { + printf(UNVIRT_TERMCOL_LIGHT_RED(("Please close current opened Vrtools file first.\n"))); + return; + } + + const char* filename = vm.GetData("file"); + if (filename == nullptr) { + printf(UNVIRT_TERMCOL_LIGHT_RED(("You should specify a file first.\n"))); + od.PrintHelp(stdout); + return; + } + + mVtFileEnv = new LibCmo::Utils::VirtoolsContext(); + const char* enc = vm.GetData("encoding"); + mVtFileEnv->NameEncoding = enc == nullptr ? "" : enc; + + mVtFile = new LibCmo::CKFile(*mVtFileEnv); + mVtFile->Load(filename, LibCmo::CK_LOAD_FLAGS::CK_LOAD_DEFAULT); } void ExecEnvironment::ProcInfo(OptionsDescription& od, VariablesMap& vm) { + printf(UNVIRT_TERMCOL_LIGHT_RED(("Sorry. This feature is not supported now.\n"))); } void ExecEnvironment::ProcClear(OptionsDescription& od, VariablesMap& vm) { + if (mVtFile == nullptr && mVtFileEnv == nullptr) { + printf(UNVIRT_TERMCOL_LIGHT_RED(("Virtools file already is empty.\n"))); + return; + } + + if (mVtFile != nullptr) delete mVtFile; + if (mVtFileEnv != nullptr) delete mVtFileEnv; + + mVtFile = nullptr; + mVtFileEnv = nullptr; } void ExecEnvironment::ProcExportSql(OptionsDescription& od, VariablesMap& vm) { + printf(UNVIRT_TERMCOL_LIGHT_RED(("Sorry. This feature is not supported now.\n"))); } #pragma endregion - #pragma region InteractiveCmd InteractiveCmd::InteractiveCmd() : - mCmdDispatcher(), mExecEnv(), mVm(), mBlank() - { + mCmdDispatcher(), mExecEnv(), mVm(), mBlank(), mExitRunFlag(false), mCmdSplitter() { // add load subcommand CmdRegisteryEntry entryLoad; + const std::string entryLoadName = "load"; entryLoad.mSubCmdDesc = "Load Virtools file."; entryLoad.mOptDesc.AddOption("file", 'f', CmdArgType::STRING, "The loaded Virtools file."); entryLoad.mOptDesc.AddPositionalOption("file"); @@ -249,33 +288,57 @@ namespace Unvirt { entryLoad.mOptDesc.AddOption("temp", 't', CmdArgType::STRING, "The temp folder used by engine."); entryLoad.mOptDesc.AddPositionalOption("temp"); entryLoad.mBindProc = std::bind(&ExecEnvironment::ProcLoad, &this->mExecEnv, std::placeholders::_1, std::placeholders::_2); - mCmdDispatcher.emplace("load", std::move(entryLoad)); + //mCmdDispatcher.emplace("load", std::move(entryLoad)); CmdRegisteryEntry entryInfo; entryInfo.mSubCmdDesc = "Show loaded Virtools file header info."; entryInfo.mBindProc = std::bind(&ExecEnvironment::ProcInfo, &this->mExecEnv, std::placeholders::_1, std::placeholders::_2); - mCmdDispatcher.emplace("info", std::move(entryInfo)); + //mCmdDispatcher.emplace("info", std::move(entryInfo)); CmdRegisteryEntry entryClear; entryClear.mSubCmdDesc = "Clear current loaded Virtools file."; entryClear.mBindProc = std::bind(&ExecEnvironment::ProcClear, &this->mExecEnv, std::placeholders::_1, std::placeholders::_2); - mCmdDispatcher.emplace("clear", std::move(entryClear)); + //mCmdDispatcher.emplace("clear", std::move(entryClear)); CmdRegisteryEntry entryExportSql; entryExportSql.mSubCmdDesc = "Export loaded Virtools file as a SQList database file."; entryExportSql.mOptDesc.AddOption("file", 'f', CmdArgType::STRING, "The exported SQL file."); entryExportSql.mOptDesc.AddPositionalOption("file"); entryExportSql.mBindProc = std::bind(&ExecEnvironment::ProcExportSql, &this->mExecEnv, std::placeholders::_1, std::placeholders::_2); - mCmdDispatcher.emplace("sql", std::move(entryExportSql)); + //mCmdDispatcher.emplace("sql", std::move(entryExportSql)); + + CmdRegisteryEntry entryExit; + entryExit.mSubCmdDesc = "Exit this interactive commander."; + entryExit.mBindProc = std::bind(&InteractiveCmd::ProcExit, this, std::placeholders::_1, std::placeholders::_2); + //mCmdDispatcher.emplace("exit", std::move(entryExit)); } InteractiveCmd::~InteractiveCmd() { - + ; } void InteractiveCmd::Run(void) { + std::string u8cmd; + mExitRunFlag = false; + while (!mExitRunFlag) { + // get command + GetCmdLine(u8cmd); + + // split cmd and parse it + CmdParser(mCmdSplitter.Convert(u8cmd)); + } + } + + void InteractiveCmd::GetCmdLine(std::string& u8cmd) { +#if defined(LIBCMO_OS_WIN32) + std::wstring wcmd; + std::getline(std::wcin, wcmd); + LibCmo::Encoding::WcharToChar(wcmd, u8cmd, CP_UTF8); +#else + std::getline(std::cin, u8cmd); +#endif } void InteractiveCmd::CmdParser(const std::vector& args) { @@ -316,7 +379,7 @@ namespace Unvirt { optsDesc.PrintHelp(f); return; } - optsDesc.GetDescByShortName(opt[1]); + optDesc = optsDesc.GetDescByShortName(opt[1]); } else { // position optDesc = optsDesc.GetDescByPosition(position_counter++); @@ -330,11 +393,17 @@ namespace Unvirt { } // get value + bool add_success = true; switch (optDesc->mType) { case CmdArgType::NONE: // just a switch - mVm.AddPair(optDesc->mLongName, optDesc->mType, this->mBlank); + add_success = mVm.AddPair(optDesc->mLongName, optDesc->mType, this->mBlank); ++arg; + if (!add_success) { + fprintf(f, UNVIRT_TERMCOL_LIGHT_RED(("Error! Duplicated option \"%s\"! \n")), opt.c_str()); + optsDesc.PrintHelp(f); + return; + } break; case CmdArgType::INT: case CmdArgType::STRING: @@ -345,8 +414,13 @@ namespace Unvirt { optsDesc.PrintHelp(f); return; } - mVm.AddPair(optDesc->mLongName, optDesc->mType, *arg); + add_success = mVm.AddPair(optDesc->mLongName, optDesc->mType, *arg); ++arg; + if (!add_success) { + fprintf(f, UNVIRT_TERMCOL_LIGHT_RED(("Error! Duplicated option \"%s\"! \n")), opt.c_str()); + optsDesc.PrintHelp(f); + return; + } break; default: throw std::invalid_argument("Invalid Option Type."); @@ -364,8 +438,13 @@ namespace Unvirt { } } + void InteractiveCmd::ProcExit(OptionsDescription&, VariablesMap&) { + mExitRunFlag = true; + } + #pragma endregion - + } } -} \ No newline at end of file + +*/ \ No newline at end of file diff --git a/Unvirt/CmdHelper.hpp b/Unvirt/CmdHelper.hpp index efbcfa5..03b5c18 100644 --- a/Unvirt/CmdHelper.hpp +++ b/Unvirt/CmdHelper.hpp @@ -6,6 +6,10 @@ #include #include #include +#include "VTUtils.hpp" +#include "VTStruct.hpp" + +/* namespace Unvirt { namespace CmdHelper { @@ -17,7 +21,7 @@ namespace Unvirt { CmdSplitter& operator=(const CmdSplitter&) = delete; ~CmdSplitter(); - std::vector Convert(const std::string& u8cmd); + const std::vector Convert(const std::string& u8cmd); private: char mCmdChar; std::string* mBuffer; @@ -154,7 +158,7 @@ namespace Unvirt { OptionDescription* GetDescByLongName(const std::string& longname); OptionDescription* GetDescByShortName(char shortname); - OptionDescription* GetDescByPosition(int pos); + OptionDescription* GetDescByPosition(size_t pos); void PrintHelp(FILE* f); private: @@ -186,7 +190,7 @@ namespace Unvirt { /// /// /// return false when this opt is existed. - bool AddPair(std::string& name, CmdArgType t, std::string& val); + bool AddPair(const std::string& name, CmdArgType t, const std::string& val); bool Contain(const char* opt) { if (opt == nullptr) throw std::invalid_argument("Invalid Option Name."); return mDataPair.contains(opt); @@ -220,7 +224,8 @@ namespace Unvirt { void ProcClear(OptionsDescription&, VariablesMap&); void ProcExportSql(OptionsDescription&, VariablesMap&); private: - + LibCmo::CKFile* mVtFile; + LibCmo::Utils::VirtoolsContext* mVtFileEnv; }; class InteractiveCmd { @@ -233,14 +238,20 @@ namespace Unvirt { void Run(void); private: + void GetCmdLine(std::string& u8cmd); void CmdParser(const std::vector& args); void PrintHelp(FILE* f); + void ProcExit(OptionsDescription&, VariablesMap&); + std::unordered_map mCmdDispatcher; + CmdSplitter mCmdSplitter; ExecEnvironment mExecEnv; VariablesMap mVm; std::string mBlank; + bool mExitRunFlag; }; } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/Unvirt/StringHelper.cpp b/Unvirt/StringHelper.cpp index aa28498..d704d52 100644 --- a/Unvirt/StringHelper.cpp +++ b/Unvirt/StringHelper.cpp @@ -17,7 +17,7 @@ namespace Unvirt { strl.resize(count); int write_result = _vsnprintf(strl.data(), count, format, argptr); - if (write_result < 0 || write_result >= count) throw new std::length_error("Invalid write_result in _vsnprintf."); + if (write_result < 0 || write_result > count) throw new std::length_error("Invalid write_result in _vsnprintf."); } } diff --git a/Unvirt/StructFormatter.cpp b/Unvirt/StructFormatter.cpp new file mode 100644 index 0000000..775adab --- /dev/null +++ b/Unvirt/StructFormatter.cpp @@ -0,0 +1,61 @@ +#include "StructFormatter.hpp" +#include "AccessibleValue.hpp" +#include "TerminalHelper.hpp" + +namespace Unvirt { + namespace StructFormatter { + + static FILE* fout = stdout; + + void PrintCKFileInfo(const LibCmo::CKFileInfo& fileinfo) { + 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 + ); + + LibCmo::CKDWORD product_series[4]{ + (fileinfo.ProductBuild >> 24) & 0xFF, + (fileinfo.ProductBuild >> 16) & 0xFF, + (fileinfo.ProductBuild >> 8) & 0xFF, + (fileinfo.ProductBuild >> 0) & 0xFF, + }; + fprintf(fout, "Product (Version / Build): %" PRIu32 " / %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", + fileinfo.ProductVersion, product_series[0], product_series[1], product_series[2], product_series[3] + ); + + Unvirt::AccessibleValue::GetFlagEnumName( + Unvirt::AccessibleValue::EnumDesc::CK_FILE_WRITEMODE, container, fileinfo.FileWriteMode + ); + fprintf(fout, "Save Flags: %s\n", container.c_str()); + + Unvirt::AccessibleValue::GetAccessibleFileSize(container, fileinfo.FileSize); + fprintf(fout, "File Size: %s\n", container.c_str()); + + fprintf(fout, "Crc: 0x%" PRIX32 "\n", fileinfo.Crc); + fputc('\n', fout); + + + fputs("Hdr1 (Pack / UnPack): ", fout); + Unvirt::AccessibleValue::GetAccessibleFileSize(container, fileinfo.Hdr1PackSize); + fprintf(fout, "%s / ", container.c_str()); + Unvirt::AccessibleValue::GetAccessibleFileSize(container, fileinfo.Hdr1UnPackSize); + fprintf(fout, "%s\n", container.c_str()); + + fputs("Data (Pack / UnPack): ", fout); + Unvirt::AccessibleValue::GetAccessibleFileSize(container, fileinfo.DataPackSize); + fprintf(fout, "%s / ", container.c_str()); + Unvirt::AccessibleValue::GetAccessibleFileSize(container, fileinfo.DataUnPackSize); + fprintf(fout, "%s\n", container.c_str()); + fputc('\n', fout); + + + fprintf(fout, "Manager Count: %" PRIu32 "\nObject Count: %" PRIu32 "\nMax ID Saved: %" PRIu32 "\n", + fileinfo.ManagerCount, fileinfo.ObjectCount, fileinfo.MaxIDSaved + ); + + } + + } +} diff --git a/Unvirt/StructFormatter.hpp b/Unvirt/StructFormatter.hpp new file mode 100644 index 0000000..6e3c245 --- /dev/null +++ b/Unvirt/StructFormatter.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "VTStruct.hpp" + +namespace Unvirt { + namespace StructFormatter { + + void PrintCKFileInfo(const LibCmo::CKFileInfo& fileinfo); + + } +} diff --git a/Unvirt/Unvirt.cpp b/Unvirt/Unvirt.cpp index 24e92de..bdd11d4 100644 --- a/Unvirt/Unvirt.cpp +++ b/Unvirt/Unvirt.cpp @@ -1,6 +1,6 @@ #include "AccessibleValue.hpp" #include "TerminalHelper.hpp" -#include "CmdHelper.hpp" +#include "StructFormatter.hpp" #include "VTStruct.hpp" #include #include @@ -13,12 +13,7 @@ int main(int argc, char* argv[]) { LibCmo::CKFile vtfile(vtctx); vtfile.Load("Language.old.nmo", LibCmo::CK_LOAD_FLAGS::CK_LOAD_DEFAULT); - //printf(UNVIRT_TERMCOL_LIGHT_YELLOW(("Hello, %s\n")), u8"㴮!"); - - //std::string bbb("load \"Language. 㴮!old.nmo\" utf8 "); - //Unvirt::CmdHelper::CmdSplitter sp; - //auto a = sp.Convert(bbb); - //printf(UNVIRT_TERMCOL_LIGHT_YELLOW(("%s\n")), a[1].c_str()); + Unvirt::StructFormatter::PrintCKFileInfo(vtfile.m_FileInfo); return 0; } diff --git a/Unvirt/Unvirt.vcxproj b/Unvirt/Unvirt.vcxproj index 91f3083..d6aebc3 100644 --- a/Unvirt/Unvirt.vcxproj +++ b/Unvirt/Unvirt.vcxproj @@ -173,6 +173,7 @@ + @@ -180,6 +181,7 @@ + diff --git a/Unvirt/Unvirt.vcxproj.filters b/Unvirt/Unvirt.vcxproj.filters index c92a160..23cb78b 100644 --- a/Unvirt/Unvirt.vcxproj.filters +++ b/Unvirt/Unvirt.vcxproj.filters @@ -30,6 +30,9 @@ Sources + + Sources + @@ -44,5 +47,8 @@ Headers + + Headers + \ No newline at end of file