update shit

This commit is contained in:
yyc12345 2023-02-13 16:52:00 +08:00
parent 21948246d0
commit a519b2d8d5
2 changed files with 134 additions and 8 deletions

View File

@ -1,4 +1,6 @@
#include "CmdHelper.hpp" #include "CmdHelper.hpp"
#include "TerminalHelper.hpp"
#include <stdexcept>
namespace Unvirt { namespace Unvirt {
namespace CmdHelper { namespace CmdHelper {
@ -14,7 +16,7 @@ namespace Unvirt {
; ;
} }
std::vector<std::string> CmdSplitter::Convert(std::string& u8cmd) { std::vector<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
// set up variables // set up variables
std::vector<std::string> result; std::vector<std::string> result;
std::string buffer; std::string buffer;
@ -69,12 +71,78 @@ namespace Unvirt {
#pragma region interactive cmd helper classes #pragma region interactive cmd helper classes
SubCmd::SubCmd() {
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));
} }
SubCmd::~SubCmd() { 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.");
}
}
// set value
mPositionalArgMapping.push_back(std::move(fullname));
} }
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());
}
}
}
VariablesMap::VariablesMap() {
}
VariablesMap::~VariablesMap() {
}
#pragma endregion #pragma endregion

View File

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <unordered_map>
namespace Unvirt { namespace Unvirt {
namespace CmdHelper { namespace CmdHelper {
@ -15,7 +16,7 @@ namespace Unvirt {
CmdSplitter& operator=(const CmdSplitter&) = delete; CmdSplitter& operator=(const CmdSplitter&) = delete;
~CmdSplitter(); ~CmdSplitter();
std::vector<std::string> Convert(std::string& u8cmd); std::vector<std::string> Convert(const std::string& u8cmd);
private: private:
char mCmdChar; char mCmdChar;
std::string* mBuffer; std::string* mBuffer;
@ -120,13 +121,68 @@ namespace Unvirt {
} }
}; };
class SubCmd { enum class CmdArgType {
NONE,
STRING,
INT
};
struct OptionDescription {
std::string mLongName;
char mShortName;
CmdArgType mType;
std::string mDescription;
};
class OptionsDescription {
public: public:
SubCmd(); OptionsDescription();
~SubCmd(); 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);
void PrintHelp(FILE* f);
private: private:
std::unordered_map<std::string, OptionDescription> mLongNameDict;
std::unordered_map<char, std::string> mShortNameMapping;
std::vector<std::string> mPositionalArgMapping;
};
struct AnyVariable {
CmdArgType mType;
void* mData;
};
class VariablesMap {
private:
std::unordered_map<std::string, AnyVariable> mDataPair;
public:
VariablesMap();
~VariablesMap();
void Clear(void);
bool AddPair(std::string& name, CmdArgType t, std::string& val);
bool Contain(const char* probe);
template<typename T>
T* GetData(const char* opt) {
;
}
};
struct CmdRegisteryEntry {
OptionsDescription mOptDesc;
std::function<void(OptionsDescription&, VariablesMap&)> mBindProc;
}; };
class InteractiveCmd { class InteractiveCmd {
@ -137,7 +193,9 @@ namespace Unvirt {
void Run(void); void Run(void);
private: private:
//std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher; bool AnalyzeCmd(std::vector<std::string>& args);
void PrintHelp(FILE* f);
std::unordered_map<std::string, CmdRegisteryEntry> mCmdDispatcher;
}; };