command_line_arg_parser.cpp
Go to the documentation of this file.
1 
8 #include <cstring>
9 
10 namespace argos {
11 
12  /****************************************/
13  /****************************************/
14 
16  m_nCurrentArgument(0) {
17  }
18 
19  /****************************************/
20  /****************************************/
21 
23  while(! m_vecArguments.empty()) {
24  delete m_vecArguments.back();
25  m_vecArguments.pop_back();
26  }
27  }
28 
29  /****************************************/
30  /****************************************/
31 
33  for(size_t i = 0; i < m_vecArguments.size(); ++i) {
34  c_log << "-" << m_vecArguments[i]->ShortOption << "|"
35  << "--" << m_vecArguments[i]->LongOption;
36  if(!m_vecArguments[i]->IsFlag) {
37  c_log << " <value>";
38  }
39  c_log << "\t"
40  << m_vecArguments[i]->Description
41  << std::endl;
42  }
43  }
44 
45  /****************************************/
46  /****************************************/
47 
49  char** ppch_argv) {
50  /* Used to store information about each argument to parse */
51  size_t unArgLength;
52  char* pchCurrentArg;
53  /* Start parsing from the beginning */
54  m_nCurrentArgument = 1;
55  /* Go through all the passed arguments */
56  while(m_nCurrentArgument < n_argc) {
57  /*
58  * Parsing does as follows:
59  * If the first characters is a - followed by other charactares, then it's an option
60  * If the second character is a - too, it's a long one
61  * Otherwise it's a (set of) short option(s)
62  * If the first character is not a -, or the string is just "-", error
63  */
64  pchCurrentArg = ppch_argv[m_nCurrentArgument];
65  unArgLength = ::strlen(pchCurrentArg);
66  if(ppch_argv[m_nCurrentArgument][0] != '-' ||
67  unArgLength == 1) {
68  THROW_ARGOSEXCEPTION("Unrecognized option \"" << pchCurrentArg << "\".");
69  }
70  else {
71  /* The first character is a - and more characters are to come */
72  if(pchCurrentArg[1] == '-') {
73  /* Also the second char is a - */
74  if(unArgLength > 2) {
75  /* We have a long option */
76  ParseLongOption(n_argc, ppch_argv);
77  }
78  else {
79  /* It's just a --, which we don't support */
80  THROW_ARGOSEXCEPTION("Unrecognized option \"" << pchCurrentArg << "\".");
81  }
82  }
83  else {
84  /* We have a short option like -x, or a set of them like -xyz */
85  if(unArgLength == 2) {
86  /* Single short option: -x */
87  ParseShortOption(n_argc, ppch_argv);
88  }
89  else {
90  /* Set of short options: -xyz */
91  ParseShortOptions(n_argc, ppch_argv);
92  }
93  }
94  }
95  /* Parse next option */
96  ++m_nCurrentArgument;
97  }
98  }
99 
100  /****************************************/
101  /****************************************/
102 
103  void CCommandLineArgParser::ParseLongOption(SInt32 n_argc,
104  char** ppch_argv) {
105  /* Strip the initial -- from the option */
106  std::string strArg(ppch_argv[m_nCurrentArgument]+2);
107  try {
108  /* Search for the option in the vector */
109  for(size_t i = 0; i < m_vecArguments.size(); ++i) {
110  if(m_vecArguments[i]->LongOption == strArg) {
111  /* The option has been found */
112  if(m_vecArguments[i]->IsFlag) {
113  /* It's a flag, pass "true" to set the boolean to true */
114  m_vecArguments[i]->Parse("true");
115  }
116  else {
117  /* It's an argument, use what follows as parameter */
118  ++m_nCurrentArgument;
119  if(m_nCurrentArgument == n_argc) {
120  THROW_ARGOSEXCEPTION("Missing argument for option \"--" << strArg << "\".");
121  }
122  m_vecArguments[i]->Parse(ppch_argv[m_nCurrentArgument]);
123  }
124  /* No need to continue searching */
125  return;
126  }
127  }
128  }
129  catch(CARGoSException& ex) {
130  /* Something went wrong with the parsing */
131  THROW_ARGOSEXCEPTION_NESTED("Error parsing option \"--" << strArg << "\".", ex);
132  }
133  /* If you get here, it's because the option hasn't been found */
134  THROW_ARGOSEXCEPTION("Unrecognized option \"--" << strArg << "\".");
135  }
136 
137  /****************************************/
138  /****************************************/
139 
140  void CCommandLineArgParser::ParseShortOption(SInt32 n_argc,
141  char** ppch_argv) {
142  /* Strip the initial - from the option */
143  char strArg(ppch_argv[m_nCurrentArgument][1]);
144  try {
145  /* Search for the option in the vector */
146  for(size_t i = 0; i < m_vecArguments.size(); ++i) {
147  if(m_vecArguments[i]->ShortOption == strArg) {
148  /* The option has been found */
149  if(m_vecArguments[i]->IsFlag) {
150  /* It's a flag, pass "true" to set the boolean to true */
151  m_vecArguments[i]->Parse("true");
152  }
153  else {
154  /* It's an argument, use what follows as parameter */
155  ++m_nCurrentArgument;
156  if(m_nCurrentArgument == n_argc) {
157  THROW_ARGOSEXCEPTION("Missing argument for option \"-" << strArg << "\".");
158  }
159  m_vecArguments[i]->Parse(ppch_argv[m_nCurrentArgument]);
160  }
161  /* No need to continue searching */
162  return;
163  }
164  }
165  }
166  catch(CARGoSException& ex) {
167  /* Something went wrong with the parsing */
168  THROW_ARGOSEXCEPTION_NESTED("Error parsing option \"-" << strArg << "\".", ex);
169  }
170  /* If you get here, it's because the option hasn't been found */
171  THROW_ARGOSEXCEPTION("Unrecognized option \"-" << strArg << "\".");
172  }
173 
174  /****************************************/
175  /****************************************/
176 
177  void CCommandLineArgParser::ParseShortOptions(SInt32 n_argc,
178  char** ppch_argv) {
179  /* Strip the initial - from the option */
180  std::string strArg(ppch_argv[m_nCurrentArgument]+1);
181  /* Go through all options */
182  for(size_t o = 0; o < strArg.length(); ++o) {
183  /* Search for the option in the vector */
184  size_t i = 0;
185  bool bFound = false;
186  try {
187  while(i < m_vecArguments.size() && !bFound) {
188  if(m_vecArguments[i]->ShortOption == strArg[o]) {
189  /* The option has been found */
190  if(m_vecArguments[i]->IsFlag) {
191  /* It's a flag, pass "true" to set the boolean to true */
192  m_vecArguments[i]->Parse("true");
193  }
194  else {
195  /* It's an argument, only the last short option is allowed to have one */
196  if(o < strArg.length()-1) {
197  THROW_ARGOSEXCEPTION("Option \"-" << strArg[o] << "\" requires an argument.");
198  }
199  else {
200  ++m_nCurrentArgument;
201  m_vecArguments[i]->Parse(ppch_argv[m_nCurrentArgument]);
202  }
203  }
204  /* No need to continue searching */
205  bFound = true;
206  }
207  else {
208  /* Try next option */
209  ++i;
210  }
211  }
212  }
213  catch(CARGoSException& ex) {
214  /* Something went wrong with the parsing */
215  THROW_ARGOSEXCEPTION_NESTED("Error parsing option \"-" << strArg << "\".", ex);
216  }
217  if(!bFound) {
218  /* The option hasn't been found */
219  THROW_ARGOSEXCEPTION("Unrecognized option \"-" << strArg[o] << "\".");
220  }
221  }
222  }
223 
224  /****************************************/
225  /****************************************/
226 
227 }
signed int SInt32
32-bit signed integer.
Definition: datatypes.h:93
virtual void PrintUsage(CARGoSLog &c_log)
Prints the arguments on the log.
virtual ~CCommandLineArgParser()
Class destructor.
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception...
virtual void Parse(SInt32 n_argc, char **ppch_argv)
Parses the arguments on the command line.
CCommandLineArgParser()
Class constructor.
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12