claw  1.9.0
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@stuff-o-matic.com
24 */
31 
32 #include <claw/assert.hpp>
33 #include <claw/claw_gettext.hpp>
35 
36 #include <sstream>
37 
42  : m_program_name(claw_gettext("<unknow>"))
43 {}
44 
49 claw::arguments::arguments(const std::string& prog_name)
50  : m_program_name(prog_name)
51 {}
52 
61 claw::arguments::arguments(int& argc, char**& argv)
62 {
63  parse(argc, argv);
64 }
65 
75 claw::arguments::arguments(int& argc, char**& argv,
77 
78 {
79  parse(argc, argv, allowed);
80 }
81 
89 void claw::arguments::parse(int& argc, char**& argv)
90 {
91  parse(argc, argv, true, claw::math::ordered_set<std::string>());
92 }
93 
103  int& argc, char**& argv,
105 {
106  parse(argc, argv, false, allowed);
107 }
108 
113 bool claw::arguments::has_value(const std::string& arg_name) const
114 {
115  return m_pairs.find(arg_name) != m_pairs.end();
116 }
117 
122 bool claw::arguments::only_integer_values(const std::string& arg_name) const
123 {
124  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
125  bool result = true;
126 
127  if(itk == m_pairs.end())
128  result = false;
129  else
130  {
131  std::list<std::string>::const_iterator it;
132  for(it = itk->second.begin(); result && (it != itk->second.end()); ++it)
133  result = result && text::is_of_type<int>(*it);
134  }
135 
136  return result;
137 }
138 
143 bool claw::arguments::only_real_values(const std::string& arg_name) const
144 {
145  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
146  bool result = true;
147 
148  if(itk == m_pairs.end())
149  result = false;
150  else
151  {
152  std::list<std::string>::const_iterator it;
153  for(it = itk->second.begin(); result && (it != itk->second.end()); ++it)
154  result = result && text::is_of_type<double>(*it);
155  }
156 
157  return result;
158 }
159 
163 const std::string& claw::arguments::get_program_name() const
164 {
165  return m_program_name;
166 }
167 
172 bool claw::arguments::get_bool(const std::string& arg_name) const
173 {
174  return m_flags.find(arg_name) != m_flags.end();
175 }
176 
182 int claw::arguments::get_integer(const std::string& arg_name) const
183 {
184  CLAW_ASSERT(has_value(arg_name),
185  "arguments::get_integer(): argument is not set.");
186 
187  std::istringstream iss(m_pairs.find(arg_name)->second.back());
188  int val;
189  iss >> val;
190 
191  return val;
192 }
193 
199 double claw::arguments::get_real(const std::string& arg_name) const
200 {
201  CLAW_ASSERT(has_value(arg_name),
202  "arguments::get_real(): argument is not set.");
203 
204  std::istringstream iss(m_pairs.find(arg_name)->second.back());
205  double val;
206  iss >> val;
207 
208  return val;
209 }
210 
216 const std::string&
217 claw::arguments::get_string(const std::string& arg_name) const
218 {
219  CLAW_ASSERT(has_value(arg_name),
220  "arguments::get_string(): argument is not set.");
221 
222  return m_pairs.find(arg_name)->second.back();
223 }
224 
229 std::list<int>
230 claw::arguments::get_all_of_integer(const std::string& arg_name) const
231 {
232  std::list<int> result;
233  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
234 
235  if(itk != m_pairs.end())
236  {
237  std::list<std::string>::const_iterator it;
238 
239  for(it = itk->second.begin(); it != itk->second.end(); ++it)
240  if(text::is_of_type<int>(*it))
241  {
242  std::istringstream iss(*it);
243  int val;
244  iss >> val;
245  result.push_back(val);
246  }
247  }
248 
249  return result;
250 }
251 
256 std::list<double>
257 claw::arguments::get_all_of_real(const std::string& arg_name) const
258 {
259  std::list<double> result;
260  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
261 
262  if(itk != m_pairs.end())
263  {
264  std::list<std::string>::const_iterator it;
265 
266  for(it = itk->second.begin(); it != itk->second.end(); ++it)
267  if(text::is_of_type<double>(*it))
268  {
269  std::istringstream iss(*it);
270  double val;
271  iss >> val;
272  result.push_back(val);
273  }
274  }
275 
276  return result;
277 }
278 
283 std::list<std::string>
284 claw::arguments::get_all_of_string(const std::string& arg_name) const
285 {
286  std::list<std::string> result;
287  const valued_arguments_map::const_iterator itk(m_pairs.find(arg_name));
288 
289  if(itk != m_pairs.end())
290  result = itk->second;
291 
292  return result;
293 }
294 
304 void claw::arguments::add_argument(const std::string& arg)
305 {
306  CLAW_ASSERT(arg != "--", "arguments::add_argument(): arg can't be '--'");
307  CLAW_ASSERT(arg[0] == '-',
308  "arguments::add_argument(): arg must begin by '-'");
309 
310  std::string name, value;
311  const bool has_value = split_argument(arg, name, value);
312 
313  if(!has_value)
314  m_flags.insert(arg);
315  else
316  m_pairs[name].push_back(value);
317 }
318 
331  int& argc, char**& argv, bool always_allowed,
333 {
334  bool stop = false;
335  int base = 0;
336 
337  if(m_program_name.empty() && (argc != 0))
338  {
339  m_program_name = argv[0];
340  argv[0] = NULL;
341  base = 1;
342  }
343 
344  for(int argi = base; (argi != argc) && !stop; ++argi)
345  {
346  std::string arg(argv[argi]);
347 
348  if(!arg.empty())
349  if((arg[0] == '-') && (arg.length() > 1))
350  {
351  if(arg == "--")
352  stop = true;
353  else
354  {
355  std::string name, value;
356  const bool has_value = split_argument(arg, name, value);
357 
358  if(!has_value)
359  process_boolean(argv[argi], always_allowed, allowed);
360  else if(always_allowed
361  || (allowed.find(name) != allowed.end()))
362  {
363  add_argument(arg);
364  argv[argi] = NULL;
365  }
366  }
367  }
368  }
369 
370  remove_null_arguments(argc, argv);
371 }
372 
381 bool claw::arguments::split_argument(const std::string& arg, std::string& name,
382  std::string& value) const
383 {
384  CLAW_ASSERT(arg != "--", "arguments::split_argument(): arg can't be '--'");
385  CLAW_ASSERT(arg[0] == '-',
386  "arguments::split_argument(): arg must begin by '-'");
387 
388  std::string::size_type pos = arg.find_first_of('=');
389  bool result(false);
390 
391  if(pos == std::string::npos)
392  {
393  name = arg;
394  value.clear();
395  }
396  else
397  {
398  name = arg.substr(0, pos);
399  value = arg.substr(pos + 1, arg.length() - pos - 1);
400  result = true;
401  }
402 
403  return result;
404 }
405 
411 void claw::arguments::remove_null_arguments(int& argc, char**& argv) const
412 {
413  unsigned int c = 0; // number of non-NULL arguments
414 
415  for(int i = 0; i != argc; ++i)
416  if(argv[i] != NULL)
417  ++c;
418  else
419  {
420  bool ok = false;
421  int j = i;
422 
423  while((j != argc) && !ok)
424  if(argv[j] == NULL)
425  ++j;
426  else
427  ok = true;
428 
429  if(ok)
430  {
431  argv[i] = argv[j];
432  argv[j] = NULL;
433  ++c;
434  }
435  }
436 
437  if(c > 0)
438  if((std::string(argv[c - 1]) == "--"))
439  --c;
440 
441  argc = c;
442 }
443 
453 void claw::arguments::process_boolean(
454  char*& arg, bool always_allowed,
456 {
457  CLAW_ASSERT(std::string(arg) != "--", "arg can't be '--'");
458  CLAW_ASSERT(std::string(arg).length() > 1,
459  "arg must be at least two characters long");
460  CLAW_ASSERT(arg[0] == '-', "arg must begin by '-'");
461 
462  if(arg[1] == '-') // long boolean
463  {
464  if(always_allowed || (allowed.find(arg) != allowed.end()))
465  {
466  add_argument(arg);
467  arg = NULL;
468  }
469  }
470  else // short boolean(s)
471  {
472  int i(1);
473  std::string s("-?"); // equivalent single character argument
474 
475  while(arg[i] != '\0')
476  {
477  s[1] = arg[i];
478 
479  if(always_allowed || (allowed.find(s) != allowed.end()))
480  {
481  add_argument(s);
482 
483  // shift remaining arguments
484  for(int j = i; arg[j] != '\0'; ++j)
485  arg[j] = arg[j + 1];
486  }
487  else
488  ++i;
489  }
490 
491  if(i == 1) // all arguments have been accepted
492  arg = NULL;
493  }
494 }
double get_real(const std::string &arg_name) const
Get the real value of an argument.
Definition: arguments.cpp:199
#define claw_gettext(s)
Call gettext on the default text domain used by Claw.
void parse(int &argc, char **&argv)
Parse arguments.
Definition: arguments.cpp:89
bool only_integer_values(const std::string &arg_name) const
Tell if only integer values are associated to an argument.
Definition: arguments.cpp:122
std::list< std::string > get_all_of_string(const std::string &arg_name) const
Get all string values of an argument.
Definition: arguments.cpp:284
int get_integer(const std::string &arg_name) const
Get the integer value of an argument.
Definition: arguments.cpp:182
bool get_bool(const std::string &arg_name) const
Get the boolean state of an argument.
Definition: arguments.cpp:172
#define CLAW_ASSERT(b, s)
Print a message on std::cerr and stop the program if a condition is not true.
Definition: assert.hpp:88
std::list< int > get_all_of_integer(const std::string &arg_name) const
Get all integer values of an argument.
Definition: arguments.cpp:230
Macros to call gettext on the libclaw textdomain.
void add_argument(const std::string &arg)
Add an argument in our list.
Definition: arguments.cpp:304
arguments()
Constructor.
Definition: arguments.cpp:41
bool only_real_values(const std::string &arg_name) const
Tell if only real values are associated to an argument.
Definition: arguments.cpp:143
A class to manage the arguments of your program.
Some assert macros to strengthen you code.
bool has_value(const std::string &arg_name) const
Tell if a value is associated to an argument.
Definition: arguments.cpp:113
const std::string & get_program_name() const
Get the name of the program.
Definition: arguments.cpp:163
Generic algorithms on strings.
const std::string & get_string(const std::string &arg_name) const
Get the string value of an argument.
Definition: arguments.cpp:217
std::list< double > get_all_of_real(const std::string &arg_name) const
Get all real values of an argument.
Definition: arguments.cpp:257