summaryrefslogtreecommitdiffhomepage
path: root/programopts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'programopts.cpp')
-rw-r--r--programopts.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/programopts.cpp b/programopts.cpp
new file mode 100644
index 0000000..aee8b05
--- /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 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;
+};
+
+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())));
+}
+
+ProgramOpts::~ProgramOpts()
+{
+}
+
+void ProgramOpts::process()
+{
+ for (size_t 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 ProgramOpts::programName()
+{
+ return m_pimpl->m_programName;
+}
+
+std::vector<std::string> ProgramOpts::nonOptionArguments()
+{
+ return m_pimpl->m_parameters;
+}
+