Mercurial > code
comparison C++/modules/OptionParser/OptionParser.h @ 334:0b576ee64d45
* Create brand new hierarchy
* Rename DynLib to Dynlib
* Remove some warnings
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 08 Mar 2015 14:26:33 +0100 |
parents | C++/OptionParser.h@99e83685d4da |
children | d5ec1174b707 |
comparison
equal
deleted
inserted
replaced
333:412ca7a5e1ea | 334:0b576ee64d45 |
---|---|
1 /* | |
2 * OptionParser.h -- command line option parser | |
3 * | |
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #ifndef _OPTION_PARSER_H_ | |
20 #define _OPTION_PARSER_H_ | |
21 | |
22 /** | |
23 * @file OptionParser.h | |
24 * @brief Command line option parser | |
25 */ | |
26 | |
27 #include <initializer_list> | |
28 #include <string> | |
29 #include <vector> | |
30 | |
31 /** | |
32 * @class Option | |
33 * @brief Option definition | |
34 */ | |
35 class Option { | |
36 public: | |
37 enum Flags { | |
38 NoArg = (1 << 0), | |
39 }; | |
40 | |
41 private: | |
42 std::string m_key; | |
43 std::string m_full; | |
44 int m_flags; | |
45 | |
46 public: | |
47 /** | |
48 * Construct an option. By default, an option requires an argument | |
49 * unless flags is set to NoArg. | |
50 * | |
51 * You <strong>must</strong> not prepend dashes to the option names. | |
52 * | |
53 * You don't need to set both short and long names, but you need at | |
54 * least one. | |
55 * | |
56 * @param key the short name (e.g v) | |
57 * @param full the long name (e.g verbose) | |
58 * @param flags the optional flags | |
59 * @see Flags | |
60 */ | |
61 inline Option(std::string key, std::string full, int flags = 0) | |
62 : m_key(std::move(key)) | |
63 , m_full(std::move(full)) | |
64 , m_flags(flags) | |
65 { | |
66 } | |
67 | |
68 /** | |
69 * Get the short name (e.g v) | |
70 * | |
71 * @return the short name | |
72 */ | |
73 inline const std::string &key() const noexcept | |
74 { | |
75 return m_key; | |
76 } | |
77 | |
78 /** | |
79 * Get the long name (e.g verbose) | |
80 * | |
81 * @return the long name | |
82 */ | |
83 inline const std::string &full() const noexcept | |
84 { | |
85 return m_full; | |
86 } | |
87 | |
88 /** | |
89 * Get the flags. | |
90 * | |
91 * @return the flags | |
92 * @see Flags | |
93 */ | |
94 inline int flags() const noexcept | |
95 { | |
96 return m_flags; | |
97 } | |
98 }; | |
99 | |
100 /** | |
101 * @class OptionValue | |
102 * @brief Result of an option parse | |
103 */ | |
104 class OptionValue { | |
105 private: | |
106 std::string m_key; | |
107 std::string m_full; | |
108 std::string m_value; | |
109 | |
110 public: | |
111 /** | |
112 * Construct an option value | |
113 * | |
114 * @param option the option | |
115 * @param value the value | |
116 */ | |
117 inline OptionValue(const Option &option, std::string value) | |
118 : m_key(option.key()) | |
119 , m_full(option.full()) | |
120 , m_value(std::move(value)) | |
121 { | |
122 } | |
123 | |
124 /** | |
125 * Get the value (if the option requires an argument). | |
126 * | |
127 * @return the value | |
128 */ | |
129 inline const std::string &value() const noexcept | |
130 { | |
131 return m_value; | |
132 } | |
133 | |
134 friend bool operator==(const OptionValue &o1, const std::string &name); | |
135 }; | |
136 | |
137 /** | |
138 * Test the option value with the specified option name. | |
139 * | |
140 * You can use both the short option or the long option name depending | |
141 * on what you have registered to the OptionParser class. | |
142 * | |
143 * @param o the option | |
144 * @param name the short or the full name | |
145 * @return true if matches | |
146 */ | |
147 inline bool operator==(const OptionValue &o, const std::string &name) | |
148 { | |
149 return o.m_key == name || o.m_full == name; | |
150 } | |
151 | |
152 /** | |
153 * @class OptionPack | |
154 * @brief Object containing results of a parse | |
155 * | |
156 * Because parsing bad options does not throw exceptions, this class is | |
157 * convertible to bool and has the error contained. | |
158 * | |
159 * It also have the number of arguments parsed so you can cut your options | |
160 * depending on the full command line. | |
161 * | |
162 * Example: | |
163 * -y install -d foo | |
164 * -y remove -f | |
165 * | |
166 * In that case, you can do two parsing, it will stops (unless Unstrict is set) | |
167 * until install or remove. | |
168 */ | |
169 class OptionPack : public std::vector<OptionValue> { | |
170 private: | |
171 friend class OptionParser; | |
172 | |
173 std::string m_error{"No error"}; | |
174 int m_argsParsed{0}; | |
175 | |
176 public: | |
177 /** | |
178 * Get the error. | |
179 * | |
180 * @return the error | |
181 */ | |
182 inline const std::string &error() const noexcept | |
183 { | |
184 return m_error; | |
185 } | |
186 | |
187 /** | |
188 * Get the number of arguments parsed <strong>not the number of | |
189 * options</strong>. | |
190 * | |
191 * @return the number of arguments parsed | |
192 */ | |
193 inline int parsed() const noexcept | |
194 { | |
195 return m_argsParsed; | |
196 } | |
197 | |
198 /** | |
199 * Convert to true on success. | |
200 * | |
201 * @return true on success | |
202 */ | |
203 inline operator bool() const noexcept | |
204 { | |
205 return m_error == "No error"; | |
206 } | |
207 }; | |
208 | |
209 /** | |
210 * @class OptionParser | |
211 * @brief Base class for parsing command line options | |
212 * | |
213 * The option parser is a replacement for getopt(3) which is reentrant | |
214 * and does not use globals. | |
215 */ | |
216 class OptionParser { | |
217 public: | |
218 using Map = std::vector<Option>; | |
219 using Args = std::vector<std::string>; | |
220 | |
221 enum Flags { | |
222 Unstrict = (1 << 0) | |
223 }; | |
224 | |
225 private: | |
226 Map m_options; | |
227 | |
228 const Option &get(const std::string &arg) const; | |
229 std::string key(const std::string &arg) const; | |
230 bool isDefined(const std::string &arg) const; | |
231 bool isToggle(const std::string &arg) const; | |
232 bool isShortCompacted(const std::string &arg) const; | |
233 bool isShort(const std::string &arg) const; | |
234 bool isLong(const std::string &arg) const; | |
235 bool isOption(const std::string &arg) const; | |
236 void readShort(OptionPack &pack, Args::const_iterator &it, Args::const_iterator end) const; | |
237 void readFull(OptionPack &pack, Args::const_iterator &it, Args::const_iterator end) const; | |
238 OptionPack parse(Args::const_iterator it, Args::const_iterator end, int flags) const; | |
239 | |
240 public: | |
241 /** | |
242 * Construct an option parser from an initializer_list of options. | |
243 * | |
244 * @param options the list of options | |
245 */ | |
246 OptionParser(std::initializer_list<Option> options); | |
247 | |
248 /** | |
249 * Construct an option parser from a vector of options. | |
250 * | |
251 * @param options the options | |
252 */ | |
253 OptionParser(std::vector<Option> options); | |
254 | |
255 /** | |
256 * Parse the arguments from main arguments. | |
257 * | |
258 * @param argc the number of arguments | |
259 * @param argv the arguments | |
260 * @param flags the optional flags | |
261 * @return the packed result | |
262 */ | |
263 OptionPack parse(int argc, char **argv, int flags = 0) const; | |
264 | |
265 /** | |
266 * Parse the arguments from a vector. | |
267 * | |
268 * @param args the arguments | |
269 * @param flags the optional flags | |
270 * @return the packed result | |
271 */ | |
272 OptionPack parse(const std::vector<std::string> &args, int flags = 0) const; | |
273 }; | |
274 | |
275 #endif // !_OPTION_PARSER_H_ |