Warning, /include/Geant4/tools/args is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_args
0005 #define tools_args
0006
0007 #ifdef TOOLS_MEM
0008 #include "mem"
0009 #include "S_STRING"
0010 #endif
0011
0012 #include "sout"
0013 #include "strip"
0014 #include "words"
0015 #include "sto"
0016 #include "forit"
0017 #include "mnmx"
0018 //#include "squote"
0019
0020 #include <ostream>
0021
0022 namespace tools {
0023
0024 class args {
0025 #ifdef TOOLS_MEM
0026 public:
0027 TOOLS_SCLASS(tools::args)
0028 #endif
0029 public:
0030 typedef std::pair<std::string,std::string> arg;
0031 public:
0032 args(){
0033 #ifdef TOOLS_MEM
0034 mem::increment(s_class().c_str());
0035 #endif
0036 }
0037 args(int a_argc,char* a_argv[]){
0038 #ifdef TOOLS_MEM
0039 mem::increment(s_class().c_str());
0040 #endif
0041 for(int index=0;index<a_argc;index++) {
0042 std::string _s(a_argv[index]);
0043 std::string::size_type pos = _s.find('=');
0044 if(pos==std::string::npos) {
0045 m_args.push_back(arg(_s,""));
0046 } else {
0047 std::string key = _s.substr(0,pos);
0048 pos++;
0049 std::string value = _s.substr(pos,_s.size()-pos);
0050 m_args.push_back(arg(key,value));
0051 }
0052 }
0053 }
0054 args(const std::vector<std::string>& a_args,bool a_strip = false){
0055 #ifdef TOOLS_MEM
0056 mem::increment(s_class().c_str());
0057 #endif
0058 add(a_args,a_strip);
0059 }
0060 args(const std::vector<arg>& a_args):m_args(a_args){
0061 #ifdef TOOLS_MEM
0062 mem::increment(s_class().c_str());
0063 #endif
0064 }
0065 args(const std::string& a_args,const std::string& a_sep,bool a_strip){
0066 #ifdef TOOLS_MEM
0067 mem::increment(s_class().c_str());
0068 #endif
0069 std::vector<std::string> _args;
0070 words(a_args,a_sep,false,_args);
0071 add(_args,a_strip);
0072 }
0073 virtual ~args(){
0074 #ifdef TOOLS_MEM
0075 mem::decrement(s_class().c_str());
0076 #endif
0077 }
0078 public:
0079 args(const args& a_from):m_args(a_from.m_args){
0080 #ifdef TOOLS_MEM
0081 mem::increment(s_class().c_str());
0082 #endif
0083 }
0084 args& operator=(const args& a_from){
0085 m_args = a_from.m_args;
0086 return *this;
0087 }
0088 public:
0089 const std::vector<arg>& get_args() const {return m_args;}
0090 //std::vector<arg>& get_args() {return m_args;}
0091
0092 bool is_arg(const std::string& a_string) const {
0093 tools_vforcit(arg,m_args,it) {
0094 if((*it).first==a_string) return true;
0095 }
0096 return false;
0097 }
0098 bool is_empty() const {return m_args.size()?false:true;}
0099 size_t size() const {return m_args.size();}
0100 size_t number() const {return m_args.size();} //back comp.
0101 bool find(const std::string& a_key,std::string& a_value,const std::string& a_def = std::string()) const {
0102 tools_vforcit(arg,m_args,it) {
0103 if((*it).first==a_key) {
0104 a_value = (*it).second;
0105 return true;
0106 }
0107 }
0108 a_value = a_def;
0109 return false;
0110 }
0111 #ifdef TOOLS_DEPRECATED
0112 std::vector<std::string> find(const std::string& a_key) const {
0113 std::vector<std::string> vals;
0114 tools_vforcit(arg,m_args,it) {
0115 if((*it).first==a_key) vals.push_back((*it).second);
0116 }
0117 return vals;
0118 }
0119 #endif
0120 void find(const std::string& a_key,std::vector<std::string>& a_vals,bool a_clear=true) const {
0121 if(a_clear) a_vals.clear();
0122 tools_vforcit(arg,m_args,it) {
0123 if((*it).first==a_key) a_vals.push_back((*it).second);
0124 }
0125 }
0126
0127 bool find(const std::string& a_string,bool& a_value,const bool& a_def = false) const {
0128 std::string _s;
0129 if(!find(a_string,_s)) {a_value = a_def;return false;}
0130 return to(_s,a_value,a_def);
0131 }
0132 template <class aT>
0133 bool find(const std::string& a_string,aT& a_value,const aT& a_def = aT()) const {
0134 std::string _s;
0135 if(!find(a_string,_s)) {a_value = a_def;return false;}
0136 return to<aT>(_s,a_value,a_def);
0137 }
0138
0139 #ifdef TOOLS_DEPRECATED
0140 std::vector<std::string> tovector() const {
0141 // Return a vector of string <name=value>
0142 std::vector<std::string> vec;
0143 tools_vforcit(arg,m_args,it) {
0144 std::string _s;
0145 if((*it).second.empty()) {
0146 _s = (*it).first;
0147 } else {
0148 _s = (*it).first;
0149 _s += "=";
0150 _s += (*it).second;
0151 }
0152 vec.push_back(_s);
0153 }
0154 return vec;
0155 }
0156 #endif
0157 void to_vector(std::vector<std::string>& a_vec) const {
0158 // Return a vector of string <name=value>
0159 a_vec.clear();
0160 std::string _s;
0161 tools_vforcit(arg,m_args,it) {
0162 _s = (*it).first;
0163 if((*it).second.size()) {
0164 _s += "=";
0165 _s += (*it).second;
0166 }
0167 a_vec.push_back(_s);
0168 }
0169 }
0170
0171 bool add(const std::string& a_key,const std::string& a_value = std::string(),bool a_override = true){
0172 if(a_override) {
0173 tools_vforit(arg,m_args,it) {
0174 if((*it).first==a_key) {
0175 (*it).second = a_value;
0176 return true;
0177 }
0178 }
0179 }
0180 if(a_key.empty()) return false;
0181 m_args.push_back(arg(a_key,a_value));
0182 return true;
0183 }
0184
0185 bool insert_begin(const std::string& a_key,const std::string& a_value = std::string(),bool a_override = true){
0186 if(a_override) {
0187 tools_vforit(arg,m_args,it) {
0188 if((*it).first==a_key) {
0189 (*it).second = a_value;
0190 return true;
0191 }
0192 }
0193 }
0194 if(a_key.empty()) return false;
0195 m_args.insert(m_args.begin(),arg(a_key,a_value));
0196 return true;
0197 }
0198
0199 void add(const std::vector<std::string>& a_args,bool a_strip = false) {
0200 tools_vforcit(std::string,a_args,it) {
0201 const std::string& sarg = *it;
0202 std::string::size_type pos = sarg.find('=');
0203 if(pos==std::string::npos) {
0204 if(a_strip) {
0205 std::string left = sarg;
0206 strip(left,both,' ');
0207 m_args.push_back(arg(left,""));
0208 } else {
0209 m_args.push_back(arg(sarg,""));
0210 }
0211 } else {
0212 std::string left = sarg.substr(0,pos);
0213 std::string right = sarg.substr((pos+1),sarg.size()-(pos+1));
0214 if(a_strip) {
0215 strip(left,both,' ');
0216 strip(right,both,' ');
0217 }
0218 m_args.push_back(arg(left,right));
0219 }
0220 }
0221 }
0222
0223 void add_keyvals(const std::vector<std::string>& a_args,bool a_strip = false) {
0224 //a_args must contain an even number of strings.
0225 size_t sz_half = a_args.size()/2;
0226 if((2*sz_half)!=a_args.size()) return;
0227 for(std::vector<std::string>::const_iterator it = a_args.begin();it!=a_args.end();it+=2) {
0228 if(a_strip) {
0229 std::string key = *it;
0230 strip(key,both,' ');
0231 std::string val = *(it+1);
0232 strip(val,both,' ');
0233 m_args.push_back(arg(key,val));
0234 } else {
0235 m_args.push_back(arg(*it,*(it+1)));
0236 }
0237 }
0238 }
0239
0240 void add(const std::vector<arg>& a_args){
0241 tools_vforcit(arg,a_args,it) m_args.push_back(*it);
0242 }
0243
0244 void add(const args& a_from){
0245 tools_vforcit(arg,a_from.m_args,it) m_args.push_back(*it);
0246 }
0247
0248
0249 int remove(const std::string& a_key){
0250 size_t nbeg = m_args.size();
0251 for(std::vector<arg>::iterator it = m_args.begin();it!=m_args.end();) {
0252 if(a_key==(*it).first) {
0253 it = m_args.erase(it);
0254 } else {
0255 ++it;
0256 }
0257 }
0258 return int(nbeg) - int(m_args.size());
0259 }
0260
0261 void remove_first(){if(m_args.size()) m_args.erase(m_args.begin());}
0262 void remove_last(){if(m_args.size()) m_args.erase(m_args.end()-1);}
0263
0264 bool last(std::string& a_key,std::string& a_value) const {
0265 a_key.clear();
0266 a_value.clear();
0267 if(m_args.empty()) return false;
0268 a_key = m_args.back().first;
0269 a_value = m_args.back().second;
0270 return true;
0271 }
0272
0273 bool prog_name(std::string& a_value) const {
0274 if(m_args.empty()) {a_value.clear();return false;}
0275 if(m_args[0].second.size()) {a_value.clear();return false;}
0276 a_value = m_args[0].first;
0277 return true;
0278 }
0279
0280 bool file(std::string& a_file) const {
0281 std::string slast;
0282 std::string _s;
0283 if((m_args.size()>1) //first arg is the program name !
0284 && last(slast,_s)
0285 && (slast.find('-')!=0)
0286 && (_s.empty()) ) {
0287 a_file = slast; //Last argument is not an option.
0288 return true;
0289 } else {
0290 a_file.clear();
0291 return false;
0292 }
0293 }
0294
0295 bool file(std::string& a_file,bool a_remove) {
0296 std::string slast;
0297 std::string _s;
0298 if((m_args.size()>1) //first arg is the program name !
0299 && last(slast,_s)
0300 && (slast.find('-')!=0)
0301 && (_s.empty()) ) {
0302 a_file = slast; //Last argument is not an option.
0303 if(a_remove) m_args.erase(m_args.end()-1);
0304 return true;
0305 } else {
0306 a_file.clear();
0307 return false;
0308 }
0309 }
0310
0311 void not_hyphens(std::vector<std::string>& a_not_hyphens,bool a_skip_first = false) const {
0312 a_not_hyphens.clear();
0313 // Get the serie of trailing args not beginning with '-'
0314 // and without a value (not of the form [-]xxx=yyy).
0315 // Note that an argument like that in between arguments
0316 // is NOT taken into account.
0317 if(m_args.empty()) return;
0318 std::vector<arg>::const_iterator it = m_args.begin();
0319 if(a_skip_first) it++;
0320 for(;it!=m_args.end();++it) {
0321 if( ((*it).first.find('-')==0) || (*it).second.size() ) {
0322 a_not_hyphens.clear();
0323 } else {
0324 a_not_hyphens.push_back((*it).first);
0325 }
0326 }
0327 }
0328
0329 void files(std::vector<std::string>& a_files,bool a_skip_first = true) const { //true and not false as in the upper.
0330 return not_hyphens(a_files,a_skip_first);
0331 }
0332
0333 bool first_not_hyphen(std::string& a_first,bool a_skip_first = false) const {
0334 std::vector<std::string> _ss;
0335 not_hyphens(_ss,a_skip_first);
0336 if(_ss.empty()) {a_first.clear();return false;}
0337 a_first = _ss[0];
0338 return true;
0339 }
0340
0341 //bool first_of_files(std::string& a_file,bool a_skip_first) const {return first_of_hyphen(a_file,a_skip_first);}
0342
0343 bool argcv(int& a_argc,char**& a_argv) const {
0344 // If using with :
0345 // int argc;
0346 // char** argv;
0347 // args.argcv(argc,argv);
0348 // you can delete with :
0349 // args::delete_argcv(argc,argv);
0350 if(m_args.empty()) {a_argc = 0;a_argv = 0;return true;}
0351 typedef char* _cstr_t;
0352 _cstr_t* av = new _cstr_t[m_args.size()+1];
0353 if(!av) {a_argc = 0;a_argv = 0;return false;}
0354 a_argv = av;
0355 for(std::vector<arg>::const_iterator it = m_args.begin();it!=m_args.end();++it,av++) {
0356 std::string::size_type lf = (*it).first.length();
0357 std::string::size_type ls = (*it).second.length();
0358 std::string::size_type sz = lf;
0359 if(ls) sz += 1 + ls;
0360 char* p = new char[sz+1];
0361 if(!p) {a_argc = 0;a_argv = 0;return false;} //some delete are lacking.
0362 *av = p;
0363 {char* pf = (char*)(*it).first.c_str();
0364 for(std::string::size_type i=0;i<lf;i++,p++,pf++) {*p = *pf;}
0365 *p = 0;}
0366 if(ls) {*p = '=';p++;}
0367 {char* ps = (char*)(*it).second.c_str();
0368 for(std::string::size_type i=0;i<ls;i++,p++,ps++) {*p = *ps;}
0369 *p = 0;}
0370 }
0371 *(a_argv+m_args.size()) = 0;
0372 a_argc = (int)m_args.size();
0373 return true;
0374 }
0375 static void delete_argcv(int& a_argc,char**& a_argv) {
0376 for(int index=0;index<a_argc;index++) delete [] a_argv[index];
0377 delete [] a_argv;
0378 a_argc = 0;
0379 a_argv = 0;
0380 }
0381
0382 bool known_options(const std::vector<std::string>& a_knowns) const {
0383 tools_vforcit(arg,m_args,it) {
0384 if((*it).first.find('-')==0) { //find '-' at first pos.
0385 bool found = false;
0386 tools_vforcit(std::string,a_knowns,it2) {
0387 if((*it).first==(*it2)) {
0388 found = true;
0389 break;
0390 }
0391 }
0392 if(!found) return false; //one option not in a_knowns.
0393 }
0394 }
0395 return true; //all options are in a_knowns.
0396 }
0397
0398 bool known_options(const std::string& a_known) const {
0399 tools_vforcit(arg,m_args,it) {
0400 if((*it).first.find('-')==0) { //find '-' at first pos.
0401 if((*it).first!=a_known) return false; //one option not a_known.
0402 }
0403 }
0404 return true; //all options are a_known.
0405 }
0406
0407 //void remove_string_delimiters_in_keys() {
0408 // tools_vforit(arg,m_args,it) {
0409 // if(!rm_quotes((*it).first)) rm_double_quotes((*it).first);
0410 // }
0411 //}
0412
0413 //void remove_string_delimiters_in_values() {
0414 // tools_vforit(arg,m_args,it) {
0415 // if(!rm_quotes((*it).second)) rm_double_quotes((*it).second);
0416 // }
0417 //}
0418
0419 void files_at_end(bool a_skip_first = true) {
0420 // reorder to have "file" arguments at end.
0421 if(m_args.empty()) return;
0422 std::vector<arg> _args;
0423 if(a_skip_first) _args.push_back(*(m_args.begin()));
0424 //first pass :
0425 {std::vector<arg>::const_iterator it = m_args.begin();
0426 if(a_skip_first) it++;
0427 for(;it!=m_args.end();++it) {
0428 if( ((*it).first.find('-')==0) || (*it).second.size() ) {
0429 _args.push_back(*it);
0430 }
0431 }}
0432 //second pass :
0433 {std::vector<arg>::const_iterator it = m_args.begin();
0434 if(a_skip_first) it++;
0435 for(;it!=m_args.end();++it) {
0436 if( ((*it).first.find('-')==0) || (*it).second.size() ) {
0437 } else {
0438 _args.push_back(*it);
0439 }
0440 }}
0441 m_args = _args;
0442 }
0443
0444 //NOTE : print is a Python keyword.
0445 void dump(std::ostream& a_out,const std::string& a_comment = std::string(),const std::string& a_prefix = std::string()) const {
0446 if(a_comment.size()) a_out << a_comment << std::endl;
0447 tools_vforcit(arg,m_args,it) {
0448 a_out << a_prefix << "key = " << sout((*it).first) << ", value = " << sout((*it).second) << std::endl;
0449 }
0450 }
0451
0452 public: //backcomp (for Panoramix).
0453 bool isAnArgument(const std::string& a_key) const {return is_arg(a_key);}
0454 protected:
0455 std::vector<arg> m_args;
0456 };
0457
0458 inline bool check_args(const std::vector<std::string>& a_args,unsigned int a_number,std::ostream& a_out){
0459 if(a_args.size()==a_number) return true;
0460 a_out << "bad argument number."
0461 << " Given " << (unsigned int)a_args.size()
0462 << " whilst " << a_number << " expected."
0463 << std::endl;
0464 return false;
0465 }
0466
0467 inline bool check_min(const std::vector<std::string>& a_args,unsigned int a_number,std::string& a_last,std::ostream& a_out){
0468 if(a_args.size()>=a_number) {
0469 if(a_number==0) {
0470 if(a_args.empty()) {
0471 a_last.clear();
0472 } else {
0473 a_last = a_args[0];
0474 for(size_t index=1;index<a_args.size();index++) a_last += " " + a_args[index];
0475 }
0476 } else {
0477 a_last = a_args[a_number-1];
0478 for(size_t index=a_number;index<a_args.size();index++) a_last += " " + a_args[index];
0479 }
0480 return true;
0481 }
0482 a_out << "bad argument number."
0483 << " Given " << (unsigned int)a_args.size()
0484 << " whilst at least " << a_number << " expected."
0485 << std::endl;
0486 return false;
0487 }
0488
0489 inline bool check_min_args(const std::vector<std::string>& aArgs,unsigned int a_number,std::ostream& a_out){
0490 if(aArgs.size()>=a_number) return true;
0491 a_out << "bad argument number."
0492 << " Given " << (unsigned int)aArgs.size()
0493 << " whilst at least " << a_number << " expected."
0494 << std::endl;
0495 return false;
0496 }
0497
0498 inline bool check_or_args(const std::vector<std::string>& aArgs,unsigned int a_1,unsigned int a_2,std::ostream& a_out){
0499 if((aArgs.size()==a_1)||(aArgs.size()==a_2)) return true;
0500 a_out << "bad argument number."
0501 << " Given " << (unsigned int)aArgs.size()
0502 << " whilst " << a_1 << " or " << a_2 << " expected."
0503 << std::endl;
0504 return false;
0505 }
0506
0507 inline std::vector<std::string> to(int a_argc,char** a_argv) {
0508 std::vector<std::string> v;
0509 for(int index=0;index<a_argc;index++) v.push_back(a_argv[index]);
0510 return v;
0511 }
0512
0513 }
0514
0515 #endif