pktools 2.6.7
Processing Kernel for geospatial data
Optionpk.h
1/**********************************************************************
2Optionpk.h: class to handle command line options (inherits from stl vector class)
3Copyright (C) 2008-2012 Pieter Kempeneers
4
5This file is part of pktools
6
7pktools is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12pktools is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
45class BadConversion : public std::runtime_error {
46 public:
47 BadConversion(std::string const& s)
48 : runtime_error(s)
49 { }
50};
51
53template<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
62template<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
72template<typename T> inline std::string type2string(T const& value){
73 std::ostringstream oss;
74 oss << value;
75 return oss.str();
76}
77
106template<class T> class Optionpk : public std::vector <T>
107{
108public:
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
191template<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
200template<class T> inline Optionpk<T>::Optionpk()
201: m_hasDefault(false)
202{
203}
204
211template<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
227template<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
232template<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
257template<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
283template<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
292template<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
304template<class T> inline Optionpk<T>::~Optionpk()
305{
306}
307
311template<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
382template<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
456template<> inline std::string string2type(std::string const& s){
457 return s;
458}
459
460template<> 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
470template<> 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
481template<> 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
493template<> inline std::string type2string(bool const& value){
494 if(value)
495 return("true");
496 else
497 return("false");
498}
499
501template<> inline std::string type2string(std::string const& value){
502 // if(value.empty())
503 // return("<empty string>");
504 // else
505 return(value);
506}
507
509template<> 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
518template<> 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
527template<> 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
537template<> 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
549template<> inline Optionpk<bool>::Optionpk(const std::string& shortName, const std::string& longName, const std::string& helpInfo)
550{
551 setAll(shortName,longName,helpInfo);
552}
553
555template<> 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)
562template<> 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
Optionpk()
default constructor
Definition: Optionpk.h:200
std::string getShortName() const
get the short name to be used as -shortName
Definition: Optionpk.h:139
std::vector< T >::const_iterator findSubstring(const T &argument) const
Definition: Optionpk.h:162
void setShortName(const std::string &shortName)
set the short name to be used as -shortName
std::string getHelp() const
get help info stored in m_help
Definition: Optionpk.h:143
friend std::ostream & operator<<(std::ostream &os, const Optionpk< T1 > &theOption)
print values for this option
Definition: Optionpk.h:191
std::string getLongName() const
get the long name to be used as –longName
Definition: Optionpk.h:141
void setLongName(const std::string &longName)
set the long name to be used as –longName
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
~Optionpk()
default destructor
Definition: Optionpk.h:304
static std::string getGPLv3License()
get license info
Definition: Optionpk.h:145
void setDefault(const T &defaultValue)
set a default value for the option
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
void setHelp(const std::string &helpInfo)
set help information
Definition: Optionpk.h:118
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