CLAW Library (a C++ Library Absolutely Wonderful) 1.5.5

arguments.cpp

Go to the documentation of this file.
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()