b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2cmdline.H
Go to the documentation of this file.
1//------------------------------------------------------------------------
2// b2cmdline.H --
3//
4// Command-line parsing classes for ./src/processor/main.C
5//
6// written by Mathias Doreille
7//
8// Copyright (c) 2004-2012,2016,2017
9// SMR Engineering & Development SA
10// 2502 Bienne, Switzerland
11//
12// All Rights Reserved. Proprietary source code. The contents of
13// this file may not be disclosed to third parties, copied or
14// duplicated in any form, in whole or in part, without the prior
15// written permission of SMR.
16//------------------------------------------------------------------------
17
18#ifndef __B2CMDLINE_H__
19#define __B2CMDLINE_H__
20
21#include <cctype>
22#include <complex>
23#include <iostream>
24#include <iterator>
25#include <map>
26#include <sstream>
27#include <string>
28#include <vector>
29
30#include "b2csda.H"
31#include "b2dictionary.H"
32#include "b2exception.H"
33#include "b2logging.H"
34#include "b2ppconfig.h"
35#include "b2rtable.H"
36
151namespace b2000 { namespace cmdline {
152
153class CmdLine;
154
157public:
159 std::string name_, std::string short_desc_, std::string long_desc_,
160 bool multiple_ = false)
161 : name(name_),
162 short_desc(short_desc_),
163 long_desc(long_desc_),
164 is_set_(false),
165 multiple(multiple_) {}
166
167 virtual ~CmdOptBase() {}
168
169 bool is_set() { return is_set_; }
170
171protected:
172 friend class CmdLine;
173 virtual void parse_arg(const std::string& arg) = 0;
174 std::string get_short_desc() const;
175 std::string name;
176 std::string short_desc;
177 std::string long_desc;
178 bool is_set_;
179 bool multiple;
180};
181
184template <typename T = std::string>
185class CmdOpt : public CmdOptBase {
186public:
187 CmdOpt(std::string name_, std::string short_desc_, std::string long_desc_, T default_ = T())
188 : CmdOptBase(name_, short_desc_, long_desc_), value(default_) {}
189 operator T&() { return value; }
190
191private:
192 void parse_arg(const std::string& arg) override {
193 std::istringstream i(arg);
194 i >> value;
195 if (!i) {
196 Exception() << "Cannot convert the command-line argument " << arg
197 << " to the specific type of the option -" << name << "." << THROW;
198 }
199 std::string s;
200 i >> s;
201 if (s.size()) {
202 Exception() << "Cannot convert the command-line argument " << arg
203 << " to the specific type of the option -" << name << "." << THROW;
204 }
205 is_set_ = true;
206 }
207
208 T value;
209};
210
213template <typename T = std::string>
214class CmdOptList : public std::vector<T>, public CmdOptBase {
215public:
216 CmdOptList(std::string name_, std::string short_desc_, std::string long_desc_)
217 : CmdOptBase(name_, short_desc_, long_desc_, true) {}
218
219private:
220 void parse_arg(const std::string& arg) override {
221 T value;
222 std::istringstream i(arg);
223 i >> value;
224 if (!i) {
225 Exception() << "Cannot convert the command-line argument " << arg
226 << " to the specific type of the option -" << name << "." << THROW;
227 }
228 std::string s;
229 i >> s;
230 if (s.size()) {
231 Exception() << "Cannot convert the command-line argument " << arg
232 << " to the specific type of the option -" << name << "." << THROW;
233 }
234 std::vector<T>::push_back(value);
235 is_set_ = true;
236 }
237};
238
242class CmdOptRTable : public CmdOptBase, public RTable {
243public:
244 CmdOptRTable(std::string name_, std::string short_desc_, std::string long_desc_)
245 : CmdOptBase(name_, (short_desc_ == "" ? "key=value" : short_desc_), long_desc_, true) {}
246
247private:
248 void parse_arg(const std::string& arg) override {
249 int pos_equal = arg.find('=');
250 if (pos_equal == -1) {
251 Exception() << "Cannot convert the command-line argument " << arg
252 << " to the specific type of the option -" << name << "."
253 << "The = character is missing." << THROW;
254 }
255 std::string key = arg.substr(0, pos_equal);
256 std::string val = arg.substr(pos_equal + 1);
257
258 {
259 std::istringstream iss(val);
260 int v;
261 iss >> v;
262 if (iss && iss.eof()) {
263 set(key, v);
264 is_set_ = true;
265 return;
266 }
267 }
268 {
269 std::istringstream iss(val);
270 float v;
271 iss >> v;
272 if (iss && iss.eof()) {
273 set(key, v);
274 is_set_ = true;
275 return;
276 }
277 }
278 set(key, val);
279 is_set_ = true;
280 }
281};
282
286class CmdOptDictionary : public CmdOptBase, public Dictionary {
287public:
288 CmdOptDictionary(std::string name_, std::string short_desc_, std::string long_desc_)
289 : CmdOptBase(name_, (short_desc_ == "" ? "key=value" : short_desc_), long_desc_, true),
290 logger(logging::get_logger(std::string("command_line.") + name_)) {}
291
292 bool has_key(const std::string& key) const override {
293 logger << logging::debug << "Try to use the key " << key << " of the command line option -"
294 << name << "." << logging::LOGFLUSH;
295 return list_key.find(key) != list_key.end();
296 }
297
298 bool get_bool(const std::string& key) const override {
299 list_key_t::const_iterator i = list_key.find(key);
300 if (i == list_key.end()) { KeyError() << THROW; }
301 const_cast<bool&>(i->second.second) = true;
302 logger << logging::debug << "Using the key " << key << " of the command-line option -"
303 << name << " has boolean." << logging::LOGFLUSH;
304 const std::string& s = i->second.first;
305 if (s == "1" || s == "yes" || s == "YES" || s == "true" || s == "TRUE") {
306 return true;
307 } else if (s == "0" || s == "no" || s == "NO" || s == "false" || s == "FALSE") {
308 return false;
309 }
310 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
311 << " to a value of type bool." << THROW;
312 return false;
313 }
314
315 int get_int(const std::string& key) const override {
316 list_key_t::const_iterator i = list_key.find(key);
317 if (i == list_key.end()) { KeyError() << THROW; }
318 const_cast<bool&>(i->second.second) = true;
319 std::istringstream o(i->second.first);
320 std::istream_iterator<int> oo(o);
321 std::vector<int> v(oo, std::istream_iterator<int>());
322 if (v.size() != 1 || !o.eof()) {
323 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
324 << " to an integer value." << THROW;
325 }
326 logger << logging::debug << "Using the key " << key << " of the command line option -"
327 << name << " has integer." << logging::LOGFLUSH;
328 return v[0];
329 }
330
331 double get_double(const std::string& key) const override {
332 list_key_t::const_iterator i = list_key.find(key);
333 if (i == list_key.end()) { KeyError() << THROW; }
334 const_cast<bool&>(i->second.second) = true;
335 std::istringstream o(i->second.first);
336 std::istream_iterator<double> oo(o);
337 std::vector<double> v(oo, std::istream_iterator<double>());
338 if (v.size() != 1 || !o.eof()) {
339 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
340 << " to a floating point value." << THROW;
341 }
342 logger << logging::debug << "Using the key " << key << " of the command line option -"
343 << name << " has floating point value." << logging::LOGFLUSH;
344 return v[0];
345 }
346
347 b2000::csda<double> get_csda_double(const std::string& key) const override {
348 list_key_t::const_iterator i = list_key.find(key);
349 if (i == list_key.end()) { KeyError() << THROW; }
350 const_cast<bool&>(i->second.second) = true;
351 std::istringstream o(i->second.first);
352 std::istream_iterator<b2000::csda<double> > oo(o);
353 std::vector<b2000::csda<double> > v(oo, std::istream_iterator<b2000::csda<double> >());
354 if (v.size() != 1 || !o.eof()) {
355 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
356 << " to a csda value." << THROW;
357 }
358 logger << logging::debug << "Using the key " << key << " of the command line option -"
359 << name << " has csda value." << logging::LOGFLUSH;
360 return v[0];
361 }
362
363 std::complex<double> get_complex_double(const std::string& key) const override {
364 list_key_t::const_iterator i = list_key.find(key);
365 if (i == list_key.end()) { KeyError() << THROW; }
366 const_cast<bool&>(i->second.second) = true;
367 std::istringstream o(i->second.first);
368 std::istream_iterator<std::complex<double> > oo(o);
369 std::vector<std::complex<double> > v(oo, std::istream_iterator<std::complex<double> >());
370 if (v.size() != 1 || !o.eof()) {
371 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
372 << " to a complex value." << THROW;
373 }
374 logger << logging::debug << "Using the key " << key << " of the command line option -"
375 << name << " has complex value." << logging::LOGFLUSH;
376 return v[0];
377 }
378
379 std::string get_string(const std::string& key) const override {
380 list_key_t::const_iterator i = list_key.find(key);
381 if (i == list_key.end()) { KeyError() << THROW; }
382 const_cast<bool&>(i->second.second) = true;
383 logger << logging::debug << "Using the key " << key << " of the command line option -"
384 << name << " has string." << logging::LOGFLUSH;
385 return i->second.first;
386 }
387
388 void get(const std::string& key, std::vector<int>& v) const override {
389 list_key_t::const_iterator i = list_key.find(key);
390 if (i == list_key.end()) { KeyError() << THROW; }
391 const_cast<bool&>(i->second.second) = true;
392 std::istringstream o(i->second.first);
393 std::istream_iterator<int> oo(o);
394 std::vector<int> vv(oo, std::istream_iterator<int>());
395 if (!o.eof()) {
396 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
397 << " to an array of integers." << THROW;
398 }
399 logger << logging::debug << "Using the key " << key << " of the command line option -"
400 << name << " has array of integers." << logging::LOGFLUSH;
401 vv.swap(v);
402 }
403
404 void get(const std::string& key, std::vector<double>& v) const override {
405 list_key_t::const_iterator i = list_key.find(key);
406 if (i == list_key.end()) { KeyError() << THROW; }
407 const_cast<bool&>(i->second.second) = true;
408 std::istringstream o(i->second.first);
409 std::istream_iterator<double> oo(o);
410 std::vector<double> vv(oo, std::istream_iterator<double>());
411 if (!o.eof()) {
412 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
413 << " to an array of floating point values." << THROW;
414 }
415 logger << logging::debug << "Using the key " << key << " of the command line option -"
416 << name << " has array of double." << logging::LOGFLUSH;
417 vv.swap(v);
418 }
419
420 void get(const std::string& key, std::vector<b2000::csda<double> >& v) const override {
421 list_key_t::const_iterator i = list_key.find(key);
422 if (i == list_key.end()) { KeyError() << THROW; }
423 const_cast<bool&>(i->second.second) = true;
424 std::istringstream o(i->second.first);
425 std::istream_iterator<b2000::csda<double> > oo(o);
426 std::vector<b2000::csda<double> > vv(oo, std::istream_iterator<b2000::csda<double> >());
427 if (!o.eof()) {
428 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
429 << " to an array of csda values." << THROW;
430 }
431 logger << logging::debug << "Using the key " << key << " of the command line option -"
432 << name << " has array of csda values." << logging::LOGFLUSH;
433 vv.swap(v);
434 }
435
436 void get(const std::string& key, std::vector<std::complex<double> >& v) const override {
437 list_key_t::const_iterator i = list_key.find(key);
438 if (i == list_key.end()) { KeyError() << THROW; }
439 const_cast<bool&>(i->second.second) = true;
440 std::istringstream o(i->second.first);
441 std::istream_iterator<std::complex<double> > oo(o);
442 std::vector<std::complex<double> > vv(oo, std::istream_iterator<std::complex<double> >());
443 if (!o.eof()) {
444 Exception() << "Cannot convert the string " << i->second.first << " of key " << key
445 << " to an array of complex values." << THROW;
446 }
447 logger << logging::debug << "Using the key " << key << " of the command line option -"
448 << name << " has array of complex doubles." << logging::LOGFLUSH;
449 vv.swap(v);
450 }
451
452 void warn_on_non_used_key() const override {
453 std::string res;
454 for (list_key_t::const_iterator i = list_key.begin(); i != list_key.end(); ++i) {
455 if (!i->second.second) {
456 if (!res.empty()) { res += ", "; }
457 res += i->first;
458 }
459 }
460 if (!res.empty()) {
461 logger << logging::warning << "Key '" << res
462 << "' of command line option ignored, because unknown" << logging::LOGFLUSH;
463 }
464 }
465
466 std::string has_string() const override {
467 std::string res = "{";
468 for (list_key_t::const_iterator i = list_key.begin(); i != list_key.end(); ++i) {
469 res += '"';
470 res += i->first;
471 res += "\": ";
472 res += i->second.first;
473 res += ", ";
474 }
475 res += '}';
476 return res;
477 }
478
479private:
480 void parse_arg(const std::string& arg) override {
481 int pos_equal = arg.find('=');
482 if (pos_equal == -1) {
483 Exception() << "Cannot convert the command-line argument " << arg
484 << " to the specific type of the option -" << name << "."
485 << "The = character is missing." << THROW;
486 }
487 std::string key = arg.substr(0, pos_equal);
488 std::string val = arg.substr(pos_equal + 1);
489
490 // The command-line argument may be given in lower-case.
491 for (std::string::iterator i = key.begin(); i != key.end(); ++i) {
492 (*i) = std::toupper(*i);
493 }
494 for (std::string::iterator i = val.begin(); i != val.end(); ++i) {
495 (*i) = std::toupper(*i);
496 }
497
498 if (has_key(key)) {
499 Exception() << "The key " << key
500 << " of the command-line "
501 "argument "
502 << arg << " of the option -" << name << " already exists." << THROW;
503 }
504 list_key[key] = std::pair<std::string, bool>(val, false);
505 is_set_ = true;
506 }
507
508 typedef std::map<std::string, std::pair<std::string, bool> > list_key_t;
509 list_key_t list_key;
510 logging::Logger& logger;
511};
512
515public:
516 CmdArgBase(std::string short_desc_, std::string long_desc_)
517 : short_desc(short_desc_), long_desc(long_desc_) {}
518 virtual ~CmdArgBase() {}
519
520protected:
521 friend class CmdLine;
522 virtual void parse_arg(const std::string& arg) = 0;
523 std::string short_desc;
524 std::string long_desc;
525};
526
529template <typename T = std::string>
530class CmdArg : public CmdArgBase {
531public:
532 CmdArg(std::string short_desc_, std::string long_desc_) : CmdArgBase(short_desc_, long_desc_) {}
533
534 operator T&() { return value; }
535
536private:
537 T value;
538 void parse_arg(const std::string& arg) override {
539 std::istringstream i(arg);
540 i >> value;
541 if (!i) {
542 Exception() << "Cannot convert the command-line argument " << arg
543 << " to the specific type of the argument " << short_desc << "." << THROW;
544 }
545 std::string s;
546 i >> s;
547 if (s.size()) {
548 Exception() << "Cannot convert the command-line argument " << arg
549 << " to the specific type of the argument " << short_desc << "." << THROW;
550 }
551 }
552};
553
557public:
558 CmdArgListBase(std::string short_desc_, std::string long_desc_)
559 : short_desc(short_desc_), long_desc(long_desc_) {}
560 virtual ~CmdArgListBase() {}
561
562protected:
563 friend class CmdLine;
564 virtual void parse_arg(const std::string& arg) = 0;
565 std::string short_desc;
566 std::string long_desc;
567};
568
571template <typename T = std::string>
572class CmdArgList : public std::vector<T>, public CmdArgListBase {
573public:
574 CmdArgList(std::string short_desc_, std::string long_desc_)
575 : CmdArgListBase(short_desc_, long_desc_) {}
576
577private:
578 void parse_arg(const std::string& arg) override {
579 T value;
580 std::istringstream i(arg);
581 i >> value;
582 if (!i) {
583 Exception() << "Cannot convert the command-line argument " << arg
584 << " to the specific type of the argument " << short_desc << "." << THROW;
585 }
586 std::string s;
587 i >> s;
588 if (s.size()) {
589 Exception() << "Cannot convert the command-line argument " << arg
590 << " to the specific type of the argument " << short_desc << "." << THROW;
591 }
592 std::vector<T>::push_back(value);
593 }
594};
595
596template <>
597inline void CmdOpt<std::string>::parse_arg(const std::string& arg) {
598 value = arg;
599 is_set_ = true;
600}
601
602template <>
603inline void CmdOptList<std::string>::parse_arg(const std::string& arg) {
604 std::vector<std::string>::push_back(arg);
605 is_set_ = true;
606}
607
608template <>
609inline void CmdArg<std::string>::parse_arg(const std::string& arg) {
610 value = arg;
611}
612
613template <>
614inline void CmdArgList<std::string>::parse_arg(const std::string& arg) {
615 std::vector<std::string>::push_back(arg);
616}
617
618template <>
619inline void CmdOpt<bool>::parse_arg(const std::string& arg) {
620 value = true;
621 is_set_ = true;
622}
623
624template <>
625inline void CmdOptList<bool>::parse_arg(const std::string& arg) {
626 std::vector<bool>::push_back(true);
627 is_set_ = true;
628}
629
630template <>
631inline void CmdArg<bool>::parse_arg(const std::string& arg) {
632 value = true;
633}
634
635template <>
636inline void CmdArgList<bool>::parse_arg(const std::string& arg) {
637 std::vector<bool>::push_back(true);
638}
639
641class CmdLine {
642public:
651 CmdLine(int argc_, char* argv_[])
652 : argc(argc_), argv(argv_), opt_parsed(false), arg_list(nullptr) {}
653
656 opts.push_back(&opt);
657 if (!name_opts.insert(name_opts_t::value_type(opt.name, &opt)).second) {
658 Exception() << "The command-line option -" << opt.name << " is already defined."
659 << THROW;
660 }
661 return *this;
662 }
663
666 args.push_back(&opt);
667 return *this;
668 }
669
672 if (arg_list != nullptr) {
673 Exception() << "Only one CmdArgList can by inserted in a CmdLine." << THROW;
674 }
675 arg_list = &opt;
676 return *this;
677 }
678
681 void parse(bool only_opt = false);
682
684 void print_short_desc(std::ostream& out) const;
685
687 void print_long_desc(std::ostream& out) const;
688
690 std::string get_command_name() const;
691
693 std::string get_command_line() const;
694
695private:
696 static void format_print(std::ostream& out, const std::string& a, const std::string& b);
697 int argc;
698 char** argv;
699 bool opt_parsed;
700 std::vector<CmdOptBase*> opts;
701 typedef std::map<std::string, CmdOptBase*> name_opts_t;
702 name_opts_t name_opts;
703 std::vector<CmdArgBase*> args;
704 CmdArgListBase* arg_list;
705};
706
707}} // namespace b2000::cmdline
708
709#endif /* __B2CMDLINE_H__ */
#define THROW
Definition b2exception.H:198
Definition b2dictionary.H:48
Definition b2exception.H:131
Definition b2rtable.H:427
void set(const std::string &key, const T &v, const bool new_key=false)
Assign a single value. If new_key is true, the key must not exist.
Definition b2rtable.H:463
Definition b2cmdline.H:514
Definition b2cmdline.H:556
Definition b2cmdline.H:572
Definition b2cmdline.H:530
Definition b2cmdline.H:641
CmdLine(int argc_, char *argv_[])
Definition b2cmdline.H:651
CmdLine & operator<<(CmdOptBase &opt)
Definition b2cmdline.H:655
void print_short_desc(std::ostream &out) const
Definition b2cmdline.C:99
void parse(bool only_opt=false)
Definition b2cmdline.C:23
std::string get_command_name() const
Definition b2cmdline.C:147
CmdLine & operator<<(CmdArgBase &opt)
Definition b2cmdline.H:665
CmdLine & operator<<(CmdArgListBase &opt)
Definition b2cmdline.H:671
void print_long_desc(std::ostream &out) const
Definition b2cmdline.C:106
std::string get_command_line() const
Definition b2cmdline.C:149
Definition b2cmdline.H:156
Definition b2cmdline.H:286
b2000::csda< double > get_csda_double(const std::string &key) const override
Definition b2cmdline.H:347
double get_double(const std::string &key) const override
Definition b2cmdline.H:331
std::complex< double > get_complex_double(const std::string &key) const override
Definition b2cmdline.H:363
void get(const std::string &key, std::vector< std::complex< double > > &v) const override
Definition b2cmdline.H:436
int get_int(const std::string &key) const override
Definition b2cmdline.H:315
void get(const std::string &key, std::vector< int > &v) const override
Definition b2cmdline.H:388
std::string get_string(const std::string &key) const override
Definition b2cmdline.H:379
bool has_key(const std::string &key) const override
Definition b2cmdline.H:292
void warn_on_non_used_key() const override
Definition b2cmdline.H:452
bool get_bool(const std::string &key) const override
Definition b2cmdline.H:298
void get(const std::string &key, std::vector< b2000::csda< double > > &v) const override
Definition b2cmdline.H:420
void get(const std::string &key, std::vector< double > &v) const override
Definition b2cmdline.H:404
Definition b2cmdline.H:214
Definition b2cmdline.H:242
Definition b2cmdline.H:185
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
GenericException< KeyError_name > KeyError
Definition b2exception.H:320