mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
chore: improve argument parser code
This commit is contained in:
parent
da18291c89
commit
2b1c048a4a
@ -1,9 +1,14 @@
|
|||||||
#include "ArgumentParser.h"
|
#include "ArgumentParser.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include "Utils/StringUtils.h"
|
||||||
|
|
||||||
const std::string PREFIX_LONG = "--";
|
#include <format>
|
||||||
const std::string PREFIX_SHORT = "-";
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
constexpr auto PREFIX_LONG = "--";
|
||||||
|
constexpr auto PREFIX_SHORT = "-";
|
||||||
|
|
||||||
ArgumentParser::ArgumentParser(const CommandLineOption* const* options, const size_t optionCount)
|
ArgumentParser::ArgumentParser(const CommandLineOption* const* options, const size_t optionCount)
|
||||||
{
|
{
|
||||||
@ -18,9 +23,7 @@ bool ArgumentParser::ParseArguments(const int argc, const char** argv)
|
|||||||
std::vector<std::string> args(argc);
|
std::vector<std::string> args(argc);
|
||||||
|
|
||||||
for (int arg = 0; arg < argc; arg++)
|
for (int arg = 0; arg < argc; arg++)
|
||||||
{
|
|
||||||
args[arg] = argv[arg];
|
args[arg] = argv[arg];
|
||||||
}
|
|
||||||
|
|
||||||
return ParseArguments(args);
|
return ParseArguments(args);
|
||||||
}
|
}
|
||||||
@ -30,26 +33,22 @@ bool ArgumentParser::ParseArguments(std::vector<std::string>& args)
|
|||||||
m_matched_arguments.clear();
|
m_matched_arguments.clear();
|
||||||
m_matched_options.clear();
|
m_matched_options.clear();
|
||||||
|
|
||||||
const size_t argCount = args.size();
|
const auto argCount = args.size();
|
||||||
for (unsigned argIndex = 0; argIndex < argCount; argIndex++)
|
for (unsigned argIndex = 0; argIndex < argCount; argIndex++)
|
||||||
{
|
{
|
||||||
std::string& arg = args[argIndex];
|
auto& arg = args[argIndex];
|
||||||
|
|
||||||
if (arg.compare(0, PREFIX_SHORT.size(), PREFIX_SHORT) == 0)
|
if (arg.compare(0, std::char_traits<char>::length(PREFIX_SHORT), PREFIX_SHORT) == 0)
|
||||||
{
|
{
|
||||||
// Options should be case insensitive. So before comparing we make the argument lower case.
|
// Options should be case-insensitive. So before comparing we make the argument lower case.
|
||||||
const size_t argStrLen = arg.size();
|
utils::MakeStringLowerCase(arg);
|
||||||
for (unsigned argStrIndex = 0; argStrIndex < argStrLen; argStrIndex++)
|
|
||||||
{
|
|
||||||
arg[argStrIndex] = tolower(arg[argStrIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CommandLineOption* matchedOption = nullptr;
|
const CommandLineOption* matchedOption = nullptr;
|
||||||
if (arg.compare(0, PREFIX_LONG.size(), PREFIX_LONG) == 0)
|
if (arg.compare(0, std::char_traits<char>::length(PREFIX_LONG), PREFIX_LONG) == 0)
|
||||||
{
|
{
|
||||||
std::string longName = arg.substr(2);
|
const auto longName = arg.substr(2);
|
||||||
|
|
||||||
for (auto option : m_command_line_options)
|
for (const auto& option : m_command_line_options)
|
||||||
{
|
{
|
||||||
if (option->m_long_name == longName)
|
if (option->m_long_name == longName)
|
||||||
{
|
{
|
||||||
@ -60,9 +59,9 @@ bool ArgumentParser::ParseArguments(std::vector<std::string>& args)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string shortName = arg.substr(1);
|
const auto shortName = arg.substr(1);
|
||||||
|
|
||||||
for (auto option : m_command_line_options)
|
for (const auto& option : m_command_line_options)
|
||||||
{
|
{
|
||||||
if (option->m_short_name == shortName)
|
if (option->m_short_name == shortName)
|
||||||
{
|
{
|
||||||
@ -74,7 +73,7 @@ bool ArgumentParser::ParseArguments(std::vector<std::string>& args)
|
|||||||
|
|
||||||
if (matchedOption == nullptr)
|
if (matchedOption == nullptr)
|
||||||
{
|
{
|
||||||
printf("Unknown option '%s'.\n", arg.c_str());
|
std::cout << std::format("Unknown option '{}'.\n", arg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ bool ArgumentParser::ParseArguments(std::vector<std::string>& args)
|
|||||||
{
|
{
|
||||||
if (!matchedOption->m_multi_use)
|
if (!matchedOption->m_multi_use)
|
||||||
{
|
{
|
||||||
printf("Option '%s' already specified.\n", arg.c_str());
|
std::cout << std::format("Option '{}' already specified.\n", arg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,21 +90,21 @@ bool ArgumentParser::ParseArguments(std::vector<std::string>& args)
|
|||||||
m_matched_options[matchedOption] = std::vector<std::string>();
|
m_matched_options[matchedOption] = std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t parameterCount = matchedOption->m_parameters.size();
|
const auto parameterCount = matchedOption->m_parameters.size();
|
||||||
if (argIndex + parameterCount >= argCount)
|
if (argIndex + parameterCount >= argCount)
|
||||||
{
|
{
|
||||||
printf("Not enough parameters for option '%s'.\n", arg.c_str());
|
std::cout << std::format("Not enough parameters for option '{}'.\n", arg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>& parameters = m_matched_options[matchedOption];
|
auto& parameters = m_matched_options[matchedOption];
|
||||||
for (unsigned parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++)
|
for (unsigned parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++)
|
||||||
{
|
{
|
||||||
std::string& param = args[argIndex + parameterIndex + 1];
|
std::string& param = args[argIndex + parameterIndex + 1];
|
||||||
|
|
||||||
if (param.compare(0, PREFIX_SHORT.size(), PREFIX_SHORT) == 0)
|
if (param.compare(0, std::char_traits<char>::length(PREFIX_SHORT), PREFIX_SHORT) == 0)
|
||||||
{
|
{
|
||||||
printf("Not enough parameters for option '%s'.\n", arg.c_str());
|
std::cout << std::format("Not enough parameters for option '{}'.\n", arg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,18 +127,19 @@ std::vector<std::string> ArgumentParser::GetArguments() const
|
|||||||
return m_matched_arguments;
|
return m_matched_arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ArgumentParser::GetValueForOption(const CommandLineOption* option)
|
std::string ArgumentParser::GetValueForOption(const CommandLineOption* option) const
|
||||||
{
|
{
|
||||||
if (!IsOptionSpecified(option))
|
const auto existingOption = m_matched_options.find(option);
|
||||||
|
if (existingOption == m_matched_options.end())
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
std::stringstream value;
|
std::stringstream value;
|
||||||
bool firstMatch = true;
|
bool firstMatch = true;
|
||||||
for (const auto& match : m_matched_options[option])
|
for (const auto& match : existingOption->second)
|
||||||
{
|
{
|
||||||
if (!firstMatch)
|
if (!firstMatch)
|
||||||
{
|
{
|
||||||
value << " " << match;
|
value << ' ' << match;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -151,15 +151,16 @@ std::string ArgumentParser::GetValueForOption(const CommandLineOption* option)
|
|||||||
return value.str();
|
return value.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ArgumentParser::GetParametersForOption(const CommandLineOption* option)
|
std::vector<std::string> ArgumentParser::GetParametersForOption(const CommandLineOption* option) const
|
||||||
{
|
{
|
||||||
if (!IsOptionSpecified(option))
|
const auto existingOption = m_matched_options.find(option);
|
||||||
|
if (existingOption == m_matched_options.end())
|
||||||
return std::vector<std::string>();
|
return std::vector<std::string>();
|
||||||
|
|
||||||
return m_matched_options[option];
|
return existingOption->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArgumentParser::IsOptionSpecified(const CommandLineOption* option)
|
bool ArgumentParser::IsOptionSpecified(const CommandLineOption* option) const
|
||||||
{
|
{
|
||||||
return m_matched_options.find(option) != m_matched_options.end();
|
return m_matched_options.find(option) != m_matched_options.end();
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,20 @@
|
|||||||
|
|
||||||
class ArgumentParser
|
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:
|
public:
|
||||||
ArgumentParser(const CommandLineOption* const* options, size_t optionCount);
|
ArgumentParser(const CommandLineOption* const* options, size_t optionCount);
|
||||||
|
|
||||||
bool ParseArguments(std::vector<std::string>& args);
|
bool ParseArguments(std::vector<std::string>& args);
|
||||||
bool ParseArguments(int argc, const char** argv);
|
bool ParseArguments(int argc, const char** argv);
|
||||||
|
|
||||||
std::vector<std::string> GetArguments() const;
|
[[nodiscard]] std::vector<std::string> GetArguments() const;
|
||||||
|
|
||||||
bool IsOptionSpecified(const CommandLineOption* option);
|
bool IsOptionSpecified(const CommandLineOption* option) const;
|
||||||
std::string GetValueForOption(const CommandLineOption* option);
|
std::string GetValueForOption(const CommandLineOption* option) const;
|
||||||
std::vector<std::string> GetParametersForOption(const CommandLineOption* option);
|
std::vector<std::string> GetParametersForOption(const CommandLineOption* option) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user