Mercurial > defical
comparison defical-c/src/basic/Argument_helper.cpp @ 0:ebed2bd0d300
Initial import from svn. History be damned.
author | Edho P. Arief <me@myconan.net> |
---|---|
date | Fri, 02 Apr 2010 23:11:57 +0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ebed2bd0d300 |
---|---|
1 /* | |
2 * | |
3 * Argument Helper | |
4 * | |
5 * Daniel Russel drussel@alumni.princeton.edu | |
6 * Stanford University | |
7 * | |
8 * | |
9 * This software is not subject to copyright protection and is in the | |
10 * public domain. Neither Stanford nor the author assume any | |
11 * responsibility whatsoever for its use by other parties, and makes no | |
12 * guarantees, expressed or implied, about its quality, reliability, or | |
13 * any other characteristic. | |
14 * | |
15 */ | |
16 | |
17 #include "Argument_helper.h" | |
18 | |
19 | |
20 #include <iostream> | |
21 #include <cstdlib> | |
22 #include <cstdio> | |
23 //#include <limits> | |
24 #include <cassert> | |
25 | |
26 | |
27 | |
28 namespace dsr { | |
29 | |
30 bool verbose=false, VERBOSE=false; | |
31 | |
32 | |
33 | |
34 // This is a base class for representing one argument value. | |
35 /* | |
36 This is inherited by many classes and which represent the different types. | |
37 */ | |
38 class Argument_helper::Argument_target { | |
39 public: | |
40 char key; | |
41 std::string long_name; | |
42 std::string description; | |
43 std::string arg_description; | |
44 | |
45 Argument_target(char k, const std::string lname, | |
46 const std::string descr, | |
47 const std::string arg_descr) { | |
48 key=k; | |
49 long_name=lname; | |
50 description=descr; | |
51 arg_description=arg_descr; | |
52 } | |
53 Argument_target(const std::string descr, | |
54 const std::string arg_descr) { | |
55 key=0; | |
56 long_name=""; | |
57 description=descr; | |
58 arg_description=arg_descr; | |
59 } | |
60 virtual bool process(int &, const char **&)=0; | |
61 virtual void write_name(std::ostream &out) const; | |
62 virtual void write_value(std::ostream &out) const=0; | |
63 virtual void write_usage(std::ostream &out) const; | |
64 virtual ~Argument_target(){} | |
65 }; | |
66 | |
67 void Argument_helper::Argument_target::write_name(std::ostream &out) const { | |
68 if (key != 0) out << '-' << key; | |
69 else if (!long_name.empty()) out << "--" << long_name; | |
70 else out << arg_description; | |
71 } | |
72 | |
73 | |
74 void Argument_helper::Argument_target::write_usage(std::ostream &out) const { | |
75 if (key != 0) { | |
76 out << '-' << key; | |
77 out << "/--" << long_name; | |
78 } | |
79 out << ' ' << arg_description; | |
80 out << "\t" << description; | |
81 out << " Value: "; | |
82 write_value(out); | |
83 out << std::endl; | |
84 } | |
85 | |
86 class Argument_helper::FlagTarget: public Argument_helper::Argument_target{ | |
87 public: | |
88 bool &val; | |
89 FlagTarget(char k, const char *lname, | |
90 const char *descr, | |
91 bool &b): Argument_target(k, std::string(lname), std::string(descr), | |
92 std::string()), val(b){} | |
93 virtual bool process(int &, const char **&){ | |
94 val= !val; | |
95 return true; | |
96 } | |
97 virtual void write_value(std::ostream &out) const { | |
98 out << val; | |
99 } | |
100 | |
101 virtual void write_usage(std::ostream &out) const { | |
102 if (key != 0) { | |
103 out << '-' << key; | |
104 out << "/--" << long_name; | |
105 } | |
106 out << "\t" << description; | |
107 out << " Value: "; | |
108 write_value(out); | |
109 out << std::endl; | |
110 } | |
111 virtual ~FlagTarget(){} | |
112 }; | |
113 | |
114 class Argument_helper::DoubleTarget: public Argument_target{ | |
115 public: | |
116 double &val; | |
117 DoubleTarget(char k, const char *lname, | |
118 const char *arg_descr, | |
119 const char *descr, double &b): Argument_target(k, std::string(lname), | |
120 std::string(descr), | |
121 std::string(arg_descr)), val(b){} | |
122 DoubleTarget(const char *arg_descr, | |
123 const char *descr, double &b): Argument_target(std::string(descr), | |
124 std::string(arg_descr)), val(b){} | |
125 virtual bool process(int &argc, const char **&argv){ | |
126 if (argc==0){ | |
127 std::cerr << "Missing value for argument." << std::endl; | |
128 return false; | |
129 } | |
130 if (my_sscanf(argv[0], "%le", &val) ==1){ | |
131 --argc; | |
132 ++argv; | |
133 return true; | |
134 } else { | |
135 std::cerr << "Double not found at " << argv[0] << std::endl; | |
136 return false; | |
137 } | |
138 } | |
139 virtual void write_value(std::ostream &out) const { | |
140 out << val; | |
141 } | |
142 virtual ~DoubleTarget(){} | |
143 }; | |
144 | |
145 class Argument_helper::IntTarget: public Argument_target{ | |
146 public: | |
147 int &val; | |
148 IntTarget(const char *arg_descr, | |
149 const char *descr, int &b): Argument_target(0, std::string(), | |
150 std::string(descr), | |
151 std::string(arg_descr)), | |
152 val(b){} | |
153 IntTarget(char k, const char *lname, | |
154 const char *arg_descr, | |
155 const char *descr, int &b): Argument_target(k, std::string(lname), | |
156 std::string(descr), | |
157 std::string(arg_descr)), | |
158 val(b){} | |
159 virtual bool process(int &argc, const char **&argv){ | |
160 if (argc==0){ | |
161 std::cerr << "Missing value for argument." << std::endl; | |
162 return false; | |
163 } | |
164 if (my_sscanf(argv[0], "%d", &val) ==1){ | |
165 --argc; | |
166 ++argv; | |
167 return true; | |
168 } else { | |
169 std::cerr << "Integer not found at " << argv[0] << std::endl; | |
170 return false; | |
171 } | |
172 } | |
173 virtual void write_value(std::ostream &out) const { | |
174 out << val; | |
175 } | |
176 virtual ~IntTarget(){} | |
177 }; | |
178 | |
179 class Argument_helper::UIntTarget: public Argument_target{ | |
180 public: | |
181 unsigned int &val; | |
182 UIntTarget(const char *arg_descr, | |
183 const char *descr, unsigned int &b): Argument_target(0, std::string(), | |
184 std::string(descr), | |
185 std::string(arg_descr)), | |
186 val(b){} | |
187 UIntTarget(char k, const char *lname, | |
188 const char *arg_descr, | |
189 const char *descr, unsigned int &b): Argument_target(k, std::string(lname), | |
190 std::string(descr), | |
191 std::string(arg_descr)), | |
192 val(b){} | |
193 virtual bool process(int &argc, const char **&argv){ | |
194 if (argc==0){ | |
195 std::cerr << "Missing value for argument." << std::endl; | |
196 return false; | |
197 } | |
198 if (my_sscanf(argv[0], "%ud", &val) ==1){ | |
199 --argc; | |
200 ++argv; | |
201 return true; | |
202 } else { | |
203 std::cerr << "Unsigned integer not found at " << argv[0] << std::endl; | |
204 return false; | |
205 } | |
206 } | |
207 virtual void write_value(std::ostream &out) const { | |
208 out << val; | |
209 } | |
210 virtual ~UIntTarget(){} | |
211 }; | |
212 | |
213 | |
214 class Argument_helper::CharTarget: public Argument_target{ | |
215 public: | |
216 char &val; | |
217 CharTarget(char k, const char *lname, | |
218 const char *arg_descr, | |
219 const char *descr, char &b): Argument_target(k, std::string(lname), | |
220 std::string(descr), | |
221 std::string(arg_descr)), val(b){} | |
222 CharTarget(const char *arg_descr, | |
223 const char *descr, char &b): Argument_target(std::string(descr), | |
224 std::string(arg_descr)), val(b){} | |
225 virtual bool process(int &argc, const char **&argv){ | |
226 if (argc==0){ | |
227 std::cerr << "Missing value for argument." << std::endl; | |
228 return false; | |
229 } | |
230 if (my_sscanf(argv[0], "%c", &val) ==1){ | |
231 --argc; | |
232 ++argv; | |
233 return true; | |
234 } else { | |
235 std::cerr << "Character not found at " << argv[0] << std::endl; | |
236 return false; | |
237 } | |
238 } | |
239 virtual void write_value(std::ostream &out) const { | |
240 out << val; | |
241 } | |
242 virtual ~CharTarget(){} | |
243 }; | |
244 | |
245 | |
246 class Argument_helper::StringTarget: public Argument_target{ | |
247 public: | |
248 std::string &val; | |
249 StringTarget(const char *arg_descr, | |
250 const char *descr, std::string &b): Argument_target(0, std::string(), | |
251 descr, | |
252 arg_descr), | |
253 val(b){} | |
254 | |
255 StringTarget(char k, const char *lname, const char *arg_descr, | |
256 const char *descr, std::string &b): Argument_target(k, lname, descr, | |
257 arg_descr), | |
258 val(b){} | |
259 | |
260 virtual bool process(int &argc, const char **&argv){ | |
261 if (argc==0){ | |
262 std::cerr << "Missing string argument." << std::endl; | |
263 return false; | |
264 } | |
265 val= argv[0]; | |
266 --argc; | |
267 ++argv; | |
268 return true; | |
269 } | |
270 virtual void write_value(std::ostream &out) const { | |
271 out << val; | |
272 } | |
273 virtual ~StringTarget(){} | |
274 }; | |
275 | |
276 | |
277 class Argument_helper::StringVectorTarget: public Argument_target{ | |
278 public: | |
279 std::vector<std::string> &val; | |
280 | |
281 StringVectorTarget(char k, const char *lname, const char *arg_descr, | |
282 const char *descr, std::vector<std::string> &b): Argument_target(k, lname, descr, | |
283 arg_descr), | |
284 val(b){} | |
285 | |
286 virtual bool process(int &argc, const char **&argv){ | |
287 while (argc >0 && argv[0][0] != '-'){ | |
288 val.push_back(argv[0]); | |
289 --argc; | |
290 ++argv; | |
291 } | |
292 return true; | |
293 } | |
294 virtual void write_value(std::ostream &out) const { | |
295 for (unsigned int i=0; i< val.size(); ++i){ | |
296 out << val[i] << " "; | |
297 } | |
298 } | |
299 virtual ~StringVectorTarget(){} | |
300 }; | |
301 | |
302 | |
303 | |
304 | |
305 Argument_helper::Argument_helper(){ | |
306 author_="Someone"; | |
307 description_= "This program does something."; | |
308 date_= "A long long time ago."; | |
309 version_=-1; | |
310 extra_arguments_=NULL; | |
311 seen_end_named_=false; | |
312 new_flag('v', "verbose", "Whether to print extra information", verbose); | |
313 new_flag('V', "VERBOSE", "Whether to print lots of extra information", VERBOSE); | |
314 } | |
315 | |
316 | |
317 | |
318 void Argument_helper::set_string_vector(const char *arg_description, | |
319 const char *description, | |
320 std::vector<std::string> &dest){ | |
321 assert(extra_arguments_==NULL); | |
322 extra_arguments_descr_= description; | |
323 extra_arguments_arg_descr_= arg_description; | |
324 extra_arguments_= &dest; | |
325 } | |
326 | |
327 void Argument_helper::set_author(const char *author){ | |
328 author_=author; | |
329 } | |
330 | |
331 void Argument_helper::set_description(const char *descr){ | |
332 description_= descr; | |
333 } | |
334 | |
335 void Argument_helper::set_name(const char *descr){ | |
336 name_= descr; | |
337 } | |
338 | |
339 void Argument_helper::set_version(float v){ | |
340 version_=v; | |
341 } | |
342 | |
343 void Argument_helper::set_version(const char *s){ | |
344 std::stringstream f; | |
345 f << s; | |
346 f >> version_; | |
347 } | |
348 | |
349 void Argument_helper::set_build_date(const char *date){ | |
350 date_=date; | |
351 } | |
352 | |
353 void Argument_helper::new_argument_target(Argument_target *t) { | |
354 assert(t!= NULL); | |
355 if (t->key != 0){ | |
356 if (short_names_.find(t->key) != short_names_.end()){ | |
357 std::cerr << "Two arguments are defined with the same character key, namely" << std::endl; | |
358 short_names_[t->key]->write_usage(std::cerr); | |
359 std::cerr << "\n and \n"; | |
360 t->write_usage(std::cerr); | |
361 std::cerr << std::endl; | |
362 } | |
363 short_names_[t->key]= t; | |
364 } | |
365 if (!t->long_name.empty()){ | |
366 if (long_names_.find(t->long_name) != long_names_.end()){ | |
367 std::cerr << "Two arguments are defined with the same long key, namely" << std::endl; | |
368 long_names_[t->long_name]->write_usage(std::cerr); | |
369 std::cerr << "\n and \n"; | |
370 t->write_usage(std::cerr); | |
371 std::cerr << std::endl; | |
372 } | |
373 long_names_[t->long_name]= t; | |
374 } | |
375 all_arguments_.push_back(t); | |
376 } | |
377 | |
378 void Argument_helper::new_flag(char key, const char *long_name, const char *description,bool &dest){ | |
379 Argument_target *t= new FlagTarget(key, long_name, description, dest); | |
380 new_argument_target(t); | |
381 }; | |
382 | |
383 | |
384 | |
385 void Argument_helper::new_string(const char *arg_description, const char *description, | |
386 std::string &dest){ | |
387 Argument_target *t= new StringTarget(arg_description, description, dest); | |
388 unnamed_arguments_.push_back(t); | |
389 all_arguments_.push_back(t); | |
390 }; | |
391 void Argument_helper::new_optional_string(const char *arg_description, const char *description, | |
392 std::string &dest){ | |
393 Argument_target *t= new StringTarget(arg_description, description, dest); | |
394 optional_unnamed_arguments_.push_back(t); | |
395 }; | |
396 void Argument_helper::new_named_string(char key, const char *long_name, | |
397 const char *arg_description, const char *description, | |
398 std::string &dest){ | |
399 Argument_target *t= new StringTarget(key, long_name, arg_description, description, dest); | |
400 new_argument_target(t); | |
401 }; | |
402 | |
403 | |
404 void Argument_helper::new_named_string_vector(char key, const char *long_name, | |
405 const char *arg_description, const char *description, | |
406 std::vector<std::string> &dest){ | |
407 Argument_target *t= new StringVectorTarget(key, long_name, arg_description, description, dest); | |
408 new_argument_target(t); | |
409 }; | |
410 | |
411 | |
412 | |
413 void Argument_helper::new_int(const char *arg_description, const char *description, | |
414 int &dest){ | |
415 Argument_target *t= new IntTarget(arg_description, description, dest); | |
416 unnamed_arguments_.push_back(t); | |
417 all_arguments_.push_back(t); | |
418 }; | |
419 void Argument_helper::new_optional_int(const char *arg_description, const char *description, | |
420 int &dest){ | |
421 Argument_target *t= new IntTarget(arg_description, description, dest); | |
422 optional_unnamed_arguments_.push_back(t); | |
423 }; | |
424 void Argument_helper::new_named_int(char key, const char *long_name, | |
425 const char *arg_description, const char *description, | |
426 int &dest){ | |
427 Argument_target *t= new IntTarget(key, long_name, arg_description, description, dest); | |
428 new_argument_target(t); | |
429 }; | |
430 | |
431 void Argument_helper::new_unsigned_int(const char *arg_description, const char *description, | |
432 unsigned int &dest){ | |
433 Argument_target *t= new UIntTarget(arg_description, description, dest); | |
434 unnamed_arguments_.push_back(t); | |
435 all_arguments_.push_back(t); | |
436 }; | |
437 void Argument_helper::new_optional_unsigned_int(const char *arg_description, const char *description, | |
438 unsigned int &dest){ | |
439 Argument_target *t= new UIntTarget(arg_description, description, dest); | |
440 optional_unnamed_arguments_.push_back(t); | |
441 }; | |
442 void Argument_helper::new_named_unsigned_int(char key, const char *long_name, | |
443 const char *arg_description, const char *description, | |
444 unsigned int &dest){ | |
445 Argument_target *t= new UIntTarget(key, long_name, arg_description, description, dest); | |
446 new_argument_target(t); | |
447 }; | |
448 | |
449 | |
450 void Argument_helper::new_double(const char *arg_description, const char *description, | |
451 double &dest){ | |
452 Argument_target *t= new DoubleTarget(arg_description, description, dest); | |
453 unnamed_arguments_.push_back(t); | |
454 all_arguments_.push_back(t); | |
455 }; | |
456 void Argument_helper::new_optional_double(const char *arg_description, const char *description, | |
457 double &dest){ | |
458 Argument_target *t= new DoubleTarget(arg_description, description, dest); | |
459 optional_unnamed_arguments_.push_back(t); | |
460 }; | |
461 void Argument_helper::new_named_double(char key, const char *long_name, | |
462 const char *arg_description, const char *description, | |
463 double &dest){ | |
464 Argument_target *t= new DoubleTarget(key, long_name, arg_description, description, dest); | |
465 new_argument_target(t); | |
466 }; | |
467 | |
468 void Argument_helper::new_char(const char *arg_description, const char *description, | |
469 char &dest){ | |
470 Argument_target *t= new CharTarget(arg_description, description, dest); | |
471 unnamed_arguments_.push_back(t); | |
472 all_arguments_.push_back(t); | |
473 }; | |
474 void Argument_helper::new_optional_char(const char *arg_description, const char *description, | |
475 char &dest){ | |
476 Argument_target *t= new CharTarget(arg_description, description, dest); | |
477 optional_unnamed_arguments_.push_back(t); | |
478 }; | |
479 void Argument_helper::new_named_char(char key, const char *long_name, | |
480 const char *arg_description, const char *description, | |
481 char &dest){ | |
482 Argument_target *t= new CharTarget(key, long_name, arg_description, description, dest); | |
483 new_argument_target(t); | |
484 }; | |
485 | |
486 | |
487 | |
488 void Argument_helper::write_usage(std::ostream &out) const { | |
489 out << name_ << " version " << version_ << ", by " << author_ << std::endl; | |
490 out << description_ << std::endl; | |
491 out << "Compiled on " << date_ << std::endl << std::endl; | |
492 out << "Usage: " << name_ << " "; | |
493 for (UVect::const_iterator it= unnamed_arguments_.begin(); it != unnamed_arguments_.end(); ++it){ | |
494 (*it)->write_name(out); | |
495 out << " "; | |
496 } | |
497 for (UVect::const_iterator it= optional_unnamed_arguments_.begin(); | |
498 it != optional_unnamed_arguments_.end(); ++it){ | |
499 out << "["; | |
500 (*it)->write_name(out); | |
501 out << "] "; | |
502 } | |
503 if (extra_arguments_ != NULL) { | |
504 out << "[" << extra_arguments_arg_descr_ << "]"; | |
505 } | |
506 | |
507 out << std::endl << std::endl; | |
508 out << "All arguments:\n"; | |
509 for (UVect::const_iterator it= unnamed_arguments_.begin(); it != unnamed_arguments_.end(); ++it){ | |
510 (*it)->write_usage(out); | |
511 } | |
512 for (UVect::const_iterator it= optional_unnamed_arguments_.begin(); | |
513 it != optional_unnamed_arguments_.end(); ++it){ | |
514 (*it)->write_usage(out); | |
515 } | |
516 | |
517 //out << extra_arguments_arg_descr_ << ": " << extra_arguments_descr_ << std::endl; | |
518 for (SMap::const_iterator it= short_names_.begin(); it != short_names_.end(); ++it){ | |
519 (it->second)->write_usage(out); | |
520 } | |
521 } | |
522 | |
523 | |
524 | |
525 void Argument_helper::write_values(std::ostream &out) const { | |
526 for (UVect::const_iterator it= unnamed_arguments_.begin(); it != unnamed_arguments_.end(); ++it){ | |
527 out << (*it)->description; | |
528 out << ": "; | |
529 (*it)->write_value(out); | |
530 out << std::endl; | |
531 } | |
532 for (UVect::const_iterator it= optional_unnamed_arguments_.begin(); | |
533 it != optional_unnamed_arguments_.end(); ++it){ | |
534 out << (*it)->description; | |
535 out << ": "; | |
536 (*it)->write_value(out); | |
537 out << std::endl; | |
538 } | |
539 if (extra_arguments_!=NULL){ | |
540 for (std::vector<std::string>::const_iterator it= extra_arguments_->begin(); | |
541 it != extra_arguments_->end(); ++it){ | |
542 out << *it << " "; | |
543 } | |
544 } | |
545 | |
546 for (SMap::const_iterator it= short_names_.begin(); it != short_names_.end(); ++it){ | |
547 out << it->second->description; | |
548 out << ": "; | |
549 it->second->write_value(out); | |
550 out << std::endl; | |
551 } | |
552 } | |
553 | |
554 Argument_helper::~Argument_helper(){ | |
555 for (std::vector<Argument_target*>::iterator it= all_arguments_.begin(); | |
556 it != all_arguments_.end(); ++it){ | |
557 delete *it; | |
558 } | |
559 } | |
560 | |
561 | |
562 void Argument_helper::process(int argc, const char **argv){ | |
563 name_= argv[0]; | |
564 ++argv; | |
565 --argc; | |
566 | |
567 current_unnamed_= unnamed_arguments_.begin(); | |
568 current_optional_unnamed_= optional_unnamed_arguments_.begin(); | |
569 | |
570 for ( int i=0; i< argc; ++i){ | |
571 if (strcmp(argv[i], "--help") == 0){ | |
572 write_usage(std::cout); | |
573 exit(0); | |
574 } | |
575 } | |
576 | |
577 while (argc != 0){ | |
578 | |
579 const char* cur_arg= argv[0]; | |
580 if (cur_arg[0]=='-' && !seen_end_named_){ | |
581 --argc; ++argv; | |
582 if (cur_arg[1]=='-'){ | |
583 if (cur_arg[2] == '\0') { | |
584 //std::cout << "Ending flags " << std::endl; | |
585 seen_end_named_=true; | |
586 } else { | |
587 // long argument | |
588 LMap::iterator f= long_names_.find(cur_arg+2); | |
589 if ( f != long_names_.end()){ | |
590 if (!f->second->process(argc, argv)) { | |
591 handle_error(); | |
592 } | |
593 } else { | |
594 std::cerr<< "Invalid long argument "<< cur_arg << ".\n"; | |
595 handle_error(); | |
596 } | |
597 } | |
598 } else { | |
599 if (cur_arg[1]=='\0') { | |
600 std::cerr << "Invalid argument " << cur_arg << ".\n"; | |
601 handle_error(); | |
602 } | |
603 SMap::iterator f= short_names_.find(cur_arg[1]); | |
604 if ( f != short_names_.end()){ | |
605 if (!f->second->process(argc, argv)) { | |
606 handle_error(); | |
607 } | |
608 } else { | |
609 std::cerr<< "Invalid short argument "<< cur_arg << ".\n"; | |
610 handle_error(); | |
611 } | |
612 } | |
613 } else { | |
614 if (current_unnamed_ != unnamed_arguments_.end()){ | |
615 Argument_target *t= *current_unnamed_; | |
616 t->process(argc, argv); | |
617 ++current_unnamed_; | |
618 } else if (current_optional_unnamed_ != optional_unnamed_arguments_.end()){ | |
619 Argument_target *t= *current_optional_unnamed_; | |
620 t->process(argc, argv); | |
621 ++current_optional_unnamed_; | |
622 } else if (extra_arguments_!= NULL){ | |
623 extra_arguments_->push_back(cur_arg); | |
624 --argc; | |
625 ++argv; | |
626 } else { | |
627 std::cerr << "Invalid extra argument " << argv[0] << std::endl; | |
628 handle_error(); | |
629 } | |
630 } | |
631 } | |
632 | |
633 if (current_unnamed_ != unnamed_arguments_.end()){ | |
634 std::cerr << "Missing required arguments:" << std::endl; | |
635 for (; current_unnamed_ != unnamed_arguments_.end(); ++current_unnamed_){ | |
636 (*current_unnamed_)->write_name(std::cerr); | |
637 std::cerr << std::endl; | |
638 } | |
639 std::cerr << std::endl; | |
640 handle_error(); | |
641 } | |
642 | |
643 if (VERBOSE) verbose=true; | |
644 } | |
645 | |
646 void Argument_helper::handle_error() const { | |
647 write_usage(std::cerr); | |
648 exit(1); | |
649 } | |
650 } | |
651 |