Claw
1.7.0
|
00001 /* 00002 CLAW - a C++ Library Absolutely Wonderful 00003 00004 CLAW is a free library without any particular aim but being useful to 00005 anyone. 00006 00007 Copyright (C) 2005-2011 Julien Jorge 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with this library; if not, write to the Free Software 00021 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00022 00023 contact: julien.jorge@gamned.org 00024 */ 00030 #include <claw/arguments.hpp> 00031 00032 #include <sstream> 00033 #include <claw/assert.hpp> 00034 #include <claw/string_algorithm.hpp> 00035 #include <claw/claw_gettext.hpp> 00036 00037 /*----------------------------------------------------------------------------*/ 00041 claw::arguments::arguments() 00042 : m_program_name( claw_gettext("<unknow>") ) 00043 { 00044 00045 } // arguments::arguments() 00046 00047 /*----------------------------------------------------------------------------*/ 00052 claw::arguments::arguments( const std::string& prog_name ) 00053 : m_program_name(prog_name) 00054 { 00055 00056 } // arguments::arguments() 00057 00058 /*----------------------------------------------------------------------------*/ 00067 claw::arguments::arguments( int& argc, char** &argv ) 00068 { 00069 parse(argc, argv); 00070 } // arguments::arguments() 00071 00072 /*----------------------------------------------------------------------------*/ 00082 claw::arguments::arguments(int& argc, char** &argv, 00083 const claw::math::ordered_set<std::string>& allowed ) 00084 00085 { 00086 parse(argc, argv, allowed); 00087 } // arguments::arguments() 00088 00089 /*----------------------------------------------------------------------------*/ 00097 void claw::arguments::parse( int& argc, char** &argv ) 00098 { 00099 parse( argc, argv, true, claw::math::ordered_set<std::string>() ); 00100 } // arguments::parse() 00101 00102 /*----------------------------------------------------------------------------*/ 00111 void claw::arguments::parse 00112 ( int& argc, char** &argv, 00113 const claw::math::ordered_set<std::string>& allowed ) 00114 { 00115 parse( argc, argv, false, allowed ); 00116 } // arguments::parse() 00117 00118 /*----------------------------------------------------------------------------*/ 00123 bool claw::arguments::has_value( const std::string& arg_name ) const 00124 { 00125 return m_pairs.find( arg_name ) != m_pairs.end(); 00126 } // arguments::has_value() 00127 00128 /*----------------------------------------------------------------------------*/ 00133 bool claw::arguments::only_integer_values( const std::string& arg_name ) const 00134 { 00135 const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name)); 00136 bool result = true; 00137 00138 if ( itk == m_pairs.end() ) 00139 result = false; 00140 else 00141 { 00142 std::list<std::string>::const_iterator it; 00143 for( it=itk->second.begin(); result && (it!=itk->second.end()); ++it ) 00144 result = result && text::is_of_type<int>(*it); 00145 } 00146 00147 return result; 00148 } // arguments::only_integer_values() 00149 00150 /*----------------------------------------------------------------------------*/ 00155 bool claw::arguments::only_real_values( const std::string& arg_name ) const 00156 { 00157 const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name)); 00158 bool result = true; 00159 00160 if ( itk == m_pairs.end() ) 00161 result = false; 00162 else 00163 { 00164 std::list<std::string>::const_iterator it; 00165 for( it=itk->second.begin(); result && (it!=itk->second.end()); ++it ) 00166 result = result && text::is_of_type<double>(*it); 00167 } 00168 00169 return result; 00170 } // arguments::only_real_values() 00171 00172 /*----------------------------------------------------------------------------*/ 00176 const std::string& claw::arguments::get_program_name() const 00177 { 00178 return m_program_name; 00179 } // arguments::get_program_name() 00180 00181 /*----------------------------------------------------------------------------*/ 00186 bool claw::arguments::get_bool( const std::string& arg_name ) const 00187 { 00188 return m_flags.find( arg_name ) != m_flags.end(); 00189 } // arguments::get_bool() 00190 00191 /*----------------------------------------------------------------------------*/ 00197 int claw::arguments::get_integer( const std::string& arg_name ) const 00198 { 00199 CLAW_ASSERT( has_value(arg_name), 00200 "arguments::get_integer(): argument is not set." ); 00201 00202 std::istringstream iss( m_pairs.find( arg_name )->second.back() ); 00203 int val; 00204 iss >> val; 00205 00206 return val; 00207 } // arguments::get_integer() 00208 00209 /*----------------------------------------------------------------------------*/ 00215 double claw::arguments::get_real( const std::string& arg_name ) const 00216 { 00217 CLAW_ASSERT( has_value(arg_name), 00218 "arguments::get_real(): argument is not set." ); 00219 00220 std::istringstream iss( m_pairs.find( arg_name )->second.back() ); 00221 double val; 00222 iss >> val; 00223 00224 return val; 00225 } // arguments::get_real() 00226 00227 /*----------------------------------------------------------------------------*/ 00233 const std::string& 00234 claw::arguments::get_string( const std::string& arg_name ) const 00235 { 00236 CLAW_ASSERT( has_value(arg_name), 00237 "arguments::get_string(): argument is not set." ); 00238 00239 return m_pairs.find( arg_name )->second.back(); 00240 } // arguments::get_string() 00241 00242 /*----------------------------------------------------------------------------*/ 00247 std::list<int> 00248 claw::arguments::get_all_of_integer( const std::string& arg_name ) const 00249 { 00250 std::list<int> result; 00251 const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name)); 00252 00253 if ( itk != m_pairs.end() ) 00254 { 00255 std::list<std::string>::const_iterator it; 00256 00257 for( it=itk->second.begin(); it!=itk->second.end(); ++it ) 00258 if ( text::is_of_type<int>(*it) ) 00259 { 00260 std::istringstream iss(*it); 00261 int val; 00262 iss >> val; 00263 result.push_back(val); 00264 } 00265 } 00266 00267 return result; 00268 } // arguments::get_all_of_integer() 00269 00270 /*----------------------------------------------------------------------------*/ 00275 std::list<double> 00276 claw::arguments::get_all_of_real( const std::string& arg_name ) const 00277 { 00278 std::list<double> result; 00279 const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name)); 00280 00281 if ( itk != m_pairs.end() ) 00282 { 00283 std::list<std::string>::const_iterator it; 00284 00285 for( it=itk->second.begin(); it!=itk->second.end(); ++it ) 00286 if ( text::is_of_type<double>(*it) ) 00287 { 00288 std::istringstream iss(*it); 00289 double val; 00290 iss >> val; 00291 result.push_back(val); 00292 } 00293 } 00294 00295 return result; 00296 } // arguments::get_all_of_real() 00297 00298 /*----------------------------------------------------------------------------*/ 00303 std::list<std::string> 00304 claw::arguments::get_all_of_string( const std::string& arg_name ) const 00305 { 00306 std::list<std::string> result; 00307 const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name)); 00308 00309 if ( itk != m_pairs.end() ) 00310 result = itk->second; 00311 00312 return result; 00313 } // arguments::get_all_of_string() 00314 00315 /*----------------------------------------------------------------------------*/ 00325 void claw::arguments::add_argument( const std::string& arg ) 00326 { 00327 CLAW_ASSERT( arg != "--", "arguments::add_argument(): arg can't be '--'" ); 00328 CLAW_ASSERT( arg[0] == '-', 00329 "arguments::add_argument(): arg must begin by '-'" ); 00330 00331 std::string name, value; 00332 const bool has_value = split_argument(arg, name, value); 00333 00334 if ( !has_value ) 00335 m_flags.insert( arg ); 00336 else 00337 m_pairs[name].push_back(value); 00338 } // arguments::add_argument() 00339 00340 /*----------------------------------------------------------------------------*/ 00352 void claw::arguments::parse 00353 ( int& argc, char** &argv, bool always_allowed, 00354 const claw::math::ordered_set<std::string>& allowed ) 00355 { 00356 bool stop = false; 00357 int base = 0; 00358 00359 if (m_program_name.empty() && (argc!=0)) 00360 { 00361 m_program_name = argv[0]; 00362 argv[0] = NULL; 00363 base = 1; 00364 } 00365 00366 for (int argi=base; (argi!=argc) && !stop; ++argi) 00367 { 00368 std::string arg(argv[argi]); 00369 00370 if ( !arg.empty() ) 00371 if ( (arg[0] == '-') && (arg.length() > 1) ) 00372 { 00373 if (arg == "--") 00374 stop = true; 00375 else 00376 { 00377 std::string name, value; 00378 const bool has_value = split_argument( arg, name, value ); 00379 00380 if ( !has_value ) 00381 process_boolean( argv[argi], always_allowed, allowed ); 00382 else if ( always_allowed 00383 || (allowed.find( name ) != allowed.end()) ) 00384 { 00385 add_argument( arg ); 00386 argv[argi] = NULL; 00387 } 00388 } 00389 } 00390 } 00391 00392 remove_null_arguments( argc, argv ); 00393 } // arguments::parse() 00394 00395 /*----------------------------------------------------------------------------*/ 00404 bool claw::arguments::split_argument 00405 ( const std::string& arg, std::string& name, std::string& value ) const 00406 { 00407 CLAW_ASSERT( arg != "--", "arguments::split_argument(): arg can't be '--'" ); 00408 CLAW_ASSERT( arg[0] == '-', 00409 "arguments::split_argument(): arg must begin by '-'" ); 00410 00411 std::string::size_type pos = arg.find_first_of('='); 00412 bool result(false); 00413 00414 if ( pos == std::string::npos ) 00415 { 00416 name = arg; 00417 value.clear(); 00418 } 00419 else 00420 { 00421 name = arg.substr(0, pos); 00422 value = arg.substr(pos+1, arg.length() - pos - 1); 00423 result = true; 00424 } 00425 00426 return result; 00427 } // arguments::split_argument() 00428 00429 /*----------------------------------------------------------------------------*/ 00435 void claw::arguments::remove_null_arguments( int& argc, char** &argv ) const 00436 { 00437 unsigned int c=0; // number of non-NULL arguments 00438 00439 for (int i=0; i!=argc; ++i) 00440 if ( argv[i] != NULL ) 00441 ++c; 00442 else 00443 { 00444 bool ok = false; 00445 int j=i; 00446 00447 while ( (j!=argc) && !ok ) 00448 if ( argv[j] == NULL ) 00449 ++j; 00450 else 00451 ok = true; 00452 00453 if (ok) 00454 { 00455 argv[i] = argv[j]; 00456 argv[j] = NULL; 00457 ++c; 00458 } 00459 } 00460 00461 if ( c > 0 ) 00462 if ( (std::string(argv[c-1]) == "--") ) 00463 --c; 00464 00465 argc=c; 00466 } // arguments::remove_null_arguments() 00467 00468 /*----------------------------------------------------------------------------*/ 00478 void claw::arguments::process_boolean 00479 ( char* &arg, bool always_allowed, 00480 const claw::math::ordered_set<std::string>& allowed ) 00481 { 00482 CLAW_ASSERT( std::string(arg) != "--", "arg can't be '--'" ); 00483 CLAW_ASSERT( std::string(arg).length() > 1, 00484 "arg must be at least two characters long" ); 00485 CLAW_ASSERT( arg[0] == '-', "arg must begin by '-'" ); 00486 00487 if ( arg[1] == '-' ) // long boolean 00488 { 00489 if ( always_allowed || (allowed.find(arg) != allowed.end()) ) 00490 { 00491 add_argument(arg); 00492 arg = NULL; 00493 } 00494 } 00495 else // short boolean(s) 00496 { 00497 int i(1); 00498 std::string s("-?"); // equivalent single character argument 00499 00500 while ( arg[i] != '\0' ) 00501 { 00502 s[1] = arg[i]; 00503 00504 if ( always_allowed || (allowed.find(s) != allowed.end()) ) 00505 { 00506 add_argument(s); 00507 00508 // shift remaining arguments 00509 for ( int j=i; arg[j]!='\0'; ++j ) 00510 arg[j] = arg[j+1]; 00511 } 00512 else 00513 ++i; 00514 } 00515 00516 if ( i==1 ) // all arguments have been accepted 00517 arg = NULL; 00518 } 00519 } // arguments::process_boolean()