pktools  2.6.7
Processing Kernel for geospatial data
Optionpk.h
1 /**********************************************************************
2 Optionpk.h: class to handle command line options (inherits from stl vector class)
3 Copyright (C) 2008-2012 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #ifndef _OPTIONPK_H_
21 #define _OPTIONPK_H_
22 
23 #include <vector>
24 #include <string>
25 #include <cstdlib>
26 #include <assert.h>
27 #include <stdexcept>
28 #include <iostream>
29 #include <iomanip>
30 #include <sstream>
31 #include <typeinfo>
32 #ifndef WIN32
33 #include <cxxabi.h>
34 #define mytypeid(T) abi::__cxa_demangle(typeid(T).name(),0,0,&status)
35 #else
36 #define mytypeid(T) typeid(T).name()
37 #endif
38 #include "ogr_feature.h"
39 
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43 
45 class BadConversion : public std::runtime_error {
46  public:
47  BadConversion(std::string const& s)
48  : runtime_error(s)
49  { }
50 };
51 
53 template<typename T> inline T string2type(std::string const& s){
54  std::istringstream i(s);
55  T x;
56  if (!(i >> x) )
57  throw BadConversion(s);
58  return x;
59 }
60 
62 template<typename T> inline T string2type(std::string const& s,bool failIfLeftoverChars){
63  std::istringstream i(s);
64  char c;
65  T x;
66  if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
67  throw BadConversion(s);
68  return x;
69 }
70 
72 template<typename T> inline std::string type2string(T const& value){
73  std::ostringstream oss;
74  oss << value;
75  return oss.str();
76 }
77 
106 template<class T> class Optionpk : public std::vector <T>
107 {
108 public:
110  Optionpk();
112  Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo);
114  Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const T& defaultValue, short hide=0);
116  ~Optionpk();
118  void setHelp(const std::string& helpInfo){m_help=helpInfo;};
120  void setHide(short hide){m_hide=hide;};
122  bool retrieveOption(int argc, const std::vector<std::string>& argv);
124  bool retrieveOption(int argc, char ** argv);
126  template<class T1> friend std::ostream& operator<<(std::ostream & os, const Optionpk<T1>& theOption);
128  void setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo);
130  void setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const T& defaultValue, short hide);
132  void setDefault(const T& defaultValue);
133  std::string getDefaultValue() const {return m_defaultValue;};
135  void setShortName(const std::string& shortName);
137  void setLongName(const std::string& longName);
139  std::string getShortName() const {return m_shortName;};
141  std::string getLongName() const {return m_longName;};
143  std::string getHelp() const {return m_help;};
145  static std::string getGPLv3License(){
146  return static_cast<std::string>("\n\
147  This program is free software: you can redistribute it and/or modify\n\
148  it under the terms of the GNU General Public License as published by\n\
149  the Free Software Foundation, either version 3 of the License, or\n\
150  (at your option) any later version.\n\
151  \n\
152  This program is distributed in the hope that it will be useful,\n\
153  but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
154  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
155  GNU General Public License for more details.\n\
156  \n\
157  You should have received a copy of the GNU General Public License\n\
158  along with this program. If not, see <http://www.gnu.org/licenses/>.\n");};
159 
162  typename std::vector<T>::const_iterator findSubstring(const T& argument) const {std::string errorString="Error: findSubstring only defined for options of type std::string"; throw(errorString);};
163 
164  private:
166  bool hasArgument() const {return m_hasArgument;};
168  bool hasShortOption() const {return m_shortName.compare("\0");};
170  bool hasLongOption() const {return m_longName.compare("\0");};
172  std::string usage() const;
174  std::string usageDoxygen() const;
176  std::string m_shortName;
178  std::string m_longName;
180  std::string m_help;
182  bool m_hasArgument;
184  T m_defaultValue;
186  bool m_hasDefault;
188  short m_hide;
189 };
190 
191 template<class T1> std::ostream& operator<<(std::ostream& os, const Optionpk<T1>& theOption)
192 {
193  os << theOption.getLongName() << ": ";
194  for(int index=0;index<theOption.size();++index)
195  os << type2string<T1>(theOption[index]) << " ";
196  os << std::endl;
197  return os;
198 }
199 
200 template<class T> inline Optionpk<T>::Optionpk()
201 : m_hasDefault(false)
202 {
203 }
204 
211 template<class T> inline Optionpk<T>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
212 : m_hasDefault(false)
213 {
214  setAll(shortName,longName,helpInfo);
215 }
216 
227 template<class T> inline Optionpk<T>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const T& defaultValue, short hide)
228 {
229  setAll(shortName,longName,helpInfo,defaultValue, hide);
230 }
231 
232 template<class T> inline std::string Optionpk<T>::usage() const
233 {
234  std::ostringstream helpss;
235  std::string shortOption=m_shortName;
236  std::string longOption=m_longName;
237  shortOption.insert(0,"-");
238  longOption.insert(0,"--");
239  if(hasShortOption()){
240  helpss << " " << std::setiosflags(std::ios::left) << std::setw(6) << shortOption;
241  }
242  else{
243  helpss << " " << std::setiosflags(std::ios::left) << std::setw(6) << " ";
244  }
245  if(hasLongOption()){
246  helpss << " " << std::setiosflags(std::ios::left) << std::setw(20) << longOption;
247  }
248  else{
249  helpss << " " << std::setiosflags(std::ios::left) << std::setw(20) << " ";
250  }
251  helpss << " " << m_help;
252  if(m_hasDefault)
253  helpss << " (default: " << type2string<T>(m_defaultValue) << ")";
254  return helpss.str();
255 }
256 
257 template<class T> inline std::string Optionpk<T>::usageDoxygen() const
258 {
259  std::ostringstream helpss;
260  std::string shortOption=m_shortName;
261  std::string longOption=m_longName;
262 
263  if(hasShortOption())
264  helpss << " | " << std::setiosflags(std::ios::left) << std::setw(6) << shortOption << " | ";
265  else
266  helpss << " | " << std::setiosflags(std::ios::left) << " | ";
267  if(hasLongOption())
268  helpss << std::setiosflags(std::ios::left) << std::setw(20) << longOption << " | ";
269  else
270  helpss << std::setiosflags(std::ios::left) << " | ";
271  int status;
272  helpss << std::setiosflags(std::ios::left) << std::setw(4) << mytypeid(T) << " | ";
273  //helpss << std::setiosflags(std::ios::left) << std::setw(4) << abi::__cxa_demangle(typeid(T).name(),0,0,&status) << " | ";
274  if(m_hasDefault)
275  helpss <<std::setiosflags(std::ios::left) << std::setw(5) << type2string<T>(m_defaultValue) << " |";
276  else
277  helpss << " |";
278  helpss << m_help << " | ";
279 
280  return helpss.str();
281 }
282 
283 template<class T> inline void Optionpk<T>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
284 {
285  m_shortName=shortName;
286  m_longName=longName;
287  m_hasArgument=true;
288  m_help=helpInfo;
289  m_hide=0;
290 }
291 
292 template<class T> inline void Optionpk<T>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const T& defaultValue, short hide)
293 {
294  m_shortName=shortName;
295  m_longName=longName;
296  m_hasArgument=true;
297  m_help=helpInfo;
298  m_defaultValue=defaultValue;
299  m_hasDefault=true;
300  m_hide=hide;
301 }
302 
303 
304 template<class T> inline Optionpk<T>::~Optionpk()
305 {
306 }
307 
311 template<class T> inline bool Optionpk<T>::retrieveOption(int argc, const std::vector<std::string>& argv){
312  bool noHelp=true;//return value, alert main program that hard coded option (help, version, license, doxygen) was invoked
313  std::string helpStringShort="-h";//short option for help (hard coded)
314  std::string helpStringLong="--help";//long option for help (hard coded)
315  std::string helpStringDoxygen="--doxygen";//option to create table of options ready to use for doxygen
316  std::string versionString="--version";//option to show current version
317  std::string licenseString="--license";//option to show current version
318  for(int i = 1; i < argc; ++i ){
319  std::string currentArgument;
320  std::string currentOption=argv[i];
321  std::string shortOption=m_shortName;
322  std::string longOption=m_longName;
323  shortOption.insert(0,"-");
324  longOption.insert(0,"--");
325  size_t foundEqual=currentOption.rfind("=");
326  if(foundEqual!=std::string::npos){
327  currentArgument=currentOption.substr(foundEqual+1);
328  currentOption=currentOption.substr(0,foundEqual);
329  }
330  if(!helpStringShort.compare(currentOption)){
331  if(m_hide<1)
332  std::cout << usage() << std::endl;
333  noHelp=false;
334  }
335  else if(!helpStringLong.compare(currentOption)){
336  if(m_hide<2)
337  std::cout << usage() << std::endl;
338  noHelp=false;
339  }
340  else if(!helpStringDoxygen.compare(currentOption)){
341  if(m_hide<2)
342  std::cout << usageDoxygen() << std::endl;
343  noHelp=false;
344  }
345  else if(!versionString.compare(currentOption)){
346  std::string theVersion="version ";
347  theVersion+=VERSION;
348  theVersion+=", Copyright (C) Pieter Kempeneers.\n\
349  This program comes with ABSOLUTELY NO WARRANTY; for details type use option -h.\n \
350  This is free software, and you are welcome to redistribute it\n \
351  under certain conditions; use option --license for details.";
352  throw(theVersion);//no need to continue registering (break prevents from multiplication of version info)
353  }
354  else if(!licenseString.compare(currentOption)){
355  throw(getGPLv3License());
356  }
357  if(hasShortOption()&&!(shortOption.compare(currentOption))){//for -option
358  if(foundEqual!=std::string::npos)
359  this->push_back(string2type<T>(currentArgument));
360  else if(m_hasArgument && i < argc-1)
361  this->push_back(string2type<T>(argv[++i]));
362  else
363  this->push_back(string2type<T>("1"));
364  }
365  else if(hasLongOption()&&!(longOption.compare(currentOption))){//for --option
366  if(foundEqual!=std::string::npos)
367  this->push_back(string2type<T>(currentArgument));
368  else if(m_hasArgument && i < argc-1)
369  this->push_back(string2type<T>(argv[++i]));
370  else
371  this->push_back(string2type<T>("1"));
372  }
373  }
374  if(!(this->size())&&m_hasDefault)//only set default value if no options were given
375  this->push_back(m_defaultValue);
376  return(noHelp);
377 }
378 
382 template<class T> inline bool Optionpk<T>::retrieveOption(int argc, char **argv){
383  bool noHelp=true;//return value, alert main program that hard coded option (help, version, license, doxygen) was invoked
384  std::string helpStringShort="-h";//short option for help (hard coded)
385  std::string helpStringLong="--help";//long option for help (hard coded)
386  std::string helpStringDoxygen="--doxygen";//option to create table of options ready to use for doxygen
387  std::string versionString="--version";//option to show current version
388  std::string licenseString="--license";//option to show current version
389  for(int i = 1; i < argc; ++i ){
390  std::string currentArgument;
391  std::string currentOption=argv[i];
392  std::string shortOption=m_shortName;
393  std::string longOption=m_longName;
394  shortOption.insert(0,"-");
395  longOption.insert(0,"--");
396  size_t foundEqual=currentOption.rfind("=");
397  if(foundEqual!=std::string::npos){
398  currentArgument=currentOption.substr(foundEqual+1);
399  currentOption=currentOption.substr(0,foundEqual);
400  }
401  if(!helpStringShort.compare(currentOption)){
402  if(m_hide<1)
403  std::cout << usage() << std::endl;
404  noHelp=false;
405  }
406  else if(!helpStringLong.compare(currentOption)){
407  if(m_hide<2)
408  std::cout << usage() << std::endl;
409  noHelp=false;
410  }
411  else if(!helpStringDoxygen.compare(currentOption)){
412  if(m_hide<2)
413  std::cout << usageDoxygen() << std::endl;
414  noHelp=false;
415  }
416  else if(!versionString.compare(currentOption)){
417  std::string theVersion="version ";
418  theVersion+=VERSION;
419  theVersion+=", Copyright (C) Pieter Kempeneers.\n\
420  This program comes with ABSOLUTELY NO WARRANTY; for details type use option -h.\n \
421  This is free software, and you are welcome to redistribute it\n \
422  under certain conditions; use option --license for details.";
423  throw(theVersion);//no need to continue registering (break prevents from multiplication of version info)
424  }
425  else if(!licenseString.compare(currentOption)){
426  throw(getGPLv3License());
427  }
428  if(hasShortOption()&&!(shortOption.compare(currentOption))){//for -option
429  if(foundEqual!=std::string::npos)
430  this->push_back(string2type<T>(currentArgument));
431  else if(m_hasArgument && i < argc-1)
432  this->push_back(string2type<T>(argv[++i]));
433  else
434  this->push_back(string2type<T>("1"));
435  }
436  else if(hasLongOption()&&!(longOption.compare(currentOption))){//for --option
437  if(foundEqual!=std::string::npos)
438  this->push_back(string2type<T>(currentArgument));
439  else if(m_hasArgument && i < argc-1)
440  this->push_back(string2type<T>(argv[++i]));
441  else
442  this->push_back(string2type<T>("1"));
443  }
444  }
445  if(!(this->size())&&m_hasDefault)//only set default value if no options were given
446  this->push_back(m_defaultValue);
447  return(noHelp);
448 }
449 
450 //template<class T> typename std::vector<T>::const_iterator Optionpk<T>::findSubstring(const T& argument) const {std::string errorString="Error: findSubstring only defined for options of type std::string"; throw(errorString);}
451 
452 //todo: to be put in .cc file
454 
456 template<> inline std::string string2type(std::string const& s){
457  return s;
458 }
459 
460 template<> inline double string2type(std::string const& s){
461  std::istringstream i;
462  i.precision(12);
463  i.str(s);
464  double x;
465  if (!(i >> std::setprecision(12) >> x) )
466  throw BadConversion(s);
467  return x;
468 }
469 
470 template<> inline float string2type(std::string const& s){
471  std::istringstream i;
472  i.precision(12);
473  i.str(s);
474  float x;
475  if (!(i >> std::setprecision(12) >> x) )
476  throw BadConversion(s);
477  return x;
478 }
479 
481 template<> inline OGRFieldType string2type(std::string const& s){
482  OGRFieldType ftype;
483  int ogr_typecount=11;//hard coded for now!
484  for(int iType = 0; iType < ogr_typecount; ++iType){
485  if( OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType) != NULL
486  && EQUAL(OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType),s.c_str()))
487  ftype=(OGRFieldType) iType;
488  }
489  return ftype;
490 }
491 
493 template<> inline std::string type2string(bool const& value){
494  if(value)
495  return("true");
496  else
497  return("false");
498 }
499 
501 template<> inline std::string type2string(std::string const& value){
502  // if(value.empty())
503  // return("<empty string>");
504  // else
505  return(value);
506 }
507 
509 template<> inline std::string type2string(float const& value){
510  std::ostringstream oss;
511  // oss.precision(1);
512  // oss.setf(ios::fixed);
513  oss << value;
514  return oss.str();
515 }
516 
518 template<> inline std::string type2string(double const& value){
519  std::ostringstream oss;
520  // oss.precision(1);
521  // oss.setf(ios::fixed);
522  oss << value;
523  return oss.str();
524 }
525 
527 template<> inline void Optionpk<bool>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
528 {
529  m_shortName=shortName;
530  m_longName=longName;
531  m_hasArgument=false;
532  m_help=helpInfo;
533  m_hide=0;
534 }
535 
537 template<> inline void Optionpk<bool>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const bool& defaultValue, short hide)
538 {
539  m_shortName=shortName;
540  m_longName=longName;
541  m_hasArgument=false;
542  m_help=helpInfo;
543  m_defaultValue=defaultValue;
544  m_hasDefault=true;
545  m_hide=hide;
546 }
547 
549 template<> inline Optionpk<bool>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
550 {
551  setAll(shortName,longName,helpInfo);
552 }
553 
555 template<> inline Optionpk<bool>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const bool& defaultValue, short hide)
556 {
557  setAll(shortName,longName,helpInfo,defaultValue, hide);
558 }
559 
560 //specialization (only makes sense for T=std::string), generic function throws exception
561 //find a substring in string option (e.g., option is of type -co INTERLEAVE=BAND)
562 template<> inline std::vector<std::string>::const_iterator Optionpk<std::string>::findSubstring(const std::string& argument) const{
563  std::vector<std::string>::const_iterator opit=this->begin();
564  while(opit!=this->end()){
565  if(opit->find(argument)!=std::string::npos)
566  break;
567  ++opit;
568  }
569  return opit;
570 }
571 
572 #endif
throw this class when syntax error in command line option
Definition: Optionpk.h:45
std::string getShortName() const
get the short name to be used as -shortName
Definition: Optionpk.h:139
Optionpk()
default constructor
Definition: Optionpk.h:200
~Optionpk()
default destructor
Definition: Optionpk.h:304
std::string getHelp() const
get help info stored in m_help
Definition: Optionpk.h:143
void setDefault(const T &defaultValue)
set a default value for the option
void setHelp(const std::string &helpInfo)
set help information
Definition: Optionpk.h:118
std::vector< T >::const_iterator findSubstring(const T &argument) const
Definition: Optionpk.h:162
static std::string getGPLv3License()
get license info
Definition: Optionpk.h:145
void setLongName(const std::string &longName)
set the long name to be used as –longName
std::string getLongName() const
get the long name to be used as –longName
Definition: Optionpk.h:141
void setAll(const std::string &shortName, const std::string &longName, const std::string &helpInfo)
set all attributes of the option, except default and hide
Definition: Optionpk.h:283
void setShortName(const std::string &shortName)
set the short name to be used as -shortName
void setHide(short hide)
hide option from short help -h (1) or make invisible to short and long help –help (2) ...
Definition: Optionpk.h:120
bool retrieveOption(int argc, const std::vector< std::string > &argv)
read option from command line (use for all options!), std::string implementation
Definition: Optionpk.h:311