00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef TOOL_OPTIONS_HXX_
00023 # define TOOL_OPTIONS_HXX_
00024
00025 # include <typeinfo>
00026 # ifdef __GNUC__
00027 # include <cxxabi.h>
00028 # endif // __GNUC__
00029 # include <vector>
00030 # include <string>
00031
00032 # include <wipal/tool/options.hh>
00033 # include <wipal/tool/endianness.hh>
00034
00035 namespace tool
00036 {
00037
00038 namespace opt
00039 {
00040
00041
00042
00043
00044
00045 inline
00046 invalid_type::invalid_type(const std::string& opt_type,
00047 const std::string& req_type):
00048 std::logic_error ("(Internal error) option type is \"" + opt_type +
00049 "\", but \"" + req_type + "\" requested")
00050 {
00051 }
00052
00053
00054
00055
00056
00057 inline
00058 value::value()
00059 {
00060 }
00061
00062 template <class T>
00063 value::value(const T& v): boost::any (v)
00064 {
00065 }
00066
00067 template <class T>
00068 T&
00069 value::get()
00070 {
00071 try
00072 {
00073 return boost::any_cast<T&>(*this);
00074 }
00075 catch (const boost::bad_any_cast&)
00076 {
00077 throw invalid_type (type().name(), typeid(T).name());
00078 }
00079 }
00080
00081 template <class T>
00082 const T&
00083 value::get() const
00084 {
00085 try
00086 {
00087 return boost::any_cast<const T&>(*this);
00088 }
00089 catch (const boost::bad_any_cast&)
00090 {
00091 throw invalid_type (type().name(), typeid(T).name());
00092 }
00093 }
00094
00095 inline
00096 value&
00097 value::operator [] (const name& n)
00098 {
00099 return get<list>()[n];
00100 }
00101
00102 inline
00103 const value&
00104 value::operator [] (const name& n) const
00105 {
00106 return get<list>()[n];
00107 }
00108
00109 namespace internals
00110 {
00111 typedef std::vector<std::string> vector_of_strings;
00112 typedef std::set< std::pair<unsigned, unsigned> > set_of_uint_pairs;
00113
00114 inline
00115 std::ostream&
00116 print_vector_of_strings(std::ostream& o, const vector_of_strings& v)
00117 {
00118 o << '[';
00119 for (vector_of_strings::const_iterator i = v.begin();
00120 i != v.end();
00121 ++i)
00122 {
00123 if (i != v.begin())
00124 o << ", ";
00125 o << '"' << *i << '"';
00126 }
00127 return o << ']';
00128 }
00129
00130 inline
00131 std::ostream&
00132 print_set_of_uint_pairs(std::ostream& o, const set_of_uint_pairs& s)
00133 {
00134 bool empty (true);
00135
00136 o << "{ ";
00137 for (set_of_uint_pairs::const_iterator i = s.begin();
00138 i != s.end();
00139 ++i)
00140 {
00141 if (not empty)
00142 o << ", ";
00143 o << i->first << '-' << i->second;
00144 empty = false;
00145 }
00146 return o << (empty? "}" : " }");
00147 }
00148
00149 }
00150
00151 inline
00152 std::ostream&
00153 value::print(std::ostream& o) const
00154 {
00155 const std::type_info& ti = type();
00156
00157 if (false)
00158 ;
00159
00160 # define WP_print_type(T) \
00161 else if (ti == typeid (T)) \
00162 return o << get<T>()
00163
00164 WP_print_type(bool);
00165 WP_print_type(int);
00166 WP_print_type(std::string);
00167 WP_print_type(list);
00168 WP_print_type(endian::endianness);
00169
00170 # undef WP_print_type
00171
00172 else if (ti == typeid (internals::vector_of_strings))
00173 return internals::
00174 print_vector_of_strings(o, get<internals::vector_of_strings>());
00175 else if (ti == typeid (internals::set_of_uint_pairs))
00176 return internals::
00177 print_set_of_uint_pairs(o, get<internals::set_of_uint_pairs>());
00178 else
00179 return o << '['
00180 # ifdef __GNUC__
00181 << abi::__cxa_demangle(ti.name(), 0, 0, 0)
00182 # else
00183 << ti.name()
00184 #endif // __GNUC__
00185 << ']';
00186 }
00187
00188 inline
00189 std::ostream&
00190 operator << (std::ostream& o, const value& v)
00191 {
00192 return v.print(o);
00193 }
00194
00195 template <class T>
00196 T&
00197 get(value& v)
00198 {
00199 return v.get<T>();
00200 }
00201
00202 template <class T>
00203 const T&
00204 get(const value& v)
00205 {
00206 return v.get<T>();
00207 }
00208
00209
00210
00211
00212
00213 inline
00214 name::name(const std::string& n): std::string (n)
00215 {
00216 }
00217
00218 inline
00219 name::name(const char* n): std::string (n)
00220 {
00221 }
00222
00223 inline
00224 internals::pair
00225 name::operator -= (const value& v) const
00226 {
00227 return internals::pair (*this, v);
00228 }
00229
00230
00231 namespace internals
00232 {
00233
00234
00235
00236
00237
00238 inline
00239 pair::pair(const name& n, const value& v): opt_name (n), opt_value (v)
00240 {
00241 }
00242
00243 inline
00244 defaults_list<pair>
00245 pair::operator , (const pair& p) const
00246 {
00247 return defaults_list<pair> (p, *this);
00248 }
00249
00250 template <class Map>
00251 void
00252 pair::populate(Map& m) const
00253 {
00254 m.insert(std::make_pair(opt_name, opt_value));
00255 }
00256
00257
00258
00259
00260
00261 template <class NDL>
00262 defaults_list<NDL>::defaults_list(const pair& p, const NDL& next):
00263 this_pair (p),
00264 next_defaults (next)
00265 {
00266 }
00267
00268 template <class NDL>
00269 defaults_list< defaults_list<NDL> >
00270 defaults_list<NDL>::operator , (const pair& p) const
00271 {
00272 return defaults_list< defaults_list<NDL> > (p, *this);
00273 }
00274
00275 template <class NDL>
00276 template <class Map>
00277 void
00278 defaults_list<NDL>::populate(Map& m) const
00279 {
00280 this_pair.populate(m);
00281 next_defaults.populate(m);
00282 }
00283
00284 }
00285
00286
00287
00288
00289
00290
00291 inline
00292 invalid_option::invalid_option(const name& option):
00293 invalid_argument (option + " is not a valid option")
00294 {
00295 }
00296
00297
00298
00299
00300
00301
00302 inline
00303 list::list()
00304 {
00305 }
00306
00307 inline
00308 list::list(const internals::pair& defaults)
00309 {
00310 defaults.populate(*this);
00311 }
00312
00313 template <class D>
00314 list::list(const internals::defaults_list<D>& defaults)
00315 {
00316 defaults.populate(*this);
00317 }
00318
00319 inline
00320 value&
00321 list::operator [] (const name& n)
00322 {
00323 iterator i = find(n);
00324
00325 if (i == end())
00326 throw invalid_option (n);
00327
00328 return i->second;
00329 }
00330
00331 inline
00332 const value&
00333 list::operator [] (const name& n) const
00334 {
00335 const_iterator i = find(n);
00336
00337 if (i == end())
00338 throw invalid_option (n);
00339
00340 return i->second;
00341 }
00342
00343 inline
00344 void
00345 list::add(const list& l)
00346 {
00347 l.populate(*this);
00348 }
00349
00350 inline
00351 void
00352 list::add(const name& n, const value& v)
00353 {
00354 if (v.type() == typeid (list))
00355 add(n, v.get<list>());
00356 else
00357 insert(std::make_pair(n, v));
00358 }
00359
00360 inline
00361 list&
00362 list::add(const name& n, const list& l)
00363 {
00364 iterator i = find(n);
00365
00366 if (i == end())
00367 i = insert(std::make_pair(n, l)).first;
00368 else
00369 {
00370 if (i->second.type() != typeid (list))
00371 i->second = list ();
00372 l.populate(get<list>(i->second));
00373 }
00374 return get<list>(i->second);
00375 }
00376
00377 inline
00378 void
00379 list::populate(list& other) const
00380 {
00381 for (const_iterator i = begin(); i != end(); ++i)
00382 other.add(i->first, i->second);
00383 }
00384
00385 inline
00386 std::ostream&
00387 list::print(std::ostream& os, unsigned depth) const
00388 {
00389 if (empty())
00390 return os << "<empty option list>" << std::endl;
00391
00392 for (const_iterator i = begin(); i != end(); ++i)
00393 {
00394 for (unsigned j = 0; j < depth; ++j)
00395 os << " ";
00396 if (i->second.type() == typeid (list))
00397 {
00398 os << "- " << i->first << '\n';
00399 get<list>(i->second).print(os, depth + 1);
00400 }
00401 else
00402 os << i->first << ": " << i->second << '\n';
00403 }
00404 return os << std::flush;
00405 }
00406
00407 inline
00408 std::ostream&
00409 operator << (std::ostream& os, const list& l)
00410 {
00411 return l.print(os);
00412 }
00413
00414 }
00415
00416 }
00417
00418 #endif // TOOL_OPTIONS_HXX_