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