OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimArgumentParser.cpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------
2 //
3 // This code was taken from Open Scene Graph and incorporated from into
4 // OSSIM.
5 //
6 //-------------------------------------------------------------------------
7 // $Id: ossimArgumentParser.cpp 22491 2013-11-26 18:17:29Z dburken $
8 
11 #include <ossim/base/ossimString.h>
12 
13 #include <cstring>
14 #include <iostream>
15 #include <set>
16 
17 using namespace std;
18 
19 bool ossimArgumentParser::isOption(const char* str)
20 {
21  return str && str[0]=='-';
22 }
23 
24 bool ossimArgumentParser::isString(const char* str)
25 {
26  if (!str) return false;
27 
28  return true;
29 // return !isOption(str);
30 }
31 
32 bool ossimArgumentParser::isNumber(const char* str)
33 {
34  if (!str) return false;
35 
36  bool hadPlusMinus = false;
37  bool hadDecimalPlace = false;
38  bool hadExponent = false;
39  bool couldBeInt = true;
40  bool couldBeFloat = true;
41  int noZeroToNine = 0;
42 
43  const char* ptr = str;
44 
45  // check if could be a hex number.
46  if (std::strncmp(ptr,"0x",2)==0)
47  {
48  // skip over leading 0x, and then go through rest of string
49  // checking to make sure all values are 0...9 or a..f.
50  ptr+=2;
51  while (
52  *ptr!=0 &&
53  ((*ptr>='0' && *ptr<='9') ||
54  (*ptr>='a' && *ptr<='f') ||
55  (*ptr>='A' && *ptr<='F'))
56  )
57  {
58  ++ptr;
59  }
60 
61  // got to end of string without failure, therefore must be a hex integer.
62  if (*ptr==0) return true;
63  }
64 
65  ptr = str;
66 
67  // check if a float or an int.
68  while (*ptr!=0 && couldBeFloat)
69  {
70  if (*ptr=='+' || *ptr=='-')
71  {
72  if (hadPlusMinus)
73  {
74  couldBeInt = false;
75  couldBeFloat = false;
76  }
77  else
78  {
79  hadPlusMinus = true;
80  }
81  }
82  else if (*ptr>='0' && *ptr<='9')
83  {
84  noZeroToNine++;
85  }
86  else if (*ptr=='.')
87  {
88  if (hadDecimalPlace)
89  {
90  couldBeInt = false;
91  couldBeFloat = false;
92  }
93  else
94  {
95  hadDecimalPlace = true;
96  couldBeInt = false;
97  }
98  }
99  else if (*ptr=='e' || *ptr=='E')
100  {
101  if (hadExponent || noZeroToNine==0)
102  {
103  couldBeInt = false;
104  couldBeFloat = false;
105  }
106  else
107  {
108  hadExponent = true;
109  couldBeInt = false;
110  hadDecimalPlace = false;
111  hadPlusMinus = false;
112  noZeroToNine=0;
113  }
114  }
115  else
116  {
117  couldBeInt = false;
118  couldBeFloat = false;
119  }
120  ++ptr;
121  }
122 
123  if (couldBeInt && noZeroToNine>0) return true;
124  if (couldBeFloat && noZeroToNine>0) return true;
125 
126  return false;
127 
128 }
129 
131 {
132  switch(theType)
133  {
134  case ossimParameter::OSSIM_FLOAT_PARAMETER: return isNumber(str);
135  case ossimParameter::OSSIM_DOUBLE_PARAMETER: return isNumber(str);
136  case ossimParameter::OSSIM_INT_PARAMETER: return isNumber(str);
137  case ossimParameter::OSSIM_UNSIGNED_INT_PARAMETER: return isNumber(str);
138  case ossimParameter::OSSIM_STRING_PARAMETER: return isString(str);
139  }
140  return false;
141 }
142 
144 {
145  if (!valid(str))
146  return false;
147 
148  switch(theType)
149  {
150  case ossimParameter::OSSIM_FLOAT_PARAMETER:
151  *theValue.theFloat = (float)ossimString(str).toDouble();
152  break;
153  case ossimParameter::OSSIM_DOUBLE_PARAMETER:
154  *theValue.theDouble = ossimString(str).toDouble();
155  break;
156  case ossimParameter::OSSIM_INT_PARAMETER:
157  *theValue.theInt = ossimString(str).toInt();
158  break;
159  case ossimParameter::OSSIM_UNSIGNED_INT_PARAMETER:
160  *theValue.theUint = ossimString(str).toUInt32();
161  break;
162  case ossimParameter::OSSIM_STRING_PARAMETER:
163  *theValue.theString = ossimString(str).chars();
164  break;
165  }
166  return true;
167 }
168 
170  theArgc(argc),
171  theArgv(argv),
172  theUsage(ossimApplicationUsage::instance()),
173  theMemAllocated(false)
174 {
175  if (theArgc)
177 }
178 
180  theArgc(new int),
181  theArgv(0),
182  theUsage(ossimApplicationUsage::instance()),
183  theMemAllocated(true)
184 {
185  vector<ossimString> args = commandLine.split(" ", true);
186  *theArgc = (int)args.size();
187  if (*theArgc > 0)
188  {
189  theArgv = new char* [*theArgc];
190  for (size_t i=0; i<args.size(); i++)
191  {
192  size_t n = args[i].size();
193  theArgv[i] = new char [n+1];
194  strncpy(theArgv[i], args[i].chars(), n);
195  theArgv[i][n] = '\0';
196  }
198  }
199 }
200 
202 {
203  if (theMemAllocated)
204  {
205  for (int i=0; i<*theArgc; ++i)
206  delete [] theArgv[i];
207  delete [] theArgv;
208  delete theArgc;
209  }
210 }
211 
212 void ossimArgumentParser::initialize(int* argc, const char **argv)
213 {
214  if(*argc > 0) delete (theArgv);
215  theArgc = argc;
216  theArgv = new char*[*argc];
217  for(int i=0;i<*argc;i++)
218  {
219  theArgv[i] = new char[strlen(argv[i])];
220  strcpy(theArgv[i], argv[i]);
221  }
222 }
223 
225 {
226  if (theArgc && *theArgc>0 ) return std::string(theArgv[0]);
227  return "";
228 }
229 
230 bool ossimArgumentParser::isOption(int pos) const
231 {
232  return pos<*theArgc && isOption(theArgv[pos]);
233 }
234 
235 bool ossimArgumentParser::isString(int pos) const
236 {
237  return pos < *theArgc && isString(theArgv[pos]);
238 }
239 
240 bool ossimArgumentParser::isNumber(int pos) const
241 {
242  return pos < *theArgc && isNumber(theArgv[pos]);
243 }
244 
245 int ossimArgumentParser::find(const std::string& str) const
246 {
247  for(int pos=1;pos<*theArgc;++pos)
248  {
249  if (str==theArgv[pos])
250  {
251  return pos;
252  }
253  }
254  return 0;
255 }
256 
257 bool ossimArgumentParser::match(int pos, const std::string& str) const
258 {
259  return pos<*theArgc && str==theArgv[pos];
260 }
261 
263 {
264  for(int pos=1;pos<*theArgc;++pos)
265  {
266  if (isOption(pos)) return true;
267  }
268  return false;
269 }
270 
271 int ossimArgumentParser::numberOfParams(const std::string& str, const ossimParameter param) const
272 {
273  int pos=find(str);
274  if (pos<=0)
275  return -1;
276 
277  ++pos;
278  int num_params = 0;
279  while (param.valid(theArgv[pos+num_params]))
280  ++num_params;
281  return num_params;
282 }
283 
284 void ossimArgumentParser::remove(int pos,int num)
285 {
286  if (num==0) return;
287 
288  for(;pos+num<*theArgc;++pos)
289  {
290  theArgv[pos]=theArgv[pos+num];
291  }
292  for(;pos<*theArgc;++pos)
293  {
294  theArgv[pos]=0;
295  }
296  *theArgc-=num;
297 }
298 
299 void ossimArgumentParser::insert(int pos, const ossimString& argstr)
300 {
301  if (argstr.size()==0)
302  return;
303 
304  // Split arg into components (separated by spaces). Need to reallocate args array to new size:
305  vector<ossimString> components = argstr.split(" ");
306  int new_argc = *theArgc + (int)components.size();
307  char** new_argv = new char*[new_argc];
308 
309  // First copy the original list, leaving space for the new components:
310  int j = 0;
311  for (int i=0; i<*theArgc; ++i)
312  {
313  if (j == pos)
314  j += (int)components.size();
315  new_argv[j] = theArgv[i];
316  ++j;
317  }
318 
319  // Insert new components:
320  for(ossim_uint32 i=0; i<components.size(); ++i)
321  new_argv[pos+i]=components[i].stringDup();
322 
323  // Need to deallocate old arg storage?
324  if (theMemAllocated)
325  delete [] theArgv;
326  theArgv = new_argv;
327  *theArgc = new_argc;
328  theMemAllocated = true;
329 }
330 
331 bool ossimArgumentParser::read(const std::string& str)
332 {
333  int pos=find(str);
334  if (pos<=0) return false;
335  remove(pos);
336  return true;
337 }
338 
339 bool ossimArgumentParser::read(const std::string& str, ossimParameter value1)
340 {
341  int pos=find(str);
342  if (pos<=0) return false;
343  if (!value1.valid(theArgv[pos+1]))
344  {
345  reportError("argument to `"+str+"` is missing");
346  return false;
347  }
348  value1.assign(theArgv[pos+1]);
349  remove(pos,2);
350  return true;
351 }
352 
353 bool ossimArgumentParser::read(const std::string& str, ossimParameter value1,
354  ossimParameter value2)
355 {
356  int pos=find(str);
357  if (pos<=0) return false;
358  if (!value1.valid(theArgv[pos+1]) ||
359  !value2.valid(theArgv[pos+2]))
360  {
361  reportError("argument to `"+str+"` is missing");
362  return false;
363  }
364  value1.assign(theArgv[pos+1]);
365  value2.assign(theArgv[pos+2]);
366  remove(pos,3);
367  return true;
368 }
369 
370 bool ossimArgumentParser::read(const std::string& str, ossimParameter value1,
371  ossimParameter value2, ossimParameter value3)
372 {
373  int pos=find(str);
374  if (pos<=0) return false;
375  if (!value1.valid(theArgv[pos+1]) ||
376  !value2.valid(theArgv[pos+2]) ||
377  !value3.valid(theArgv[pos+3]))
378  {
379  reportError("argument to `"+str+"` is missing");
380  return false;
381  }
382  value1.assign(theArgv[pos+1]);
383  value2.assign(theArgv[pos+2]);
384  value3.assign(theArgv[pos+3]);
385  remove(pos,4);
386  return true;
387 }
388 
389 bool ossimArgumentParser::read(const std::string& str, ossimParameter value1,
390  ossimParameter value2, ossimParameter value3,
391  ossimParameter value4)
392 {
393  int pos=find(str);
394  if (pos<=0) return false;
395  if (!value1.valid(theArgv[pos+1]) ||
396  !value2.valid(theArgv[pos+2]) ||
397  !value3.valid(theArgv[pos+3]) ||
398  !value4.valid(theArgv[pos+4]))
399  {
400  reportError("argument to `"+str+"` is missing");
401  return false;
402  }
403  value1.assign(theArgv[pos+1]);
404  value2.assign(theArgv[pos+2]);
405  value3.assign(theArgv[pos+3]);
406  value4.assign(theArgv[pos+4]);
407  remove(pos,5);
408  return true;
409 }
410 
411 bool ossimArgumentParser::read(const std::string& str, ossimParameter value1,
412  ossimParameter value2, ossimParameter value3,
413  ossimParameter value4, ossimParameter value5)
414 {
415  int pos=find(str);
416  if (pos<=0) return false;
417  if (!value1.valid(theArgv[pos+1]) ||
418  !value2.valid(theArgv[pos+2]) ||
419  !value3.valid(theArgv[pos+3]) ||
420  !value4.valid(theArgv[pos+4]) ||
421  !value5.valid(theArgv[pos+5]))
422  {
423  reportError("argument to `"+str+"` is missing");
424  return false;
425  }
426  value1.assign(theArgv[pos+1]);
427  value2.assign(theArgv[pos+2]);
428  value3.assign(theArgv[pos+3]);
429  value4.assign(theArgv[pos+4]);
430  value5.assign(theArgv[pos+5]);
431  remove(pos,6);
432  return true;
433 }
434 
435 bool ossimArgumentParser::read(const std::string& str, ossimParameter value1,
436  ossimParameter value2, ossimParameter value3,
437  ossimParameter value4, ossimParameter value5,
438  ossimParameter value6)
439 {
440  int pos=find(str);
441  if (pos<=0) return false;
442  if (!value1.valid(theArgv[pos+1]) ||
443  !value2.valid(theArgv[pos+2]) ||
444  !value3.valid(theArgv[pos+3]) ||
445  !value4.valid(theArgv[pos+4]) ||
446  !value5.valid(theArgv[pos+5]) ||
447  !value6.valid(theArgv[pos+6]))
448  {
449  reportError("argument to `"+str+"` is missing");
450  return false;
451  }
452  value1.assign(theArgv[pos+1]);
453  value2.assign(theArgv[pos+2]);
454  value3.assign(theArgv[pos+3]);
455  value4.assign(theArgv[pos+4]);
456  value5.assign(theArgv[pos+5]);
457  value6.assign(theArgv[pos+6]);
458  remove(pos,7);
459  return true;
460 }
461 
462 bool ossimArgumentParser::read(const std::string& str, std::vector<ossimString>& param_list)
463 {
464  // This method reads a comma-separated list.
465  param_list.clear();
466 
467  int pos=find(str);
468  if (pos<=0)
469  return false;
470 
471  // Option is removed even if no values found:
472  remove(pos, 1);
473  bool includeNextItem = true;
474  while (pos < *theArgc)
475  {
476  // Check for occurence of next option:
477  if (theArgv[pos][0] == '-')
478  break;
479 
480  // Skip a comma surrounded by spaces:
481  ossimString arg = theArgv[pos];
482  if (arg == ",")
483  {
484  remove(pos, 1);
485  includeNextItem = true;
486  continue;
487  }
488 
489  if (!includeNextItem && (arg.string()[0] != ','))
490  break;
491 
492  // Handle comma separated with no spaces (i.e., multiple args reflected as one in theArgv):
493  vector<ossimString> sub_args = arg.split(",", true);
494  for (ossim_uint32 i=0; i<sub_args.size(); ++i)
495  param_list.push_back(sub_args[i]);
496 
497  // If current item ends with comma, the list continues:
498  if (arg[arg.length()-1] != ',')
499  includeNextItem = false;
500 
501  remove(pos, 1);
502  }
503 
504  return true;
505 }
506 
509 bool ossimArgumentParser::read(int pos, const std::string& str)
510 {
511  if (match(pos,str))
512  {
513  remove(pos,1);
514  return true;
515  }
516  else
517  {
518  return false;
519  }
520 }
521 
522 bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1)
523 {
524  if (match(pos,str) &&
525  value1.valid(theArgv[pos+1]))
526  {
527  value1.assign(theArgv[pos+1]);
528  remove(pos,2);
529  return true;
530  }
531  else
532  {
533  return false;
534  }
535 }
536 
537 bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2)
538 {
539  if (match(pos,str) &&
540  value1.valid(theArgv[pos+1]) &&
541  value2.valid(theArgv[pos+2]))
542  {
543  value1.assign(theArgv[pos+1]);
544  value2.assign(theArgv[pos+2]);
545  remove(pos,3);
546  return true;
547  }
548  else
549  {
550  return false;
551  }
552 }
553 
554 bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3)
555 {
556  if (match(pos,str) &&
557  value1.valid(theArgv[pos+1]) &&
558  value2.valid(theArgv[pos+2]) &&
559  value3.valid(theArgv[pos+3]))
560  {
561  value1.assign(theArgv[pos+1]);
562  value2.assign(theArgv[pos+2]);
563  value3.assign(theArgv[pos+3]);
564  remove(pos,4);
565  return true;
566  }
567  else
568  {
569  return false;
570  }
571 }
572 
573 bool ossimArgumentParser::read(int pos, const std::string& str, ossimParameter value1, ossimParameter value2, ossimParameter value3, ossimParameter value4)
574 {
575  if (match(pos,str) &&
576  value1.valid(theArgv[pos+1]) &&
577  value2.valid(theArgv[pos+2]) &&
578  value3.valid(theArgv[pos+3]) &&
579  value4.valid(theArgv[pos+4]))
580  {
581  value1.assign(theArgv[pos+1]);
582  value2.assign(theArgv[pos+2]);
583  value3.assign(theArgv[pos+3]);
584  value4.assign(theArgv[pos+4]);
585  remove(pos,5);
586  return true;
587  }
588  else
589  {
590  return false;
591  }
592 }
593 
595 {
596  for(ossimErrorMessageMap::const_iterator itr=theErrorMessageMap.begin();
597  itr!=theErrorMessageMap.end();
598  ++itr)
599  {
600  if (itr->second>=severity) return true;
601  }
602  return false;
603 }
604 
605 void ossimArgumentParser::reportError(const std::string& message, ossimErrorSeverity severity)
606 {
607  theErrorMessageMap[message]=severity;
608 }
609 
611 {
612  std::set<std::string> options;
613  if (theUsage)
614  {
615  // parse the usage options to get all the option that the application can potential handle.
616  for(ossimApplicationUsage::UsageMap::const_iterator itr=theUsage->getCommandLineOptions().begin();
617  itr!=theUsage->getCommandLineOptions().end();
618  ++itr)
619  {
620  const std::string& option = itr->first;
621  std::string::size_type prevpos = 0, pos = 0;
622  while ((pos=option.find(' ',prevpos))!=std::string::npos)
623  {
624  if (option[prevpos]=='-')
625  {
626  options.insert(std::string(option,prevpos,pos-prevpos));
627  }
628  prevpos=pos+1;
629  }
630  if (option[prevpos]=='-')
631  {
632 
633  options.insert(std::string(option,prevpos,std::string::npos));
634  }
635  }
636 
637  }
638 
639  for(int pos=1;pos<argc();++pos)
640  {
641  // if an option and havn't been previous querried for report as unrecognized.
642  if (isOption(pos) && options.find(theArgv[pos])==options.end())
643  {
644  reportError(getApplicationName() +": unrecognized option "+theArgv[pos],severity);
645  }
646  }
647 }
648 
650 {
651  return theErrorMessageMap;
652 }
653 
655 {
656  return theErrorMessageMap;
657 }
658 
660 {
661  for(ossimErrorMessageMap::iterator itr=theErrorMessageMap.begin();
662  itr!=theErrorMessageMap.end();
663  ++itr)
664  {
665  if (itr->second>=severity)
666  {
667  output<< getApplicationName() << ": " << itr->first << std::endl;
668  }
669  }
670 }
void insert(int pos, const ossimString &arg)
Inserts string into the argv argument list, and increment the argc respectively.
std::string getApplicationName() const
return the application name, as specified by argv[0]
const UsageMap & getCommandLineOptions() const
bool read(const std::string &str)
search for an occurance of a string in the argument list, on sucess remove that occurance from the li...
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
ossim_uint32 toUInt32() const
static bool isNumber(const char *str)
return return true if specified parameter is an number.
int numberOfParams(const std::string &str, const ossimParameter value) const
int find(const std::string &str) const
return the position of an occurence of a string in the argument list.
void reportRemainingOptionsAsUnrecognized(ossimErrorSeverity severity=OSSIM_BENIGN)
for each remaining option report it as an unrecongnized.
bool match(int pos, const std::string &str) const
return true if specified argument matches string.
bool errors(ossimErrorSeverity severity=OSSIM_BENIGN) const
std::string::size_type length() const
Definition: ossimString.h:408
std::string::size_type size() const
Definition: ossimString.h:405
os2<< "> n<< " > nendobj n
unsigned int ossim_uint32
const char * chars() const
For backward compatibility.
Definition: ossimString.h:77
double toDouble() const
void setApplicationName(const ossimString &name)
void initialize(int *argc, const char **argv)
Initialize from command arguments.
std::map< std::string, ossimErrorSeverity > ossimErrorMessageMap
void remove(int pos, int num=1)
remove one or more arguments from the argv argument list, and decrement the argc respectively.
ossimApplicationUsage * theUsage
void reportError(const std::string &message, ossimErrorSeverity severity=OSSIM_CRITICAL)
report an error message by adding to the ErrorMessageMap.
static bool isString(const char *str)
return return true if string is any other string apart from an option.
ossimErrorMessageMap theErrorMessageMap
static bool isOption(const char *str)
return return true if specified string is an option in the form of -option or –option ...
char ** argv()
return the argument array.
int & argc()
return the argument count.
ossimArgumentParser(int *argc, char **argv)
int toInt() const
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
ossimErrorMessageMap & getErrorMessageMap()
void writeErrorMessages(std::ostream &output, ossimErrorSeverity sevrity=OSSIM_BENIGN)
write out error messages at an above specified .
const std::string & string() const
Definition: ossimString.h:414