CLAW Library (a C++ Library Absolutely Wonderful) 1.5.5
|
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-2010 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@yahoo.fr 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 split_argument(arg, name, value); 00333 00334 if ( value.empty() ) 00335 m_flags.insert( arg ); 00336 else 00337 m_pairs[name].push_back(value); 00338 } // arguments::add_argument() 00339 00340 /*----------------------------------------------------------------------------*/ 00351 void claw::arguments::parse 00352 ( int& argc, char** &argv, bool always_allowed, 00353 const claw::math::ordered_set<std::string>& allowed ) 00354 { 00355 bool stop = false; 00356 int base = 0; 00357 00358 if (m_program_name.empty() && (argc!=0)) 00359 { 00360 m_program_name = argv[0]; 00361 argv[0] = NULL; 00362 base = 1; 00363 } 00364 00365 for (int argi=base; (argi!=argc) && !stop; ++argi) 00366 { 00367 std::string arg(argv[argi]); 00368 00369 if ( !arg.empty() ) 00370 if ( (arg[0] == '-') && (arg.length() > 1) ) 00371 { 00372 if (arg == "--") 00373 stop = true; 00374 else 00375 { 00376 std::string name, value; 00377 split_argument( arg, name, value ); 00378 00379 if ( value.empty() ) 00380 process_boolean( argv[argi], always_allowed, allowed ); 00381 else if ( always_allowed 00382 || (allowed.find( name ) != allowed.end()) ) 00383 { 00384 add_argument( arg ); 00385 argv[argi] = NULL; 00386 } 00387 } 00388 } 00389 } 00390 00391 remove_null_arguments( argc, argv ); 00392 } // arguments::parse() 00393 00394 /*----------------------------------------------------------------------------*/ 00402 void claw::arguments::split_argument( const std::string& arg, std::string& name, 00403 std::string& value ) const 00404 { 00405 CLAW_ASSERT( arg != "--", "arguments::split_argument(): arg can't be '--'" ); 00406 CLAW_ASSERT( arg[0] == '-', 00407 "arguments::split_argument(): arg must begin by '-'" ); 00408 00409 std::string::size_type pos = arg.find_first_of('='); 00410 00411 if ( pos == std::string::npos ) 00412 { 00413 name = arg; 00414 value.clear(); 00415 } 00416 else 00417 { 00418 name = arg.substr(0, pos); 00419 value = arg.substr(pos+1, arg.length() - pos - 1); 00420 } 00421 } // arguments::split_argument() 00422 00423 /*----------------------------------------------------------------------------*/ 00429 void claw::arguments::remove_null_arguments( int& argc, char** &argv ) const 00430 { 00431 unsigned int c=0; // number of non-NULL arguments 00432 00433 for (int i=0; i!=argc; ++i) 00434 if ( argv[i] != NULL ) 00435 ++c; 00436 else 00437 { 00438 bool ok = false; 00439 int j=i; 00440 00441 while ( (j!=argc) && !ok ) 00442 if ( argv[j] == NULL ) 00443 ++j; 00444 else 00445 ok = true; 00446 00447 if (ok) 00448 { 00449 argv[i] = argv[j]; 00450 argv[j] = NULL; 00451 ++c; 00452 } 00453 } 00454 00455 if ( c > 0 ) 00456 if ( (std::string(argv[c-1]) == "--") ) 00457 --c; 00458 00459 argc=c; 00460 } // arguments::remove_null_arguments() 00461 00462 /*----------------------------------------------------------------------------*/ 00472 void claw::arguments::process_boolean 00473 ( char* &arg, bool always_allowed, 00474 const claw::math::ordered_set<std::string>& allowed ) 00475 { 00476 CLAW_ASSERT( std::string(arg) != "--", "arg can't be '--'" ); 00477 CLAW_ASSERT( std::string(arg).length() > 1, 00478 "arg must be at least two characters long" ); 00479 CLAW_ASSERT( arg[0] == '-', "arg must begin by '-'" ); 00480 00481 if ( arg[1] == '-' ) // long boolean 00482 { 00483 if ( always_allowed || (allowed.find(arg) != allowed.end()) ) 00484 { 00485 add_argument(arg); 00486 arg = NULL; 00487 } 00488 } 00489 else // short boolean(s) 00490 { 00491 int i(1); 00492 std::string s("-?"); // equivalent single character argument 00493 00494 while ( arg[i] != '\0' ) 00495 { 00496 s[1] = arg[i]; 00497 00498 if ( always_allowed || (allowed.find(s) != allowed.end()) ) 00499 { 00500 add_argument(s); 00501 00502 // shift remaining arguments 00503 for ( int j=i; arg[j]!='\0'; ++j ) 00504 arg[j] = arg[j+1]; 00505 } 00506 else 00507 ++i; 00508 } 00509 00510 if ( i==1 ) // all arguments have been accepted 00511 arg = NULL; 00512 } 00513 } // arguments::process_boolean()