00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef OPTIONMM_option
00023 #define OPTIONMM_option
00024
00025 #ifndef __TYPEINFO__
00026 #include <typeinfo>
00027 #endif
00028 #ifndef __VECTOR__
00029 #include <vector>
00030 #endif
00031 #ifndef __STRING__
00032 #include <string>
00033 #endif
00034 #ifndef __IOSTREAM__
00035 #include <iostream>
00036 #endif
00037 #ifndef __IOMANIP__
00038 #include <iomanip>
00039 #endif
00040 #ifndef __SSTREAM__
00041 #include <sstream>
00042 #endif
00043 #ifndef __STDEXCEPT__
00044 #include <stdexcept>
00045 #endif
00046
00047
00048
00049
00050
00051
00052 namespace optionmm
00053 {
00054
00055
00056
00057
00058
00059
00060 class option_base
00061 {
00062 public:
00063 typedef std::vector<int> position_list;
00064 protected:
00065
00066 char _short_name;
00067
00068 std::string _long_name;
00069
00070 std::string _help_string;
00071
00072 position_list _positions;
00073 public:
00074 enum {
00075 cannot_handle,
00076 can_handle,
00077 bad_argument,
00078 missing_argument
00079 };
00080
00081
00082
00083
00084 option_base(char s,
00085 const std::string& l,
00086 const std::string& h);
00087
00088 virtual ~option_base() {}
00089
00090
00091 char short_name() const { return _short_name; }
00092
00093
00094 const std::string& long_name() const { return _long_name; }
00095
00096
00097 const std::string& help_string() const { return _help_string; }
00098
00099
00100 virtual bool need_argument() const { return true; }
00101
00102
00103 virtual bool many_values() const { return true; }
00104
00105
00106
00107
00108 virtual int push_arg(const char* arg, int pos) = 0;
00109
00110
00111
00112 virtual int push_arg(int pos) = 0;
00113
00114
00115
00116
00117 virtual int position(int i=0) const;
00118
00119
00120
00121 virtual void print(int ll, std::ostream& o=std::cout) const = 0;
00122
00123
00124
00125
00126 virtual int handle(const std::string& arg, int pos);
00127
00128
00129
00130
00131
00132 virtual int handle(char*& opt, char*& arg, int pos);
00133 };
00134
00135
00136 inline
00137 option_base::option_base(char s,
00138 const std::string& l,
00139 const std::string& h)
00140 : _short_name(s),
00141 _long_name(l),
00142 _help_string(h)
00143 {}
00144
00145
00146 inline
00147 int
00148 option_base::position(int i) const
00149 {
00150 if (i < 0 || i >= _positions.size()) return 0;
00151 if (!many_values()) return _positions[0];
00152 return _positions[i];
00153 }
00154
00155
00156 inline
00157 int
00158 option_base::handle(const std::string& arg, int pos)
00159 {
00160 if (_long_name.empty() ||
00161 #if defined(__GNUC__) && __GNUC__ <= 2
00162 arg.compare(_long_name, size_t(2), _long_name.size())
00163 #else
00164 arg.compare(size_t(2), _long_name.size(), _long_name)
00165 #endif
00166 ) return cannot_handle;
00167 if (!need_argument()) return push_arg(pos);
00168
00169 std::string::size_type eq = arg.find_last_of('=');
00170 if (eq == std::string::npos) return missing_argument;
00171
00172 std::string value(arg);
00173 value.erase(0, eq+1);
00174 return push_arg(value.c_str(), pos);
00175 }
00176
00177
00178 inline
00179 int
00180 option_base::handle(char*& opt, char*& arg, int pos)
00181 {
00182 if (_short_name == '\0' || opt[0] != _short_name) return cannot_handle;
00183 if (!need_argument()) return push_arg(pos);
00184
00185 int ret = can_handle;
00186 if (opt[1] != '\0') {
00187 ret = push_arg(&(opt[1]), pos);
00188 if (ret > cannot_handle) opt[1] = '\0';
00189 }
00190 else if (arg) {
00191 ret = push_arg(arg, pos);
00192
00193 if (ret > cannot_handle) arg = 0;
00194 }
00195 else
00196 ret = missing_argument;
00197
00198 return ret;
00199 }
00200
00201
00202
00203
00204
00205 template <typename Type>
00206 struct option_trait
00207 {
00208
00209 typedef Type value_type;
00210
00211 typedef std::vector<value_type> list_type;
00212
00213 typedef typename list_type::reference reference;
00214
00215
00216
00217
00218
00219 static bool convert(const char* arg, value_type& val)
00220 {
00221 std::stringstream str(arg);
00222 str.unsetf(std::ios::skipws);
00223 str >> val;
00224 if (str.bad() || str.fail()) return false;
00225 std::string t;
00226 str >> t;
00227 if (!t.empty()) return false;
00228 return true;
00229 }
00230
00231
00232
00233 static bool convert(reference val)
00234 {
00235 value_type tmp = !val;
00236 val = tmp;
00237 return true;
00238 }
00239 };
00240
00241
00242 template <>
00243 struct option_trait<std::string>
00244 {
00245 typedef std::string value_type;
00246 typedef std::vector<value_type> list_type;
00247 typedef list_type::reference reference;
00248
00249 static bool convert(const char* arg, value_type& val)
00250 {
00251 val = arg;
00252 return true;
00253 }
00254 static bool convert(reference val)
00255 {
00256 return true;
00257 }
00258 };
00259
00260
00261
00262
00263
00264
00265
00266
00267 template <typename Type,
00268 bool argument=true,
00269 bool multivalue=true,
00270 typename Trait=option_trait<Type> >
00271 class basic_option : public option_base
00272 {
00273 public:
00274 typedef Type value_type;
00275 typedef std::vector<value_type> value_list;
00276 typedef Trait trait_type;
00277 protected:
00278 value_list _values;
00279 value_type _default;
00280 public:
00281
00282
00283
00284
00285
00286 basic_option(char s,
00287 const std::string& l,
00288 const std::string& h,
00289 value_type d);
00290
00291 virtual ~basic_option() {}
00292
00293
00294 bool need_argument() const { return argument; }
00295
00296 bool many_values() const { return multivalue; }
00297
00298 int size() const { return (_values.size() == 0 ? 1 : _values.size()); }
00299
00300
00301
00302
00303
00304 const value_type& value(int i=0) const;
00305
00306 const value_list& values() const { return _values; }
00307
00308
00309
00310
00311
00312
00313
00314 int push_arg(const char* arg, int pos);
00315
00316
00317
00318
00319
00320 int push_arg(int pos);
00321
00322
00323
00324
00325 virtual void print(int ll, std::ostream& o=std::cout) const;
00326 };
00327
00328 template<typename Type, bool arg, bool multi, typename Trait>
00329 inline
00330 basic_option<Type,arg,multi,Trait>::basic_option(char s,
00331 const std::string& l,
00332 const std::string& h,
00333 value_type d)
00334 : option_base(s, l, h), _default(d)
00335 {}
00336
00337
00338 template<typename Type, bool arg, bool multi, typename Trait>
00339 inline const Type&
00340 basic_option<Type,arg,multi,Trait>::value(int i) const
00341 {
00342 if (i >= _values.size() || i < 0) return _default;
00343 const value_type& ret = _values[i];
00344 return ret;
00345 }
00346
00347
00348 template<typename Type, bool arg, bool multi, typename Trait>
00349 inline
00350 int
00351 basic_option<Type,arg,multi,Trait>::push_arg(const char* a, int pos)
00352 {
00353 value_type val;
00354 if (!trait_type::convert(a, val)) return bad_argument;
00355
00356 if (!many_values()) {
00357 if (_values.size() == 0) {
00358 _values.push_back(val);
00359 _positions.push_back(pos);
00360 }
00361 else {
00362 _values[0] = val;
00363 _positions[0] = pos;
00364 }
00365 } else {
00366 _values.push_back(val);
00367 _positions.push_back(pos);
00368 }
00369 return can_handle;
00370 }
00371
00372
00373 template<typename Type, bool arg, bool multi, typename Trait>
00374 inline
00375 int
00376 basic_option<Type,arg,multi,Trait>::push_arg(int pos)
00377 {
00378 if (many_values()) {
00379 _values.push_back(_default);
00380 _positions.push_back(pos);
00381 }
00382 else {
00383 if (_values.size() == 0) {
00384 _values.push_back(_default);
00385 _positions.push_back(pos);
00386 }
00387 else
00388 _positions[0] = pos;
00389 trait_type::convert(_values[0]);
00390 }
00391 return can_handle;
00392 }
00393
00394
00395 template<typename Type, bool arg, bool multi, typename Trait>
00396 inline
00397 void
00398 basic_option<Type,arg,multi,Trait>::print(int ll, std::ostream& o) const
00399 {
00400 if (ll <= 0) ll=16;
00401 if (_short_name != '\0') o << "-" << _short_name <<", ";
00402 else o << " ";
00403 if (!_long_name.empty()) {
00404 o << "--" << _long_name;
00405 if (need_argument()) o << "=VALUE";
00406 else o << " ";
00407 for (int i = _long_name.size(); i < ll; i++) o << " ";
00408 }
00409 else {
00410 o << std::setw(ll+2) << " ";
00411 if (need_argument()) o << " VALUE";
00412 else o << " ";
00413 }
00414 o << "\t" << _help_string;
00415 if (many_values()) o << " (*)";
00416 }
00417 }
00418
00419 #endif
00420
00421
00422
00423
00424