fix command helper
This commit is contained in:
parent
3252e61c0d
commit
168d76939b
|
@ -150,46 +150,145 @@ namespace Unvirt::CmdHelper {
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Help Document
|
||||||
|
|
||||||
|
HelpDocument::HelpDocument() : m_Stack(), m_Results() {}
|
||||||
|
|
||||||
|
HelpDocument::~HelpDocument() {}
|
||||||
|
|
||||||
|
void HelpDocument::Push(const std::string& arg_name, const std::string& arg_desc) {
|
||||||
|
m_Stack.emplace_back(StackItem { arg_name, arg_desc });
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpDocument::Pop() {
|
||||||
|
m_Stack.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpDocument::Terminate(std::string& command_desc) {
|
||||||
|
// create new result and copy stack
|
||||||
|
ResultItem result(command_desc);
|
||||||
|
result.m_ArgDesc.insert(result.m_ArgDesc.end(), m_Stack.begin(), m_Stack.end());
|
||||||
|
// add into result
|
||||||
|
m_Results.emplace_back(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpDocument::Print() {
|
||||||
|
for (auto& item : m_Results) {
|
||||||
|
for (auto& cmd : item.m_ArgDesc) {
|
||||||
|
fputs(cmd.m_Name.c_str(), stdout);
|
||||||
|
fputc(' ', stdout);
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
|
|
||||||
|
if (!item.m_CmdDesc.empty()) {
|
||||||
|
fputs(item.m_CmdDesc.c_str(), stdout);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& cmd : item.m_ArgDesc) {
|
||||||
|
if (!cmd.m_Desc.empty()) {
|
||||||
|
fprintf(stdout, "\t%s: %s\n", cmd.m_Name.c_str(), cmd.m_Desc.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Abstract Node
|
#pragma region Abstract Node
|
||||||
|
|
||||||
|
AbstractNode::AbstractNode() :
|
||||||
|
m_Execution(nullptr), m_Comment(),
|
||||||
|
m_Literals(), m_Choices(), m_Args() {}
|
||||||
|
|
||||||
|
AbstractNode::~AbstractNode() {
|
||||||
|
for (auto& ptr : m_Literals) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
for (auto& ptr : m_Choices) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
for (auto& ptr : m_Args) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AbstractNode* AbstractNode::Then(AbstractNode* node) {
|
AbstractNode* AbstractNode::Then(AbstractNode* node) {
|
||||||
// check literal duplication
|
// check conflict
|
||||||
for (auto& pnode : m_Nodes) {
|
for (auto& pnode : m_Literals) {
|
||||||
if (pnode->IsConflictWith(node))
|
if (pnode->IsConflictWith(node))
|
||||||
throw std::invalid_argument("conflict node.");
|
throw std::invalid_argument("conflict node.");
|
||||||
}
|
}
|
||||||
|
for (auto& pnode : m_Choices) {
|
||||||
|
if (pnode->IsConflictWith(node))
|
||||||
|
throw std::invalid_argument("conflict node.");
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Args) {
|
||||||
|
if (pnode->IsConflictWith(node))
|
||||||
|
throw std::invalid_argument("conflict node.");
|
||||||
|
}
|
||||||
|
|
||||||
// add into list
|
// add into list
|
||||||
m_Nodes.emplace_back(node);
|
switch (node->GetNodeType()) {
|
||||||
|
case NodeType::Argument:
|
||||||
|
m_Literals.emplace_back(node);
|
||||||
|
break;
|
||||||
|
case NodeType::Choice:
|
||||||
|
m_Choices.emplace_back(node);
|
||||||
|
break;
|
||||||
|
case NodeType::Literal:
|
||||||
|
m_Args.emplace_back(node);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("No such node type.");
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode* AbstractNode::Executes(ExecutionFct fct, const char* cmt) {
|
AbstractNode* AbstractNode::Executes(ExecutionFct fct, const char* cmt) {
|
||||||
if (m_Execution != nullptr)
|
if (m_Execution != nullptr) throw std::invalid_argument("duplicated executions.");
|
||||||
throw std::invalid_argument("duplicated executions.");
|
if (fct == nullptr) throw std::invalid_argument("no function.");
|
||||||
m_Execution = fct;
|
m_Execution = fct;
|
||||||
|
m_ExecutionDesc = cmt == nullptr ? "" : cmt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractNode* AbstractNode::Comment(const char* cmt) {
|
||||||
|
if (cmt == nullptr)
|
||||||
|
throw std::invalid_argument("no comment.");
|
||||||
m_Comment = cmt;
|
m_Comment = cmt;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractNode::Help(HelpDocument& doc) {
|
void AbstractNode::Help(HelpDocument* doc) {
|
||||||
// add self
|
// add self
|
||||||
BeginHelp(doc);
|
std::string symbol(GetHelpSymbol());
|
||||||
|
doc->Push(symbol, m_Comment);
|
||||||
|
|
||||||
// check terminal
|
// check terminal
|
||||||
if (m_Execution != nullptr) {
|
if (m_Execution != nullptr) {
|
||||||
doc.Terminate(m_Comment);
|
doc->Terminate(m_ExecutionDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate children
|
// iterate children
|
||||||
for (auto& pnode : m_Nodes) {
|
for (auto& pnode : m_Literals) {
|
||||||
|
pnode->Help(doc);
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Choices) {
|
||||||
|
pnode->Help(doc);
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Args) {
|
||||||
pnode->Help(doc);
|
pnode->Help(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pop self
|
// pop self
|
||||||
EndHelp(doc);
|
doc->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractNode::Consume(std::deque<std::string>& arglist, ArgumentsMap& argmap) {
|
bool AbstractNode::Consume(std::deque<std::string>& arglist, ArgumentsMap* argmap) {
|
||||||
// if no data can consume, return
|
// if no data can consume, return
|
||||||
if (arglist.empty()) return false;
|
if (arglist.empty()) return false;
|
||||||
|
|
||||||
|
@ -222,7 +321,19 @@ namespace Unvirt::CmdHelper {
|
||||||
} else {
|
} else {
|
||||||
// have following command, try match them
|
// have following command, try match them
|
||||||
// iterate literal and argument to check terminal
|
// iterate literal and argument to check terminal
|
||||||
for (auto& pnode : m_Nodes) {
|
for (auto& pnode : m_Literals) {
|
||||||
|
if (pnode->Consume(arglist, argmap)) {
|
||||||
|
CONSUME_DEFER;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Choices) {
|
||||||
|
if (pnode->Consume(arglist, argmap)) {
|
||||||
|
CONSUME_DEFER;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Args) {
|
||||||
if (pnode->Consume(arglist, argmap)) {
|
if (pnode->Consume(arglist, argmap)) {
|
||||||
CONSUME_DEFER;
|
CONSUME_DEFER;
|
||||||
return true;
|
return true;
|
||||||
|
@ -240,7 +351,240 @@ namespace Unvirt::CmdHelper {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Argument Impl
|
#pragma region Command Root
|
||||||
|
|
||||||
|
CommandRoot::CommandRoot() : AbstractNode() {}
|
||||||
|
|
||||||
|
CommandRoot::~CommandRoot() {}
|
||||||
|
|
||||||
|
bool CommandRoot::RootConsume(std::deque<std::string>& arglist) {
|
||||||
|
// if no data can consume, return
|
||||||
|
if (arglist.empty()) return false;
|
||||||
|
|
||||||
|
// create a argument map
|
||||||
|
ArgumentsMap amap;
|
||||||
|
|
||||||
|
// and we only just need iterate all children
|
||||||
|
for (auto& pnode : m_Literals) {
|
||||||
|
if (pnode->Consume(arglist, &amap)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Choices) {
|
||||||
|
if (pnode->Consume(arglist, &amap)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Args) {
|
||||||
|
if (pnode->Consume(arglist, &amap)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no matched
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HelpDocument* CommandRoot::RootHelp() {
|
||||||
|
HelpDocument* doc = new HelpDocument();
|
||||||
|
|
||||||
|
// we only just need iterate all children
|
||||||
|
for (auto& pnode : m_Literals) {
|
||||||
|
pnode->Help(doc);
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Choices) {
|
||||||
|
pnode->Help(doc);
|
||||||
|
}
|
||||||
|
for (auto& pnode : m_Args) {
|
||||||
|
pnode->Help(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Literal
|
||||||
|
|
||||||
|
Literal::Literal(const char* words) :
|
||||||
|
AbstractNode(),
|
||||||
|
m_Literal(words == nullptr ? "" : words) {
|
||||||
|
if (words == nullptr || m_Literal.empty())
|
||||||
|
throw std::invalid_argument("Invalid literal.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Literal::~Literal() {}
|
||||||
|
|
||||||
|
NodeType Literal::GetNodeType() {
|
||||||
|
return NodeType::Literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Literal::IsConflictWith(AbstractNode* node) {
|
||||||
|
switch (node->GetNodeType()) {
|
||||||
|
case NodeType::Literal:
|
||||||
|
return dynamic_cast<Literal*>(node)->m_Literal == m_Literal;
|
||||||
|
case NodeType::Choice:
|
||||||
|
for (const auto& item : dynamic_cast<Choice*>(node)->m_Vocabulary) {
|
||||||
|
if (item == m_Literal) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case NodeType::Argument:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("No such node type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Literal::GetHelpSymbol() {
|
||||||
|
return m_Literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Literal::BeginAccept(const std::string& strl, ArgumentsMap*) {
|
||||||
|
return strl == m_Literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Literal::EndAccept(ArgumentsMap*) {}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Choice
|
||||||
|
|
||||||
|
Choice::Choice(const char* argname, const std::initializer_list<std::string>& vocabulary) :
|
||||||
|
AbstractNode(),
|
||||||
|
m_GottenIndex(0u), m_Accepted(false),
|
||||||
|
m_ChoiceName(argname == nullptr ? "" : argname), m_Vocabulary(vocabulary) {
|
||||||
|
if (argname == nullptr || m_ChoiceName.empty())
|
||||||
|
throw std::invalid_argument("Invalid choice name.");
|
||||||
|
if (m_Vocabulary.size() < 2)
|
||||||
|
throw std::invalid_argument("Too less vocabulary. At least 2 items.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Choice::~Choice() {}
|
||||||
|
|
||||||
|
size_t* Choice::GetIndex() {
|
||||||
|
return &m_GottenIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeType Choice::GetNodeType() {
|
||||||
|
return NodeType::Choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Choice::IsConflictWith(AbstractNode* node) {
|
||||||
|
switch (node->GetNodeType()) {
|
||||||
|
case NodeType::Literal:
|
||||||
|
{
|
||||||
|
Literal* pliteral = dynamic_cast<Literal*>(node);
|
||||||
|
for (const auto& word : m_Vocabulary) {
|
||||||
|
if (word == pliteral->m_Literal)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case NodeType::Choice:
|
||||||
|
{
|
||||||
|
Choice* pchoice = dynamic_cast<Choice*>(node);
|
||||||
|
if (pchoice->m_ChoiceName == m_ChoiceName)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (const auto& thisword : m_Vocabulary) {
|
||||||
|
for (const auto& thatword : pchoice->m_Vocabulary) {
|
||||||
|
if (thisword == thatword)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case NodeType::Argument:
|
||||||
|
return m_ChoiceName == dynamic_cast<AbstractArgument*>(node)->m_ArgName;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("No such node type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Choice::GetHelpSymbol() {
|
||||||
|
std::string switches;
|
||||||
|
for (const auto& item : m_Vocabulary) {
|
||||||
|
if (!switches.empty()) switches += " | ";
|
||||||
|
switches += item;
|
||||||
|
}
|
||||||
|
return "[" + switches + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Choice::BeginAccept(const std::string& strl, ArgumentsMap* amap) {
|
||||||
|
for (size_t i = 0; i < m_Vocabulary.size(); ++i) {
|
||||||
|
if (strl == m_Vocabulary[i]) {
|
||||||
|
m_Accepted = true;
|
||||||
|
m_GottenIndex = i;
|
||||||
|
amap->Add(m_ChoiceName, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Choice::EndAccept(ArgumentsMap* amap) {
|
||||||
|
if (m_Accepted) {
|
||||||
|
m_Accepted = false;
|
||||||
|
amap->Remove(m_ChoiceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Abstract Argument
|
||||||
|
|
||||||
|
AbstractArgument::AbstractArgument(const char* argname) :
|
||||||
|
AbstractNode(),
|
||||||
|
m_ArgName(argname == nullptr ? "" : argname),
|
||||||
|
m_Accepted(false), m_ParsedData(nullptr) {
|
||||||
|
if (argname == nullptr || m_ArgName.empty())
|
||||||
|
throw std::invalid_argument("Invalid argument name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractArgument::~AbstractArgument() {}
|
||||||
|
|
||||||
|
NodeType AbstractArgument::GetNodeType() {
|
||||||
|
return NodeType::Argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractArgument::IsConflictWith(AbstractNode* node) {
|
||||||
|
switch (node->GetNodeType()) {
|
||||||
|
case NodeType::Literal:
|
||||||
|
return false;
|
||||||
|
case NodeType::Choice:
|
||||||
|
return m_ArgName == dynamic_cast<Choice*>(node)->m_ChoiceName;
|
||||||
|
case NodeType::Argument:
|
||||||
|
return m_ArgName == dynamic_cast<AbstractArgument*>(node)->m_ArgName;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("No such node type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AbstractArgument::GetHelpSymbol() {
|
||||||
|
std::string newargname = "<";
|
||||||
|
newargname.append(m_ArgName);
|
||||||
|
newargname.append(">");
|
||||||
|
return newargname;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractArgument::BeginAccept(const std::string& strl, ArgumentsMap* amap) {
|
||||||
|
m_Accepted = BeginParse(strl);
|
||||||
|
if (m_Accepted) amap->Add(m_ArgName, this);
|
||||||
|
return m_Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractArgument::EndAccept(ArgumentsMap* amap) {
|
||||||
|
if (m_Accepted) {
|
||||||
|
amap->Remove(m_ArgName);
|
||||||
|
EndParse();
|
||||||
|
m_Accepted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Argument Detail Impl
|
||||||
|
|
||||||
bool IntArgument::BeginParse(const std::string& val) {
|
bool IntArgument::BeginParse(const std::string& val) {
|
||||||
char* pend = nullptr;
|
char* pend = nullptr;
|
||||||
|
@ -255,97 +599,69 @@ namespace Unvirt::CmdHelper {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ParsedData = new int32_t(value);
|
m_ParsedData = new IntArgument::vType(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntArgument::EndParse() {
|
void IntArgument::EndParse() {
|
||||||
delete reinterpret_cast<int32_t*>(m_ParsedData);
|
delete reinterpret_cast<IntArgument::vType*>(m_ParsedData);
|
||||||
m_ParsedData = nullptr;
|
m_ParsedData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringArgument::BeginParse(const std::string& strl) {
|
bool StringArgument::BeginParse(const std::string& strl) {
|
||||||
// string always accept every text
|
// string always accept every text
|
||||||
m_ParsedData = new std::string(strl);
|
m_ParsedData = new StringArgument::vType(strl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArgument::EndParse() {
|
void StringArgument::EndParse() {
|
||||||
delete reinterpret_cast<std::string*>(m_ParsedData);
|
delete reinterpret_cast<StringArgument::vType*>(m_ParsedData);
|
||||||
|
m_ParsedData = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy from Gamepiaynmo/BallanceModLoader
|
||||||
|
std::vector<std::string> SplitString(const std::string& str, const std::string& de) {
|
||||||
|
size_t lpos, pos = 0;
|
||||||
|
std::vector<std::string> res;
|
||||||
|
|
||||||
|
lpos = str.find_first_not_of(de, pos);
|
||||||
|
while (lpos != std::string::npos) {
|
||||||
|
pos = str.find_first_of(de, lpos);
|
||||||
|
res.push_back(str.substr(lpos, pos - lpos));
|
||||||
|
if (pos == std::string::npos) break;
|
||||||
|
|
||||||
|
lpos = str.find_first_not_of(de, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
res.push_back("");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodingArgument::BeginParse(const std::string& strl) {
|
||||||
|
// encoding always accept every text
|
||||||
|
m_ParsedData = new EncodingArgument::vType(SplitString(strl, ","));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EncodingArgument::EndParse() {
|
||||||
|
delete reinterpret_cast<EncodingArgument::vType*>(m_ParsedData);
|
||||||
m_ParsedData = nullptr;
|
m_ParsedData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Command Root
|
#pragma region Argument Map
|
||||||
|
|
||||||
bool CommandRoot::RootConsume(std::deque<std::string>& arglist) {
|
void ArgumentsMap::Add(const std::string& k, AbstractNode* v) {
|
||||||
// if no data can consume, return
|
m_Data.emplace(std::make_pair(k, v));
|
||||||
if (arglist.empty()) return false;
|
|
||||||
|
|
||||||
// create a argument map
|
|
||||||
ArgumentsMap amap;
|
|
||||||
|
|
||||||
// and we only just need iterate all children
|
|
||||||
for (auto& pnode : m_Nodes) {
|
|
||||||
if (pnode->Consume(arglist, amap)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no matched
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HelpDocument* CommandRoot::RootHelp() {
|
void ArgumentsMap::Remove(const std::string& k) {
|
||||||
HelpDocument* doc = new HelpDocument();
|
m_Data.erase(k);
|
||||||
|
|
||||||
// we only just need iterate all children
|
|
||||||
for (auto& pnode : m_Nodes) {
|
|
||||||
pnode->Help(*doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return doc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Help Document
|
|
||||||
|
|
||||||
void HelpDocument::Terminate(std::string& command_desc) {
|
|
||||||
// create new result and copy stack
|
|
||||||
ResultItem result(command_desc);
|
|
||||||
result.m_ArgDesc.insert(result.m_ArgDesc.end(), m_Stack.begin(), m_Stack.end());
|
|
||||||
// add into result
|
|
||||||
m_Results.emplace_back(std::move(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HelpDocument::Print() {
|
|
||||||
fputs("Command Help:\n", stdout);
|
|
||||||
|
|
||||||
for (auto& item : m_Results) {
|
|
||||||
for (auto& cmd : item.m_ArgDesc) {
|
|
||||||
fputs(cmd.m_Name.c_str(), stdout);
|
|
||||||
fputc(' ', stdout);
|
|
||||||
}
|
|
||||||
fputc('\n', stdout);
|
|
||||||
|
|
||||||
if (!item.m_CmdDesc.empty()) {
|
|
||||||
fputs(item.m_CmdDesc.c_str(), stdout);
|
|
||||||
fputc('\n', stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& cmd : item.m_ArgDesc) {
|
|
||||||
if (!cmd.m_Desc.empty()) {
|
|
||||||
fprintf(stdout, "\t%s: %s\n", cmd.m_Name.c_str(), cmd.m_Desc.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fputc('\n', stdout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,19 +45,12 @@ namespace Unvirt::CmdHelper {
|
||||||
|
|
||||||
class HelpDocument {
|
class HelpDocument {
|
||||||
public:
|
public:
|
||||||
HelpDocument() : m_Stack(), m_Results() {}
|
HelpDocument();
|
||||||
~HelpDocument() {}
|
~HelpDocument();
|
||||||
LIBCMO_DISABLE_COPY_MOVE(HelpDocument);
|
LIBCMO_DISABLE_COPY_MOVE(HelpDocument);
|
||||||
|
|
||||||
void PushLiteral(const std::string& literal_name) {
|
void Push(const std::string& arg_name, const std::string& arg_desc);
|
||||||
m_Stack.emplace_back(StackItem(literal_name, ""));
|
void Pop();
|
||||||
}
|
|
||||||
void PushArgument(const std::string& arg_name, const std::string& arg_desc) {
|
|
||||||
m_Stack.emplace_back(StackItem(arg_name, arg_desc));
|
|
||||||
}
|
|
||||||
void Pop() {
|
|
||||||
m_Stack.pop_back();
|
|
||||||
}
|
|
||||||
void Terminate(std::string& command_desc);
|
void Terminate(std::string& command_desc);
|
||||||
void Print();
|
void Print();
|
||||||
|
|
||||||
|
@ -80,210 +73,127 @@ namespace Unvirt::CmdHelper {
|
||||||
std::vector<ResultItem> m_Results;
|
std::vector<ResultItem> m_Results;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AbstractArgument;
|
enum class NodeType {
|
||||||
class ArgumentsMap {
|
Literal, Choice, Argument
|
||||||
public:
|
|
||||||
ArgumentsMap() : m_Data() {}
|
|
||||||
~ArgumentsMap() {}
|
|
||||||
LIBCMO_DISABLE_COPY_MOVE(ArgumentsMap);
|
|
||||||
|
|
||||||
void Add(const std::string& k, AbstractArgument* v) {
|
|
||||||
m_Data.emplace(std::make_pair(k, v));
|
|
||||||
}
|
|
||||||
void Remove(const std::string& k) {
|
|
||||||
m_Data.erase(k);
|
|
||||||
}
|
|
||||||
AbstractArgument* Get(const char* k) const {
|
|
||||||
auto finder = m_Data.find(k);
|
|
||||||
if (finder == m_Data.end()) throw std::invalid_argument("No such argument name.");
|
|
||||||
return finder->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::unordered_map<std::string, AbstractArgument*> m_Data;
|
|
||||||
};
|
};
|
||||||
|
class ArgumentsMap;
|
||||||
class CommandRoot;
|
using ExecutionFct = std::function<void(const ArgumentsMap*)>;
|
||||||
using ExecutionFct = std::function<void(const ArgumentsMap&)>;
|
|
||||||
class AbstractNode {
|
class AbstractNode {
|
||||||
friend class CommandRoot;
|
|
||||||
public:
|
public:
|
||||||
AbstractNode() : m_Execution(nullptr), m_Nodes(), m_Comment() {}
|
AbstractNode();
|
||||||
virtual ~AbstractNode() {
|
virtual ~AbstractNode();
|
||||||
for (auto& ptr : m_Nodes) {
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LIBCMO_DISABLE_COPY_MOVE(AbstractNode);
|
LIBCMO_DISABLE_COPY_MOVE(AbstractNode);
|
||||||
|
|
||||||
AbstractNode* Then(AbstractNode*);
|
AbstractNode* Then(AbstractNode*);
|
||||||
AbstractNode* Executes(ExecutionFct, const char*);
|
AbstractNode* Executes(ExecutionFct, const char* = nullptr);
|
||||||
|
AbstractNode* Comment(const char*);
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
void Help(HelpDocument&);
|
void Help(HelpDocument*);
|
||||||
bool Consume(std::deque<std::string>&, ArgumentsMap&);
|
bool Consume(std::deque<std::string>&, ArgumentsMap*);
|
||||||
virtual bool IsLiteral() = 0;
|
virtual NodeType GetNodeType() = 0;
|
||||||
virtual bool IsConflictWith(AbstractNode*) = 0;
|
virtual bool IsConflictWith(AbstractNode*) = 0;
|
||||||
virtual void BeginHelp(HelpDocument&) = 0;
|
protected:
|
||||||
virtual void EndHelp(HelpDocument&) = 0;
|
virtual std::string GetHelpSymbol() = 0;
|
||||||
virtual bool BeginAccept(const std::string&, ArgumentsMap&) = 0;
|
virtual bool BeginAccept(const std::string&, ArgumentsMap*) = 0;
|
||||||
virtual void EndAccept(ArgumentsMap&) = 0;
|
virtual void EndAccept(ArgumentsMap*) = 0;
|
||||||
|
|
||||||
std::vector<AbstractNode*> m_Nodes;
|
std::vector<AbstractNode*> m_Literals;
|
||||||
|
std::vector<AbstractNode*> m_Choices;
|
||||||
|
std::vector<AbstractNode*> m_Args;
|
||||||
ExecutionFct m_Execution;
|
ExecutionFct m_Execution;
|
||||||
|
std::string m_ExecutionDesc;
|
||||||
std::string m_Comment;
|
std::string m_Comment;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandRoot : public AbstractNode {
|
class CommandRoot : public AbstractNode {
|
||||||
public:
|
public:
|
||||||
CommandRoot() : AbstractNode() {}
|
CommandRoot();
|
||||||
virtual ~CommandRoot() {}
|
virtual ~CommandRoot();
|
||||||
LIBCMO_DISABLE_COPY_MOVE(CommandRoot);
|
LIBCMO_DISABLE_COPY_MOVE(CommandRoot);
|
||||||
|
|
||||||
// Root use special consume and help functions.
|
// Root use special consume and help functions.
|
||||||
bool RootConsume(std::deque<std::string>&);
|
bool RootConsume(std::deque<std::string>&);
|
||||||
HelpDocument* RootHelp();
|
HelpDocument* RootHelp();
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
virtual bool IsLiteral() override { throw std::logic_error("Root can not be called."); }
|
virtual NodeType GetNodeType() override { throw std::logic_error("Root can not be called."); }
|
||||||
virtual bool IsConflictWith(AbstractNode*) override { throw std::logic_error("Root can not be called."); }
|
virtual bool IsConflictWith(AbstractNode*) override { throw std::logic_error("Root can not be called."); }
|
||||||
virtual void BeginHelp(HelpDocument&) override { throw std::logic_error("Root can not be called."); }
|
protected:
|
||||||
virtual void EndHelp(HelpDocument&) override { throw std::logic_error("Root can not be called."); }
|
virtual std::string GetHelpSymbol() override { throw std::logic_error("Root can not be called."); }
|
||||||
virtual bool BeginAccept(const std::string&, ArgumentsMap&) override { throw std::logic_error("Root can not be called."); }
|
virtual bool BeginAccept(const std::string&, ArgumentsMap*) override { throw std::logic_error("Root can not be called."); }
|
||||||
virtual void EndAccept(ArgumentsMap&) override { throw std::logic_error("Root can not be called."); }
|
virtual void EndAccept(ArgumentsMap*) override { throw std::logic_error("Root can not be called."); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Literal : public AbstractNode {
|
class Literal : public AbstractNode {
|
||||||
friend class Choice;
|
friend class Choice;
|
||||||
|
friend class AbstractArgument;
|
||||||
public:
|
public:
|
||||||
Literal(const char* words) : AbstractNode(), m_Literal(words) {
|
Literal(const char* words);
|
||||||
if (m_Literal.empty() || words == nullptr) throw std::invalid_argument("Invalid literal.");
|
virtual ~Literal();
|
||||||
}
|
|
||||||
virtual ~Literal() {}
|
|
||||||
LIBCMO_DISABLE_COPY_MOVE(Literal);
|
LIBCMO_DISABLE_COPY_MOVE(Literal);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual NodeType GetNodeType() override;
|
||||||
|
virtual bool IsConflictWith(AbstractNode* node) override;
|
||||||
protected:
|
protected:
|
||||||
virtual bool IsLiteral() override { return true; }
|
virtual std::string GetHelpSymbol() override;
|
||||||
virtual bool IsConflictWith(AbstractNode* node) override {
|
virtual bool BeginAccept(const std::string&, ArgumentsMap*) override;
|
||||||
Literal* pliteral = dynamic_cast<Literal*>(node);
|
virtual void EndAccept(ArgumentsMap*) override;
|
||||||
if (pliteral == nullptr) return false;
|
|
||||||
return pliteral->m_Literal == this->m_Literal;
|
|
||||||
}
|
|
||||||
virtual void BeginHelp(HelpDocument& doc) override {
|
|
||||||
doc.PushLiteral(m_Literal);
|
|
||||||
}
|
|
||||||
virtual void EndHelp(HelpDocument& doc) override {
|
|
||||||
doc.Pop();
|
|
||||||
}
|
|
||||||
virtual bool BeginAccept(const std::string& strl, ArgumentsMap&) override { return strl == m_Literal; }
|
|
||||||
virtual void EndAccept(ArgumentsMap&) override {}
|
|
||||||
|
|
||||||
std::string m_Literal;
|
std::string m_Literal;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Choice : public AbstractNode {
|
class Choice : public AbstractNode {
|
||||||
|
friend class Literal;
|
||||||
|
friend class AbstractArgument;
|
||||||
public:
|
public:
|
||||||
Choice(const char* argname, const std::initializer_list<std::string>& vocabulary) :
|
using vType = int32_t;
|
||||||
AbstractNode(), m_ChoiceName(argname == nullptr ? "" : argname), m_Vocabulary(vocabulary) {
|
Choice(const char* argname, const std::initializer_list<std::string>& vocabulary);
|
||||||
if (m_ChoiceName.empty() || argname == nullptr) throw std::invalid_argument("Invalid choice name.");
|
virtual ~Choice();
|
||||||
if (m_Vocabulary.size() < 2) throw std::invalid_argument("Too less vocabulary. At least 2 items.");
|
LIBCMO_DISABLE_COPY_MOVE(Choice);
|
||||||
}
|
|
||||||
virtual ~Choice() {}
|
|
||||||
LIBCMO_DISABLE_COPY_MOVE(Choice)
|
|
||||||
|
|
||||||
|
size_t* GetIndex();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual NodeType GetNodeType() override;
|
||||||
|
virtual bool IsConflictWith(AbstractNode* node) override;
|
||||||
protected:
|
protected:
|
||||||
virtual bool IsLiteral() override { return true; }
|
virtual std::string GetHelpSymbol() override;
|
||||||
virtual bool IsConflictWith(AbstractNode* node) override {
|
virtual bool BeginAccept(const std::string&, ArgumentsMap*) override;
|
||||||
Literal* pliteral = dynamic_cast<Literal*>(node);
|
virtual void EndAccept(ArgumentsMap*) override;
|
||||||
if (pliteral != nullptr) {
|
|
||||||
for (const auto& word : m_Vocabulary) {
|
|
||||||
if (word == pliteral->m_Literal)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Choice* pchoice = dynamic_cast<Choice*>(node);
|
|
||||||
if (pchoice != nullptr) {
|
|
||||||
for (const auto& thisword : m_Vocabulary) {
|
|
||||||
for (const auto& thatword : pchoice->m_Vocabulary) {
|
|
||||||
if (thisword == thatword)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual void BeginHelp(HelpDocument& doc) override {
|
|
||||||
std::string switches;
|
|
||||||
for (const auto& item : m_Vocabulary) {
|
|
||||||
if (!switches.empty()) switches += " | ";
|
|
||||||
switches += item;
|
|
||||||
}
|
|
||||||
doc.PushLiteral("[" + switches + "]");
|
|
||||||
}
|
|
||||||
virtual void EndHelp(HelpDocument& doc) override {
|
|
||||||
doc.Pop();
|
|
||||||
}
|
|
||||||
virtual bool BeginAccept(const std::string& strl, ArgumentsMap& amap) override {
|
|
||||||
for (const auto& item : m_Vocabulary) {
|
|
||||||
if (strl == item) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual void EndAccept(ArgumentsMap&) override {}
|
|
||||||
|
|
||||||
std::string m_ChoiceName;
|
std::string m_ChoiceName;
|
||||||
std::vector<std::string> m_Vocabulary;
|
std::vector<std::string> m_Vocabulary;
|
||||||
|
bool m_Accepted;
|
||||||
|
size_t m_GottenIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AbstractArgument : public AbstractNode {
|
class AbstractArgument : public AbstractNode {
|
||||||
|
friend class Literal;
|
||||||
|
friend class Choice;
|
||||||
public:
|
public:
|
||||||
AbstractArgument(const char* argname, const char* argdesc) : AbstractNode(),
|
AbstractArgument(const char* argname);
|
||||||
m_ArgName(argname == nullptr ? "" : argname), m_ArgDesc(argdesc), m_Accepted(false), m_ParsedData(nullptr) {
|
virtual ~AbstractArgument();
|
||||||
if (m_ArgName.empty() || argname == nullptr) throw std::invalid_argument("Invalid argument name.");
|
|
||||||
}
|
|
||||||
virtual ~AbstractArgument() {}
|
|
||||||
LIBCMO_DISABLE_COPY_MOVE(AbstractArgument);
|
LIBCMO_DISABLE_COPY_MOVE(AbstractArgument);
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T* GetData() { return reinterpret_cast<T*>(m_ParsedData); }
|
T GetData() {
|
||||||
|
return reinterpret_cast<T>(m_ParsedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual NodeType GetNodeType() override;
|
||||||
|
virtual bool IsConflictWith(AbstractNode* node) override;
|
||||||
protected:
|
protected:
|
||||||
|
virtual std::string GetHelpSymbol() override;
|
||||||
|
virtual bool BeginAccept(const std::string&, ArgumentsMap*) override;
|
||||||
|
virtual void EndAccept(ArgumentsMap*) override;
|
||||||
|
|
||||||
virtual bool BeginParse(const std::string&) = 0;
|
virtual bool BeginParse(const std::string&) = 0;
|
||||||
virtual void EndParse() = 0;
|
virtual void EndParse() = 0;
|
||||||
|
|
||||||
virtual bool IsLiteral() override { return false; }
|
|
||||||
virtual bool IsConflictWith(AbstractNode* node) override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual void BeginHelp(HelpDocument& doc) override {
|
|
||||||
std::string newargname = "<";
|
|
||||||
newargname.append(m_ArgName);
|
|
||||||
newargname.append(">");
|
|
||||||
doc.PushArgument(newargname, m_ArgDesc);
|
|
||||||
}
|
|
||||||
virtual void EndHelp(HelpDocument& doc) override {
|
|
||||||
doc.Pop();
|
|
||||||
}
|
|
||||||
virtual bool BeginAccept(const std::string& strl, ArgumentsMap& amap) override {
|
|
||||||
m_Accepted = BeginParse(strl);
|
|
||||||
if (m_Accepted) amap.Add(m_ArgName, this);
|
|
||||||
return m_Accepted;
|
|
||||||
}
|
|
||||||
virtual void EndAccept(ArgumentsMap& amap) override {
|
|
||||||
if (m_Accepted) {
|
|
||||||
amap.Remove(m_ArgName);
|
|
||||||
EndParse();
|
|
||||||
m_Accepted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_ArgName;
|
std::string m_ArgName;
|
||||||
std::string m_ArgDesc;
|
|
||||||
bool m_Accepted;
|
bool m_Accepted;
|
||||||
void* m_ParsedData;
|
void* m_ParsedData;
|
||||||
};
|
};
|
||||||
|
@ -294,8 +204,9 @@ namespace Unvirt::CmdHelper {
|
||||||
using IntLimit = std::function<bool(int32_t)>;
|
using IntLimit = std::function<bool(int32_t)>;
|
||||||
class IntArgument : public AbstractArgument {
|
class IntArgument : public AbstractArgument {
|
||||||
public:
|
public:
|
||||||
IntArgument(const char* argname, const char* argdesc = nullptr, IntLimit limit = nullptr) :
|
using vType = int32_t;
|
||||||
AbstractArgument(argname, argdesc), m_IntLimit(limit) {}
|
IntArgument(const char* argname, IntLimit limit = nullptr) :
|
||||||
|
AbstractArgument(argname), m_IntLimit(limit) {}
|
||||||
virtual ~IntArgument() {}
|
virtual ~IntArgument() {}
|
||||||
LIBCMO_DISABLE_COPY_MOVE(IntArgument);
|
LIBCMO_DISABLE_COPY_MOVE(IntArgument);
|
||||||
|
|
||||||
|
@ -308,7 +219,8 @@ namespace Unvirt::CmdHelper {
|
||||||
|
|
||||||
class StringArgument : public AbstractArgument {
|
class StringArgument : public AbstractArgument {
|
||||||
public:
|
public:
|
||||||
StringArgument(const char* argname, const char* argdesc = nullptr) : AbstractArgument(argname, argdesc) {}
|
using vType = std::string;
|
||||||
|
StringArgument(const char* argname) : AbstractArgument(argname) {}
|
||||||
virtual ~StringArgument() {}
|
virtual ~StringArgument() {}
|
||||||
LIBCMO_DISABLE_COPY_MOVE(StringArgument);
|
LIBCMO_DISABLE_COPY_MOVE(StringArgument);
|
||||||
|
|
||||||
|
@ -319,7 +231,8 @@ namespace Unvirt::CmdHelper {
|
||||||
|
|
||||||
class EncodingArgument : public AbstractArgument {
|
class EncodingArgument : public AbstractArgument {
|
||||||
public:
|
public:
|
||||||
EncodingArgument(const char* argname, const char* argdesc = nullptr) : AbstractArgument(argname, argdesc) {}
|
using vType = std::vector<std::string>;
|
||||||
|
EncodingArgument(const char* argname) : AbstractArgument(argname) {}
|
||||||
virtual ~EncodingArgument() {}
|
virtual ~EncodingArgument() {}
|
||||||
LIBCMO_DISABLE_COPY_MOVE(EncodingArgument);
|
LIBCMO_DISABLE_COPY_MOVE(EncodingArgument);
|
||||||
|
|
||||||
|
@ -328,5 +241,36 @@ namespace Unvirt::CmdHelper {
|
||||||
virtual void EndParse() override;
|
virtual void EndParse() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ArgumentsMap {
|
||||||
|
public:
|
||||||
|
ArgumentsMap() : m_Data() {}
|
||||||
|
~ArgumentsMap() {}
|
||||||
|
LIBCMO_DISABLE_COPY_MOVE(ArgumentsMap);
|
||||||
|
|
||||||
|
void Add(const std::string& k, AbstractNode* v);
|
||||||
|
void Remove(const std::string& k);
|
||||||
|
|
||||||
|
template<class _Ty>
|
||||||
|
_Ty* Get(const char* k) const {
|
||||||
|
if (k == nullptr) throw std::invalid_argument("Null argument name.");
|
||||||
|
std::string conv(k);
|
||||||
|
|
||||||
|
auto finder = m_Data.find(conv);
|
||||||
|
if (finder == m_Data.end()) throw std::invalid_argument("No such argument name.");
|
||||||
|
AbstractNode* node = finder->second;
|
||||||
|
switch (node->GetNodeType()) {
|
||||||
|
case NodeType::Argument:
|
||||||
|
return dynamic_cast<AbstractArgument*>(node)->GetData<_Ty*>();
|
||||||
|
case NodeType::Choice:
|
||||||
|
return dynamic_cast<Choice*>(node)->GetIndex();
|
||||||
|
case NodeType::Literal:
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("No such argument type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unordered_map<std::string, AbstractNode*> m_Data;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,50 +6,23 @@ namespace Unvirt::Context {
|
||||||
|
|
||||||
#pragma region Encoding Arg
|
#pragma region Encoding Arg
|
||||||
|
|
||||||
// Copy from Gamepiaynmo/BallanceModLoader
|
|
||||||
std::vector<std::string> SplitString(const std::string& str, const std::string& de) {
|
|
||||||
size_t lpos, pos = 0;
|
|
||||||
std::vector<std::string> res;
|
|
||||||
|
|
||||||
lpos = str.find_first_not_of(de, pos);
|
|
||||||
while (lpos != std::string::npos) {
|
|
||||||
pos = str.find_first_of(de, lpos);
|
|
||||||
res.push_back(str.substr(lpos, pos - lpos));
|
|
||||||
if (pos == std::string::npos) break;
|
|
||||||
|
|
||||||
lpos = str.find_first_not_of(de, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
res.push_back("");
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EncodingArgument::BeginParse(const std::string& strl) {
|
|
||||||
// encoding always accept every text
|
|
||||||
m_ParsedData = new std::vector<std::string>(SplitString(strl, ","));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncodingArgument::EndParse() {
|
|
||||||
delete reinterpret_cast<std::vector<std::string>*>(m_ParsedData);
|
|
||||||
m_ParsedData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region UnvirtContext Misc
|
#pragma region UnvirtContext Misc
|
||||||
|
|
||||||
UnvirtContext::UnvirtContext() :
|
UnvirtContext::UnvirtContext() :
|
||||||
m_Root(), m_Splitter(), m_Help(nullptr),
|
m_Root(), m_Splitter(), m_Help(nullptr),
|
||||||
m_PageLen(10u), m_Ctx(nullptr), m_FileReader(nullptr) {
|
m_PageLen(10u), m_OrderExit(false),
|
||||||
|
m_Ctx(nullptr), m_FileReader(nullptr) {
|
||||||
|
|
||||||
// create command root
|
// create command root
|
||||||
CmdHelper::CommandRoot* root = &m_Root;
|
CmdHelper::CommandRoot* root = &m_Root;
|
||||||
|
|
||||||
root->Then(
|
root->Then(
|
||||||
(new CmdHelper::Literal("deepload"))->Then(
|
(new CmdHelper::Literal("deepload"))
|
||||||
(new CmdHelper::StringArgument("filepath", "The path to loading file."))->Executes(
|
->Then((new CmdHelper::StringArgument("filepath"))
|
||||||
|
->Comment("The path to loading file.")
|
||||||
|
->Executes(
|
||||||
std::bind(&UnvirtContext::ProcLoad, this, true, std::placeholders::_1),
|
std::bind(&UnvirtContext::ProcLoad, this, true, std::placeholders::_1),
|
||||||
"Load a Virtools composition deeply. Load file to CKObject stage."
|
"Load a Virtools composition deeply. Load file to CKObject stage."
|
||||||
)
|
)
|
||||||
|
@ -78,28 +51,28 @@ namespace Unvirt::Context {
|
||||||
|
|
||||||
|
|
||||||
root->Then(
|
root->Then(
|
||||||
(new CmdHelper::Literal("foo"))->Then(
|
(new CmdHelper::Literal("foo"))->Then(
|
||||||
(new CmdHelper::Literal("bar"))->Executes([](const CmdHelper::ArgumentsMap& amap) -> void {
|
(new CmdHelper::Literal("bar"))->Executes([](const CmdHelper::ArgumentsMap& amap) -> void {
|
||||||
fprintf(stdout, "foobar!\n");
|
fprintf(stdout, "foobar!\n");
|
||||||
}, "simple foobar")
|
}, "simple foobar")
|
||||||
)->Then(
|
|
||||||
(new CmdHelper::IntArgument("bar", "the calling target 1"))->Executes([](const CmdHelper::ArgumentsMap& amap) -> void {
|
|
||||||
fprintf(stdout, "foo%" PRIi32 "!\n", *(amap.Get("bar")->GetData<int32_t>()));
|
|
||||||
}, "specialized foo bar")
|
|
||||||
)
|
|
||||||
)->Then(
|
)->Then(
|
||||||
|
(new CmdHelper::IntArgument("bar", "the calling target 1"))->Executes([](const CmdHelper::ArgumentsMap& amap) -> void {
|
||||||
|
fprintf(stdout, "foo%" PRIi32 "!\n", *(amap.Get("bar")->GetData<int32_t>()));
|
||||||
|
}, "specialized foo bar")
|
||||||
|
)
|
||||||
|
)->Then(
|
||||||
(new CmdHelper::Literal("call"))->Then(
|
(new CmdHelper::Literal("call"))->Then(
|
||||||
(new CmdHelper::IntArgument("bar", "the calling taget 2"))->Executes([](const CmdHelper::ArgumentsMap& amap) -> void {
|
(new CmdHelper::IntArgument("bar", "the calling taget 2"))->Executes([](const CmdHelper::ArgumentsMap& amap) -> void {
|
||||||
fprintf(stdout, "call%" PRIi32 "!\n", *(amap.Get("bar")->GetData<int32_t>()));
|
fprintf(stdout, "call%" PRIi32 "!\n", *(amap.Get("bar")->GetData<int32_t>()));
|
||||||
}, "calling someone")
|
}, "calling someone")
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
// create help
|
// create help
|
||||||
m_Help = root->RootHelp();
|
m_Help = root->RootHelp();
|
||||||
|
|
||||||
// create context
|
// create context
|
||||||
m_Ctx = new LibCmo::CK2::CKContext();
|
m_Ctx = new LibCmo::CK2::CKContext();
|
||||||
m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1));
|
m_Ctx->SetOutputCallback(std::bind(&UnvirtContext::PrintContextMsg, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
UnvirtContext::~UnvirtContext() {
|
UnvirtContext::~UnvirtContext() {
|
||||||
|
@ -165,14 +138,15 @@ namespace Unvirt::Context {
|
||||||
|
|
||||||
#pragma region Proc Detail
|
#pragma region Proc Detail
|
||||||
|
|
||||||
void UnvirtContext::ProcLoad(bool is_deep, const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcLoad(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// check pre-requirement
|
// check pre-requirement
|
||||||
if (HasOpenedFile()) {
|
if (HasOpenedFile()) {
|
||||||
PrintCommonError("Already have a opened file. Close it before calling \"load\".");
|
PrintCommonError("Already have a opened file. Close it before calling \"load\".");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filepath = *amap.Get("filepath")->GetData<std::string>();
|
std::string filepath = *amap->Get<CmdHelper::StringArgument::vType>("filepath");
|
||||||
|
bool is_deep = *amap->Get<CmdHelper::Choice::vType>("stage") == 0;
|
||||||
|
|
||||||
// proc
|
// proc
|
||||||
m_FileReader = new LibCmo::CK2::CKFileReader(m_Ctx);
|
m_FileReader = new LibCmo::CK2::CKFileReader(m_Ctx);
|
||||||
|
@ -193,7 +167,7 @@ namespace Unvirt::Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcUnLoad(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcUnLoad(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// check pre-requirement
|
// check pre-requirement
|
||||||
if (!HasOpenedFile()) {
|
if (!HasOpenedFile()) {
|
||||||
this->PrintCommonError("No loaded file.");
|
this->PrintCommonError("No loaded file.");
|
||||||
|
@ -204,7 +178,7 @@ namespace Unvirt::Context {
|
||||||
ClearDocument();
|
ClearDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcInfo(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcInfo(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// check pre-requirement
|
// check pre-requirement
|
||||||
if (!HasOpenedFile()) {
|
if (!HasOpenedFile()) {
|
||||||
PrintCommonError("No loaded file.");
|
PrintCommonError("No loaded file.");
|
||||||
|
@ -215,7 +189,7 @@ namespace Unvirt::Context {
|
||||||
Unvirt::StructFormatter::PrintCKFileInfo(m_FileReader->GetFileInfo());
|
Unvirt::StructFormatter::PrintCKFileInfo(m_FileReader->GetFileInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcLs(ViewPart parts, const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcLs(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// check pre-requirement
|
// check pre-requirement
|
||||||
if (!HasOpenedFile()) {
|
if (!HasOpenedFile()) {
|
||||||
this->PrintCommonError("No loaded file.");
|
this->PrintCommonError("No loaded file.");
|
||||||
|
@ -257,15 +231,15 @@ namespace Unvirt::Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcData(ViewPart parts, const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcData( const CmdHelper::ArgumentsMap* amap) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcChunk(ViewPart parts, const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcChunk(const CmdHelper::ArgumentsMap* amap) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcItems(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcItems(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// check requirement
|
// check requirement
|
||||||
int32_t count = *amap.Get("count")->GetData<int32_t>();
|
int32_t count = *amap.Get("count")->GetData<int32_t>();
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
|
@ -277,11 +251,11 @@ namespace Unvirt::Context {
|
||||||
m_PageLen = static_cast<size_t>(count);
|
m_PageLen = static_cast<size_t>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcEncoding(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcEncoding(const CmdHelper::ArgumentsMap* amap) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcTemp(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcTemp(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// check requirement
|
// check requirement
|
||||||
std::string temppath = *amap.Get("temppath")->GetData<std::string>();
|
std::string temppath = *amap.Get("temppath")->GetData<std::string>();
|
||||||
|
|
||||||
|
@ -289,7 +263,7 @@ namespace Unvirt::Context {
|
||||||
m_Ctx->SetTempPath(temppath.c_str());
|
m_Ctx->SetTempPath(temppath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcExit(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcExit(const CmdHelper::ArgumentsMap* amap) {
|
||||||
m_OrderExit = true;
|
m_OrderExit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,16 @@ namespace Unvirt::Context {
|
||||||
};
|
};
|
||||||
void PrintCommonError(const char* u8_fmt, ...);
|
void PrintCommonError(const char* u8_fmt, ...);
|
||||||
|
|
||||||
void ProcLoad(bool is_deep, const CmdHelper::ArgumentsMap& amap);
|
void ProcLoad(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcUnLoad(const CmdHelper::ArgumentsMap& amap);
|
void ProcUnLoad(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcInfo(const CmdHelper::ArgumentsMap& amap);
|
void ProcInfo(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcLs(ViewPart parts, const CmdHelper::ArgumentsMap& amap);
|
void ProcLs(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcData(ViewPart parts, const CmdHelper::ArgumentsMap& amap);
|
void ProcData(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcChunk(ViewPart parts, const CmdHelper::ArgumentsMap& amap);
|
void ProcChunk(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcItems(const CmdHelper::ArgumentsMap& amap);
|
void ProcItems(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcEncoding(const CmdHelper::ArgumentsMap& amap);
|
void ProcEncoding(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcTemp(const CmdHelper::ArgumentsMap& amap);
|
void ProcTemp(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcExit(const CmdHelper::ArgumentsMap& amap);
|
void ProcExit(const CmdHelper::ArgumentsMap* amap);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool HasOpenedFile();
|
bool HasOpenedFile();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user