1 /***** This code was generated by Yaggo. Do not edit ******/
2 
3 /* Quorum
4  * Copyright (C) 2012  Genome group at University of Maryland.
5  *
6  * This program is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 
22 #ifndef __CMDLINE_HPP__
23 #define __CMDLINE_HPP__
24 
25 #include <stdint.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <getopt.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <stdexcept>
32 #include <string>
33 #include <limits>
34 #include <vector>
35 #include <iostream>
36 #include <sstream>
37 #include <memory>
38 
39 class cmdline {
40  // Boiler plate stuff. Conversion from string to other formats
adjust_double_si_suffix(double & res,const char * suffix)41   static bool adjust_double_si_suffix(double &res, const char *suffix) {
42     if(*suffix == '\0')
43       return true;
44     if(*(suffix + 1) != '\0')
45       return false;
46 
47     switch(*suffix) {
48     case 'a': res *= 1e-18; break;
49     case 'f': res *= 1e-15; break;
50     case 'p': res *= 1e-12; break;
51     case 'n': res *= 1e-9;  break;
52     case 'u': res *= 1e-6;  break;
53     case 'm': res *= 1e-3;  break;
54     case 'k': res *= 1e3;   break;
55     case 'M': res *= 1e6;   break;
56     case 'G': res *= 1e9;   break;
57     case 'T': res *= 1e12;  break;
58     case 'P': res *= 1e15;  break;
59     case 'E': res *= 1e18;  break;
60     default: return false;
61     }
62     return true;
63   }
64 
conv_double(const char * str,::std::string & err,bool si_suffix)65   static double conv_double(const char *str, ::std::string &err, bool si_suffix) {
66     char *endptr = 0;
67     errno = 0;
68     double res = strtod(str, &endptr);
69     if(errno) {
70       err.assign(strerror(errno));
71       return (double)0.0;
72     }
73     bool invalid =
74       si_suffix ? !adjust_double_si_suffix(res, endptr) : *endptr != '\0';
75     if(invalid) {
76       err.assign("Invalid character");
77       return (double)0.0;
78     }
79     return res;
80   }
81 
conv_enum(const char * str,::std::string & err,const char * const strs[])82   static int conv_enum(const char* str, ::std::string& err, const char* const strs[]) {
83     int res = 0;
84     for(const char* const* cstr = strs; *cstr; ++cstr, ++res)
85       if(!strcmp(*cstr, str))
86         return res;
87     err += "Invalid constant '";
88     err += str;
89     err += "'. Expected one of { ";
90     for(const char* const* cstr = strs; *cstr; ++cstr) {
91       if(cstr != strs)
92         err += ", ";
93       err += *cstr;
94     }
95     err += " }";
96     return -1;
97   }
98 
99   template<typename T>
adjust_int_si_suffix(T & res,const char * suffix)100   static bool adjust_int_si_suffix(T &res, const char *suffix) {
101     if(*suffix == '\0')
102       return true;
103     if(*(suffix + 1) != '\0')
104       return false;
105 
106     switch(*suffix) {
107     case 'k': res *= (T)1000; break;
108     case 'M': res *= (T)1000000; break;
109     case 'G': res *= (T)1000000000; break;
110     case 'T': res *= (T)1000000000000; break;
111     case 'P': res *= (T)1000000000000000; break;
112     case 'E': res *= (T)1000000000000000000; break;
113     default: return false;
114     }
115     return true;
116   }
117 
118   template<typename T>
conv_int(const char * str,::std::string & err,bool si_suffix)119   static T conv_int(const char *str, ::std::string &err, bool si_suffix) {
120     char *endptr = 0;
121     errno = 0;
122     long long int res = strtoll(str, &endptr, 0);
123     if(errno) {
124       err.assign(strerror(errno));
125       return (T)0;
126     }
127     bool invalid =
128       si_suffix ? !adjust_int_si_suffix(res, endptr) : *endptr != '\0';
129     if(invalid) {
130       err.assign("Invalid character");
131       return (T)0;
132     }
133     if(res > ::std::numeric_limits<T>::max() ||
134        res < ::std::numeric_limits<T>::min()) {
135       err.assign("Value out of range");
136       return (T)0;
137     }
138     return (T)res;
139   }
140 
141   template<typename T>
conv_uint(const char * str,::std::string & err,bool si_suffix)142   static T conv_uint(const char *str, ::std::string &err, bool si_suffix) {
143     char *endptr = 0;
144     errno = 0;
145     while(isspace(*str)) { ++str; }
146     if(*str == '-') {
147       err.assign("Negative value");
148       return (T)0;
149     }
150     unsigned long long int res = strtoull(str, &endptr, 0);
151     if(errno) {
152       err.assign(strerror(errno));
153       return (T)0;
154     }
155     bool invalid =
156       si_suffix ? !adjust_int_si_suffix(res, endptr) : *endptr != '\0';
157     if(invalid) {
158       err.assign("Invalid character");
159       return (T)0;
160     }
161     if(res > ::std::numeric_limits<T>::max()) {
162       err.assign("Value out of range");
163       return (T)0;
164     }
165     return (T)res;
166   }
167 
168   template<typename T>
vec_str(const std::vector<T> & vec)169   static ::std::string vec_str(const std::vector<T> &vec) {
170     ::std::ostringstream os;
171     for(typename ::std::vector<T>::const_iterator it = vec.begin();
172         it != vec.end(); ++it) {
173       if(it != vec.begin())
174         os << ",";
175       os << *it;
176     }
177     return os.str();
178   }
179 
180   class string : public ::std::string {
181   public:
string()182     string() : ::std::string() {}
string(const::std::string & s)183     explicit string(const ::std::string &s) : std::string(s) {}
string(const char * s)184     explicit string(const char *s) : ::std::string(s) {}
as_enum(const char * const strs[])185     int as_enum(const char* const strs[]) {
186       ::std::string err;
187       int res = conv_enum((const char*)this->c_str(), err, strs);
188       if(!err.empty())
189         throw ::std::runtime_error(err);
190       return res;
191     }
192 
193 
as_uint32_suffix() const194     uint32_t as_uint32_suffix() const { return as_uint32(true); }
as_uint32(bool si_suffix=false) const195     uint32_t as_uint32(bool si_suffix = false) const {
196       ::std::string err;
197       uint32_t res = conv_uint<uint32_t>((const char*)this->c_str(), err, si_suffix);
198       if(!err.empty()) {
199         ::std::string msg("Invalid conversion of '");
200         msg += *this;
201         msg += "' to uint32_t: ";
202         msg += err;
203         throw ::std::runtime_error(msg);
204       }
205       return res;
206     }
as_uint64_suffix() const207     uint64_t as_uint64_suffix() const { return as_uint64(true); }
as_uint64(bool si_suffix=false) const208     uint64_t as_uint64(bool si_suffix = false) const {
209       ::std::string err;
210       uint64_t res = conv_uint<uint64_t>((const char*)this->c_str(), err, si_suffix);
211       if(!err.empty()) {
212         ::std::string msg("Invalid conversion of '");
213         msg += *this;
214         msg += "' to uint64_t: ";
215         msg += err;
216         throw ::std::runtime_error(msg);
217       }
218       return res;
219     }
as_int32_suffix() const220     int32_t as_int32_suffix() const { return as_int32(true); }
as_int32(bool si_suffix=false) const221     int32_t as_int32(bool si_suffix = false) const {
222       ::std::string err;
223       int32_t res = conv_int<int32_t>((const char*)this->c_str(), err, si_suffix);
224       if(!err.empty()) {
225         ::std::string msg("Invalid conversion of '");
226         msg += *this;
227         msg += "' to int32_t: ";
228         msg += err;
229         throw ::std::runtime_error(msg);
230       }
231       return res;
232     }
as_int64_suffix() const233     int64_t as_int64_suffix() const { return as_int64(true); }
as_int64(bool si_suffix=false) const234     int64_t as_int64(bool si_suffix = false) const {
235       ::std::string err;
236       int64_t res = conv_int<int64_t>((const char*)this->c_str(), err, si_suffix);
237       if(!err.empty()) {
238         ::std::string msg("Invalid conversion of '");
239         msg += *this;
240         msg += "' to int64_t: ";
241         msg += err;
242         throw ::std::runtime_error(msg);
243       }
244       return res;
245     }
as_int_suffix() const246     int as_int_suffix() const { return as_int(true); }
as_int(bool si_suffix=false) const247     int as_int(bool si_suffix = false) const {
248       ::std::string err;
249       int res = conv_int<int>((const char*)this->c_str(), err, si_suffix);
250       if(!err.empty()) {
251         ::std::string msg("Invalid conversion of '");
252         msg += *this;
253         msg += "' to int_t: ";
254         msg += err;
255         throw ::std::runtime_error(msg);
256       }
257       return res;
258     }
as_long_suffix() const259     long as_long_suffix() const { return as_long(true); }
as_long(bool si_suffix=false) const260     long as_long(bool si_suffix = false) const {
261       ::std::string err;
262       long res = conv_int<long>((const char*)this->c_str(), err, si_suffix);
263       if(!err.empty()) {
264         ::std::string msg("Invalid conversion of '");
265         msg += *this;
266         msg += "' to long_t: ";
267         msg += err;
268         throw ::std::runtime_error(msg);
269       }
270       return res;
271     }
as_double_suffix() const272     double as_double_suffix() const { return as_double(true); }
as_double(bool si_suffix=false) const273     double as_double(bool si_suffix = false) const {
274       ::std::string err;
275       double res = conv_double((const char*)this->c_str(), err, si_suffix);
276       if(!err.empty()) {
277         ::std::string msg("Invalid conversion of '");
278         msg += *this;
279         msg += "' to double_t: ";
280         msg += err;
281         throw ::std::runtime_error(msg);
282       }
283       return res;
284     }
285   };
286 
287 public:
288   ::std::vector<const char *>    file_arg;
289   typedef ::std::vector<const char *>::iterator file_arg_it;
290   typedef ::std::vector<const char *>::const_iterator file_arg_const_it;
291 
292   enum {
293     START_OPT = 1000
294   };
295 
cmdline()296   cmdline() :
297     file_arg()
298   { }
299 
cmdline(int argc,char * argv[])300   cmdline(int argc, char* argv[]) :
301     file_arg()
302   { parse(argc, argv); }
303 
parse(int argc,char * argv[])304   void parse(int argc, char* argv[]) {
305     static struct option long_options[] = {
306       {"help", 0, 0, 'h'},
307       {"usage", 0, 0, 'U'},
308       {"version", 0, 0, 'V'},
309       {0, 0, 0, 0}
310     };
311     static const char *short_options = "hVU";
312 
313 #define CHECK_ERR(type,val,which) if(!err.empty()) { ::std::cerr << "Invalid " #type " '" << val << "' for [" which "]: " << err << "\n"; exit(1); }
314     while(true) {
315       int index = -1;
316       int c = getopt_long(argc, argv, short_options, long_options, &index);
317       if(c == -1) break;
318       switch(c) {
319       case ':':
320         ::std::cerr << "Missing required argument for "
321                   << (index == -1 ? ::std::string(1, (char)optopt) : std::string(long_options[index].name))
322                   << ::std::endl;
323         exit(1);
324       case 'h':
325         ::std::cout << usage() << "\n\n" << help() << std::endl;
326         exit(0);
327       case 'U':
328         ::std::cout << usage() << "\nUse --help for more information." << std::endl;
329         exit(0);
330       case 'V':
331         print_version();
332         exit(0);
333       case '?':
334         ::std::cerr << "Use --usage or --help for some help\n";
335         exit(1);
336       }
337     }
338 
339     // Parse arguments
340     if(argc - optind < 2)
341       error("Requires at least 2 arguments.");
342     for( ; optind < argc; ++optind) {
343       file_arg.push_back(argv[optind]);
344     }
345   }
usage()346   static const char * usage() { return "Merge input files"; }
347   class error {
348     int code_;
349     std::ostringstream msg_;
350 
351     // Select the correct version (GNU or XSI) version of
352     // strerror_r. strerror_ behaves like the GNU version of strerror_r,
353     // regardless of which version is provided by the system.
strerror__(char * buf,int res)354     static const char* strerror__(char* buf, int res) {
355       return res != -1 ? buf : "Invalid error";
356     }
strerror__(char * buf,char * res)357     static const char* strerror__(char* buf, char* res) {
358       return res;
359     }
strerror_(int err,char * buf,size_t buflen)360     static const char* strerror_(int err, char* buf, size_t buflen) {
361       return strerror__(buf, strerror_r(err, buf, buflen));
362     }
363     struct no_t { };
364 
365   public:
366     static no_t no;
error(int code=EXIT_FAILURE)367     error(int code = EXIT_FAILURE) : code_(code) { }
error(const char * msg,int code=EXIT_FAILURE)368     explicit error(const char* msg, int code = EXIT_FAILURE) : code_(code)
369       { msg_ << msg; }
error(const std::string & msg,int code=EXIT_FAILURE)370     error(const std::string& msg, int code = EXIT_FAILURE) : code_(code)
371       { msg_ << msg; }
operator <<(no_t)372     error& operator<<(no_t) {
373       char buf[1024];
374       msg_ << ": " << strerror_(errno, buf, sizeof(buf));
375       return *this;
376     }
377     template<typename T>
operator <<(const T & x)378     error& operator<<(const T& x) { msg_ << x; return (*this); }
~error()379     ~error() {
380       ::std::cerr << "Error: " << msg_.str() << "\n"
381                   << usage() << "\n"
382                   << "Use --help for more information"
383                   << ::std::endl;
384       exit(code_);
385     }
386   };
help()387   static const char * help() { return
388     "Take an even number of files and interleave sequences from even and odd files.\n\n"
389     "Options (default value in (), *required):\n"
390     " -U, --usage                              Usage\n"
391     " -h, --help                               This message\n"
392     " -V, --version                            Version";
393   }
hidden()394   static const char* hidden() { return ""; }
print_version(::std::ostream & os=std::cout) const395   void print_version(::std::ostream &os = std::cout) const {
396 #ifndef PACKAGE_VERSION
397 #define PACKAGE_VERSION "0.0.0"
398 #endif
399     os << PACKAGE_VERSION << "\n";
400   }
dump(::std::ostream & os=std::cout)401   void dump(::std::ostream &os = std::cout) {
402     os << "file_arg:" << vec_str(file_arg) << "\n";
403   }
404 };
405 #endif // __CMDLINE_HPP__"
406