summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2024-05-09 11:53:46 +0200
committerRoland Reichwein <mail@reichwein.it>2024-05-09 11:53:46 +0200
commit20a2aa6070d6e7e6a1bd9e0bb2e85eca10543bbc (patch)
tree61af71c9a6a4d255fa5366b5b866b7091d13a406
parent89b05af725d216553924fbec4331c13e7313e66c (diff)
Added programopts
-rw-r--r--Makefile3
-rw-r--r--debian/changelog1
-rw-r--r--debian/libreichwein-dev.install1
-rw-r--r--programopts.cpp84
-rw-r--r--programopts.h29
5 files changed, 118 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 1c29509..6735c82 100644
--- a/Makefile
+++ b/Makefile
@@ -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