diff options
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | debian/changelog | 1 | ||||
| -rw-r--r-- | debian/libreichwein-dev.install | 1 | ||||
| -rw-r--r-- | programopts.cpp | 84 | ||||
| -rw-r--r-- | programopts.h | 29 | 
5 files changed, 118 insertions, 0 deletions
| @@ -24,6 +24,7 @@ PROGSRC=\      mime.cpp \      os.cpp \      process.cpp \ +    programopts.cpp \      stringhelper.cpp \      tempfile.cpp \      url.cpp \ @@ -114,6 +115,8 @@ os.cpp \  os.h \  process.cpp \  process.h \ +programopts.cpp \ +programopts.h \  remote-install.sh \  stringhelper.cpp \  stringhelper.h \ diff --git a/debian/changelog b/debian/changelog index 5481d63..1ada900 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@  libreichwein (1.6) UNRELEASED; urgency=medium    * Fixed dependencies +  * Added programopts.h   -- Roland Reichwein <mail@reichwein.it>  Sun, 07 Jan 2024 20:37:30 +0100 diff --git a/debian/libreichwein-dev.install b/debian/libreichwein-dev.install index dc2511d..65a3203 100644 --- a/debian/libreichwein-dev.install +++ b/debian/libreichwein-dev.install @@ -4,6 +4,7 @@ usr/include/libreichwein/file.h  usr/include/libreichwein/mime.h  usr/include/libreichwein/os.h  usr/include/libreichwein/process.h +usr/include/libreichwein/programopts.h  usr/include/libreichwein/stringhelper.h  usr/include/libreichwein/tempfile.h  usr/include/libreichwein/url.h 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 <algorithm> +#include <iterator> + +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<std::string> m_parameters; + std::map<std::string, std::function<bool(const std::string&)>, PrefixCmp> m_option_prefixes; +}; + +Reichwein::ProgramOpts::ProgramOpts(int argc, char* argv[], std::map<std::string, std::function<bool(const std::string&)>>& option_prefixes): + m_pimpl(std::make_unique<impl>()) +{ + 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<std::string> Reichwein::ProgramOpts::nonOptionArguments() +{ + return m_pimpl->m_parameters; +} + diff --git a/programopts.h b/programopts.h new file mode 100644 index 0000000..442d3b0 --- /dev/null +++ b/programopts.h @@ -0,0 +1,29 @@ +// Parse command line options of program + +#pragma once + +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <vector> + +#define EXPORT __attribute__((visibility("default"))) + +namespace Reichwein { + +class EXPORT ProgramOpts +{ +public: + // Processing of options in lambdas: each do return true iff parameter was consumed + ProgramOpts(int argc, char* argv[], std::map<std::string, std::function<bool(const std::string&)>>& option_prefixes); + ~ProgramOpts(); + void process(); // must be called to run functions per option, given to ctor + std::string programName(); + std::vector<std::string> nonOptionArguments(); +private: + struct impl; + std::unique_ptr<impl> m_pimpl; +}; + +} // namespace | 
