Implement ArgumentParser Utility based on the CSharp version of ZoneCodeGenerator

This commit is contained in:
Jan 2019-09-26 21:43:03 +02:00
parent 8991b6ab15
commit 75bd49d501
2 changed files with 171 additions and 2 deletions

View File

@ -0,0 +1,164 @@
#include "ArgumentParser.h"
#include <sstream>
const std::string PREFIX_LONG = "--";
const std::string PREFIX_SHORT = "-";
ArgumentParser::ArgumentParser(const CommandLineOption** options, const size_t optionCount)
{
for(unsigned optionIndex = 0; optionIndex < optionCount; optionIndex++)
{
m_command_line_options.push_back(options[optionIndex]);
}
}
bool ArgumentParser::ParseArguments(const int argc, const char** argv)
{
std::vector<std::string> args(argc);
for(int arg = 0; arg < argc; arg++)
{
args[arg] = argv[arg];
}
return ParseArguments(args);
}
bool ArgumentParser::ParseArguments(std::vector<std::string>& args)
{
m_matched_arguments.clear();
m_matched_options.clear();
const size_t argCount = args.size();
for (unsigned argIndex = 0; argIndex < argCount; argIndex++)
{
std::string& arg = args[argIndex];
if(arg.compare(0, PREFIX_SHORT.size(), PREFIX_SHORT) == 0)
{
// Options should be case insensitive. So before comparing we make the argument lower case.
const size_t argStrLen = arg.size();
for(unsigned argStrIndex = 0; argStrIndex < argStrLen; argStrIndex++)
{
arg[argStrIndex] = tolower(arg[argStrIndex]);
}
const CommandLineOption* matchedOption = nullptr;
if(arg.compare(0, PREFIX_LONG.size(), PREFIX_LONG) == 0)
{
std::string longName = arg.substr(2);
for (auto option : m_command_line_options)
{
if(option->m_long_name == longName)
{
matchedOption = option;
break;
}
}
}
else
{
std::string shortName = arg.substr(1);
for (auto option : m_command_line_options)
{
if(option->m_short_name == shortName)
{
matchedOption = option;
break;
}
}
}
if(matchedOption == nullptr)
{
printf("Unknown option '%s'.\n", arg.c_str());
return false;
}
if(m_matched_options.find(matchedOption) != m_matched_options.end())
{
if(!matchedOption->m_multi_use)
{
printf("Option '%s' already specified.\n", arg.c_str());
return false;
}
}
else
{
m_matched_options[matchedOption] = std::vector<std::string>();
}
const size_t parameterCount = matchedOption->m_parameters.size();
if(argIndex + parameterCount >= argCount)
{
printf("Not enough parameters for option '%s'.\n", arg.c_str());
return false;
}
std::vector<std::string>& parameters = m_matched_options[matchedOption];
for(unsigned parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++)
{
std::string& param = args[argIndex + parameterIndex + 1];
if(param.compare(0, PREFIX_SHORT.size(), PREFIX_SHORT) == 0)
{
printf("Not enough parameters for option '%s'.\n", arg.c_str());
return false;
}
parameters.push_back(param);
}
argIndex += parameterCount;
}
else
{
m_matched_arguments.push_back(arg);
}
}
return true;
}
std::vector<std::string> ArgumentParser::GetArguments() const
{
return m_matched_arguments;
}
std::string ArgumentParser::GetValueForOption(const CommandLineOption* option)
{
if(!IsOptionSpecified(option))
return "";
std::stringstream value;
bool firstMatch = true;
for (const auto& match : m_matched_options[option])
{
if(!firstMatch)
{
value << " " << match;
}
else
{
value << match;
firstMatch = false;
}
}
return value.str();
}
std::vector<std::string> ArgumentParser::GetParametersForOption(const CommandLineOption* option)
{
if(!IsOptionSpecified(option))
return std::vector<std::string>();
return m_matched_options[option];
}
bool ArgumentParser::IsOptionSpecified(const CommandLineOption* option)
{
return m_matched_options.find(option) != m_matched_options.end();
}

View File

@ -2,18 +2,23 @@
#include "CommandLineOption.h"
#include <string>
#include <vector>
#include <map>
class ArgumentParser
{
std::vector<const CommandLineOption*> m_command_line_options;
std::map<const CommandLineOption*, std::vector<std::string>> m_matched_options;
std::vector<std::string> m_matched_arguments;
public:
ArgumentParser(const CommandLineOption** options, size_t optionCount);
bool ParseArguments(std::vector<std::string>& args);
bool ParseArguments(int argc, const char** argv);
std::vector<std::string> GetArguments();
std::vector<std::string> GetArguments() const;
bool IsOptionSpecified(const CommandLineOption* option);
std::string GetValueForOption(const CommandLineOption* option);
std::vector<std::string> GetParametersForOption(const CommandLineOption* option);
};
};