Claw  1.7.3
arguments.cpp
Go to the documentation of this file.
1 /*
2  CLAW - a C++ Library Absolutely Wonderful
3 
4  CLAW is a free library without any particular aim but being useful to
5  anyone.
6 
7  Copyright (C) 2005-2011 Julien Jorge
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 
23  contact: julien.jorge@gamned.org
24 */
30 #include <claw/arguments.hpp>
31 
32 #include <sstream>
33 #include <claw/assert.hpp>
35 #include <claw/claw_gettext.hpp>
36 
37 /*----------------------------------------------------------------------------*/
42  : m_program_name( claw_gettext("<unknow>") )
43 {
44 
45 } // arguments::arguments()
46 
47 /*----------------------------------------------------------------------------*/
52 claw::arguments::arguments( const std::string& prog_name )
53  : m_program_name(prog_name)
54 {
55 
56 } // arguments::arguments()
57 
58 /*----------------------------------------------------------------------------*/
67 claw::arguments::arguments( int& argc, char** &argv )
68 {
69  parse(argc, argv);
70 } // arguments::arguments()
71 
72 /*----------------------------------------------------------------------------*/
82 claw::arguments::arguments(int& argc, char** &argv,
84 
85 {
86  parse(argc, argv, allowed);
87 } // arguments::arguments()
88 
89 /*----------------------------------------------------------------------------*/
97 void claw::arguments::parse( int& argc, char** &argv )
98 {
99  parse( argc, argv, true, claw::math::ordered_set<std::string>() );
100 } // arguments::parse()
101 
102 /*----------------------------------------------------------------------------*/
112 ( int& argc, char** &argv,
113  const claw::math::ordered_set<std::string>& allowed )
114 {
115  parse( argc, argv, false, allowed );
116 } // arguments::parse()
117 
118 /*----------------------------------------------------------------------------*/
123 bool claw::arguments::has_value( const std::string& arg_name ) const
124 {
125  return m_pairs.find( arg_name ) != m_pairs.end();
126 } // arguments::has_value()
127 
128 /*----------------------------------------------------------------------------*/
133 bool claw::arguments::only_integer_values( const std::string& arg_name ) const
134 {
135  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
136  bool result = true;
137 
138  if ( itk == m_pairs.end() )
139  result = false;
140  else
141  {
142  std::list<std::string>::const_iterator it;
143  for( it=itk->second.begin(); result && (it!=itk->second.end()); ++it )
144  result = result && text::is_of_type<int>(*it);
145  }
146 
147  return result;
148 } // arguments::only_integer_values()
149 
150 /*----------------------------------------------------------------------------*/
155 bool claw::arguments::only_real_values( const std::string& arg_name ) const
156 {
157  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
158  bool result = true;
159 
160  if ( itk == m_pairs.end() )
161  result = false;
162  else
163  {
164  std::list<std::string>::const_iterator it;
165  for( it=itk->second.begin(); result && (it!=itk->second.end()); ++it )
166  result = result && text::is_of_type<double>(*it);
167  }
168 
169  return result;
170 } // arguments::only_real_values()
171 
172 /*----------------------------------------------------------------------------*/
176 const std::string& claw::arguments::get_program_name() const
177 {
178  return m_program_name;
179 } // arguments::get_program_name()
180 
181 /*----------------------------------------------------------------------------*/
186 bool claw::arguments::get_bool( const std::string& arg_name ) const
187 {
188  return m_flags.find( arg_name ) != m_flags.end();
189 } // arguments::get_bool()
190 
191 /*----------------------------------------------------------------------------*/
197 int claw::arguments::get_integer( const std::string& arg_name ) const
198 {
199  CLAW_ASSERT( has_value(arg_name),
200  "arguments::get_integer(): argument is not set." );
201 
202  std::istringstream iss( m_pairs.find( arg_name )->second.back() );
203  int val;
204  iss >> val;
205 
206  return val;
207 } // arguments::get_integer()
208 
209 /*----------------------------------------------------------------------------*/
215 double claw::arguments::get_real( const std::string& arg_name ) const
216 {
217  CLAW_ASSERT( has_value(arg_name),
218  "arguments::get_real(): argument is not set." );
219 
220  std::istringstream iss( m_pairs.find( arg_name )->second.back() );
221  double val;
222  iss >> val;
223 
224  return val;
225 } // arguments::get_real()
226 
227 /*----------------------------------------------------------------------------*/
233 const std::string&
234 claw::arguments::get_string( const std::string& arg_name ) const
235 {
236  CLAW_ASSERT( has_value(arg_name),
237  "arguments::get_string(): argument is not set." );
238 
239  return m_pairs.find( arg_name )->second.back();
240 } // arguments::get_string()
241 
242 /*----------------------------------------------------------------------------*/
247 std::list<int>
248 claw::arguments::get_all_of_integer( const std::string& arg_name ) const
249 {
250  std::list<int> result;
251  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
252 
253  if ( itk != m_pairs.end() )
254  {
255  std::list<std::string>::const_iterator it;
256 
257  for( it=itk->second.begin(); it!=itk->second.end(); ++it )
258  if ( text::is_of_type<int>(*it) )
259  {
260  std::istringstream iss(*it);
261  int val;
262  iss >> val;
263  result.push_back(val);
264  }
265  }
266 
267  return result;
268 } // arguments::get_all_of_integer()
269 
270 /*----------------------------------------------------------------------------*/
275 std::list<double>
276 claw::arguments::get_all_of_real( const std::string& arg_name ) const
277 {
278  std::list<double> result;
279  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
280 
281  if ( itk != m_pairs.end() )
282  {
283  std::list<std::string>::const_iterator it;
284 
285  for( it=itk->second.begin(); it!=itk->second.end(); ++it )
286  if ( text::is_of_type<double>(*it) )
287  {
288  std::istringstream iss(*it);
289  double val;
290  iss >> val;
291  result.push_back(val);
292  }
293  }
294 
295  return result;
296 } // arguments::get_all_of_real()
297 
298 /*----------------------------------------------------------------------------*/
303 std::list<std::string>
304 claw::arguments::get_all_of_string( const std::string& arg_name ) const
305 {
306  std::list<std::string> result;
307  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
308 
309  if ( itk != m_pairs.end() )
310  result = itk->second;
311 
312  return result;
313 } // arguments::get_all_of_string()
314 
315 /*----------------------------------------------------------------------------*/
325 void claw::arguments::add_argument( const std::string& arg )
326 {
327  CLAW_ASSERT( arg != "--", "arguments::add_argument(): arg can't be '--'" );
328  CLAW_ASSERT( arg[0] == '-',
329  "arguments::add_argument(): arg must begin by '-'" );
330 
331  std::string name, value;
332  const bool has_value = split_argument(arg, name, value);
333 
334  if ( !has_value )
335  m_flags.insert( arg );
336  else
337  m_pairs[name].push_back(value);
338 } // arguments::add_argument()
339 
340 /*----------------------------------------------------------------------------*/
353 ( int& argc, char** &argv, bool always_allowed,
354  const claw::math::ordered_set<std::string>& allowed )
355 {
356  bool stop = false;
357  int base = 0;
358 
359  if (m_program_name.empty() && (argc!=0))
360  {
361  m_program_name = argv[0];
362  argv[0] = NULL;
363  base = 1;
364  }
365 
366  for (int argi=base; (argi!=argc) && !stop; ++argi)
367  {
368  std::string arg(argv[argi]);
369 
370  if ( !arg.empty() )
371  if ( (arg[0] == '-') && (arg.length() > 1) )
372  {
373  if (arg == "--")
374  stop = true;
375  else
376  {
377  std::string name, value;
378  const bool has_value = split_argument( arg, name, value );
379 
380  if ( !has_value )
381  process_boolean( argv[argi], always_allowed, allowed );
382  else if ( always_allowed
383  || (allowed.find( name ) != allowed.end()) )
384  {
385  add_argument( arg );
386  argv[argi] = NULL;
387  }
388  }
389  }
390  }
391 
392  remove_null_arguments( argc, argv );
393 } // arguments::parse()
394 
395 /*----------------------------------------------------------------------------*/
404 bool claw::arguments::split_argument
405 ( const std::string& arg, std::string& name, std::string& value ) const
406 {
407  CLAW_ASSERT( arg != "--", "arguments::split_argument(): arg can't be '--'" );
408  CLAW_ASSERT( arg[0] == '-',
409  "arguments::split_argument(): arg must begin by '-'" );
410 
411  std::string::size_type pos = arg.find_first_of('=');
412  bool result(false);
413 
414  if ( pos == std::string::npos )
415  {
416  name = arg;
417  value.clear();
418  }
419  else
420  {
421  name = arg.substr(0, pos);
422  value = arg.substr(pos+1, arg.length() - pos - 1);
423  result = true;
424  }
425 
426  return result;
427 } // arguments::split_argument()
428 
429 /*----------------------------------------------------------------------------*/
435 void claw::arguments::remove_null_arguments( int& argc, char** &argv ) const
436 {
437  unsigned int c=0; // number of non-NULL arguments
438 
439  for (int i=0; i!=argc; ++i)
440  if ( argv[i] != NULL )
441  ++c;
442  else
443  {
444  bool ok = false;
445  int j=i;
446 
447  while ( (j!=argc) && !ok )
448  if ( argv[j] == NULL )
449  ++j;
450  else
451  ok = true;
452 
453  if (ok)
454  {
455  argv[i] = argv[j];
456  argv[j] = NULL;
457  ++c;
458  }
459  }
460 
461  if ( c > 0 )
462  if ( (std::string(argv[c-1]) == "--") )
463  --c;
464 
465  argc=c;
466 } // arguments::remove_null_arguments()
467 
468 /*----------------------------------------------------------------------------*/
478 void claw::arguments::process_boolean
479 ( char* &arg, bool always_allowed,
480  const claw::math::ordered_set<std::string>& allowed )
481 {
482  CLAW_ASSERT( std::string(arg) != "--", "arg can't be '--'" );
483  CLAW_ASSERT( std::string(arg).length() > 1,
484  "arg must be at least two characters long" );
485  CLAW_ASSERT( arg[0] == '-', "arg must begin by '-'" );
486 
487  if ( arg[1] == '-' ) // long boolean
488  {
489  if ( always_allowed || (allowed.find(arg) != allowed.end()) )
490  {
491  add_argument(arg);
492  arg = NULL;
493  }
494  }
495  else // short boolean(s)
496  {
497  int i(1);
498  std::string s("-?"); // equivalent single character argument
499 
500  while ( arg[i] != '\0' )
501  {
502  s[1] = arg[i];
503 
504  if ( always_allowed || (allowed.find(s) != allowed.end()) )
505  {
506  add_argument(s);
507 
508  // shift remaining arguments
509  for ( int j=i; arg[j]!='\0'; ++j )
510  arg[j] = arg[j+1];
511  }
512  else
513  ++i;
514  }
515 
516  if ( i==1 ) // all arguments have been accepted
517  arg = NULL;
518  }
519 } // arguments::process_boolean()