Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/args

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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:
 27   TOOLS_SCLASS(tools::args)
 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 {
 93     tools_vforcit(arg,m_args,it) {
 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