libcmo21/Unvirt/CmdHelper.hpp

256 lines
6.4 KiB
C++
Raw Normal View History

2023-02-13 10:57:10 +08:00
#pragma once
#include <unordered_map>
#include <string>
#include <functional>
#include <vector>
2023-02-13 16:52:00 +08:00
#include <unordered_map>
2023-02-13 22:13:30 +08:00
#include <stdexcept>
2023-02-14 16:28:37 +08:00
#include "VTUtils.hpp"
/*
2023-02-13 10:57:10 +08:00
namespace Unvirt {
namespace CmdHelper {
class CmdSplitter {
public:
CmdSplitter();
CmdSplitter(const CmdSplitter&) = delete;
CmdSplitter& operator=(const CmdSplitter&) = delete;
~CmdSplitter();
2023-02-14 16:28:37 +08:00
const std::vector<std::string> Convert(const std::string& u8cmd);
2023-02-13 10:57:10 +08:00
private:
char mCmdChar;
std::string* mBuffer;
std::vector<std::string>* mResult;
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 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 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;
}
}
};
2023-02-13 16:52:00 +08:00
enum class CmdArgType {
NONE,
STRING,
INT
};
struct OptionDescription {
std::string mLongName;
char mShortName;
CmdArgType mType;
std::string mDescription;
};
class OptionsDescription {
2023-02-13 10:57:10 +08:00
public:
2023-02-13 16:52:00 +08:00
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);
2023-02-13 22:13:30 +08:00
OptionDescription* GetDescByLongName(const std::string& longname);
OptionDescription* GetDescByShortName(char shortname);
2023-02-14 16:28:37 +08:00
OptionDescription* GetDescByPosition(size_t pos);
2023-02-13 22:13:30 +08:00
2023-02-13 16:52:00 +08:00
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 {
2023-02-13 22:13:30 +08:00
size_t mDataBasicSize;
2023-02-13 16:52:00 +08:00
void* mData;
};
2023-02-13 10:57:10 +08:00
2023-02-13 16:52:00 +08:00
class VariablesMap {
2023-02-13 10:57:10 +08:00
private:
2023-02-13 16:52:00 +08:00
std::unordered_map<std::string, AnyVariable> mDataPair;
public:
VariablesMap();
2023-02-13 22:13:30 +08:00
VariablesMap(const VariablesMap&) = delete;
VariablesMap& operator=(const VariablesMap&) = delete;
2023-02-13 16:52:00 +08:00
~VariablesMap();
void Clear(void);
2023-02-13 22:13:30 +08:00
/// <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>
2023-02-14 16:28:37 +08:00
bool AddPair(const std::string& name, CmdArgType t, const std::string& val);
2023-02-13 22:13:30 +08:00
bool Contain(const char* opt) {
if (opt == nullptr) throw std::invalid_argument("Invalid Option Name.");
return mDataPair.contains(opt);
}
2023-02-13 16:52:00 +08:00
template<typename T>
T* GetData(const char* opt) {
2023-02-13 22:13:30 +08:00
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);
2023-02-13 16:52:00 +08:00
}
};
2023-02-13 10:57:10 +08:00
2023-02-13 16:52:00 +08:00
struct CmdRegisteryEntry {
2023-02-13 22:13:30 +08:00
std::string mSubCmdDesc;
2023-02-13 16:52:00 +08:00
OptionsDescription mOptDesc;
std::function<void(OptionsDescription&, VariablesMap&)> mBindProc;
2023-02-13 10:57:10 +08:00
};
2023-02-13 22:13:30 +08:00
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:
2023-02-14 16:28:37 +08:00
LibCmo::CKFile* mVtFile;
LibCmo::Utils::VirtoolsContext* mVtFileEnv;
2023-02-13 22:13:30 +08:00
};
2023-02-13 10:57:10 +08:00
class InteractiveCmd {
public:
InteractiveCmd();
2023-02-13 22:13:30 +08:00
InteractiveCmd(const InteractiveCmd&) = delete;
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
2023-02-13 10:57:10 +08:00
~InteractiveCmd();
void Run(void);
private:
2023-02-14 16:28:37 +08:00
void GetCmdLine(std::string& u8cmd);
2023-02-13 22:13:30 +08:00
void CmdParser(const std::vector<std::string>& args);
2023-02-13 16:52:00 +08:00
void PrintHelp(FILE* f);
2023-02-13 10:57:10 +08:00
2023-02-14 16:28:37 +08:00
void ProcExit(OptionsDescription&, VariablesMap&);
2023-02-13 22:13:30 +08:00
std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher;
2023-02-14 16:28:37 +08:00
CmdSplitter mCmdSplitter;
2023-02-13 22:13:30 +08:00
ExecEnvironment mExecEnv;
VariablesMap mVm;
std::string mBlank;
2023-02-14 16:28:37 +08:00
bool mExitRunFlag;
2023-02-13 10:57:10 +08:00
};
}
2023-02-14 16:28:37 +08:00
}
*/