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