update cmd dispatcher
This commit is contained in:
@ -1,32 +1,10 @@
|
||||
#include "CmdHelper.hpp"
|
||||
#include "TerminalHelper.hpp"
|
||||
#include "StructFormatter.hpp"
|
||||
#include "AccessibleValue.hpp"
|
||||
|
||||
#include <CKMinContext.hpp>
|
||||
#include <CKFile.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <functional>
|
||||
|
||||
namespace Unvirt::CmdHelper {
|
||||
|
||||
static FILE* fout = stdout;
|
||||
|
||||
#pragma region CmdSplitter
|
||||
|
||||
CmdSplitter::CmdSplitter() :
|
||||
mCmdChar(0), mBuffer(nullptr), mResult(nullptr),
|
||||
mState(StateType::NORMAL), mPreState(StateType::NORMAL) {
|
||||
;
|
||||
}
|
||||
CmdSplitter::~CmdSplitter() {
|
||||
;
|
||||
}
|
||||
|
||||
const std::deque<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
|
||||
std::deque<std::string> CmdSplitter::Convert(const std::string& u8cmd) {
|
||||
// set up variables
|
||||
std::deque<std::string> result;
|
||||
std::string buffer;
|
||||
@ -35,8 +13,8 @@ namespace Unvirt::CmdHelper {
|
||||
mState = mPreState = StateType::SPACE;
|
||||
|
||||
// split
|
||||
for (auto it = u8cmd.begin(); it != u8cmd.end(); ++it) {
|
||||
mCmdChar = (*it);
|
||||
for (auto& c : u8cmd) {
|
||||
mCmdChar = c;
|
||||
|
||||
// skip all invalid characters, \0 and etc.
|
||||
// mCmdChar >= 0 to ensure all non-ASCII UTF8 char can be accepted directly.
|
||||
@ -82,367 +60,292 @@ namespace Unvirt::CmdHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
void CmdSplitter::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;
|
||||
}
|
||||
}
|
||||
void CmdSplitter::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;
|
||||
}
|
||||
}
|
||||
void CmdSplitter::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;
|
||||
}
|
||||
}
|
||||
void CmdSplitter::ProcEscape(void) {
|
||||
// add itself
|
||||
mBuffer->push_back(mCmdChar);
|
||||
// restore state
|
||||
mState = mPreState;
|
||||
}
|
||||
void CmdSplitter::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;
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ArgParser
|
||||
#pragma region Abstract Node
|
||||
|
||||
bool ArgParser::ParseInt(const std::deque<std::string>& cmd, const size_t expected_index, int32_t& result) {
|
||||
if (expected_index >= cmd.size()) {
|
||||
result = 0;
|
||||
AbstractNode* AbstractNode::Then(AbstractNode* node) {
|
||||
// check literal duplication
|
||||
for (auto& pnode : m_Nodes) {
|
||||
if (pnode->IsConflictWith(node))
|
||||
throw std::invalid_argument("conflict node.");
|
||||
}
|
||||
// add into list
|
||||
m_Nodes.emplace_back(node);
|
||||
return this;
|
||||
}
|
||||
|
||||
AbstractNode* AbstractNode::Executes(ExecutionFct fct, const char* cmt) {
|
||||
if (m_Execution != nullptr)
|
||||
throw std::invalid_argument("duplicated executions.");
|
||||
m_Execution = fct;
|
||||
m_Comment = cmt;
|
||||
return this;
|
||||
}
|
||||
|
||||
void AbstractNode::Help(HelpDocument& doc) {
|
||||
// add self
|
||||
BeginHelp(doc);
|
||||
|
||||
// check terminal
|
||||
if (m_Execution != nullptr) {
|
||||
doc.Terminate(m_Comment);
|
||||
}
|
||||
|
||||
// iterate children
|
||||
for (auto& pnode : m_Nodes) {
|
||||
pnode->Help(doc);
|
||||
}
|
||||
|
||||
// pop self
|
||||
EndHelp(doc);
|
||||
}
|
||||
|
||||
bool AbstractNode::Consume(std::deque<std::string>& arglist, ArgumentsMap& argmap) {
|
||||
// if no data can consume, return
|
||||
if (arglist.empty()) return false;
|
||||
|
||||
// backup current value
|
||||
std::string cur = arglist.front();
|
||||
// consume self
|
||||
if (!BeginAccept(cur, argmap)) {
|
||||
// fail to consume self. not matched. return
|
||||
return false;
|
||||
}
|
||||
|
||||
// pop front for following code
|
||||
arglist.pop_front();
|
||||
|
||||
#define CONSUME_DEFER \
|
||||
arglist.push_front(cur); \
|
||||
EndAccept(argmap);
|
||||
|
||||
if (arglist.empty()) {
|
||||
// this is must be a terminal.
|
||||
// check whether we have execution.
|
||||
if (m_Execution == nullptr) {
|
||||
CONSUME_DEFER;
|
||||
return false;
|
||||
} else {
|
||||
m_Execution(argmap);
|
||||
CONSUME_DEFER;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// have following command, try match them
|
||||
// iterate literal and argument to check terminal
|
||||
for (auto& pnode : m_Nodes) {
|
||||
if (pnode->Consume(arglist, argmap)) {
|
||||
CONSUME_DEFER;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// if still nothing to match, return false
|
||||
CONSUME_DEFER;
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef CONSUME_DEFER
|
||||
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Argument Impl
|
||||
|
||||
bool IntArgument::BeginParse(const std::string& val) {
|
||||
char* pend = nullptr;
|
||||
errno = 0;
|
||||
int64_t v = std::strtoll(cmd[expected_index].c_str(), &pend, 10);
|
||||
int64_t v = std::strtoll(val.c_str(), &pend, 10);
|
||||
|
||||
if (pend == cmd[expected_index].c_str() || errno == ERANGE) {
|
||||
result = 0;
|
||||
if (pend == val.c_str() || errno == ERANGE) return false;
|
||||
|
||||
// check limit
|
||||
int32_t value = static_cast<int32_t>(v);
|
||||
if (m_IntLimit != nullptr && !m_IntLimit(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = static_cast<int>(v);
|
||||
m_ParsedData = new int32_t(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArgParser::ParseString(const std::deque<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;
|
||||
}
|
||||
void IntArgument::EndParse() {
|
||||
delete reinterpret_cast<int32_t*>(m_ParsedData);
|
||||
m_ParsedData = nullptr;
|
||||
}
|
||||
|
||||
bool ArgParser::ParseSwitch(const std::deque<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;
|
||||
}
|
||||
bool StringArgument::BeginParse(const std::string& strl) {
|
||||
// string always accept every text
|
||||
m_ParsedData = new std::string(strl);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& sw : switches) {
|
||||
if (cmd[expected_index] == sw) {
|
||||
gotten = cmd[expected_index];
|
||||
void StringArgument::EndParse() {
|
||||
delete reinterpret_cast<std::string*>(m_ParsedData);
|
||||
m_ParsedData = nullptr;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Command Root
|
||||
|
||||
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_Nodes) {
|
||||
if (pnode->Consume(arglist, amap)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
gotten.clear();
|
||||
// no matched
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
HelpDocument* CommandRoot::RootHelp() {
|
||||
HelpDocument* doc = new HelpDocument();
|
||||
|
||||
#pragma region InteractiveCmd Misc
|
||||
// we only just need iterate all children
|
||||
for (auto& pnode : m_Nodes) {
|
||||
pnode->Help(*doc);
|
||||
}
|
||||
|
||||
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;
|
||||
// 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);
|
||||
return doc;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region InteractiveCmd Dispatch
|
||||
#pragma region Help Document
|
||||
|
||||
void InteractiveCmd::Run(void) {
|
||||
std::string u8cmd;
|
||||
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));
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// get command
|
||||
GetCmdLine(u8cmd);
|
||||
void HelpDocument::Print() {
|
||||
fputs("Command Help:\n", stdout);
|
||||
|
||||
// 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;
|
||||
for (auto& item : m_Results) {
|
||||
for (auto& cmd : item.m_ArgDesc) {
|
||||
fputs(cmd.m_Name.c_str(), stdout);
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
std::string subcmd(cmds.front());
|
||||
cmds.pop_front();
|
||||
fputc('\n', stdout);
|
||||
|
||||
// dispatch command
|
||||
if (subcmd == "load") this->ProcLoad(cmds);
|
||||
else if (subcmd == "unload") this->ProcUnLoad(cmds);
|
||||
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 {
|
||||
this->PrintCommonError("No such command \"%s\".", subcmd.c_str());
|
||||
this->PrintHelp();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveCmd::GetCmdLine(std::string& u8cmd) {
|
||||
fputs("Unvirt> ", fout);
|
||||
#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
|
||||
}
|
||||
|
||||
void InteractiveCmd::PrintHelp(void) {
|
||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Allowed Subcommands: \n")), fout);
|
||||
|
||||
fputs("load\n", fout);
|
||||
fputs("\tDescription: Load a Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: load <file path>\n", fout);
|
||||
|
||||
fputs("unload\n", fout);
|
||||
fputs("\tDescription: Release loaded Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: unload\n", fout);
|
||||
|
||||
fputs("info\n", fout);
|
||||
fputs("\tDescription: Show the header info of loaded Virtools composition.\n", fout);
|
||||
fputs("\tSyntax: info\n", fout);
|
||||
|
||||
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", 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("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(fout, UNVIRT_TERMCOL_LIGHT_RED(("Lost argument at position %zu.\n")), pos);
|
||||
} else {
|
||||
fprintf(fout, 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, fout);
|
||||
std::vfprintf(fout, u8_fmt, argptr);
|
||||
std::fputs(UNVIRT_TERMCOLTAIL, fout);
|
||||
va_end(argptr);
|
||||
std::fputc('\n', fout);
|
||||
}
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region InteractiveCmd Processors
|
||||
|
||||
void InteractiveCmd::ProcLoad(const std::deque<std::string>& cmd) {
|
||||
// check pre-requirement
|
||||
if (HasOpenedFile()) {
|
||||
this->PrintCommonError("Already have a opened file. Close it before calling \"load\".");
|
||||
return;
|
||||
}
|
||||
|
||||
// check requirement
|
||||
size_t pos = 0u;
|
||||
std::string filepath;
|
||||
if (!ArgParser::ParseString(cmd, pos, filepath)) {
|
||||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
// proc
|
||||
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) {
|
||||
// fail to load. release all.
|
||||
this->PrintCommonError("Fail to open file. Function return: %s\n%s",
|
||||
Unvirt::AccessibleValue::GetCkErrorName(err).c_str(),
|
||||
Unvirt::AccessibleValue::GetCkErrorDescription(err).c_str()
|
||||
);
|
||||
|
||||
this->ClearDocument();
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcUnLoad(const std::deque<std::string>& cmd) {
|
||||
// check pre-requirement
|
||||
if (!HasOpenedFile()) {
|
||||
this->PrintCommonError("No loaded file.");
|
||||
return;
|
||||
}
|
||||
|
||||
// free all
|
||||
this->ClearDocument();
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcInfo(const std::deque<std::string>& cmd) {
|
||||
// check pre-requirement
|
||||
if (!HasOpenedFile()) {
|
||||
this->PrintCommonError("No loaded file.");
|
||||
return;
|
||||
}
|
||||
|
||||
// print
|
||||
Unvirt::StructFormatter::PrintCKFileInfo(m_Doc->m_FileInfo);
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcLs(const std::deque<std::string>& cmd) {
|
||||
// static values of switches
|
||||
static const std::vector<std::string> c_AllowedSwitches{
|
||||
"obj", "mgr"
|
||||
};
|
||||
|
||||
// check pre-requirement
|
||||
if (!HasOpenedFile()) {
|
||||
this->PrintCommonError("No loaded file.");
|
||||
return;
|
||||
}
|
||||
|
||||
// check requirement
|
||||
size_t pos = 0u;
|
||||
std::string sw;
|
||||
if (!ArgParser::ParseSwitch(cmd, pos, c_AllowedSwitches, sw)) {
|
||||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
++pos;
|
||||
int32_t gotten_page;
|
||||
if (!ArgParser::ParseInt(cmd, pos, gotten_page)) {
|
||||
gotten_page = 1; // asssume as 1
|
||||
}
|
||||
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]) {
|
||||
// obj list
|
||||
if (page * this->m_PageLen >= m_Doc->m_FileObjects.size()) {
|
||||
this->PrintCommonError("Page out of range.");
|
||||
return;
|
||||
}
|
||||
|
||||
Unvirt::StructFormatter::PrintObjectList(this->m_Doc->m_FileObjects, page, this->m_PageLen);
|
||||
|
||||
} else {
|
||||
// mgr list
|
||||
if (page * this->m_PageLen >= m_Doc->m_FileManagersData.size()) {
|
||||
this->PrintCommonError("Page out of range.");
|
||||
return;
|
||||
}
|
||||
|
||||
Unvirt::StructFormatter::PrintManagerList(this->m_Doc->m_FileManagersData, page, this->m_PageLen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcItems(const std::deque<std::string>& cmd) {
|
||||
// check requirement
|
||||
size_t pos = 0u;
|
||||
int32_t count;
|
||||
if (!ArgParser::ParseInt(cmd, pos, count) || count <= 0) {
|
||||
this->PrintArgParseError(cmd, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
// assign
|
||||
m_PageLen = static_cast<size_t>(count);
|
||||
}
|
||||
|
||||
void InteractiveCmd::ProcEncoding(const std::deque<std::string>& cmd) {
|
||||
// create list first
|
||||
std::vector<std::string> encoding_list;
|
||||
|
||||
// get list item
|
||||
size_t pos = 0u;
|
||||
while (true) {
|
||||
std::string pending;
|
||||
if (!ArgParser::ParseString(cmd, pos, pending)) {
|
||||
break; // no more encoding, break
|
||||
}
|
||||
|
||||
// add and move to next
|
||||
++pos;
|
||||
encoding_list.push_back(std::move(pending));
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user