Skip to content

Instantly share code, notes, and snippets.

@ganler
Last active April 29, 2020 16:14
Show Gist options
  • Save ganler/f083cfacdfa46fd1d00c6041acc95e93 to your computer and use it in GitHub Desktop.
Save ganler/f083cfacdfa46fd1d00c6041acc95e93 to your computer and use it in GitHub Desktop.
#include <string>
#include <iostream>
#include <unordered_map>
class CmdLineParser {
public:
CmdLineParser(int args, char** argv) {
try {
for(size_t i = 1; i < args; ++i) {
enum class State {
kKEY, kVAL, kEQUAL, kOTHER
};
auto state = State::kOTHER;
const char* line = argv[i];
size_t curse = 0;
size_t begin = 0;
std::string k, v;
bool shutdown = false;
while(!shutdown) {
switch (state) {
case State::kKEY:
if (std::isalpha(line[curse]) || std::isdigit(line[curse])) {
++curse;
continue;
}
switch (line[curse]) {
case '=':
state = State::kEQUAL;
k = std::string(line + begin, line + curse);
while(!k.empty() and (k.back() == ' ' or k.back() == '\t'))
k.pop_back();
++curse;
begin = curse + 1;
continue;
case ' ':
case '\t':
++curse;
continue;
}
throw std::logic_error("CmdLineParser: Syntax error(syntax: .^*k{empty}^*={empty}^v.^*)");
case State::kEQUAL:
if (line[curse] > 32 and line[curse] <= 126) {
state = State::kVAL;
begin = curse;
continue;
}
++curse;
break;
case State::kVAL:
if (line[curse] > 32 and line[curse] <= 126)
++curse;
else {
v = std::string(line + begin, line + curse);
shutdown = true;
}
break;
case State::kOTHER:
if (std::isalpha(line[curse])) {
state = State::kKEY;
begin = curse;
continue;
}
// Default
++curse;
break;
}
}
if (k.empty() or v.empty())
throw std::logic_error("CmdLineParser: Syntax error(syntax: .^*k{empty}^*={empty}^v.^*)");
std::cout << "[CmdLineParser] Key: " << k << '=' << v << std::endl;
m_kv[k] = v;
}
} catch (const std::logic_error& err) {
std::cerr << err.what() << std::endl;
}
}
std::string Get(const std::string& k) const {
auto res = m_kv.find(k);
return m_kv.cend() == res ? std::string{} : (res->second);
}
const std::unordered_map<std::string, std::string>& Get() {
return m_kv;
}
private:
std::unordered_map<std::string, std::string> m_kv;
};
int main(int args, char** argv) {
CmdLineParser parser(args, argv);
for (auto&& p : parser.Get())
std::cout << p.first << ' ' << p.second << std::endl;
std::cout << parser.Get("hello");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment