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-2008 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 
00036 /*----------------------------------------------------------------------------*/
00040 claw::arguments::arguments()
00041   : m_program_name("<unknow>")
00042 {
00043 
00044 } // arguments::arguments()
00045 
00046 /*----------------------------------------------------------------------------*/
00051 claw::arguments::arguments( const std::string& prog_name )
00052   : m_program_name(prog_name)
00053 {
00054 
00055 } // arguments::arguments()
00056 
00057 /*----------------------------------------------------------------------------*/
00066 claw::arguments::arguments( int& argc, char** &argv )
00067 {
00068   parse(argc, argv);
00069 } // arguments::arguments()
00070 
00071 /*----------------------------------------------------------------------------*/
00081 claw::arguments::arguments(int& argc, char** &argv,
00082                            const claw::math::ordered_set<std::string>& allowed )
00083 
00084 {
00085   parse(argc, argv, allowed);
00086 } // arguments::arguments()
00087 
00088 /*----------------------------------------------------------------------------*/
00096 void claw::arguments::parse( int& argc, char** &argv )
00097 {
00098   parse( argc, argv, true, claw::math::ordered_set<std::string>() );
00099 } // arguments::parse()
00100 
00101 /*----------------------------------------------------------------------------*/
00110 void claw::arguments::parse
00111 ( int& argc, char** &argv,
00112   const claw::math::ordered_set<std::string>& allowed )
00113 {
00114   parse( argc, argv, false, allowed );
00115 } // arguments::parse()
00116 
00117 /*----------------------------------------------------------------------------*/
00122 bool claw::arguments::has_value( const std::string& arg_name ) const
00123 {
00124   return m_pairs.find( arg_name ) != m_pairs.end();
00125 } // arguments::has_value()
00126 
00127 /*----------------------------------------------------------------------------*/
00132 bool claw::arguments::only_integer_values( const std::string& arg_name ) const
00133 {
00134   const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
00135   bool result;
00136 
00137   if ( itk == m_pairs.end() )
00138     result = false;
00139   else
00140     {
00141       std::list<std::string>::const_iterator it;
00142       result = true;
00143 
00144       for( it=itk->second.begin(); result && (it!=itk->second.end()); ++it )
00145         result = result && text::is_of_type<int>(*it);
00146     }
00147 
00148   return result;
00149 } // arguments::only_integer_values()
00150 
00151 /*----------------------------------------------------------------------------*/
00156 bool claw::arguments::only_real_values( const std::string& arg_name ) const
00157 {
00158   const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
00159   bool result;
00160 
00161   if ( itk == m_pairs.end() )
00162     result = false;
00163   else
00164     {
00165       std::list<std::string>::const_iterator it;
00166       result = true;
00167 
00168       for( it=itk->second.begin(); result && (it!=itk->second.end()); ++it )
00169         result = result && text::is_of_type<double>(*it);
00170     }
00171 
00172   return result;
00173 } // arguments::only_real_values()
00174 
00175 /*----------------------------------------------------------------------------*/
00179 const std::string& claw::arguments::get_program_name() const
00180 {
00181   return m_program_name;
00182 } // arguments::get_program_name()
00183 
00184 /*----------------------------------------------------------------------------*/
00189 bool claw::arguments::get_bool( const std::string& arg_name ) const
00190 {
00191   return m_flags.find( arg_name ) != m_flags.end();
00192 } // arguments::get_bool()
00193 
00194 /*----------------------------------------------------------------------------*/
00200 int claw::arguments::get_integer( const std::string& arg_name ) const
00201 {
00202   CLAW_ASSERT( has_value(arg_name),
00203                "arguments::get_integer(): argument is not set." );
00204 
00205   std::istringstream iss( m_pairs.find( arg_name )->second.back() );
00206   int val;
00207   iss >> val;
00208 
00209   return val;
00210 } // arguments::get_integer()
00211 
00212 /*----------------------------------------------------------------------------*/
00218 double claw::arguments::get_real( const std::string& arg_name ) const
00219 {
00220   CLAW_ASSERT( has_value(arg_name),
00221                "arguments::get_real(): argument is not set." );
00222 
00223   std::istringstream iss( m_pairs.find( arg_name )->second.back() );
00224   double val;
00225   iss >> val;
00226 
00227   return val;
00228 } // arguments::get_real()
00229 
00230 /*----------------------------------------------------------------------------*/
00236 const std::string&
00237 claw::arguments::get_string( const std::string& arg_name ) const
00238 {
00239   CLAW_ASSERT( has_value(arg_name),
00240                "arguments::get_string(): argument is not set." );
00241 
00242   return m_pairs.find( arg_name )->second.back();
00243 } // arguments::get_string()
00244 
00245 /*----------------------------------------------------------------------------*/
00250 std::list<int>
00251 claw::arguments::get_all_of_integer( const std::string& arg_name ) const
00252 {
00253   std::list<int> result;
00254   const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
00255 
00256   if ( itk != m_pairs.end() )
00257     {
00258       std::list<std::string>::const_iterator it;
00259 
00260       for( it=itk->second.begin(); it!=itk->second.end(); ++it )
00261         if ( text::is_of_type<int>(*it) )
00262           {
00263             std::istringstream iss(*it);
00264             int val;
00265             iss >> val;
00266             result.push_back(val);
00267           }
00268     }
00269 
00270   return result;
00271 } // arguments::get_all_of_integer()
00272 
00273 /*----------------------------------------------------------------------------*/
00278 std::list<double>
00279 claw::arguments::get_all_of_real( const std::string& arg_name ) const
00280 {
00281   std::list<double> result;
00282   const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
00283 
00284   if ( itk != m_pairs.end() )
00285     {
00286       std::list<std::string>::const_iterator it;
00287 
00288       for( it=itk->second.begin(); it!=itk->second.end(); ++it )
00289         if ( text::is_of_type<double>(*it) )
00290           {
00291             std::istringstream iss(*it);
00292             double val;
00293             iss >> val;
00294             result.push_back(val);
00295           }
00296     }
00297 
00298   return result;
00299 } // arguments::get_all_of_real()
00300 
00301 /*----------------------------------------------------------------------------*/
00306 std::list<std::string>
00307 claw::arguments::get_all_of_string( const std::string& arg_name ) const
00308 {
00309   std::list<std::string> result;
00310   const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
00311 
00312   if ( itk != m_pairs.end() )
00313     result = itk->second;
00314 
00315   return result;
00316 } // arguments::get_all_of_string()
00317 
00318 /*----------------------------------------------------------------------------*/
00328 void claw::arguments::add_argument( const std::string& arg )
00329 {
00330   CLAW_ASSERT( arg != "--", "arguments::add_argument(): arg can't be '--'" );
00331   CLAW_ASSERT( arg[0] == '-',
00332                "arguments::add_argument(): arg must begin by '-'" );
00333   
00334   std::string name, value;
00335   split_argument(arg, name, value);
00336 
00337   if ( value.empty() )
00338     m_flags.insert( arg );
00339   else
00340     m_pairs[name].push_back(value);
00341 } // arguments::add_argument()
00342 
00343 /*----------------------------------------------------------------------------*/
00354 void claw::arguments::parse
00355 ( int& argc, char** &argv, bool always_allowed,
00356   const claw::math::ordered_set<std::string>& allowed )
00357 {
00358   bool stop = false;
00359   int base = 0;
00360 
00361   if (m_program_name.empty() && (argc!=0))
00362     {
00363       m_program_name = argv[0];
00364       argv[0] = NULL;
00365       base = 1;
00366     }
00367 
00368   for (int argi=base; (argi!=argc) && !stop; ++argi)
00369     {
00370       std::string arg(argv[argi]);
00371 
00372       if ( !arg.empty() )
00373         if ( (arg[0] == '-') && (arg.length() > 1) )
00374           {
00375             if (arg == "--")
00376               stop = true;
00377             else
00378               {
00379                 std::string name, value;
00380                 split_argument( arg, name, value );
00381 
00382                 if ( value.empty() )
00383                   process_boolean( argv[argi], always_allowed, allowed );
00384                 else if ( always_allowed
00385                           || (allowed.find( name ) != allowed.end()) )
00386                   {
00387                     add_argument( arg );
00388                     argv[argi] = NULL;
00389                   }
00390               }
00391           }
00392     }
00393 
00394   remove_null_arguments( argc, argv );
00395 } // arguments::parse()
00396 
00397 /*----------------------------------------------------------------------------*/
00405 void claw::arguments::split_argument( const std::string& arg, std::string& name,
00406                                       std::string& value ) const
00407 {
00408   CLAW_ASSERT( arg != "--", "arguments::split_argument(): arg can't be '--'" );
00409   CLAW_ASSERT( arg[0] == '-',
00410                "arguments::split_argument(): arg must begin by '-'" );
00411   
00412   std::string::size_type pos = arg.find_first_of('=');
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     }
00424 } // arguments::split_argument()
00425 
00426 /*----------------------------------------------------------------------------*/
00432 void claw::arguments::remove_null_arguments( int& argc, char** &argv ) const
00433 {
00434   unsigned int c=0; // number of non-NULL arguments
00435   
00436   for (int i=0; i!=argc; ++i)
00437     if ( argv[i] != NULL )
00438       ++c;
00439     else
00440       {
00441         bool ok = false;
00442         int j=i;
00443         
00444         while ( (j!=argc) && !ok )
00445           if ( argv[j] == NULL )
00446             ++j;
00447           else
00448             ok = true;
00449 
00450         if (ok)
00451           {
00452             argv[i] = argv[j];
00453             argv[j] = NULL;
00454             ++c;
00455           }
00456       }
00457 
00458   if ( c > 0 )
00459     if ( (std::string(argv[c-1]) == "--") )
00460       --c;
00461     
00462   argc=c;
00463 } // arguments::remove_null_arguments()
00464 
00465 /*----------------------------------------------------------------------------*/
00475 void claw::arguments::process_boolean
00476 ( char* &arg, bool always_allowed,
00477   const claw::math::ordered_set<std::string>& allowed )
00478 {
00479   CLAW_ASSERT( std::string(arg) != "--", "arg can't be '--'" );
00480   CLAW_ASSERT( std::string(arg).length() > 1,
00481                "arg must be at least two characters long" );
00482   CLAW_ASSERT( arg[0] == '-', "arg must begin by '-'" );
00483 
00484   if ( arg[1] == '-' ) // long boolean
00485     {
00486       if ( always_allowed || (allowed.find(arg) != allowed.end()) )
00487         {
00488           add_argument(arg);
00489           arg = NULL;
00490         }
00491     }
00492   else // short boolean(s)
00493     {
00494       int i(1);
00495       std::string s("-?"); // equivalent single character argument
00496 
00497       while ( arg[i] != '\0' )
00498         {
00499           s[1] = arg[i];
00500 
00501           if ( always_allowed || (allowed.find(s) != allowed.end()) )
00502             {
00503               add_argument(s);
00504 
00505               // shift remaining arguments
00506               for ( int j=i; arg[j]!='\0'; ++j )
00507                 arg[j] = arg[j+1];
00508             }
00509           else
00510             ++i;
00511         }
00512 
00513       if ( i==1 ) // all arguments have been accepted
00514         arg = NULL;
00515     }
00516 } // arguments::process_boolean()

Generated on 9 Nov 2009 for CLAW Library (a C++ Library Absolutely Wonderful) by  doxygen 1.6.1