pktools  2.6.5
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, char ** argv);
124  template<class T1> friend std::ostream& operator<<(std::ostream & os, const Optionpk<T1>& theOption);
126  void setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo);
128  void setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const T& defaultValue, short hide);
130  void setDefault(const T& defaultValue);
131  std::string getDefaultValue() const {return m_defaultValue;};
133  void setShortName(const std::string& shortName);
135  void setLongName(const std::string& longName);
137  std::string getShortName() const {return m_shortName;};
139  std::string getLongName() const {return m_longName;};
141  std::string getHelp() const {return m_help;};
143  static std::string getGPLv3License(){
144  return static_cast<std::string>("\n\
145  This program is free software: you can redistribute it and/or modify\n\
146  it under the terms of the GNU General Public License as published by\n\
147  the Free Software Foundation, either version 3 of the License, or\n\
148  (at your option) any later version.\n\
149  \n\
150  This program is distributed in the hope that it will be useful,\n\
151  but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
152  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
153  GNU General Public License for more details.\n\
154  \n\
155  You should have received a copy of the GNU General Public License\n\
156  along with this program. If not, see <http://www.gnu.org/licenses/>.\n");};
157 
160  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);};
161 
162  private:
164  bool hasArgument() const {return m_hasArgument;};
166  bool hasShortOption() const {return m_shortName.compare("\0");};
168  bool hasLongOption() const {return m_longName.compare("\0");};
170  std::string usage() const;
172  std::string usageDoxygen() const;
174  std::string m_shortName;
176  std::string m_longName;
178  std::string m_help;
180  bool m_hasArgument;
182  T m_defaultValue;
184  bool m_hasDefault;
186  short m_hide;
187 };
188 
189 template<class T1> std::ostream& operator<<(std::ostream& os, const Optionpk<T1>& theOption)
190 {
191  os << theOption.getLongName() << ": ";
192  for(int index=0;index<theOption.size();++index)
193  os << type2string<T1>(theOption[index]) << " ";
194  os << std::endl;
195  return os;
196 }
197 
198 template<class T> inline Optionpk<T>::Optionpk()
199 : m_hasDefault(false)
200 {
201 }
202 
209 template<class T> inline Optionpk<T>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
210 : m_hasDefault(false)
211 {
212  setAll(shortName,longName,helpInfo);
213 }
214 
225 template<class T> inline Optionpk<T>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const T& defaultValue, short hide)
226 {
227  setAll(shortName,longName,helpInfo,defaultValue, hide);
228 }
229 
230 template<class T> inline std::string Optionpk<T>::usage() const
231 {
232  std::ostringstream helpss;
233  std::string shortOption=m_shortName;
234  std::string longOption=m_longName;
235  shortOption.insert(0,"-");
236  longOption.insert(0,"--");
237  if(hasShortOption())
238  helpss << " " << std::setiosflags(std::ios::left) << std::setw(4) << shortOption;
239  else
240  helpss << " " << std::setiosflags(std::ios::left) << std::setw(4) << " ";
241  if(hasLongOption())
242  helpss << " " << std::setiosflags(std::ios::left) << std::setw(20) << longOption;
243  else
244  helpss << " " << std::setiosflags(std::ios::left) << std::setw(20) << " ";
245  helpss << " " << m_help;
246  if(m_hasDefault)
247  helpss << " (default: " << type2string<T>(m_defaultValue) << ")";
248  return helpss.str();
249 }
250 
251 template<class T> inline std::string Optionpk<T>::usageDoxygen() const
252 {
253  std::ostringstream helpss;
254  std::string shortOption=m_shortName;
255  std::string longOption=m_longName;
256 
257  if(hasShortOption())
258  helpss << " | " << std::setiosflags(std::ios::left) << std::setw(6) << shortOption << " | ";
259  else
260  helpss << " | " << std::setiosflags(std::ios::left) << " | ";
261  if(hasLongOption())
262  helpss << std::setiosflags(std::ios::left) << std::setw(20) << longOption << " | ";
263  else
264  helpss << std::setiosflags(std::ios::left) << " | ";
265  int status;
266  helpss << std::setiosflags(std::ios::left) << std::setw(4) << mytypeid(T) << " | ";
267  //helpss << std::setiosflags(std::ios::left) << std::setw(4) << abi::__cxa_demangle(typeid(T).name(),0,0,&status) << " | ";
268  if(m_hasDefault)
269  helpss <<std::setiosflags(std::ios::left) << std::setw(5) << type2string<T>(m_defaultValue) << " |";
270  else
271  helpss << " |";
272  helpss << m_help << " | ";
273 
274  return helpss.str();
275 }
276 
277 template<class T> inline void Optionpk<T>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
278 {
279  m_shortName=shortName;
280  m_longName=longName;
281  m_hasArgument=true;
282  m_help=helpInfo;
283  m_hide=0;
284 }
285 
286 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)
287 {
288  m_shortName=shortName;
289  m_longName=longName;
290  m_hasArgument=true;
291  m_help=helpInfo;
292  m_defaultValue=defaultValue;
293  m_hasDefault=true;
294  m_hide=hide;
295 }
296 
297 
298 template<class T> inline Optionpk<T>::~Optionpk()
299 {
300 }
301 
305 template<class T> inline bool Optionpk<T>::retrieveOption(int argc, char **argv){
306  bool noHelp=true;//return value, alert main program that hard coded option (help, version, license, doxygen) was invoked
307  std::string helpStringShort="-h";//short option for help (hard coded)
308  std::string helpStringLong="--help";//long option for help (hard coded)
309  std::string helpStringDoxygen="--doxygen";//option to create table of options ready to use for doxygen
310  std::string versionString="--version";//option to show current version
311  std::string licenseString="--license";//option to show current version
312  for(int i = 1; i < argc; ++i ){
313  std::string currentArgument;
314  std::string currentOption=argv[i];
315  std::string shortOption=m_shortName;
316  std::string longOption=m_longName;
317  shortOption.insert(0,"-");
318  longOption.insert(0,"--");
319  size_t foundEqual=currentOption.rfind("=");
320  if(foundEqual!=std::string::npos){
321  currentArgument=currentOption.substr(foundEqual+1);
322  currentOption=currentOption.substr(0,foundEqual);
323  }
324  if(!helpStringShort.compare(currentOption)){
325  if(m_hide<1)
326  std::cout << usage() << std::endl;
327  noHelp=false;
328  }
329  else if(!helpStringLong.compare(currentOption)){
330  if(m_hide<2)
331  std::cout << usage() << std::endl;
332  noHelp=false;
333  }
334  else if(!helpStringDoxygen.compare(currentOption)){
335  if(m_hide<2)
336  std::cout << usageDoxygen() << std::endl;
337  noHelp=false;
338  }
339  else if(!versionString.compare(currentOption)){
340  std::string theVersion="version ";
341  theVersion+=VERSION;
342  theVersion+=", Copyright (C) Pieter Kempeneers.\n\
343  This program comes with ABSOLUTELY NO WARRANTY; for details type use option -h.\n \
344  This is free software, and you are welcome to redistribute it\n \
345  under certain conditions; use option --license for details.";
346  throw(theVersion);//no need to continue registering (break prevents from multiplication of version info)
347  }
348  else if(!licenseString.compare(currentOption)){
349  throw(getGPLv3License());
350  }
351  if(hasShortOption()&&!(shortOption.compare(currentOption))){//for -option
352  if(foundEqual!=std::string::npos)
353  this->push_back(string2type<T>(currentArgument));
354  else if(m_hasArgument && i < argc-1)
355  this->push_back(string2type<T>(argv[++i]));
356  else
357  this->push_back(string2type<T>("1"));
358  }
359  else if(hasLongOption()&&!(longOption.compare(currentOption))){//for --option
360  if(foundEqual!=std::string::npos)
361  this->push_back(string2type<T>(currentArgument));
362  else if(m_hasArgument && i < argc-1)
363  this->push_back(string2type<T>(argv[++i]));
364  else
365  this->push_back(string2type<T>("1"));
366  }
367  }
368  if(!(this->size())&&m_hasDefault)//only set default value if no options were given
369  this->push_back(m_defaultValue);
370  return(noHelp);
371 }
372 
373 //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);}
374 
375 //todo: to be put in .cc file
377 
379 template<> inline std::string string2type(std::string const& s){
380  return s;
381 }
382 
383 template<> inline double string2type(std::string const& s){
384  std::istringstream i;
385  i.precision(12);
386  i.str(s);
387  double x;
388  if (!(i >> std::setprecision(12) >> x) )
389  throw BadConversion(s);
390  return x;
391 }
392 
393 template<> inline float string2type(std::string const& s){
394  std::istringstream i;
395  i.precision(12);
396  i.str(s);
397  float x;
398  if (!(i >> std::setprecision(12) >> x) )
399  throw BadConversion(s);
400  return x;
401 }
402 
404 template<> inline OGRFieldType string2type(std::string const& s){
405  OGRFieldType ftype;
406  int ogr_typecount=11;//hard coded for now!
407  for(int iType = 0; iType < ogr_typecount; ++iType){
408  if( OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType) != NULL
409  && EQUAL(OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType),s.c_str()))
410  ftype=(OGRFieldType) iType;
411  }
412  return ftype;
413 }
414 
416 template<> inline std::string type2string(bool const& value){
417  if(value)
418  return("true");
419  else
420  return("false");
421 }
422 
424 template<> inline std::string type2string(std::string const& value){
425  // if(value.empty())
426  // return("<empty string>");
427  // else
428  return(value);
429 }
430 
432 template<> inline std::string type2string(float const& value){
433  std::ostringstream oss;
434  // oss.precision(1);
435  // oss.setf(ios::fixed);
436  oss << value;
437  return oss.str();
438 }
439 
441 template<> inline std::string type2string(double const& value){
442  std::ostringstream oss;
443  // oss.precision(1);
444  // oss.setf(ios::fixed);
445  oss << value;
446  return oss.str();
447 }
448 
450 template<> inline void Optionpk<bool>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
451 {
452  m_shortName=shortName;
453  m_longName=longName;
454  m_hasArgument=false;
455  m_help=helpInfo;
456  m_hide=0;
457 }
458 
460 template<> inline void Optionpk<bool>::setAll(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const bool& defaultValue, short hide)
461 {
462  m_shortName=shortName;
463  m_longName=longName;
464  m_hasArgument=false;
465  m_help=helpInfo;
466  m_defaultValue=defaultValue;
467  m_hasDefault=true;
468  m_hide=hide;
469 }
470 
472 template<> inline Optionpk<bool>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
473 {
474  setAll(shortName,longName,helpInfo);
475 }
476 
478 template<> inline Optionpk<bool>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo,const bool& defaultValue, short hide)
479 {
480  setAll(shortName,longName,helpInfo,defaultValue, hide);
481 }
482 
483 //specialization (only makes sense for T=std::string), generic function throws exception
484 //find a substring in string option (e.g., option is of type -co INTERLEAVE=BAND)
485 template<> inline std::vector<std::string>::const_iterator Optionpk<std::string>::findSubstring(const std::string& argument) const{
486  std::vector<std::string>::const_iterator opit=this->begin();
487  while(opit!=this->end()){
488  if(opit->find(argument)!=std::string::npos)
489  break;
490  ++opit;
491  }
492  return opit;
493 }
494 
495 #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:137
Optionpk()
default constructor
Definition: Optionpk.h:198
~Optionpk()
default destructor
Definition: Optionpk.h:298
std::string getHelp() const
get help info stored in m_help
Definition: Optionpk.h:141
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:160
static std::string getGPLv3License()
get license info
Definition: Optionpk.h:143
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:139
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:277
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, char **argv)
read option from command line (use for all options!)
Definition: Optionpk.h:305