|
libpsynth 0.2.1
|
00001 00011 /* 00012 * Copyright (C) 2007, 2009 Juan Pedro BolĂvar Puente 00013 * 00014 * This file is part of Psychosynth. 00015 * 00016 * Psychosynth is free software: you can redistribute it and/or modify 00017 * it under the terms of the GNU General Public License as published by 00018 * the Free Software Foundation, either version 3 of the License, or 00019 * (at your option) any later version. 00020 * 00021 * Psychosynth is distributed in the hope that it will be useful, 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 * GNU General Public License for more details. 00025 * 00026 * You should have received a copy of the GNU General Public License 00027 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00028 * 00029 */ 00030 00031 #ifndef PSYNTH_ARG_PARSER_H 00032 #define PSYNTH_ARG_PARSER_H 00033 00034 #include <sstream> 00035 #include <cstring> 00036 #include <string> 00037 #include <limits> 00038 #include <list> 00039 #include <map> 00040 00041 #include <psynth/base/exception.hpp> 00042 #include <psynth/base/iterator.hpp> 00043 #include <psynth/base/util.hpp> 00044 00045 namespace psynth 00046 { 00047 namespace base 00048 { 00049 00053 PSYNTH_DECLARE_ERROR (error, arg_parser_error) 00054 PSYNTH_DECLARE_ERROR (arg_parser_error, unknown_option_error) 00055 PSYNTH_DECLARE_ERROR (arg_parser_error, parse_option_error) 00056 00061 class parse_error : public std::exception {}; 00062 00063 namespace detail 00064 { 00065 00069 struct ltstr 00070 { 00077 bool operator () (const char *s1, const char *s2) const 00078 { 00079 return strcmp (s1, s2) < 0; 00080 } 00081 }; 00082 00086 struct atoi_func 00087 { 00088 int operator () (const char *str) 00089 { 00090 char* end = 0; 00091 int res = strtol (str, &end, 10); 00092 if (end <= str) 00093 throw parse_error (); 00094 return res; 00095 } 00096 }; 00097 00101 struct atof_func 00102 { 00103 float operator () (const char *str) 00104 { 00105 char* end = 0; 00106 float res = strtof (str, &end); 00107 00108 if (end <= str) 00109 throw parse_error (); 00110 return res; 00111 } 00112 }; 00113 00118 template <class T> 00119 struct atoany_func 00120 { 00121 T operator () (const char *str) 00122 { 00123 return T (str); 00124 } 00125 }; 00126 00127 } /* namespace detail */ 00128 00132 class option 00133 { 00134 public: 00138 virtual ~option () 00139 { 00140 } 00141 00148 virtual bool parse (const char *arg) 00149 { 00150 return false; 00151 }; 00152 00158 virtual bool parse () 00159 { 00160 return false; 00161 }; 00162 }; 00163 00170 template <class T, class ConvFunc = detail::atoany_func <T> > 00171 class option_generic : public option 00172 { 00173 public: 00178 option_generic (T* data) 00179 : _data (data) 00180 {} 00181 00187 bool parse (const char *arg) 00188 { 00189 *_data = ConvFunc ()(arg); 00190 return true; 00191 } 00192 00193 private: 00194 T* _data; 00195 }; 00196 00200 class option_flag : public option 00201 { 00202 bool* _flag; 00203 00204 public: 00209 option_flag (bool* f) 00210 : _flag (f) 00211 {} 00212 00217 bool parse () 00218 { 00219 *_flag = true; 00220 return true; 00221 } 00222 }; 00223 00227 class option_not_flag : public option 00228 { 00229 bool* _flag; 00230 00231 public: 00236 option_not_flag (bool* f) 00237 : _flag (f) 00238 {} 00239 00244 bool parse () 00245 { 00246 *_flag = false; 00247 return true; 00248 } 00249 }; 00250 00255 template <class T> 00256 class option_stream : public option 00257 { 00258 T *m_data; 00259 00260 public: 00265 option_stream (T * data): 00266 m_data (data) 00267 {} 00268 00274 bool parse (const char *arg) 00275 { 00276 std::stringstream stream (std::string (arg), std::ios_base::in); 00277 stream.exceptions (std::stringstream::eofbit | 00278 std::stringstream::failbit | 00279 std::stringstream::badbit); 00280 try { 00281 stream >> *m_data; 00282 } catch (...) { 00283 throw parse_error (); 00284 } 00285 00286 return true; 00287 } 00288 }; 00289 00291 typedef option_generic <int, detail::atoi_func> option_int; 00293 typedef option_generic <float, detail::atof_func> option_float; 00295 typedef option_generic <std::string> option_string; 00297 typedef option_generic <const char*> option_cstring; 00298 00306 class arg_parser : public boost::noncopyable 00307 { 00308 public: 00312 typedef std::list <const char*>::iterator iterator; 00313 00317 typedef std::list <const char*>::const_iterator const_iterator; 00318 00324 void add (unsigned char flag, const char* str, int* data) 00325 { 00326 add (flag, str, data ? new option_int (data) : 0); 00327 } 00328 00335 void add (unsigned char flag, const char* str, float* data) 00336 { 00337 add (flag, str, data ? new option_float (data) : 0); 00338 } 00339 00346 void add (unsigned char flag, const char* str, bool* data) 00347 { 00348 add (flag, str, data ? new option_flag (data) : 0); 00349 } 00350 00357 void add (unsigned char flag, const char* str, std::string* data) 00358 { 00359 add (flag, str, data ? new option_string (data) : 0); 00360 } 00361 00368 void add (unsigned char flag, const char* str, const char** data) 00369 { 00370 add (flag, str, data ? new option_cstring (data) : 0); 00371 } 00372 00381 void add (unsigned char flag, const char* str, option* op); 00382 00394 void parse (int argc, const char* argv[]); 00395 00399 iterator begin () 00400 { 00401 return _free.begin (); 00402 } 00403 00407 const_iterator begin () const 00408 { 00409 return _free.begin (); 00410 } 00411 00415 iterator end () 00416 { 00417 return _free.end (); 00418 } 00419 00423 const_iterator end () const 00424 { 00425 return _free.end (); 00426 } 00427 00431 size_t free_args () const 00432 { 00433 return _free.size (); 00434 } 00435 00439 bool has_free_args () const 00440 { 00441 return !_free.empty (); 00442 } 00443 00444 private: 00445 typedef ptr_iterator<std::list<option*>::iterator> option_iterator; 00446 typedef std::list<option*> option_list; 00447 typedef std::list<std::unique_ptr<option> > unique_option_list; 00448 typedef std::map <const char*, option_list, detail::ltstr> 00449 option_map; 00450 00451 static const unsigned char null_flag = '\0'; 00452 00453 option_list _short [256]; 00454 option_map _long; 00455 unique_option_list _all; 00456 std::list <const char *> _free; 00457 00458 const char** parse_short (const char** argv, const char** argv_end); 00459 const char** parse_long (const char** argv, const char** argv_end); 00460 }; 00461 00462 } /* namespace base */ 00463 } /* namespace psynth */ 00464 00465 #endif /* PSYNTH_ARGPARSER_H */
1.7.4