From 20a2aa6070d6e7e6a1bd9e0bb2e85eca10543bbc Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Thu, 9 May 2024 11:53:46 +0200 Subject: Added programopts --- programopts.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 programopts.cpp (limited to 'programopts.cpp') diff --git a/programopts.cpp b/programopts.cpp new file mode 100644 index 0000000..81f1be9 --- /dev/null +++ b/programopts.cpp @@ -0,0 +1,84 @@ +#include "programopts.h" + +#include +#include + +using namespace std::string_literals; + +namespace { + struct PrefixCmp + { + bool operator()(const std::string& lhs, const std::string& rhs) const + { + return !(lhs.starts_with(rhs) || rhs.starts_with(lhs)) && lhs < rhs; + } + }; +} + +struct Reichwein::ProgramOpts::impl +{ + int m_argc; + char** m_argv; + std::string m_programName; + std::vector m_parameters; + std::map, PrefixCmp> m_option_prefixes; +}; + +Reichwein::ProgramOpts::ProgramOpts(int argc, char* argv[], std::map>& option_prefixes): + m_pimpl(std::make_unique()) +{ + m_pimpl->m_argc = argc; + m_pimpl->m_argv = argv; + if (m_pimpl->m_argc >= 1) + m_pimpl->m_programName = m_pimpl->m_argv[0]; + //std::copy(option_prefixes.begin(), option_prefixes.end(), std::inserter(m_pimpl->m_option_prefixes, std::next(m_pimpl->m_option_prefixes.begin()))); +} + +Reichwein::ProgramOpts::~ProgramOpts() +{ +} + +void Reichwein::ProgramOpts::process() +{ + for (int i = 1; i < m_pimpl->m_argc; i++) { + std::string arg{ m_pimpl->m_argv[i] }; + if (arg.size() == 0) + throw std::runtime_error("Empty option #"s + std::to_string(i)); + + if (arg[0] != '-') { // non-option parameter + m_pimpl->m_parameters.push_back(arg); + } else { + auto prefix_iterator = m_pimpl->m_option_prefixes.find(arg); + if (prefix_iterator == m_pimpl->m_option_prefixes.end()) + throw std::runtime_error("Unknown option: "s + arg); + auto& [prefix, f] = *prefix_iterator; + std::string optional_parameter; + bool parameter_provided{ false }; + + if (prefix.size() < arg.size()) { + optional_parameter = arg.substr(prefix.size()); + } else { + if (i < m_pimpl->m_argc - 1) + optional_parameter = m_pimpl->m_argv[i + 1]; + if (optional_parameter.size() > 0 && optional_parameter[0] == '-') + optional_parameter = ""; + else + parameter_provided = true; + } + bool parameter_consumed = f(optional_parameter); // call the function from the map + if (parameter_provided && parameter_consumed) + i++; // skip parameter + } + } +} + +std::string Reichwein::ProgramOpts::programName() +{ + return m_pimpl->m_programName; +} + +std::vector Reichwein::ProgramOpts::nonOptionArguments() +{ + return m_pimpl->m_parameters; +} + -- cgit v1.2.3