update shit
This commit is contained in:
@ -1,78 +1,243 @@
|
||||
#include "CmdHelper.hpp"
|
||||
#include "TerminalHelper.hpp"
|
||||
#include "VTUtils.hpp"
|
||||
#include "VTEncoding.hpp"
|
||||
|
||||
#include <CKMinContext.hpp>
|
||||
#include <CKFile.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
/*
|
||||
|
||||
namespace Unvirt {
|
||||
namespace CmdHelper {
|
||||
namespace Unvirt::CmdHelper {
|
||||
|
||||
#pragma region CmdSplitter
|
||||
|
||||
CmdSplitter::CmdSplitter() :
|
||||
mCmdChar(0), mBuffer(nullptr), mResult(nullptr),
|
||||
mState(StateType::NORMAL), mPreState(StateType::NORMAL) {
|
||||
;
|
||||
}
|
||||
CmdSplitter::~CmdSplitter() {
|
||||
;
|
||||
}
|
||||
CmdSplitter::CmdSplitter() :
|
||||
mCmdChar(0), mBuffer(nullptr), mResult(nullptr),
|
||||
mState(StateType::NORMAL), mPreState(StateType::NORMAL) {
|
||||
;
|
||||
}
|
||||
CmdSplitter::~CmdSplitter() {
|
||||
;
|
||||
}
|
||||
|
||||
const std::vector<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
|
||||
// set up variables
|
||||
std::vector<std::string> result;
|
||||
std::string buffer;
|
||||
mBuffer = &buffer;
|
||||
mResult = &result;
|
||||
mState = mPreState = StateType::SPACE;
|
||||
const std::deque<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
|
||||
// set up variables
|
||||
std::deque<std::string> result;
|
||||
std::string buffer;
|
||||
mBuffer = &buffer;
|
||||
mResult = &result;
|
||||
mState = mPreState = StateType::SPACE;
|
||||
|
||||
// split
|
||||
for (auto it = u8cmd.begin(); it != u8cmd.end(); ++it) {
|
||||
mCmdChar = (*it);
|
||||
// split
|
||||
for (auto it = u8cmd.begin(); it != u8cmd.end(); ++it) {
|
||||
mCmdChar = (*it);
|
||||
|
||||
switch (mState) {
|
||||
case StateType::SPACE:
|
||||
ProcSpace();
|
||||
break;
|
||||
case StateType::SINGLE:
|
||||
ProcSingle();
|
||||
break;
|
||||
case StateType::DOUBLE:
|
||||
ProcDouble();
|
||||
break;
|
||||
case StateType::ESCAPE:
|
||||
ProcEscape();
|
||||
break;
|
||||
case StateType::NORMAL:
|
||||
ProcNormal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// final proc
|
||||
switch (mState) {
|
||||
case StateType::SPACE:
|
||||
break;
|
||||
case StateType::NORMAL:
|
||||
// push the last one
|
||||
mResult->push_back(*mBuffer);
|
||||
ProcSpace();
|
||||
break;
|
||||
case StateType::SINGLE:
|
||||
ProcSingle();
|
||||
break;
|
||||
case StateType::DOUBLE:
|
||||
ProcDouble();
|
||||
break;
|
||||
case StateType::ESCAPE:
|
||||
// error
|
||||
result.clear();
|
||||
ProcEscape();
|
||||
break;
|
||||
case StateType::NORMAL:
|
||||
ProcNormal();
|
||||
break;
|
||||
}
|
||||
|
||||
// return value
|
||||
return result;
|
||||
}
|
||||
|
||||
// final proc
|
||||
switch (mState) {
|
||||
case StateType::SPACE:
|
||||
break;
|
||||
case StateType::NORMAL:
|
||||
// push the last one
|
||||
mResult->push_back(*mBuffer);
|
||||
break;
|
||||
case StateType::SINGLE:
|
||||
case StateType::DOUBLE:
|
||||
case StateType::ESCAPE:
|
||||
// error
|
||||
result.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
// return value
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ArgParser
|
||||
|
||||
bool ArgParser::ParseInt(const std::vector<std::string>& cmd, const size_t expected_index, int32_t& result) {
|
||||
if (expected_index >= cmd.size()) {
|
||||
result = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
char* pend = nullptr;
|
||||
errno = 0;
|
||||
int64_t v = std::strtoll(cmd[expected_index].c_str(), &pend, 10);
|
||||
|
||||
if (pend == cmd[expected_index].c_str() || errno == ERANGE) {
|
||||
result = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = static_cast<int>(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArgParser::ParseString(const std::vector<std::string>& cmd, const size_t expected_index, std::string& result) {
|
||||
if (expected_index >= cmd.size()) {
|
||||
result.clear();
|
||||
return false;
|
||||
} else {
|
||||
result = cmd[expected_index];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ArgParser::ParseSwitch(const std::vector<std::string>& cmd, const size_t expected_index, const std::vector<std::string>& switches, std::string& gotten) {
|
||||
if (expected_index >= cmd.size()) {
|
||||
gotten.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& sw : switches) {
|
||||
if (cmd[expected_index] == sw) {
|
||||
gotten = cmd[expected_index];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
gotten.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region InteractiveCmd
|
||||
|
||||
InteractiveCmd::InteractiveCmd() :
|
||||
m_CmdSplitter(), m_ExitRunFlag(false),
|
||||
m_Ctx(nullptr), m_Doc(nullptr) {
|
||||
|
||||
}
|
||||
|
||||
InteractiveCmd::~InteractiveCmd() {
|
||||
if (m_Doc != nullptr) delete m_Doc;
|
||||
if (m_Ctx != nullptr) delete m_Ctx;
|
||||
}
|
||||
|
||||
void InteractiveCmd::Run(void) {
|
||||
std::string u8cmd;
|
||||
|
||||
m_ExitRunFlag = false;
|
||||
while (!m_ExitRunFlag) {
|
||||
// get command
|
||||
GetCmdLine(u8cmd);
|
||||
|
||||
// split cmd and parse it
|
||||
auto cmds = m_CmdSplitter.Convert(u8cmd);
|
||||
|
||||
// get sub command
|
||||
if (cmds.size() < 1u) {
|
||||
this->PrintCommonError("No command specified!");
|
||||
this->PrintHelp();
|
||||
continue;
|
||||
}
|
||||
std::string subcmd(cmds.front());
|
||||
cmds.pop_front();
|
||||
|
||||
// dispatch command
|
||||
bool success = true;
|
||||
if (subcmd == "load") success = this->ProcLoad(cmds);
|
||||
else if (subcmd == "unload") success = this->ProcUnLoad(cmds);
|
||||
else if (subcmd == "info") success = this->ProcInfo(cmds);
|
||||
else if (subcmd == "ls") success = this->ProcLs(cmds);
|
||||
else {
|
||||
this->PrintCommonError("No such command \"\".", subcmd.c_str());
|
||||
this->PrintHelp();
|
||||
}
|
||||
|
||||
if (!success) this->PrintHelp();
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveCmd::GetCmdLine(std::string& u8cmd) {
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
std::wstring wcmd;
|
||||
std::getline(std::wcin, wcmd);
|
||||
LibCmo::EncodingHelper::WcharToChar(wcmd, u8cmd, CP_UTF8);
|
||||
#else
|
||||
std::getline(std::cin, u8cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool InteractiveCmd::HasOpenedFile(void) {
|
||||
return (m_Ctx != nullptr || m_Doc != nullptr);
|
||||
}
|
||||
|
||||
void InteractiveCmd::PrintHelp(void) {
|
||||
FILE* f = stdout;
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Subcommands: \n")), f);
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
fprintf(stdout, UNVIRT_TERMCOL_LIGHT_RED(("Unexpected argument \"%s\".\n")), cmd[pos].c_str());
|
||||
}
|
||||
|
||||
// arg error always print help
|
||||
this->PrintHelp();
|
||||
}
|
||||
|
||||
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);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Command Processors
|
||||
|
||||
bool InteractiveCmd::ProcLoad(const std::deque<std::string>& cmd) {
|
||||
}
|
||||
|
||||
bool InteractiveCmd::ProcUnLoad(const std::deque<std::string>& cmd) {
|
||||
}
|
||||
|
||||
bool InteractiveCmd::ProcInfo(const std::deque<std::string>& cmd) {
|
||||
}
|
||||
|
||||
bool InteractiveCmd::ProcLs(const std::deque<std::string>& cmd) {
|
||||
static const std::vector<std::string> c_AllowedSwitches {
|
||||
"obj", "mgr"
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#pragma region OptionsDescription
|
||||
|
||||
OptionsDescription::OptionsDescription() :
|
||||
@ -444,7 +609,7 @@ namespace Unvirt {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -1,256 +1,290 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <VTUtils.h>
|
||||
#include <CKDefines.hpp>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include "VTUtils.hpp"
|
||||
#include <deque>
|
||||
|
||||
/*
|
||||
namespace Unvirt::CmdHelper {
|
||||
|
||||
namespace Unvirt {
|
||||
namespace CmdHelper {
|
||||
class CmdSplitter {
|
||||
public:
|
||||
CmdSplitter();
|
||||
CmdSplitter(const CmdSplitter&) = delete;
|
||||
CmdSplitter& operator=(const CmdSplitter&) = delete;
|
||||
~CmdSplitter();
|
||||
|
||||
class CmdSplitter {
|
||||
public:
|
||||
CmdSplitter();
|
||||
CmdSplitter(const CmdSplitter&) = delete;
|
||||
CmdSplitter& operator=(const CmdSplitter&) = delete;
|
||||
~CmdSplitter();
|
||||
const std::deque<std::string> Convert(const std::string& u8cmd);
|
||||
private:
|
||||
char mCmdChar;
|
||||
std::string* mBuffer;
|
||||
std::deque<std::string>* mResult;
|
||||
|
||||
const std::vector<std::string> Convert(const std::string& u8cmd);
|
||||
private:
|
||||
char mCmdChar;
|
||||
std::string* mBuffer;
|
||||
std::vector<std::string>* mResult;
|
||||
enum class StateType : int {
|
||||
SPACE,
|
||||
SINGLE,
|
||||
DOUBLE,
|
||||
ESCAPE,
|
||||
NORMAL
|
||||
};
|
||||
StateType mState, mPreState;
|
||||
|
||||
enum class StateType : int {
|
||||
SPACE,
|
||||
SINGLE,
|
||||
DOUBLE,
|
||||
ESCAPE,
|
||||
NORMAL
|
||||
};
|
||||
StateType mState, mPreState;
|
||||
|
||||
inline void ProcSpace(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mState = StateType::SINGLE;
|
||||
break;
|
||||
case '"':
|
||||
mState = StateType::DOUBLE;
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::NORMAL;
|
||||
break;
|
||||
case ' ':
|
||||
break; // skip blank
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
mState = StateType::NORMAL;
|
||||
break;
|
||||
}
|
||||
inline void ProcSpace(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mState = StateType::SINGLE;
|
||||
break;
|
||||
case '"':
|
||||
mState = StateType::DOUBLE;
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::NORMAL;
|
||||
break;
|
||||
case ' ':
|
||||
break; // skip blank
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
mState = StateType::NORMAL;
|
||||
break;
|
||||
}
|
||||
inline void ProcSingle(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mState = StateType::NORMAL;
|
||||
break;
|
||||
case '"':
|
||||
mBuffer->push_back('"');
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::SINGLE;
|
||||
break;
|
||||
case ' ':
|
||||
mBuffer->push_back(' ');
|
||||
break;
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
inline void ProcSingle(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mState = StateType::NORMAL;
|
||||
break;
|
||||
case '"':
|
||||
mBuffer->push_back('"');
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::SINGLE;
|
||||
break;
|
||||
case ' ':
|
||||
mBuffer->push_back(' ');
|
||||
break;
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
break;
|
||||
}
|
||||
inline void ProcDouble(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mBuffer->push_back('\'');
|
||||
break;
|
||||
case '"':
|
||||
mState = StateType::NORMAL;
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::DOUBLE;
|
||||
break;
|
||||
case ' ':
|
||||
mBuffer->push_back(' ');
|
||||
break;
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
inline void ProcDouble(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mBuffer->push_back('\'');
|
||||
break;
|
||||
case '"':
|
||||
mState = StateType::NORMAL;
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::DOUBLE;
|
||||
break;
|
||||
case ' ':
|
||||
mBuffer->push_back(' ');
|
||||
break;
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
break;
|
||||
}
|
||||
inline void ProcEscape(void) {
|
||||
// add itself
|
||||
mBuffer->push_back(mCmdChar);
|
||||
// restore state
|
||||
mState = mPreState;
|
||||
}
|
||||
inline void ProcEscape(void) {
|
||||
// add itself
|
||||
mBuffer->push_back(mCmdChar);
|
||||
// restore state
|
||||
mState = mPreState;
|
||||
}
|
||||
inline void ProcNormal(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mBuffer->push_back('\'');
|
||||
break;
|
||||
case '"':
|
||||
mBuffer->push_back('"');
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::NORMAL;
|
||||
break;
|
||||
case ' ':
|
||||
mResult->push_back(*mBuffer);
|
||||
mBuffer->clear();
|
||||
mState = StateType::SPACE;
|
||||
break;
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
break;
|
||||
}
|
||||
inline void ProcNormal(void) {
|
||||
switch (mCmdChar) {
|
||||
case '\'':
|
||||
mBuffer->push_back('\'');
|
||||
break;
|
||||
case '"':
|
||||
mBuffer->push_back('"');
|
||||
break;
|
||||
case '\\':
|
||||
mState = StateType::ESCAPE;
|
||||
mPreState = StateType::NORMAL;
|
||||
break;
|
||||
case ' ':
|
||||
mResult->push_back(*mBuffer);
|
||||
mBuffer->clear();
|
||||
mState = StateType::SPACE;
|
||||
break;
|
||||
default:
|
||||
mBuffer->push_back(mCmdChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
enum class CmdArgType {
|
||||
NONE,
|
||||
STRING,
|
||||
INT
|
||||
};
|
||||
class ArgParser {
|
||||
public:
|
||||
ArgParser() {}
|
||||
ArgParser(const ArgParser&) = delete;
|
||||
ArgParser& operator=(const ArgParser&) = delete;
|
||||
~ArgParser() {}
|
||||
|
||||
struct OptionDescription {
|
||||
std::string mLongName;
|
||||
char mShortName;
|
||||
CmdArgType mType;
|
||||
std::string mDescription;
|
||||
};
|
||||
static bool ParseInt(const std::vector<std::string>& cmd, const size_t expected_index, int32_t& result);
|
||||
static bool ParseString(const std::vector<std::string>& cmd, const size_t expected_index, std::string& result);
|
||||
static bool ParseSwitch(const std::vector<std::string>& cmd, const size_t expected_index, const std::vector<std::string>& switches, std::string& gotten);
|
||||
};
|
||||
|
||||
class OptionsDescription {
|
||||
public:
|
||||
OptionsDescription();
|
||||
OptionsDescription(const OptionsDescription&) = delete;
|
||||
OptionsDescription& operator=(const OptionsDescription&) = delete;
|
||||
~OptionsDescription();
|
||||
class InteractiveCmd {
|
||||
public:
|
||||
InteractiveCmd();
|
||||
InteractiveCmd(const InteractiveCmd&) = delete;
|
||||
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
||||
~InteractiveCmd();
|
||||
|
||||
/// <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);
|
||||
void Run(void);
|
||||
|
||||
OptionDescription* GetDescByLongName(const std::string& longname);
|
||||
OptionDescription* GetDescByShortName(char shortname);
|
||||
OptionDescription* GetDescByPosition(size_t pos);
|
||||
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, ...);
|
||||
|
||||
void PrintHelp(FILE* f);
|
||||
private:
|
||||
std::unordered_map<std::string, OptionDescription> mLongNameDict;
|
||||
std::unordered_map<char, std::string> mShortNameMapping;
|
||||
std::vector<std::string> mPositionalArgMapping;
|
||||
};
|
||||
bool ProcLoad(const std::deque<std::string>& cmd);
|
||||
bool ProcUnLoad(const std::deque<std::string>& cmd);
|
||||
bool ProcInfo(const std::deque<std::string>& cmd);
|
||||
bool ProcLs(const std::deque<std::string>& cmd);
|
||||
|
||||
struct AnyVariable {
|
||||
size_t mDataBasicSize;
|
||||
void* mData;
|
||||
};
|
||||
bool m_ExitRunFlag;
|
||||
CmdSplitter m_CmdSplitter;
|
||||
LibCmo::CK2::CKMinContext* m_Ctx;
|
||||
LibCmo::CK2::CKFileDocument* m_Doc;
|
||||
};
|
||||
|
||||
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;
|
||||
enum class CmdArgType {
|
||||
NONE,
|
||||
STRING,
|
||||
INT
|
||||
};
|
||||
|
||||
if (sizeof(T) > search->second.mDataBasicSize) throw std::invalid_argument("Memory Violation.");
|
||||
return reinterpret_cast<T*>(search->second.mData);
|
||||
}
|
||||
};
|
||||
struct OptionDescription {
|
||||
std::string mLongName;
|
||||
char mShortName;
|
||||
CmdArgType mType;
|
||||
std::string mDescription;
|
||||
};
|
||||
|
||||
struct CmdRegisteryEntry {
|
||||
std::string mSubCmdDesc;
|
||||
OptionsDescription mOptDesc;
|
||||
std::function<void(OptionsDescription&, VariablesMap&)> mBindProc;
|
||||
};
|
||||
class OptionsDescription {
|
||||
public:
|
||||
OptionsDescription();
|
||||
OptionsDescription(const OptionsDescription&) = delete;
|
||||
OptionsDescription& operator=(const OptionsDescription&) = delete;
|
||||
~OptionsDescription();
|
||||
|
||||
class ExecEnvironment {
|
||||
public:
|
||||
ExecEnvironment();
|
||||
ExecEnvironment(const ExecEnvironment&) = delete;
|
||||
ExecEnvironment& operator=(const ExecEnvironment&) = delete;
|
||||
~ExecEnvironment();
|
||||
/// <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);
|
||||
|
||||
void ProcLoad(OptionsDescription&, VariablesMap&);
|
||||
void ProcInfo(OptionsDescription&, VariablesMap&);
|
||||
void ProcClear(OptionsDescription&, VariablesMap&);
|
||||
void ProcExportSql(OptionsDescription&, VariablesMap&);
|
||||
private:
|
||||
LibCmo::CKFile* mVtFile;
|
||||
LibCmo::Utils::VirtoolsContext* mVtFileEnv;
|
||||
};
|
||||
OptionDescription* GetDescByLongName(const std::string& longname);
|
||||
OptionDescription* GetDescByShortName(char shortname);
|
||||
OptionDescription* GetDescByPosition(size_t pos);
|
||||
|
||||
class InteractiveCmd {
|
||||
public:
|
||||
InteractiveCmd();
|
||||
InteractiveCmd(const InteractiveCmd&) = delete;
|
||||
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
||||
~InteractiveCmd();
|
||||
void PrintHelp(FILE* f);
|
||||
private:
|
||||
std::unordered_map<std::string, OptionDescription> mLongNameDict;
|
||||
std::unordered_map<char, std::string> mShortNameMapping;
|
||||
std::vector<std::string> mPositionalArgMapping;
|
||||
};
|
||||
|
||||
void Run(void);
|
||||
struct AnyVariable {
|
||||
size_t mDataBasicSize;
|
||||
void* mData;
|
||||
};
|
||||
|
||||
private:
|
||||
void GetCmdLine(std::string& u8cmd);
|
||||
void CmdParser(const std::vector<std::string>& args);
|
||||
void PrintHelp(FILE* f);
|
||||
class VariablesMap {
|
||||
private:
|
||||
std::unordered_map<std::string, AnyVariable> mDataPair;
|
||||
|
||||
void ProcExit(OptionsDescription&, VariablesMap&);
|
||||
public:
|
||||
VariablesMap();
|
||||
VariablesMap(const VariablesMap&) = delete;
|
||||
VariablesMap& operator=(const VariablesMap&) = delete;
|
||||
~VariablesMap();
|
||||
|
||||
std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher;
|
||||
CmdSplitter mCmdSplitter;
|
||||
ExecEnvironment mExecEnv;
|
||||
VariablesMap mVm;
|
||||
std::string mBlank;
|
||||
bool mExitRunFlag;
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
*/
|
||||
}
|
@ -6,6 +6,28 @@ namespace Unvirt{
|
||||
#define UNVIRT_REMOVE_PARENS_IMPL(...) __VA_ARGS__
|
||||
#define UNVIRT_REMOVE_PARENS(T) UNVIRT_REMOVE_PARENS_IMPL T
|
||||
|
||||
|
||||
#define UNVIRT_TERMCOLHDR_BLACK "\033[30m"
|
||||
#define UNVIRT_TERMCOLHDR_RED "\033[31m"
|
||||
#define UNVIRT_TERMCOLHDR_GREEN "\033[32m"
|
||||
#define UNVIRT_TERMCOLHDR_YELLOW "\033[33m"
|
||||
#define UNVIRT_TERMCOLHDR_BLUE "\033[34m"
|
||||
#define UNVIRT_TERMCOLHDR_MAGENTA "\033[35m"
|
||||
#define UNVIRT_TERMCOLHDR_CYAN "\033[36m"
|
||||
#define UNVIRT_TERMCOLHDR_WHITE "\033[37m"
|
||||
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_BLACK "\033[90m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_RED "\033[91m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_GREEN "\033[92m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_YELLOW "\033[93m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_BLUE "\033[94m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_MAGENTA "\033[95m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_CYAN "\033[96m"
|
||||
#define UNVIRT_TERMCOLHDR_LIGHT_WHITE "\033[97m"
|
||||
|
||||
#define UNVIRT_TERMCOLTAIL "\033[97m"
|
||||
|
||||
|
||||
#define UNVIRT_TERMCOL_BLACK(T) "\033[30m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
||||
#define UNVIRT_TERMCOL_RED(T) "\033[31m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
||||
#define UNVIRT_TERMCOL_GREEN(T) "\033[32m" UNVIRT_REMOVE_PARENS(T) "\033[0m"
|
||||
|
@ -17,8 +17,8 @@ int main(int argc, char* argv[]) {
|
||||
vtctx.SetEncoding("850");
|
||||
|
||||
LibCmo::CK2::CKFile vtfile(&vtctx);
|
||||
LibCmo::CK2::CKFileData::DeepDocument* doc;
|
||||
LibCmo::CK2::CKERROR err = vtfile.DeepLoad("Level_01.NMO", &doc);
|
||||
LibCmo::CK2::CKFileDocument* doc;
|
||||
LibCmo::CK2::CKERROR err = vtfile.DeepLoad("Level_02.NMO", &doc);
|
||||
|
||||
if (doc)
|
||||
Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo);
|
||||
|
@ -96,7 +96,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
@ -114,7 +114,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
@ -136,7 +136,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
@ -154,7 +154,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
|
Reference in New Issue
Block a user