Bincimap 2.0.16
Easy Imapping
Loading...
Searching...
No Matches
argparser.cc
Go to the documentation of this file.
1
7#include "argparser.h"
8#include "convert.h"
9
10#include <string>
11#include <map>
12
13using namespace ::std;
14using namespace Binc;
15
16//----------------------------------------------------------------------
18{
19 errString = "Unknown error for args";
20 ac = 0;
21}
22
23//----------------------------------------------------------------------
24bool CommandLineArgs::parse(int argc, char *argv[])
25{
26 ac = -1;
27 head = argv[0];
28 head += " <options> --\n";
29
30 if (argc > 1) {
31 string lastKey;
32 bool lastIsBoolean = false;
33
34 for (int i = 1; i < argc; ++i) {
35 string s = argv[i];
36 if (s.length() < 2) {
37 unqualified.push_back(s);
38 continue;
39 }
40
41 if (s[0] != '-') {
42 // read value of last argument
43 if (lastKey == "") {
44 unqualified.push_back(s);
45 continue;
46 }
47
48 if (lastIsBoolean && (s != "yes" && s != "no")) {
49 errString = "syntax error: " + s;
50 errString += " (expected yes or no)";
51 return false;
52 }
53
54 args[lastKey] = s;
55 passedArgs[lastKey] = true;
56 lastKey = "";
57 lastIsBoolean = false;
58 } else if (s[1] == '-') {
59 if (lastKey != "") {
60 if (lastIsBoolean) {
61 args[lastKey] = "yes";
62 passedArgs[lastKey] = true;
63 lastKey = "";
64 lastIsBoolean = false;
65 } else {
66 errString = "expected value of ";
67 errString += lastKey;
68 return false;
69 }
70 }
71
72 // break if '--' is detected
73 if (s.length() == 2) {
74 ac = i + 1;
75 break;
76 }
77
78 // parse --argument
79 string arg = s.substr(2);
80 string val;
81 string::size_type epos = arg.find('=');
82 if (epos != string::npos) {
83 val = arg.substr(epos + 1);
84 arg = arg.substr(0, epos);
85 }
86
87 if (reg.find(arg) == reg.end()) {
88 errString = "unrecognized argument: --" + arg;
89 return false;
90 }
91
92 if (reg.find(arg)->second.b) {
93 if (val != "" && val != "yes" && val != "no") {
94 errString = "syntax error: " + val;
95 errString += " (expected yes or no)";
96 return false;
97 } else if (val == "") {
98 val = "yes";
99 }
100 }
101
102 if (val == "") {
103 errString = "syntax error: " + arg;
104 errString += " (expected --" + arg + "=<str>)";
105 return false;
106 }
107
108 args[arg] = val;
109 passedArgs[arg] = true;
110
111 lastKey = "";
112 lastIsBoolean = false;
113 } else {
114 if (lastKey != "") {
115 if (lastIsBoolean) {
116 args[lastKey] = "yes";
117 passedArgs[lastKey] = true;
118 lastKey = "";
119 lastIsBoolean = false;
120 } else {
121 errString = "expected value of ";
122 errString += lastKey;
123 return false;
124 }
125 }
126
127 // parse -argument
128 string arg = s.substr(1);
129 if (arg.length() == 1) {
130 map<string, ArgOpts>::const_iterator it = reg.begin();
131 bool match = false;
132 for (; it != reg.end(); ++it) {
133 if (it->second.c.find(arg[0]) != string::npos) {
134 lastKey = it->first;
135 if (it->second.b) lastIsBoolean = true;
136 match = true;
137 break;
138 }
139 }
140
141 if (!match) {
142 errString = "unrecognized argument: -";
143 errString += arg[0];
144 return false;
145 }
146 } else {
147 string::const_iterator its = arg.begin();
148 for (; its != arg.end(); ++its) {
149 map<string, ArgOpts>::const_iterator it = reg.begin();
150 bool match = false;
151 for (; it != reg.end(); ++it) {
152 if (it->second.c.find(*its) != string::npos) {
153 if (!it->second.b) {
154 errString = "argument is not a boolean: ";
155 errString += "--" + it->first;
156 errString += " / -";
157 errString += it->second.c;
158 return false;
159 }
160
161 match = true;
162 args[it->first] = "yes";
163 passedArgs[it->first] = true;
164
165 lastKey = "";
166 lastIsBoolean = false;
167 break;
168 }
169 }
170
171 if (!match) {
172 errString = "unrecognized argument: ";
173 errString += s;
174 return false;
175 }
176 }
177 }
178 }
179 }
180
181 if (lastKey != "") {
182 if (lastIsBoolean) {
183 args[lastKey] = "yes";
184 passedArgs[lastKey] = true;
185 } else {
186 errString = "expected value of ";
187 errString += lastKey;
188 return false;
189 }
190 }
191 }
192
193 // assign default "no" values for arguments that were not passed.
194 map<string, ArgOpts>::const_iterator it = reg.begin();
195 for (; it != reg.end(); ++it) {
196 if (args.find(it->first) == args.end()) {
197 if (!it->second.o) {
198 errString = "missing argument: ";
199 errString += it->first;
200 return false;
201 }
202 if (it->second.b) args[it->first] = "no";
203 }
204 }
205 if (ac == -1) ac = argc;
206
207 return true;
208}
209
210//----------------------------------------------------------------------
212{
213 return errString;
214}
215
216//----------------------------------------------------------------------
217const string CommandLineArgs::operator [](const string &arg) const
218{
219 if (args.find(arg) == args.end()) return "";
220 return args.find(arg)->second;
221}
222
223//----------------------------------------------------------------------
224void CommandLineArgs::addOptional(const string &arg, const string &desc,
225 bool boolean)
226{
227 registerArg(arg, desc, boolean, true);
228}
229
230//----------------------------------------------------------------------
231void CommandLineArgs::addRequired(const string &arg,
232 const string &desc, bool boolean)
233{
234 registerArg(arg, desc, boolean, false);
235}
236
237//----------------------------------------------------------------------
238void CommandLineArgs::registerArg(const string &arg, const string &desc,
239 bool boolean, bool optional)
240{
241 string name = arg;
242
243 string shorts;
244 while (name.size() > 1 && name[1] == '|') {
245 shorts += name[0];
246 name = name.substr(2);
247 }
248
249 reg.insert(make_pair(name, ArgOpts(shorts, boolean, optional, desc)));
250}
251
252//----------------------------------------------------------------------
253bool CommandLineArgs::hasArg(const std::string &arg) const
254{
255 string tmp = arg; lowercase(tmp);
256 return passedArgs.find(tmp) != passedArgs.end();
257}
258
259//----------------------------------------------------------------------
261{
262 string tmp = head;
263 tmp += '\n';
264
265 map<string, ArgOpts>::const_iterator it = reg.begin();
266 for (; it != reg.end(); ++it) {
267 if (it->second.c != "") {
268 string::const_iterator sit = it->second.c.begin();
269 for (; sit != it->second.c.end(); ++sit) {
270 if (sit != it->second.c.begin()) tmp += '\n';
271 tmp += " -";
272 tmp += *sit;
273 }
274 tmp += ", ";
275 } else {
276 tmp += " ";
277 }
278
279 tmp += "--";
280 tmp += it->first;
281 if (!it->second.b) tmp += "=<str>";
282
283 if (!it->second.o) tmp += " (required)";
284
285 string::size_type lineStart = tmp.rfind('\n');
286 if (lineStart == string::npos) lineStart = 0;
287
288 int pad = 21 - (tmp.length() - lineStart);
289 if (pad < 0) {
290 tmp += '\n';
291 pad = 20;
292 }
293
294 tmp += string(pad, ' ');
295 tmp += it->second.desc;
296 tmp += '\n';
297 }
298
299 tmp += '\n';
300 tmp += tail;
301 tmp += '\n';
302
303 return tmp;
304}
305
306//----------------------------------------------------------------------
308{
309 return ac;
310}
311
312//----------------------------------------------------------------------
313void CommandLineArgs::setTail(const string &str)
314{
315 tail = str;
316}
317
318//----------------------------------------------------------------------
319const vector<string> &CommandLineArgs::getUnqualifiedArgs() const
320{
321 return unqualified;
322}
Declaration of the argument parser class.
void setTail(const std::string &str)
Definition: argparser.cc:313
const std::string operator[](const std::string &arg) const
Definition: argparser.cc:217
void addRequired(const std::string &arg, const std::string &desc, bool boolean)
Definition: argparser.cc:231
std::string usageString(void) const
Definition: argparser.cc:260
bool hasArg(const std::string &arg) const
Definition: argparser.cc:253
bool parse(int argc, char *argv[])
Definition: argparser.cc:24
std::string errorString(void) const
Definition: argparser.cc:211
const std::vector< std::string > & getUnqualifiedArgs() const
Definition: argparser.cc:319
int argc(void) const
Definition: argparser.cc:307
void addOptional(const std::string &arg, const std::string &desc, bool boolean)
Definition: argparser.cc:224
Declaration of miscellaneous convertion functions.
Definition: bincimapd.cc:9
void lowercase(std::string &input)
Definition: convert.h:122