Graph Framework
Loading...
Searching...
No Matches
commandline_parser.hpp
Go to the documentation of this file.
1//------------------------------------------------------------------------------
4//------------------------------------------------------------------------------
5
6#ifndef commandline_parser_h
7#define commandline_parser_h
8
9#include <map>
10#include <type_traits>
11#include <utility>
12#include <mutex>
13
15namespace commandline {
17 static std::mutex sync;
18
19//------------------------------------------------------------------------------
21//------------------------------------------------------------------------------
22 class parser {
23 private:
25 std::map<std::string, std::pair<bool, std::string>> options;
27 std::map<std::string, std::string> parsed_options;
29 std::map<std::string, std::set<std::string>> option_values;
31 const std::string command;
32
33//------------------------------------------------------------------------------
38//------------------------------------------------------------------------------
39 static std::string_view take_end(const char *string,
40 const char character) {
41 std::string_view view(string);
42 return view.substr(view.find_last_of('/') + 1);
43 }
44
45 public:
46//------------------------------------------------------------------------------
48//------------------------------------------------------------------------------
49 parser(const char *name) :
50 command(take_end(name, '/')) {
51 options.emplace(std::make_pair("help",
52 std::make_pair(false,
53 "Show this help.")));
54 }
55
56//------------------------------------------------------------------------------
63//------------------------------------------------------------------------------
64 void add_option(const std::string &option,
65 const bool takes_value,
66 const std::string &help_text,
67 const std::set<std::string> &values = {}) {
68 options.try_emplace(option, takes_value, help_text);
69 if (!values.empty()) {
70 option_values.try_emplace(option, values);
71 }
72 }
73
74//------------------------------------------------------------------------------
78//------------------------------------------------------------------------------
79 void show_help(const std::string &command) const {
80 sync.lock();
81 size_t longest = 0;
82 for (auto &[option, value] : options) {
83 longest = std::max(longest, option.size());
84 }
85 std::cout << "USAGE: " << command << " [--options] [--options=with_value]" << std::endl << std::endl;
86 std::cout << "OPTIONS:" << std::endl;
87 for (auto &[option, value] : options) {
88 std::cout << " --" << option
89 << (std::get<bool> (value) ? "= " : " ");
90 for (size_t i = option.size(); i < longest; i++) {
91 std::cout << " ";
92 }
93 std::cout << std::get<std::string> (value) << std::endl;
94 if (option_values.find(option) != option_values.cend()) {
95 for (auto &option_value : option_values.at(option)) {
96 std::cout << " ";
97 for (size_t i = 0; i < longest; i++) {
98 std::cout << " ";
99 }
100 std::cout << " * " << option_value << std::endl;
101 }
102 }
103 }
104 std::cout << std::endl;
105 sync.unlock();
106 exit(0);
107 }
108
109//------------------------------------------------------------------------------
114//------------------------------------------------------------------------------
115 void parse(const int argc, const char * argv[]) {
116 for (int i = 1; i < argc; i++) {
117 std::string_view view(argv[i]);
118 const size_t option_end = view.find_first_of('=');
119 std::string option(view.substr(2, option_end - 2));
120 if (is_option_set(option)) {
121 std::cout << "Warning --" << option << " set more than once." << std::endl;
122 std::cout << " Overwriting --" << option << std::endl;
123 }
124 if (options.find(option) == options.cend()) {
125 std::cout << "UNKNOWN OPTION: " << view << std::endl << std::endl;
126 show_help(std::string(argv[0]));
127 }
128 if (option_end != view.size()) {
129 parsed_options[option] = std::string(view.substr(option_end + 1));
130 if ((option_values.find(option) != option_values.cend()) &&
131 !(option_values.at(option).find(parsed_options[option]) !=
132 option_values.at(option).cend())) {
133 std::cout << "UNKNOWN VALUE: " << parsed_options[option]
134 << std::endl << std::endl;
135 }
136 } else {
137 parsed_options[option] = "";
138 }
139 }
140
141 if (is_option_set("help")) {
142 show_help(std::string(argv[0]));
143 }
144 }
145
146//------------------------------------------------------------------------------
150//------------------------------------------------------------------------------
151 bool is_option_set(const std::string &option) const {
152 return parsed_options.find(option) != parsed_options.cend();
153 }
154
155//------------------------------------------------------------------------------
159//------------------------------------------------------------------------------
160 template<typename T>
161 T get_option_value(const std::string &option) const {
162 if (is_option_set(option)) {
163 std::string value = parsed_options.at(option);
164 if constexpr (std::is_same<T, std::string> ()) {
165 return value;
166 } else if constexpr (std::is_same<T, float> () ||
167 std::is_same<T, std::complex<float>> ()) {
168 return static_cast<T> (std::stof(value));
169 } else if constexpr (std::is_same<T, double> () ||
170 std::is_same<T, std::complex<double>> ()) {
171 return static_cast<T> (std::stod(value));
172 } else if constexpr (std::is_same<T, int> ()) {
173 return std::stoi(value);
174 } else if constexpr (std::is_same<T, long> ()) {
175 return std::stol(value);
176 } else if constexpr (std::is_same<T, unsigned long> ()) {
177 return std::stoul(value);
178 }
179 } else {
180 std::cout << "Expected option : --" << option << std::endl << std::endl;
181 show_help(command);
182 }
183 return NULL;
184 }
185 };
186}
187
188#endif /* commandline_parser_h */
Parser class.
Definition commandline_parser.hpp:22
void add_option(const std::string &option, const bool takes_value, const std::string &help_text, const std::set< std::string > &values={})
Add commandline option.
Definition commandline_parser.hpp:64
parser(const char *name)
Default constructor.
Definition commandline_parser.hpp:49
void show_help(const std::string &command) const
Display help.
Definition commandline_parser.hpp:79
T get_option_value(const std::string &option) const
Get the option value.
Definition commandline_parser.hpp:161
bool is_option_set(const std::string &option) const
Check if option is set.
Definition commandline_parser.hpp:151
void parse(const int argc, const char *argv[])
Parse the command line.
Definition commandline_parser.hpp:115
Name space for the command line parsing.
Definition commandline_parser.hpp:15