werkamsus / Lilith

Lilith, C++ Cybersecurity Research Project
https://nick.sl
MIT License
717 stars 207 forks source link

Advice for command handler function #19

Closed czs108 closed 5 years ago

czs108 commented 6 years ago

You can use std::map<> to create mapping between command string (such as 'connect', 'remoteControl') and its handler:

void handleConnect(std::vector<std::string> params);
void handleBroadcast(std::vector<std::string> params);
void handleListClients(std::vector<std::string> params);
// ...
using LPFN_CommandHandler = void(Server::*)(std::vector<std::string> params);
std::map<std::string, LPFN_CommandHandler> handlers;

Considering that some handler may have more than one param, so use std::vector\<std::string>, not std::string.

Init map:

void Server::initHandler()
{
    handlers.insert({ "connect", &Server::handleConnect });
    handlers.insert({ "broadcast", &Server::handleBroadcast });
    handlers.insert({ "listClients", &Server::handleListClients });
    // ...
}

Parse input and get command and its params.

eg:

"connect 0" => cmd: "connect", params: { '0' }

std::string parseCmd(std::string input, std::vector<std::string> &params)
{
    std::string temp;
    std::stringstream ss(input);
    while (ss >> temp)
    {
        params.push_back(temp);
    }

    std::string cmd = params.front();
    params.erase(params.begin());
    return cmd;
}

So you can reduce complexity when handle user's input

std::getline(std::cin, userinput);
std::vector<std::string> params;
std::string cmd = General::parseCmd(userinput, params);
// Find handler function
std::map<std::string, LPFN_CommandHandler>::iterator it = handlers.find(cmd);
if (it != handlers.end())
{
    (this->*it->second)(params);
}
// else ...
werkamsus commented 6 years ago

Will implement in the GUI Refactor, thank you!