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