mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
Implement ArgumentParser Utility based on the CSharp version of ZoneCodeGenerator
This commit is contained in:
parent
8991b6ab15
commit
75bd49d501
@ -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();
|
||||
}
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user