update cmd. improve encoding
This commit is contained in:
parent
e166b8ec5b
commit
79aaf6b1ea
|
@ -14,8 +14,7 @@ namespace LibCmo::CK2 {
|
|||
#pragma region Ctor Dtor
|
||||
|
||||
CKMinContext::CKMinContext() :
|
||||
m_NameEncoding(), m_NameEncodingToken(EncodingHelper::ENCODING_TOKEN_DEFAULT),
|
||||
m_TempFolder(),
|
||||
m_NameEncoding(), m_TempFolder(),
|
||||
m_PrintCallback(nullptr),
|
||||
m_CKObjectMaxID(0u),
|
||||
// register CKObjects
|
||||
|
@ -106,6 +105,15 @@ namespace LibCmo::CK2 {
|
|||
}
|
||||
}
|
||||
|
||||
void CKMinContext::ClearCKObject(void) {
|
||||
// free all created objects
|
||||
for (const auto& [key, value] : this->m_ObjectsList) {
|
||||
delete value;
|
||||
}
|
||||
// clear list
|
||||
this->m_ObjectsList.clear();
|
||||
}
|
||||
|
||||
CK_ID CKMinContext::GetObjectMaxID(void) {
|
||||
return this->m_CKObjectMaxID;
|
||||
}
|
||||
|
@ -122,17 +130,45 @@ namespace LibCmo::CK2 {
|
|||
|
||||
#pragma region Misc Funcs
|
||||
|
||||
void CKMinContext::GetUtf8String(std::string& native_name, std::string& u8_name) {
|
||||
EncodingHelper::GetUtf8VirtoolsName(native_name, u8_name, this->m_NameEncodingToken);
|
||||
void CKMinContext::GetUtf8String(const std::string& native_name, std::string& u8_name) {
|
||||
bool success = false;
|
||||
for (const auto& token : this->m_NameEncoding) {
|
||||
success = LibCmo::EncodingHelper::GetUtf8VirtoolsName(native_name, u8_name, token);
|
||||
if (success) break;
|
||||
}
|
||||
|
||||
// fallback
|
||||
if (!success) {
|
||||
u8_name = native_name;
|
||||
this->Printf("Error when converting to UTF8 string.");
|
||||
}
|
||||
}
|
||||
|
||||
void CKMinContext::GetNativeString(std::string& u8_name, std::string& native_name) {
|
||||
EncodingHelper::GetNativeVirtoolsName(u8_name, native_name, this->m_NameEncodingToken);
|
||||
void CKMinContext::GetNativeString(const std::string& u8_name, std::string& native_name) {
|
||||
bool success = false;
|
||||
for (const auto& token : this->m_NameEncoding) {
|
||||
success = LibCmo::EncodingHelper::GetNativeVirtoolsName(u8_name, native_name, token);
|
||||
if (success) break;
|
||||
}
|
||||
|
||||
// fallback
|
||||
if (!success) {
|
||||
native_name = u8_name;
|
||||
this->Printf("Error when converting to native string.");
|
||||
}
|
||||
}
|
||||
|
||||
void CKMinContext::SetEncoding(CKSTRING encoding) {
|
||||
this->m_NameEncoding = encoding;
|
||||
this->RefetchEncodingToken();
|
||||
void CKMinContext::SetEncoding(const std::vector<std::string> encoding_series) {
|
||||
// free all current series
|
||||
for (const auto& encoding : this->m_NameEncoding) {
|
||||
LibCmo::EncodingHelper::DestroyEncodingToken(encoding);
|
||||
}
|
||||
this->m_NameEncoding.clear();
|
||||
|
||||
// add new encoding
|
||||
for (const auto& encoding_str : encoding_series) {
|
||||
this->m_NameEncoding.push_back(LibCmo::EncodingHelper::CreateEncodingToken(encoding_str));
|
||||
}
|
||||
}
|
||||
|
||||
void CKMinContext::SetTempPath(CKSTRING u8_temp) {
|
||||
|
@ -147,10 +183,6 @@ namespace LibCmo::CK2 {
|
|||
return EncodingHelper::OpenStdPathFile(realfile, is_read);
|
||||
}
|
||||
|
||||
void CKMinContext::RefetchEncodingToken(void) {
|
||||
EncodingHelper::DestroyEncodingToken(this->m_NameEncodingToken);
|
||||
this->m_NameEncodingToken = EncodingHelper::CreateEncodingToken(this->m_NameEncoding);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
|
|
@ -16,13 +16,14 @@ namespace LibCmo::CK2 {
|
|||
CKMinContext& operator=(const CKMinContext&) = delete;
|
||||
~CKMinContext();
|
||||
|
||||
using PrintCallback = void (*)(std::string&);
|
||||
using PrintCallback = std::function<void(const std::string&)>;
|
||||
void Printf(CKSTRING fmt, ...);
|
||||
void SetPrintCallback(PrintCallback cb);
|
||||
|
||||
CKObjectImplements::CKObject* CreateCKObject(CK_ID id, CK_CLASSID cls, CKSTRING name);
|
||||
CKObjectImplements::CKObject* GetCKObject(CK_ID id);
|
||||
void DestroyCKObject(CK_ID id);
|
||||
void ClearCKObject(void);
|
||||
|
||||
//CKManagerImplements::CKBaseManager* CreateCKManager(CKGUID guid);
|
||||
//CKManagerImplements::CKBaseManager* GetCKManager(CK_ID guid);
|
||||
|
@ -31,17 +32,15 @@ namespace LibCmo::CK2 {
|
|||
CK_ID GetObjectMaxID(void);
|
||||
void SetObjectMaxID(CK_ID id);
|
||||
|
||||
void GetUtf8String(std::string& native_name, std::string& u8_name);
|
||||
void GetNativeString(std::string& u8_name, std::string& native_name);
|
||||
void GetUtf8String(const std::string& native_name, std::string& u8_name);
|
||||
void GetNativeString(const std::string& u8_name, std::string& native_name);
|
||||
|
||||
void SetEncoding(CKSTRING encoding);
|
||||
void SetEncoding(const std::vector<std::string> encoding_series);
|
||||
void SetTempPath(CKSTRING u8_temp);
|
||||
|
||||
FILE* OpenTempFile(CKSTRING u8_filename, bool is_read);
|
||||
|
||||
private:
|
||||
void RefetchEncodingToken(void);
|
||||
|
||||
std::map<CK_ID, CKObjectImplements::CKObject*> m_ObjectsList;
|
||||
std::map<CK_ID, CKManagerImplements::CKBaseManager*> m_ManagersList;
|
||||
|
||||
|
@ -50,8 +49,7 @@ namespace LibCmo::CK2 {
|
|||
|
||||
CK_ID m_CKObjectMaxID;
|
||||
|
||||
std::string m_NameEncoding;
|
||||
EncodingHelper::ENCODING_TOKEN m_NameEncodingToken;
|
||||
std::vector<EncodingHelper::ENCODING_TOKEN> m_NameEncoding;
|
||||
std::filesystem::path m_TempFolder;
|
||||
PrintCallback m_PrintCallback;
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace LibCmo::EncodingHelper {
|
|||
}
|
||||
#undef LIBCMO_STR_EQUAL
|
||||
|
||||
bool WcharToChar(const wchar_t* src, std::string& dest, UINT codepage) {
|
||||
bool WcharToChar(const wchar_t* src, std::string& dest, const UINT codepage) {
|
||||
int count, write_result;
|
||||
|
||||
//converter to CHAR
|
||||
|
@ -38,11 +38,11 @@ namespace LibCmo::EncodingHelper {
|
|||
|
||||
return true;
|
||||
}
|
||||
bool WcharToChar(std::wstring& src, std::string& dest, UINT codepage) {
|
||||
bool WcharToChar(const std::wstring& src, std::string& dest, const UINT codepage) {
|
||||
return WcharToChar(src.c_str(), dest, codepage);
|
||||
}
|
||||
|
||||
bool CharToWchar(const char* src, std::wstring& dest, UINT codepage) {
|
||||
bool CharToWchar(const char* src, std::wstring& dest, const UINT codepage) {
|
||||
int wcount, write_result;
|
||||
|
||||
// convert to WCHAR
|
||||
|
@ -55,17 +55,17 @@ namespace LibCmo::EncodingHelper {
|
|||
|
||||
return true;
|
||||
}
|
||||
bool CharToWchar(std::string& src, std::wstring& dest, UINT codepage) {
|
||||
bool CharToWchar(const std::string& src, std::wstring& dest, const UINT codepage) {
|
||||
return CharToWchar(src.c_str(), dest, codepage);
|
||||
}
|
||||
|
||||
bool CharToChar(const char* src, std::string& dest, UINT src_codepage, UINT dest_codepage) {
|
||||
bool CharToChar(const char* src, std::string& dest, const UINT src_codepage, const 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) {
|
||||
bool CharToChar(const std::string& src, std::string& dest, const UINT src_codepage, const UINT dest_codepage) {
|
||||
return CharToChar(src.c_str(), dest, src_codepage, dest_codepage);
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ namespace LibCmo::EncodingHelper {
|
|||
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
|
||||
ENCODING_TOKEN CreateEncodingToken(std::string& token_string) {
|
||||
ENCODING_TOKEN CreateEncodingToken(const std::string& token_string) {
|
||||
ENCODING_TOKEN token = new(std::nothrow) UINT();
|
||||
if (token == nullptr) return ENCODING_TOKEN_DEFAULT;
|
||||
|
||||
|
@ -153,34 +153,20 @@ namespace LibCmo::EncodingHelper {
|
|||
}
|
||||
return token;
|
||||
}
|
||||
void DestroyEncodingToken(ENCODING_TOKEN token) {
|
||||
void DestroyEncodingToken(const 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;
|
||||
}
|
||||
|
||||
// convert with fallback
|
||||
if (!CharToChar(native_name, u8_name, *token, CP_UTF8)) {
|
||||
u8_name = native_name.c_str();
|
||||
}
|
||||
bool GetUtf8VirtoolsName(const std::string& native_name, std::string& u8_name, const ENCODING_TOKEN& token) {
|
||||
if (token == ENCODING_TOKEN_DEFAULT) return false;
|
||||
return CharToChar(native_name, u8_name, *token, CP_UTF8);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
bool GetNativeVirtoolsName(const std::string& u8_name, std::string& native_name, const ENCODING_TOKEN& token) {
|
||||
if (token == ENCODING_TOKEN_DEFAULT) return false;
|
||||
return CharToChar(u8_name, native_name, CP_UTF8, *token);
|
||||
}
|
||||
|
||||
void SetStdPathFromU8Path(std::filesystem::path& stdpath, const char* u8_path) {
|
||||
|
|
|
@ -19,14 +19,14 @@ namespace LibCmo::EncodingHelper {
|
|||
|
||||
bool GetWindowsCodePage(const char* u8_encoding_spec, UINT* result);
|
||||
|
||||
bool WcharToChar(const wchar_t* src, std::string& dest, UINT codepage);
|
||||
bool WcharToChar(std::wstring& src, std::string& dest, UINT codepage);
|
||||
bool WcharToChar(const wchar_t* src, std::string& dest, const UINT codepage);
|
||||
bool WcharToChar(const std::wstring& src, std::string& dest, const UINT codepage);
|
||||
|
||||
bool CharToWchar(const char* src, std::wstring& dest, UINT codepage);
|
||||
bool CharToWchar(std::string& src, std::wstring& dest, UINT codepage);
|
||||
bool CharToWchar(const char* src, std::wstring& dest, const UINT codepage);
|
||||
bool CharToWchar(const std::string& src, std::wstring& dest, const 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);
|
||||
bool CharToChar(const char* src, std::string& dest, const UINT src_codepage, const UINT dest_codepage);
|
||||
bool CharToChar(const std::string& src, std::string& dest, const UINT src_codepage, const UINT dest_codepage);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -52,11 +52,11 @@ namespace LibCmo::EncodingHelper {
|
|||
|
||||
#endif
|
||||
|
||||
ENCODING_TOKEN CreateEncodingToken(std::string& token_string);
|
||||
void DestroyEncodingToken(ENCODING_TOKEN token);
|
||||
ENCODING_TOKEN CreateEncodingToken(const std::string& token_string);
|
||||
void DestroyEncodingToken(const 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);
|
||||
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* OpenStdPathFile(std::filesystem::path& u8_filepath, bool is_read);
|
||||
|
|
|
@ -9,17 +9,12 @@
|
|||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
/* TODO:
|
||||
do not re-allocated ctx and file for each loading in future.
|
||||
this will be implemented by free all objects within doc.
|
||||
|
||||
split encoding and temp folder setting
|
||||
and load command only have file name arg.
|
||||
*/
|
||||
#include <functional>
|
||||
|
||||
namespace Unvirt::CmdHelper {
|
||||
|
||||
static FILE* fout = stdout;
|
||||
|
||||
#pragma region CmdSplitter
|
||||
|
||||
CmdSplitter::CmdSplitter() :
|
||||
|
@ -42,7 +37,11 @@ namespace Unvirt::CmdHelper {
|
|||
// split
|
||||
for (auto it = u8cmd.begin(); it != u8cmd.end(); ++it) {
|
||||
mCmdChar = (*it);
|
||||
if (!std::isprint(mCmdChar)) continue; // skip all invalid characters
|
||||
|
||||
// skip all invalid characters, \0 and etc.
|
||||
// mCmdChar >= 0 to ensure all non-ASCII UTF8 char can be accepted directly.
|
||||
if (mCmdChar >= 0 && (!std::isprint(mCmdChar)))
|
||||
continue;
|
||||
|
||||
switch (mState) {
|
||||
case StateType::SPACE:
|
||||
|
@ -135,20 +134,54 @@ namespace Unvirt::CmdHelper {
|
|||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region InteractiveCmd
|
||||
#pragma region InteractiveCmd Misc
|
||||
|
||||
InteractiveCmd::InteractiveCmd() :
|
||||
m_CmdSplitter(), m_PageLen(10),
|
||||
m_Ctx(nullptr), m_File(nullptr), m_Doc(nullptr) {
|
||||
|
||||
// create context and file
|
||||
m_Ctx = new LibCmo::CK2::CKMinContext();
|
||||
m_File = new LibCmo::CK2::CKFile(m_Ctx);
|
||||
|
||||
// bind callback
|
||||
m_Ctx->SetPrintCallback(std::bind(&InteractiveCmd::PrintMinContextMsg, this, std::placeholders::_1));
|
||||
|
||||
}
|
||||
|
||||
InteractiveCmd::~InteractiveCmd() {
|
||||
// delete doc if necessary
|
||||
if (m_Doc != nullptr) delete m_Doc;
|
||||
if (m_File != nullptr) delete m_File;
|
||||
if (m_Ctx != nullptr) delete m_Ctx;
|
||||
// delete file and ctx
|
||||
delete m_File;
|
||||
delete m_Ctx;
|
||||
}
|
||||
|
||||
bool InteractiveCmd::HasOpenedFile(void) {
|
||||
return m_Doc != nullptr;
|
||||
}
|
||||
|
||||
void InteractiveCmd::ClearDocument(void) {
|
||||
if (m_Doc == nullptr) return;
|
||||
|
||||
// clear doc
|
||||
delete m_Doc;
|
||||
m_Doc = nullptr;
|
||||
|
||||
// clear all loaded objects
|
||||
m_Ctx->ClearCKObject();
|
||||
}
|
||||
|
||||
void InteractiveCmd::PrintMinContextMsg(const std::string& msg) {
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("[CKMinContext] ")), fout);
|
||||
fputs(msg.c_str(), fout);
|
||||
fputc('\n', fout);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region InteractiveCmd Dispatch
|
||||
|
||||
void InteractiveCmd::Run(void) {
|
||||
std::string u8cmd;
|
||||
|
||||
|
@ -174,6 +207,8 @@ namespace Unvirt::CmdHelper {
|
|||
else if (subcmd == "info") this->ProcInfo(cmds);
|
||||
else if (subcmd == "ls") this->ProcLs(cmds);
|
||||
else if (subcmd == "items") this->ProcItems(cmds);
|
||||
else if (subcmd == "encoding") this->ProcEncoding(cmds);
|
||||
else if (subcmd == "temp") this->ProcTemp(cmds);
|
||||
else if (subcmd == "help") this->PrintHelp();
|
||||
else if (subcmd == "exit") break;
|
||||
else {
|
||||
|
@ -185,7 +220,7 @@ namespace Unvirt::CmdHelper {
|
|||
}
|
||||
|
||||
void InteractiveCmd::GetCmdLine(std::string& u8cmd) {
|
||||
fputs("Unvirt> ", stdout);
|
||||
fputs("Unvirt> ", fout);
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
std::wstring wcmd;
|
||||
std::getline(std::wcin, wcmd);
|
||||
|
@ -195,45 +230,48 @@ namespace Unvirt::CmdHelper {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool InteractiveCmd::HasOpenedFile(void) {
|
||||
return (m_Ctx != nullptr || m_File != nullptr || m_Doc != nullptr);
|
||||
}
|
||||
|
||||
void InteractiveCmd::PrintHelp(void) {
|
||||
FILE* f = stdout;
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Subcommands: \n")), f);
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Subcommands: \n")), fout);
|
||||
|
||||
fputs("load\n", f);
|
||||
fputs("\tDescription: Load a Virtools composition.\n", f);
|
||||
fputs("\tSyntax: load <file path> [encoding] [temp path]\n", f);
|
||||
fputs("load\n", fout);
|
||||
fputs("\tDescription: Load a Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: load <file path>\n", fout);
|
||||
|
||||
fputs("unload\n", f);
|
||||
fputs("\tDescription: Release loaded Virtools composition.\n", f);
|
||||
fputs("\tSyntax: unload\n", f);
|
||||
fputs("unload\n", fout);
|
||||
fputs("\tDescription: Release loaded Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: unload\n", fout);
|
||||
|
||||
fputs("info\n", f);
|
||||
fputs("\tDescription: Show the header info of loaded Virtools composition.\n", f);
|
||||
fputs("\tSyntax: info\n", f);
|
||||
fputs("info\n", fout);
|
||||
fputs("\tDescription: Show the header info of loaded Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: info\n", fout);
|
||||
|
||||
fputs("ls\n", f);
|
||||
fputs("\tDescription: List something about loaded Virtools composition.\n", f);
|
||||
fputs("\tSyntax: ls <obj | mgr> [page]\n", f);
|
||||
fputs("ls\n", fout);
|
||||
fputs("\tDescription: List something about loaded Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: ls <obj | mgr> [page]\n", fout);
|
||||
|
||||
fputs("items\n", f);
|
||||
fputs("\tDescription: Set up how many items should be listed in one page when using \"ls\" command.\n", f);
|
||||
fputs("\tSyntax: items <num>\n", f);
|
||||
fputs("items\n", fout);
|
||||
fputs("\tDescription: Set up how many items should be listed in one page when using \"ls\" command.\n", fout);
|
||||
fputs("\tSyntax: items <num>\n", fout);
|
||||
|
||||
fputs("exit\n", f);
|
||||
fputs("\tDescription: Exit program\n", f);
|
||||
fputs("\tSyntax: exit\n", f);
|
||||
fputs("encoding\n", fout);
|
||||
fputs("\tDescription: Set the encoding series for CKMinContext.\n", fout);
|
||||
fputs("\tSyntax: encoding [encoding name1] [encoding name2] [encoding name3] ...\n", fout);
|
||||
|
||||
fputs("temp\n", fout);
|
||||
fputs("\tDescription: Set the Temp path for CKMinContext.\n", fout);
|
||||
fputs("\tSyntax: temp <temp path>\n", fout);
|
||||
|
||||
fputs("exit\n", fout);
|
||||
fputs("\tDescription: Exit program\n", fout);
|
||||
fputs("\tSyntax: exit\n", fout);
|
||||
|
||||
}
|
||||
|
||||
void InteractiveCmd::PrintArgParseError(const std::deque<std::string>& cmd, size_t pos) {
|
||||
if (pos >= cmd.size()) {
|
||||
fprintf(stdout, UNVIRT_TERMCOL_LIGHT_RED(("Lost argument at position %zu.\n")), pos);
|
||||
fprintf(fout, UNVIRT_TERMCOL_LIGHT_RED(("Lost argument at position %zu.\n")), pos);
|
||||
} else {
|
||||
fprintf(stdout, UNVIRT_TERMCOL_LIGHT_RED(("Unexpected argument \"%s\".\n")), cmd[pos].c_str());
|
||||
fprintf(fout, UNVIRT_TERMCOL_LIGHT_RED(("Unexpected argument \"%s\".\n")), cmd[pos].c_str());
|
||||
}
|
||||
|
||||
// arg error always print help
|
||||
|
@ -243,17 +281,17 @@ namespace Unvirt::CmdHelper {
|
|||
void InteractiveCmd::PrintCommonError(const char* u8_fmt, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, u8_fmt);
|
||||
std::fputs(UNVIRT_TERMCOLHDR_LIGHT_RED, stdout);
|
||||
std::vfprintf(stdout, u8_fmt, argptr);
|
||||
std::fputs(UNVIRT_TERMCOLTAIL, stdout);
|
||||
std::fputs(UNVIRT_TERMCOLHDR_LIGHT_RED, fout);
|
||||
std::vfprintf(fout, u8_fmt, argptr);
|
||||
std::fputs(UNVIRT_TERMCOLTAIL, fout);
|
||||
va_end(argptr);
|
||||
std::fputc('\n', stdout);
|
||||
std::fputc('\n', fout);
|
||||
}
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Command Processors
|
||||
#pragma region InteractiveCmd Processors
|
||||
|
||||
void InteractiveCmd::ProcLoad(const std::deque<std::string>& cmd) {
|
||||
// check pre-requirement
|
||||
|
@ -269,25 +307,8 @@ namespace Unvirt::CmdHelper {
|
|||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
++pos;
|
||||
std::string encoding;
|
||||
if (!ArgParser::ParseString(cmd, pos, encoding)) {
|
||||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
++pos;
|
||||
std::string temppath;
|
||||
if (!ArgParser::ParseString(cmd, pos, temppath)) {
|
||||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
// proc
|
||||
m_Ctx = new LibCmo::CK2::CKMinContext();
|
||||
m_Ctx->SetEncoding(encoding.c_str());
|
||||
m_Ctx->SetTempPath(temppath.c_str());
|
||||
|
||||
m_File = new LibCmo::CK2::CKFile(m_Ctx);
|
||||
m_Doc = new LibCmo::CK2::CKFileDocument();
|
||||
LibCmo::CK2::CKERROR err = m_File->DeepLoad(filepath.c_str(), &m_Doc);
|
||||
if (err != LibCmo::CK2::CKERROR::CKERR_OK) {
|
||||
|
@ -297,13 +318,7 @@ namespace Unvirt::CmdHelper {
|
|||
Unvirt::AccessibleValue::GetCkErrorDescription(err).c_str()
|
||||
);
|
||||
|
||||
if (m_Doc != nullptr) delete m_Doc;
|
||||
if (m_File != nullptr) delete m_File;
|
||||
if (m_Ctx != nullptr) delete m_Ctx;
|
||||
|
||||
m_Doc = nullptr;
|
||||
m_File = nullptr;
|
||||
m_Ctx = nullptr;
|
||||
this->ClearDocument();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,13 +330,7 @@ namespace Unvirt::CmdHelper {
|
|||
}
|
||||
|
||||
// free all
|
||||
if (m_Doc != nullptr) delete m_Doc;
|
||||
if (m_File != nullptr) delete m_File;
|
||||
if (m_Ctx != nullptr) delete m_Ctx;
|
||||
|
||||
m_Doc = nullptr;
|
||||
m_File = nullptr;
|
||||
m_Ctx = nullptr;
|
||||
this->ClearDocument();
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcInfo(const std::deque<std::string>& cmd) {
|
||||
|
@ -356,10 +365,14 @@ namespace Unvirt::CmdHelper {
|
|||
}
|
||||
++pos;
|
||||
int32_t gotten_page;
|
||||
if (!ArgParser::ParseInt(cmd, pos, gotten_page) || gotten_page <= 0) {
|
||||
gotten_page = 0; // asssume as zero
|
||||
if (!ArgParser::ParseInt(cmd, pos, gotten_page)) {
|
||||
gotten_page = 1; // asssume as 1
|
||||
}
|
||||
size_t page = static_cast<size_t>(gotten_page);
|
||||
if (gotten_page <= 0) {
|
||||
this->PrintCommonError("Page out of range.");
|
||||
return;
|
||||
}
|
||||
size_t page = static_cast<size_t>(gotten_page) - 1;
|
||||
|
||||
// show list
|
||||
if (sw == c_AllowedSwitches[0]) {
|
||||
|
@ -396,383 +409,40 @@ namespace Unvirt::CmdHelper {
|
|||
m_PageLen = static_cast<size_t>(count);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
void InteractiveCmd::ProcEncoding(const std::deque<std::string>& cmd) {
|
||||
// create list first
|
||||
std::vector<std::string> encoding_list;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#pragma region OptionsDescription
|
||||
|
||||
OptionsDescription::OptionsDescription() :
|
||||
mLongNameDict(), mShortNameMapping(), mPositionalArgMapping() {
|
||||
;
|
||||
}
|
||||
OptionsDescription::~OptionsDescription() { ; }
|
||||
|
||||
void OptionsDescription::AddOption(
|
||||
const char* fullname, char shortname, CmdArgType type, const char* description) {
|
||||
// pre-check
|
||||
if (fullname == nullptr ||
|
||||
fullname[0] == '\0' ||
|
||||
fullname[0] == '-')
|
||||
throw std::invalid_argument("Invalid Option Long Name.");
|
||||
|
||||
// construct data
|
||||
std::string sfullname(fullname);
|
||||
OptionDescription data{
|
||||
fullname, shortname, type, (description != nullptr ? description : "")
|
||||
};
|
||||
|
||||
// check requirement
|
||||
if (mLongNameDict.contains(sfullname)) throw std::invalid_argument("Duplicated Option Long Name.");
|
||||
if (shortname != '\0')
|
||||
if (mShortNameMapping.contains(shortname)) throw std::invalid_argument("Duplicated Option Short Name.");
|
||||
|
||||
// add them
|
||||
mShortNameMapping.emplace(shortname, sfullname);
|
||||
mLongNameDict.emplace(sfullname, std::move(data));
|
||||
}
|
||||
|
||||
void OptionsDescription::AddPositionalOption(const char* corresponding_longname) {
|
||||
// pre-check
|
||||
if (corresponding_longname == nullptr) throw std::invalid_argument("Invalid Option Long Name.");
|
||||
|
||||
// construct data
|
||||
std::string fullname(corresponding_longname);
|
||||
|
||||
// check requirement
|
||||
if (!mLongNameDict.contains(fullname)) throw std::invalid_argument("No Matched Option.");
|
||||
if (!mPositionalArgMapping.empty()) {
|
||||
for (const auto& i : mPositionalArgMapping) {
|
||||
if (i == fullname)throw std::invalid_argument("Duplicated Option.");
|
||||
}
|
||||
// get list item
|
||||
size_t pos = 0u;
|
||||
while (true) {
|
||||
std::string pending;
|
||||
if (!ArgParser::ParseString(cmd, pos, pending)) {
|
||||
break; // no more encoding, break
|
||||
}
|
||||
|
||||
// set value
|
||||
mPositionalArgMapping.push_back(std::move(fullname));
|
||||
// add and move to next
|
||||
++pos;
|
||||
encoding_list.push_back(std::move(pending));
|
||||
}
|
||||
|
||||
OptionDescription* OptionsDescription::GetDescByLongName(const std::string& longname) {
|
||||
const auto search = mLongNameDict.find(longname);
|
||||
if (search == mLongNameDict.end()) return nullptr;
|
||||
return &(*search).second;
|
||||
}
|
||||
OptionDescription* OptionsDescription::GetDescByShortName(const char shortname) {
|
||||
const auto search = mShortNameMapping.find(shortname);
|
||||
if (search == mShortNameMapping.end()) return nullptr;
|
||||
return GetDescByLongName((*search).second);
|
||||
}
|
||||
OptionDescription* OptionsDescription::GetDescByPosition(size_t pos) {
|
||||
if (pos >= mPositionalArgMapping.size()) return nullptr;
|
||||
return GetDescByLongName(mPositionalArgMapping[pos]);
|
||||
}
|
||||
|
||||
void OptionsDescription::PrintHelp(FILE* f) {
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Options: \n")), f);
|
||||
for (const auto& [key, value] : mLongNameDict) {
|
||||
fprintf(f, "--%s\t%s\n", value.mLongName.c_str(), value.mDescription.c_str());
|
||||
}
|
||||
|
||||
if (!mPositionalArgMapping.empty()) {
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("\nPositional Options: \n")), f);
|
||||
for (const auto& i : mPositionalArgMapping) {
|
||||
fprintf(f, "[%s] ", i.c_str());
|
||||
}
|
||||
}
|
||||
// apply list
|
||||
this->m_Ctx->SetEncoding(encoding_list);
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcTemp(const std::deque<std::string>& cmd) {
|
||||
// check requirement
|
||||
size_t pos = 0u;
|
||||
std::string temppath;
|
||||
if (!ArgParser::ParseString(cmd, pos, temppath)) {
|
||||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
// assign
|
||||
m_Ctx->SetTempPath(temppath.c_str());
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region VariablesMap
|
||||
|
||||
VariablesMap::VariablesMap() : mDataPair() {
|
||||
;
|
||||
}
|
||||
VariablesMap::~VariablesMap() {
|
||||
this->Clear();
|
||||
}
|
||||
|
||||
void VariablesMap::Clear(void) {
|
||||
for (const auto& [key, value] : mDataPair) {
|
||||
if (value.mData != nullptr) free(value.mData);
|
||||
}
|
||||
mDataPair.clear();
|
||||
}
|
||||
|
||||
bool VariablesMap::AddPair(const std::string& name, CmdArgType t, const std::string& val) {
|
||||
if (mDataPair.contains(name)) return false;
|
||||
|
||||
AnyVariable var;
|
||||
switch (t) {
|
||||
case Unvirt::CmdHelper::CmdArgType::NONE:
|
||||
{
|
||||
var.mDataBasicSize = 1;
|
||||
var.mData = nullptr;
|
||||
break;
|
||||
}
|
||||
case Unvirt::CmdHelper::CmdArgType::STRING:
|
||||
{
|
||||
var.mDataBasicSize = sizeof(char);
|
||||
var.mData = malloc(val.size() + 1);
|
||||
if (var.mData == nullptr) break;
|
||||
|
||||
memcpy(var.mData, val.c_str(), val.size() + 1);
|
||||
break;
|
||||
}
|
||||
case Unvirt::CmdHelper::CmdArgType::INT:
|
||||
{
|
||||
var.mDataBasicSize = sizeof(int);
|
||||
var.mData = malloc(sizeof(int));
|
||||
if (var.mData == nullptr) break;
|
||||
|
||||
char* pend = nullptr;
|
||||
errno = 0;
|
||||
int64_t v = std::strtoll(val.c_str(), &pend, 10);
|
||||
|
||||
if (pend == val.c_str() || errno == ERANGE) v = INT64_C(0);
|
||||
*((int*)var.mData) = static_cast<int>(v);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::invalid_argument("Invalid Option Type.");
|
||||
}
|
||||
|
||||
mDataPair.emplace(name, std::move(var));
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region 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<char>("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<char>("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(), 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");
|
||||
entryLoad.mOptDesc.AddOption("encoding", 'e', CmdArgType::STRING, "The encoding to decode Virtools string.");
|
||||
entryLoad.mOptDesc.AddPositionalOption("encoding");
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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<std::string>& args) {
|
||||
FILE* f = stdout;
|
||||
|
||||
if (args.size() == 0) {
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Error! Fail to get subcommand token.\n")), f);
|
||||
PrintHelp(f);
|
||||
return;
|
||||
}
|
||||
|
||||
auto arg = args.begin();
|
||||
auto subcmd = mCmdDispatcher.find(*arg);
|
||||
if (subcmd == mCmdDispatcher.end()) {
|
||||
fprintf(f, UNVIRT_TERMCOL_LIGHT_RED(("Error! No such subcommand \"%s\"! \n")), arg->c_str());
|
||||
PrintHelp(f);
|
||||
return;
|
||||
}
|
||||
|
||||
// analyze options
|
||||
++arg;
|
||||
auto& optsDesc = subcmd->second.mOptDesc;
|
||||
mVm.Clear();
|
||||
int position_counter = 0;
|
||||
while (true) {
|
||||
if (arg == args.end()) break;
|
||||
|
||||
const std::string& opt = *arg;
|
||||
OptionDescription* optDesc;
|
||||
if (opt.starts_with("--")) {
|
||||
// long name
|
||||
optDesc = optsDesc.GetDescByLongName(opt.substr(2));
|
||||
} else if (opt.starts_with("-")) {
|
||||
// short name
|
||||
if (opt.size() != 2u) {
|
||||
// invalid short name
|
||||
fprintf(f, UNVIRT_TERMCOL_LIGHT_RED(("Error! Invalid short name option \"%s\"! \n")), opt.c_str());
|
||||
optsDesc.PrintHelp(f);
|
||||
return;
|
||||
}
|
||||
optDesc = optsDesc.GetDescByShortName(opt[1]);
|
||||
} else {
|
||||
// position
|
||||
optDesc = optsDesc.GetDescByPosition(position_counter++);
|
||||
}
|
||||
|
||||
// invalid option
|
||||
if (optDesc == nullptr) {
|
||||
fprintf(f, UNVIRT_TERMCOL_LIGHT_RED(("Error! Invalid option \"%s\"! \n")), opt.c_str());
|
||||
optsDesc.PrintHelp(f);
|
||||
return;
|
||||
}
|
||||
|
||||
// get value
|
||||
bool add_success = true;
|
||||
switch (optDesc->mType) {
|
||||
case CmdArgType::NONE:
|
||||
// just a switch
|
||||
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:
|
||||
// check next value
|
||||
++arg;
|
||||
if (arg == args.end()) {
|
||||
fprintf(f, UNVIRT_TERMCOL_LIGHT_RED(("Error! Option \"%s\" lost parameter! \n")), opt.c_str());
|
||||
optsDesc.PrintHelp(f);
|
||||
return;
|
||||
}
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
// execute proc
|
||||
subcmd->second.mBindProc(optsDesc, mVm);
|
||||
}
|
||||
|
||||
void InteractiveCmd::PrintHelp(FILE* f) {
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Subcommands: \n")), f);
|
||||
for (const auto& [key, value] : mCmdDispatcher) {
|
||||
fprintf(f, "%s\t- %s\n", key.c_str(), value.mSubCmdDesc.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcExit(OptionsDescription&, VariablesMap&) {
|
||||
mExitRunFlag = true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -143,7 +143,6 @@ namespace Unvirt::CmdHelper {
|
|||
|
||||
private:
|
||||
void GetCmdLine(std::string& u8cmd);
|
||||
bool HasOpenedFile(void);
|
||||
void PrintHelp(void);
|
||||
void PrintArgParseError(const std::deque<std::string>& cmd, size_t pos);
|
||||
void PrintCommonError(const char* u8_fmt, ...);
|
||||
|
@ -153,6 +152,12 @@ namespace Unvirt::CmdHelper {
|
|||
void ProcInfo(const std::deque<std::string>& cmd);
|
||||
void ProcLs(const std::deque<std::string>& cmd);
|
||||
void ProcItems(const std::deque<std::string>& cmd);
|
||||
void ProcEncoding(const std::deque<std::string>& cmd);
|
||||
void ProcTemp(const std::deque<std::string>& cmd);
|
||||
|
||||
bool HasOpenedFile(void);
|
||||
void ClearDocument(void);
|
||||
void PrintMinContextMsg(const std::string& msg);
|
||||
|
||||
CmdSplitter m_CmdSplitter;
|
||||
size_t m_PageLen;
|
||||
|
@ -161,132 +166,4 @@ namespace Unvirt::CmdHelper {
|
|||
LibCmo::CK2::CKFileDocument* m_Doc;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
|
||||
enum class CmdArgType {
|
||||
NONE,
|
||||
STRING,
|
||||
INT
|
||||
};
|
||||
|
||||
struct OptionDescription {
|
||||
std::string mLongName;
|
||||
char mShortName;
|
||||
CmdArgType mType;
|
||||
std::string mDescription;
|
||||
};
|
||||
|
||||
class OptionsDescription {
|
||||
public:
|
||||
OptionsDescription();
|
||||
OptionsDescription(const OptionsDescription&) = delete;
|
||||
OptionsDescription& operator=(const OptionsDescription&) = delete;
|
||||
~OptionsDescription();
|
||||
|
||||
/// <summary>
|
||||
/// Add an option
|
||||
/// </summary>
|
||||
/// <param name="fullname">The long name of this option. Should NOT be blank or NULL.</param>
|
||||
/// <param name="shortname">A single char for the short name of this option. Leave ZERO to omit this.</param>
|
||||
/// <param name="type">The value type of this option. Set to CmdArgType::NONE to indicate this is a switch (no value).</param>
|
||||
/// <param name="sescription">The description of this option. This can be NULL.</param>
|
||||
void AddOption(const char* fullname, char shortname, CmdArgType type, const char* sescription);
|
||||
void AddPositionalOption(const char* corresponding_longname);
|
||||
|
||||
OptionDescription* GetDescByLongName(const std::string& longname);
|
||||
OptionDescription* GetDescByShortName(char shortname);
|
||||
OptionDescription* GetDescByPosition(size_t pos);
|
||||
|
||||
void PrintHelp(FILE* f);
|
||||
private:
|
||||
std::unordered_map<std::string, OptionDescription> mLongNameDict;
|
||||
std::unordered_map<char, std::string> mShortNameMapping;
|
||||
std::vector<std::string> mPositionalArgMapping;
|
||||
};
|
||||
|
||||
struct AnyVariable {
|
||||
size_t mDataBasicSize;
|
||||
void* mData;
|
||||
};
|
||||
|
||||
class VariablesMap {
|
||||
private:
|
||||
std::unordered_map<std::string, AnyVariable> mDataPair;
|
||||
|
||||
public:
|
||||
VariablesMap();
|
||||
VariablesMap(const VariablesMap&) = delete;
|
||||
VariablesMap& operator=(const VariablesMap&) = delete;
|
||||
~VariablesMap();
|
||||
|
||||
void Clear(void);
|
||||
/// <summary>
|
||||
/// Add option key value pair.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="val"></param>
|
||||
/// <returns>return false when this opt is existed.</returns>
|
||||
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);
|
||||
}
|
||||
template<typename T>
|
||||
T* GetData(const char* opt) {
|
||||
if (opt == nullptr) throw std::invalid_argument("Invalid Option Name.");
|
||||
const auto search = mDataPair.find(opt);
|
||||
if (search == mDataPair.end()) return nullptr;
|
||||
|
||||
if (sizeof(T) > search->second.mDataBasicSize) throw std::invalid_argument("Memory Violation.");
|
||||
return reinterpret_cast<T*>(search->second.mData);
|
||||
}
|
||||
};
|
||||
|
||||
struct CmdRegisteryEntry {
|
||||
std::string mSubCmdDesc;
|
||||
OptionsDescription mOptDesc;
|
||||
std::function<void(OptionsDescription&, VariablesMap&)> mBindProc;
|
||||
};
|
||||
|
||||
class ExecEnvironment {
|
||||
public:
|
||||
ExecEnvironment();
|
||||
ExecEnvironment(const ExecEnvironment&) = delete;
|
||||
ExecEnvironment& operator=(const ExecEnvironment&) = delete;
|
||||
~ExecEnvironment();
|
||||
|
||||
void ProcLoad(OptionsDescription&, VariablesMap&);
|
||||
void ProcInfo(OptionsDescription&, VariablesMap&);
|
||||
void ProcClear(OptionsDescription&, VariablesMap&);
|
||||
void ProcExportSql(OptionsDescription&, VariablesMap&);
|
||||
private:
|
||||
LibCmo::CKFile* mVtFile;
|
||||
LibCmo::Utils::VirtoolsContext* mVtFileEnv;
|
||||
};
|
||||
|
||||
class InteractiveCmd {
|
||||
public:
|
||||
InteractiveCmd();
|
||||
InteractiveCmd(const InteractiveCmd&) = delete;
|
||||
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
||||
~InteractiveCmd();
|
||||
|
||||
private:
|
||||
void GetCmdLine(std::string& u8cmd);
|
||||
void CmdParser(const std::vector<std::string>& args);
|
||||
void PrintHelp(FILE* f);
|
||||
|
||||
void ProcExit(OptionsDescription&, VariablesMap&);
|
||||
|
||||
std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher;
|
||||
CmdSplitter mCmdSplitter;
|
||||
ExecEnvironment mExecEnv;
|
||||
VariablesMap mVm;
|
||||
std::string mBlank;
|
||||
bool mExitRunFlag;
|
||||
};
|
||||
|
||||
*/
|
||||
}
|
|
@ -78,13 +78,14 @@ namespace Unvirt::StructFormatter {
|
|||
fullpage = fulllen / pageitems;
|
||||
|
||||
// print header
|
||||
fputs("Index\tCK ID\tCKObject\tCKStateChunk\tName\n", fout);
|
||||
fputs("CK ID\tType\tCKObject\tCKStateChunk\tName\n", fout);
|
||||
|
||||
// print body
|
||||
for (size_t counter = startpos; counter < fulllen && (counter - startpos) < pageitems; ++counter) {
|
||||
const auto& obj = ls[counter];
|
||||
|
||||
fprintf(stdout, "%zu\t%" PRIu32 "\t", counter, obj.ObjectId);
|
||||
fprintf(fout, "%" PRIu32 "\t", obj.ObjectId);
|
||||
fprintf(fout, "%s\t", Unvirt::AccessibleValue::GetClassIdName(obj.ObjectCid).c_str());
|
||||
PrintPointer(obj.ObjPtr);
|
||||
fputc('\t', fout);
|
||||
PrintPointer(obj.Data);
|
||||
|
@ -93,7 +94,7 @@ namespace Unvirt::StructFormatter {
|
|||
fputc('\n', fout);
|
||||
}
|
||||
|
||||
fprintf(fout, "Page %zu of %zu\n", page, fullpage);
|
||||
fprintf(fout, "Page %zu of %zu\n", page + 1, fullpage + 1);
|
||||
}
|
||||
|
||||
void PrintManagerList(const LibCmo::CK2::XArray<LibCmo::CK2::CKFileManagerData>& ls, size_t page, size_t pageitems) {
|
||||
|
@ -104,13 +105,12 @@ namespace Unvirt::StructFormatter {
|
|||
fullpage = fulllen / pageitems;
|
||||
|
||||
// print header
|
||||
fputs("Index\tCKGUID\tCKBaseManager\tCKStateChunk\n", fout);
|
||||
fputs("CKGUID\tCKBaseManager\tCKStateChunk\n", fout);
|
||||
|
||||
// print body
|
||||
for (size_t counter = startpos; counter < fulllen && (counter - startpos) < pageitems; ++counter) {
|
||||
const auto& mgr = ls[counter];
|
||||
|
||||
fprintf(stdout, "%zu\t", counter);
|
||||
PrintCKGUID(mgr.Manager);
|
||||
fputc('\t', fout);
|
||||
PrintPointer(mgr.MgrPtr);
|
||||
|
@ -119,7 +119,7 @@ namespace Unvirt::StructFormatter {
|
|||
fputc('\n', fout);
|
||||
}
|
||||
|
||||
fprintf(fout, "Page %zu of %zu\n", page, fullpage);
|
||||
fprintf(fout, "Page %zu of %zu\n", page + 1, fullpage + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user