g4tools  5.4.0
args
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_args
5 #define tools_args
6 
7 #ifdef TOOLS_MEM
8 #include "mem"
9 #include "S_STRING"
10 #endif
11 
12 #include "sout"
13 #include "strip"
14 #include "words"
15 #include "sto"
16 #include "forit"
17 #include "mnmx"
18 //#include "squote"
19 
20 #include <ostream>
21 
22 namespace tools {
23 
24 class args {
25 #ifdef TOOLS_MEM
26 public:
28 #endif
29 public:
30  typedef std::pair<std::string,std::string> arg;
31 public:
32  args(){
33 #ifdef TOOLS_MEM
34  mem::increment(s_class().c_str());
35 #endif
36  }
37  args(int a_argc,char* a_argv[]){
38 #ifdef TOOLS_MEM
39  mem::increment(s_class().c_str());
40 #endif
41  for(int index=0;index<a_argc;index++) {
42  std::string s(a_argv[index]);
43  std::string::size_type pos = s.find('=');
44  if(pos==std::string::npos) {
45  m_args.push_back(arg(s,""));
46  } else {
47  std::string key = s.substr(0,pos);
48  pos++;
49  std::string value = s.substr(pos,s.size()-pos);
50  m_args.push_back(arg(key,value));
51  }
52  }
53  }
54  args(const std::vector<std::string>& a_args,bool a_strip = false){
55 #ifdef TOOLS_MEM
56  mem::increment(s_class().c_str());
57 #endif
58  add(a_args,a_strip);
59  }
60  args(const std::vector<arg>& a_args):m_args(a_args){
61 #ifdef TOOLS_MEM
62  mem::increment(s_class().c_str());
63 #endif
64  }
65  args(const std::string& a_args,const std::string& a_sep,bool a_strip){
66 #ifdef TOOLS_MEM
67  mem::increment(s_class().c_str());
68 #endif
69  std::vector<std::string> _args;
70  words(a_args,a_sep,false,_args);
71  add(_args,a_strip);
72  }
73  virtual ~args(){
74 #ifdef TOOLS_MEM
75  mem::decrement(s_class().c_str());
76 #endif
77  }
78 public:
79  args(const args& a_from):m_args(a_from.m_args){
80 #ifdef TOOLS_MEM
81  mem::increment(s_class().c_str());
82 #endif
83  }
84  args& operator=(const args& a_from){
85  m_args = a_from.m_args;
86  return *this;
87  }
88 public:
89  const std::vector<arg>& get_args() const {return m_args;}
90  //std::vector<arg>& get_args() {return m_args;}
91 
92  bool is_arg(const std::string& a_string) const {
94  if((*it).first==a_string) return true;
95  }
96  return false;
97  }
98  bool is_empty() const {return m_args.size()?false:true;}
99  size_t size() const {return m_args.size();}
100  size_t number() const {return m_args.size();} //back comp.
101  bool find(const std::string& a_key,std::string& a_value,const std::string& a_def = std::string()) const {
102  tools_vforcit(arg,m_args,it) {
103  if((*it).first==a_key) {
104  a_value = (*it).second;
105  return true;
106  }
107  }
108  a_value = a_def;
109  return false;
110  }
111 #ifdef TOOLS_DEPRECATED
112  std::vector<std::string> find(const std::string& a_key) const {
113  std::vector<std::string> vals;
114  tools_vforcit(arg,m_args,it) {
115  if((*it).first==a_key) vals.push_back((*it).second);
116  }
117  return vals;
118  }
119 #endif
120  void find(const std::string& a_key,std::vector<std::string>& a_vals,bool a_clear=true) const {
121  if(a_clear) a_vals.clear();
122  tools_vforcit(arg,m_args,it) {
123  if((*it).first==a_key) a_vals.push_back((*it).second);
124  }
125  }
126 
127  bool find(const std::string& a_string,bool& a_value,const bool& a_def = false) const {
128  std::string s;
129  if(!find(a_string,s)) {a_value = a_def;return false;}
130  return to(s,a_value,a_def);
131  }
132  template <class aT>
133  bool find(const std::string& a_string,aT& a_value,const aT& a_def = aT()) const {
134  std::string _s;
135  if(!find(a_string,_s)) {a_value = a_def;return false;}
136  return to<aT>(_s,a_value,a_def);
137  }
138 
139 #ifdef TOOLS_DEPRECATED
140  std::vector<std::string> tovector() const {
141  // Return a vector of string <name=value>
142  std::vector<std::string> vec;
143  tools_vforcit(arg,m_args,it) {
144  std::string s;
145  if((*it).second.empty()) {
146  s = (*it).first;
147  } else {
148  s = (*it).first;
149  s += "=";
150  s += (*it).second;
151  }
152  vec.push_back(s);
153  }
154  return vec;
155  }
156 #endif
157  void to_vector(std::vector<std::string>& a_vec) const {
158  // Return a vector of string <name=value>
159  a_vec.clear();
160  std::string s;
161  tools_vforcit(arg,m_args,it) {
162  s = (*it).first;
163  if((*it).second.size()) {
164  s += "=";
165  s += (*it).second;
166  }
167  a_vec.push_back(s);
168  }
169  }
170 
171  bool add(const std::string& a_key,const std::string& a_value = std::string(),bool a_override = true){
172  if(a_override) {
173  tools_vforit(arg,m_args,it) {
174  if((*it).first==a_key) {
175  (*it).second = a_value;
176  return true;
177  }
178  }
179  }
180  if(a_key.empty()) return false;
181  m_args.push_back(arg(a_key,a_value));
182  return true;
183  }
184 
185  bool insert_begin(const std::string& a_key,const std::string& a_value = std::string(),bool a_override = true){
186  if(a_override) {
187  tools_vforit(arg,m_args,it) {
188  if((*it).first==a_key) {
189  (*it).second = a_value;
190  return true;
191  }
192  }
193  }
194  if(a_key.empty()) return false;
195  m_args.insert(m_args.begin(),arg(a_key,a_value));
196  return true;
197  }
198 
199  void add(const std::vector<std::string>& a_args,bool a_strip = false) {
200  tools_vforcit(std::string,a_args,it) {
201  const std::string& sarg = *it;
202  std::string::size_type pos = sarg.find('=');
203  if(pos==std::string::npos) {
204  if(a_strip) {
205  std::string left = sarg;
206  strip(left,both,' ');
207  m_args.push_back(arg(left,""));
208  } else {
209  m_args.push_back(arg(sarg,""));
210  }
211  } else {
212  std::string left = sarg.substr(0,pos);
213  std::string right = sarg.substr((pos+1),sarg.size()-(pos+1));
214  if(a_strip) {
215  strip(left,both,' ');
216  strip(right,both,' ');
217  }
218  m_args.push_back(arg(left,right));
219  }
220  }
221  }
222 
223  void add_keyvals(const std::vector<std::string>& a_args,bool a_strip = false) {
224  //a_args must contain an even number of strings.
225  size_t sz_half = a_args.size()/2;
226  if((2*sz_half)!=a_args.size()) return;
227  for(std::vector<std::string>::const_iterator it = a_args.begin();it!=a_args.end();it+=2) {
228  if(a_strip) {
229  std::string key = *it;
230  strip(key,both,' ');
231  std::string val = *(it+1);
232  strip(val,both,' ');
233  m_args.push_back(arg(key,val));
234  } else {
235  m_args.push_back(arg(*it,*(it+1)));
236  }
237  }
238  }
239 
240  void add(const std::vector<arg>& a_args){
241  tools_vforcit(arg,a_args,it) m_args.push_back(*it);
242  }
243 
244  void add(const args& a_from){
245  tools_vforcit(arg,a_from.m_args,it) m_args.push_back(*it);
246  }
247 
248 
249  int remove(const std::string& a_key){
250  size_t nbeg = m_args.size();
251  for(std::vector<arg>::iterator it = m_args.begin();it!=m_args.end();) {
252  if(a_key==(*it).first) {
253  it = m_args.erase(it);
254  } else {
255  ++it;
256  }
257  }
258  return int(nbeg) - int(m_args.size());
259  }
260 
261  void remove_first(){if(m_args.size()) m_args.erase(m_args.begin());}
262  void remove_last(){if(m_args.size()) m_args.erase(m_args.end()-1);}
263 
264  bool last(std::string& a_key,std::string& a_value) const {
265  a_key.clear();
266  a_value.clear();
267  if(m_args.empty()) return false;
268  a_key = m_args.back().first;
269  a_value = m_args.back().second;
270  return true;
271  }
272 
273  bool prog_name(std::string& a_value) const {
274  if(m_args.empty()) {a_value.clear();return false;}
275  if(m_args[0].second.size()) {a_value.clear();return false;}
276  a_value = m_args[0].first;
277  return true;
278  }
279 
280  bool file(std::string& a_file) const {
281  std::string slast;
282  std::string s;
283  if((m_args.size()>1) //first arg is the program name !
284  && last(slast,s)
285  && (slast.find('-')!=0)
286  && (s.empty()) ) {
287  a_file = slast; //Last argument is not an option.
288  return true;
289  } else {
290  a_file.clear();
291  return false;
292  }
293  }
294 
295  bool file(std::string& a_file,bool a_remove) {
296  std::string slast;
297  std::string s;
298  if((m_args.size()>1) //first arg is the program name !
299  && last(slast,s)
300  && (slast.find('-')!=0)
301  && (s.empty()) ) {
302  a_file = slast; //Last argument is not an option.
303  if(a_remove) m_args.erase(m_args.end()-1);
304  return true;
305  } else {
306  a_file.clear();
307  return false;
308  }
309  }
310 
311  void not_hyphens(std::vector<std::string>& a_not_hyphens,bool a_skip_first = false) const {
312  a_not_hyphens.clear();
313  // Get the serie of trailing args not beginning with '-'
314  // and without a value (not of the form [-]xxx=yyy).
315  // Note that an argument like that in between arguments
316  // is NOT taken into account.
317  if(m_args.empty()) return;
318  std::vector<arg>::const_iterator it = m_args.begin();
319  if(a_skip_first) it++;
320  for(;it!=m_args.end();++it) {
321  if( ((*it).first.find('-')==0) || (*it).second.size() ) {
322  a_not_hyphens.clear();
323  } else {
324  a_not_hyphens.push_back((*it).first);
325  }
326  }
327  }
328 
329  void files(std::vector<std::string>& a_files,bool a_skip_first = true) const { //true and not false as in the upper.
330  return not_hyphens(a_files,a_skip_first);
331  }
332 
333  bool first_not_hyphen(std::string& a_first,bool a_skip_first = false) const {
334  std::vector<std::string> _ss;
335  not_hyphens(_ss,a_skip_first);
336  if(_ss.empty()) {a_first.clear();return false;}
337  a_first = _ss[0];
338  return true;
339  }
340 
341 //bool first_of_files(std::string& a_file,bool a_skip_first) const {return first_of_hyphen(a_file,a_skip_first);}
342 
343  bool argcv(int& a_argc,char**& a_argv) const {
344  // If using with :
345  // int argc;
346  // char** argv;
347  // args.argcv(argc,argv);
348  // you can delete with :
349  // args::delete_argcv(argc,argv);
350  if(m_args.empty()) {a_argc = 0;a_argv = 0;return true;}
351  typedef char* _cstr_t;
352  _cstr_t* av = new _cstr_t[m_args.size()+1];
353  if(!av) {a_argc = 0;a_argv = 0;return false;}
354  a_argv = av;
355  for(std::vector<arg>::const_iterator it = m_args.begin();it!=m_args.end();++it,av++) {
356  std::string::size_type lf = (*it).first.length();
357  std::string::size_type ls = (*it).second.length();
358  std::string::size_type sz = lf;
359  if(ls) sz += 1 + ls;
360  char* p = new char[sz+1];
361  if(!p) {a_argc = 0;a_argv = 0;return false;} //some delete are lacking.
362  *av = p;
363  {char* pf = (char*)(*it).first.c_str();
364  for(std::string::size_type i=0;i<lf;i++,p++,pf++) {*p = *pf;}
365  *p = 0;}
366  if(ls) {*p = '=';p++;}
367  {char* ps = (char*)(*it).second.c_str();
368  for(std::string::size_type i=0;i<ls;i++,p++,ps++) {*p = *ps;}
369  *p = 0;}
370  }
371  *(a_argv+m_args.size()) = 0;
372  a_argc = (int)m_args.size();
373  return true;
374  }
375  static void delete_argcv(int& a_argc,char**& a_argv) {
376  for(int index=0;index<a_argc;index++) delete [] a_argv[index];
377  delete [] a_argv;
378  a_argc = 0;
379  a_argv = 0;
380  }
381 
382  bool known_options(const std::vector<std::string>& a_knowns) const {
383  tools_vforcit(arg,m_args,it) {
384  if((*it).first.find('-')==0) { //find '-' at first pos.
385  bool found = false;
386  tools_vforcit(std::string,a_knowns,it2) {
387  if((*it).first==(*it2)) {
388  found = true;
389  break;
390  }
391  }
392  if(!found) return false; //one option not in a_knowns.
393  }
394  }
395  return true; //all options are in a_knowns.
396  }
397 
398  bool known_options(const std::string& a_known) const {
399  tools_vforcit(arg,m_args,it) {
400  if((*it).first.find('-')==0) { //find '-' at first pos.
401  if((*it).first!=a_known) return false; //one option not a_known.
402  }
403  }
404  return true; //all options are a_known.
405  }
406 
407 //void remove_string_delimiters_in_keys() {
408 // tools_vforit(arg,m_args,it) {
409 // if(!rm_quotes((*it).first)) rm_double_quotes((*it).first);
410 // }
411 //}
412 
413 //void remove_string_delimiters_in_values() {
414 // tools_vforit(arg,m_args,it) {
415 // if(!rm_quotes((*it).second)) rm_double_quotes((*it).second);
416 // }
417 //}
418 
419  void files_at_end(bool a_skip_first = true) {
420  // reorder to have "file" arguments at end.
421  if(m_args.empty()) return;
422  std::vector<arg> _args;
423  if(a_skip_first) _args.push_back(*(m_args.begin()));
424  //first pass :
425  {std::vector<arg>::const_iterator it = m_args.begin();
426  if(a_skip_first) it++;
427  for(;it!=m_args.end();++it) {
428  if( ((*it).first.find('-')==0) || (*it).second.size() ) {
429  _args.push_back(*it);
430  }
431  }}
432  //second pass :
433  {std::vector<arg>::const_iterator it = m_args.begin();
434  if(a_skip_first) it++;
435  for(;it!=m_args.end();++it) {
436  if( ((*it).first.find('-')==0) || (*it).second.size() ) {
437  } else {
438  _args.push_back(*it);
439  }
440  }}
441  m_args = _args;
442  }
443 
444  //NOTE : print is a Python keyword.
445  void dump(std::ostream& a_out,const std::string& a_comment = std::string(),const std::string& a_prefix = std::string()) const {
446  if(a_comment.size()) a_out << a_comment << std::endl;
447  tools_vforcit(arg,m_args,it) {
448  a_out << a_prefix << "key = " << sout((*it).first) << ", value = " << sout((*it).second) << std::endl;
449  }
450  }
451 
452 public: //backcomp (for Panoramix).
453  bool isAnArgument(const std::string& a_key) const {return is_arg(a_key);}
454 protected:
455  std::vector<arg> m_args;
456 };
457 
458 inline bool check_args(const std::vector<std::string>& a_args,unsigned int a_number,std::ostream& a_out){
459  if(a_args.size()==a_number) return true;
460  a_out << "bad argument number."
461  << " Given " << (unsigned int)a_args.size()
462  << " whilst " << a_number << " expected."
463  << std::endl;
464  return false;
465 }
466 
467 inline bool check_min(const std::vector<std::string>& a_args,unsigned int a_number,std::string& a_last,std::ostream& a_out){
468  if(a_args.size()>=a_number) {
469  if(a_number==0) {
470  if(a_args.empty()) {
471  a_last.clear();
472  } else {
473  a_last = a_args[0];
474  for(size_t index=1;index<a_args.size();index++) a_last += " " + a_args[index];
475  }
476  } else {
477  a_last = a_args[a_number-1];
478  for(size_t index=a_number;index<a_args.size();index++) a_last += " " + a_args[index];
479  }
480  return true;
481  }
482  a_out << "bad argument number."
483  << " Given " << (unsigned int)a_args.size()
484  << " whilst at least " << a_number << " expected."
485  << std::endl;
486  return false;
487 }
488 
489 inline bool check_min_args(const std::vector<std::string>& aArgs,unsigned int a_number,std::ostream& a_out){
490  if(aArgs.size()>=a_number) return true;
491  a_out << "bad argument number."
492  << " Given " << (unsigned int)aArgs.size()
493  << " whilst at least " << a_number << " expected."
494  << std::endl;
495  return false;
496 }
497 
498 inline bool check_or_args(const std::vector<std::string>& aArgs,unsigned int a_1,unsigned int a_2,std::ostream& a_out){
499  if((aArgs.size()==a_1)||(aArgs.size()==a_2)) return true;
500  a_out << "bad argument number."
501  << " Given " << (unsigned int)aArgs.size()
502  << " whilst " << a_1 << " or " << a_2 << " expected."
503  << std::endl;
504  return false;
505 }
506 
507 inline std::vector<std::string> to(int a_argc,char** a_argv) {
508  std::vector<std::string> v;
509  for(int index=0;index<a_argc;index++) v.push_back(a_argv[index]);
510  return v;
511 }
512 
513 }
514 
515 #endif
tools::args::delete_argcv
static void delete_argcv(int &a_argc, char **&a_argv)
Definition: args:375
tools::args::is_arg
bool is_arg(const std::string &a_string) const
Definition: args:92
tools::check_or_args
bool check_or_args(const std::vector< std::string > &aArgs, unsigned int a_1, unsigned int a_2, std::ostream &a_out)
Definition: args:498
tools::args::add
void add(const args &a_from)
Definition: args:244
tools::value
Definition: value:18
tools::args::not_hyphens
void not_hyphens(std::vector< std::string > &a_not_hyphens, bool a_skip_first=false) const
Definition: args:311
tools::args::find
bool find(const std::string &a_string, aT &a_value, const aT &a_def=aT()) const
Definition: args:133
tools::args::args
args()
Definition: args:32
tools::args::get_args
const std::vector< arg > & get_args() const
Definition: args:89
tools::args::~args
virtual ~args()
Definition: args:73
tools::args::args
args(const args &a_from)
Definition: args:79
tools::args::files
void files(std::vector< std::string > &a_files, bool a_skip_first=true) const
Definition: args:329
tools::args::args
args(const std::string &a_args, const std::string &a_sep, bool a_strip)
Definition: args:65
tools::check_min
bool check_min(const std::vector< std::string > &a_args, unsigned int a_number, std::string &a_last, std::ostream &a_out)
Definition: args:467
tools::sg::right
@ right
Definition: enums:76
tools::args::known_options
bool known_options(const std::string &a_known) const
Definition: args:398
tools::args::last
bool last(std::string &a_key, std::string &a_value) const
Definition: args:264
strip
tools::args::add_keyvals
void add_keyvals(const std::vector< std::string > &a_args, bool a_strip=false)
Definition: args:223
tools::args::add
void add(const std::vector< std::string > &a_args, bool a_strip=false)
Definition: args:199
TOOLS_SCLASS
#define TOOLS_SCLASS(a_name)
Definition: S_STRING:41
tools::args::args
args(const std::vector< std::string > &a_args, bool a_strip=false)
Definition: args:54
tools::args::arg
std::pair< std::string, std::string > arg
Definition: args:30
mem
tools::args
Definition: args:24
tools::args::find
bool find(const std::string &a_key, std::string &a_value, const std::string &a_def=std::string()) const
Definition: args:101
tools::sg::left
@ left
Definition: enums:74
tools::args::is_empty
bool is_empty() const
Definition: args:98
sto
tools::args::remove_last
void remove_last()
Definition: args:262
tools::check_min_args
bool check_min_args(const std::vector< std::string > &aArgs, unsigned int a_number, std::ostream &a_out)
Definition: args:489
tools::args::remove_first
void remove_first()
Definition: args:261
tools::sout
Definition: sout:17
tools::args::prog_name
bool prog_name(std::string &a_value) const
Definition: args:273
mnmx
tools::both
@ both
Definition: strip:12
tools::args::to_vector
void to_vector(std::vector< std::string > &a_vec) const
Definition: args:157
tools::args::isAnArgument
bool isAnArgument(const std::string &a_key) const
Definition: args:453
tools::to
std::vector< std::string > to(int a_argc, char **a_argv)
Definition: args:507
tools_vforit
#define tools_vforit(a__T, a__v, a__it)
Definition: forit:13
tools::args::known_options
bool known_options(const std::vector< std::string > &a_knowns) const
Definition: args:382
tools::args::file
bool file(std::string &a_file) const
Definition: args:280
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::words
void words(const std::string &a_string, const std::string &a_sep, bool a_take_empty, std::vector< std::string > &a_words, bool a_clear=true)
Definition: words:12
tools::args::argcv
bool argcv(int &a_argc, char **&a_argv) const
Definition: args:343
words
tools::args::args
args(const std::vector< arg > &a_args)
Definition: args:60
tools::args::size
size_t size() const
Definition: args:99
tools::args::first_not_hyphen
bool first_not_hyphen(std::string &a_first, bool a_skip_first=false) const
Definition: args:333
tools::args::find
void find(const std::string &a_key, std::vector< std::string > &a_vals, bool a_clear=true) const
Definition: args:120
S_STRING
tools::args::operator=
args & operator=(const args &a_from)
Definition: args:84
tools::args::add
void add(const std::vector< arg > &a_args)
Definition: args:240
tools::file::found
bool found(const std::string &a_file, const std::string &a_what, std::vector< std::string > &a_found)
Definition: file:507
tools::args::add
bool add(const std::string &a_key, const std::string &a_value=std::string(), bool a_override=true)
Definition: args:171
tools::args::m_args
std::vector< arg > m_args
Definition: args:455
tools::args::dump
void dump(std::ostream &a_out, const std::string &a_comment=std::string(), const std::string &a_prefix=std::string()) const
Definition: args:445
forit
tools::strip
bool strip(std::string &a_string, what a_type=both, char a_char=' ')
Definition: strip:14
tools::args::number
size_t number() const
Definition: args:100
tools_vforcit
#define tools_vforcit(a__T, a__v, a__it)
Definition: forit:7
tools::args::args
args(int a_argc, char *a_argv[])
Definition: args:37
tools::args::files_at_end
void files_at_end(bool a_skip_first=true)
Definition: args:419
tools::check_args
bool check_args(const std::vector< std::string > &a_args, unsigned int a_number, std::ostream &a_out)
Definition: args:458
sout
tools::args::insert_begin
bool insert_begin(const std::string &a_key, const std::string &a_value=std::string(), bool a_override=true)
Definition: args:185
tools::args::file
bool file(std::string &a_file, bool a_remove)
Definition: args:295
tools::args::find
bool find(const std::string &a_string, bool &a_value, const bool &a_def=false) const
Definition: args:127
tools::args::remove
int remove(const std::string &a_key)
Definition: args:249