From 2b1c048a4ad19ec42146861640bc7e48a1e07bfb Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 23 Sep 2024 20:15:52 +0200 Subject: [PATCH] chore: improve argument parser code --- src/Utils/Utils/Arguments/ArgumentParser.cpp | 69 ++++++++++---------- src/Utils/Utils/Arguments/ArgumentParser.h | 17 ++--- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/Utils/Utils/Arguments/ArgumentParser.cpp b/src/Utils/Utils/Arguments/ArgumentParser.cpp index 9625fd34..221e1f9c 100644 --- a/src/Utils/Utils/Arguments/ArgumentParser.cpp +++ b/src/Utils/Utils/Arguments/ArgumentParser.cpp @@ -1,9 +1,14 @@ #include "ArgumentParser.h" -#include +#include "Utils/StringUtils.h" -const std::string PREFIX_LONG = "--"; -const std::string PREFIX_SHORT = "-"; +#include +#include +#include +#include + +constexpr auto PREFIX_LONG = "--"; +constexpr auto PREFIX_SHORT = "-"; 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 args(argc); for (int arg = 0; arg < argc; arg++) - { args[arg] = argv[arg]; - } return ParseArguments(args); } @@ -30,26 +33,22 @@ bool ArgumentParser::ParseArguments(std::vector& args) m_matched_arguments.clear(); m_matched_options.clear(); - const size_t argCount = args.size(); + const auto argCount = args.size(); 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::length(PREFIX_SHORT), 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]); - } + // Options should be case-insensitive. So before comparing we make the argument lower case. + utils::MakeStringLowerCase(arg); const CommandLineOption* matchedOption = nullptr; - if (arg.compare(0, PREFIX_LONG.size(), PREFIX_LONG) == 0) + if (arg.compare(0, std::char_traits::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) { @@ -60,9 +59,9 @@ bool ArgumentParser::ParseArguments(std::vector& args) } 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) { @@ -74,7 +73,7 @@ bool ArgumentParser::ParseArguments(std::vector& args) if (matchedOption == nullptr) { - printf("Unknown option '%s'.\n", arg.c_str()); + std::cout << std::format("Unknown option '{}'.\n", arg); return false; } @@ -82,7 +81,7 @@ bool ArgumentParser::ParseArguments(std::vector& args) { 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; } } @@ -91,21 +90,21 @@ bool ArgumentParser::ParseArguments(std::vector& args) m_matched_options[matchedOption] = std::vector(); } - const size_t parameterCount = matchedOption->m_parameters.size(); + const auto parameterCount = matchedOption->m_parameters.size(); 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; } - std::vector& parameters = m_matched_options[matchedOption]; + auto& 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) + if (param.compare(0, std::char_traits::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; } @@ -128,18 +127,19 @@ std::vector ArgumentParser::GetArguments() const 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 ""; std::stringstream value; bool firstMatch = true; - for (const auto& match : m_matched_options[option]) + for (const auto& match : existingOption->second) { if (!firstMatch) { - value << " " << match; + value << ' ' << match; } else { @@ -151,15 +151,16 @@ std::string ArgumentParser::GetValueForOption(const CommandLineOption* option) return value.str(); } -std::vector ArgumentParser::GetParametersForOption(const CommandLineOption* option) +std::vector 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(); - 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(); } diff --git a/src/Utils/Utils/Arguments/ArgumentParser.h b/src/Utils/Utils/Arguments/ArgumentParser.h index 1983d2f2..71522302 100644 --- a/src/Utils/Utils/Arguments/ArgumentParser.h +++ b/src/Utils/Utils/Arguments/ArgumentParser.h @@ -7,19 +7,20 @@ class ArgumentParser { - std::vector m_command_line_options; - std::map> m_matched_options; - std::vector m_matched_arguments; - public: ArgumentParser(const CommandLineOption* const* options, size_t optionCount); bool ParseArguments(std::vector& args); bool ParseArguments(int argc, const char** argv); - std::vector GetArguments() const; + [[nodiscard]] std::vector GetArguments() const; - bool IsOptionSpecified(const CommandLineOption* option); - std::string GetValueForOption(const CommandLineOption* option); - std::vector GetParametersForOption(const CommandLineOption* option); + bool IsOptionSpecified(const CommandLineOption* option) const; + std::string GetValueForOption(const CommandLineOption* option) const; + std::vector GetParametersForOption(const CommandLineOption* option) const; + +private: + std::vector m_command_line_options; + std::map> m_matched_options; + std::vector m_matched_arguments; };