00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ADOBE_ARG_STREAM_H
00021 #define ADOBE_ARG_STREAM_H
00022
00023 #include <boost/function_types/result_type.hpp>
00024 #include <boost/function_types/function_type.hpp>
00025 #include <boost/function_types/function_arity.hpp>
00026
00027 #include <boost/mpl/begin.hpp>
00028 #include <boost/mpl/end.hpp>
00029 #include <boost/mpl/next.hpp>
00030 #include <boost/mpl/deref.hpp>
00031
00032
00033 #ifdef nil
00034 #undef nil
00035 #endif
00036
00037 #include <boost/fusion/include/push_back.hpp>
00038 #include <boost/fusion/include/cons.hpp>
00039 #include <boost/fusion/include/invoke.hpp>
00040
00041 #include <boost/type_traits/remove_cv.hpp>
00042 #include <boost/type_traits/remove_reference.hpp>
00043 #include <boost/type_traits/add_pointer.hpp>
00044
00045 #include <boost/utility/enable_if.hpp>
00046
00047 #include <adobe/type_inspection.hpp>
00048
00049
00050
00051 namespace boost
00052 {
00053 template <typename F> class function;
00054 }
00055
00056
00057 namespace adobe
00058 {
00059
00096 namespace arg_stream
00097 {
00098
00099
00104 struct no_more_args : std::exception
00105 {
00106 };
00107
00108
00109 namespace detail
00110 {
00111 ADOBE_HAS_TYPE_IMPL(eof);
00112
00113 template <typename T>
00114 struct has_eof_member
00115 {
00116 static const bool value = ADOBE_HAS_TYPE(T, eof);
00117 };
00118 }
00119
00128 template <typename T>
00129 struct traits
00130 {
00131 static const bool has_eof_member = detail::has_eof_member<T>::value;
00132 };
00133
00134
00135 namespace detail
00136 {
00137 template <class ArgStream>
00138 static bool eof_check(ArgStream & as, typename boost::enable_if_c<traits<ArgStream>::has_eof_memberfunction>::type * dummy = 0)
00139 {
00140 return as.eof();
00141 }
00142
00143 template <class ArgStream>
00144 static bool eof_check(ArgStream & as, typename boost::disable_if_c<traits<ArgStream>::has_eof_memberfunction>::type * dummy = 0)
00145 {
00146 return false;
00147 }
00148
00149 template <class ArgStream>
00150 static bool eof_check(ArgStream *as)
00151 {
00152 return as ? eof_check(*as) : true;
00153 }
00154 }
00155
00167 template <typename ArgStream>
00168 bool eof(ArgStream const & as)
00169 {
00170 return detail::eof_check(as);
00171 }
00172
00185 template <typename R, typename ArgStream>
00186 R get_next_arg(ArgStream const & as)
00187 {
00188 return as.get_next_arg<R>();
00189 }
00190
00191 template <typename R, typename ArgStream>
00192 R get_next_arg(ArgStream & as)
00193 {
00194 return as.get_next_arg<R>();
00195 }
00196 template <typename R, typename ArgStream>
00197 R get_next_arg(ArgStream * as)
00198 {
00199 return get_next_arg<R>(*as);
00200 }
00201 template <typename R, typename ArgStream>
00202 R get_next_arg(ArgStream const * as)
00203 {
00204 return get_next_arg<R>(*as);
00205 }
00206
00207
00216
00217
00218
00219 template <typename F>
00220 struct signature
00221 {
00222 typedef F type;
00223 };
00224
00225 template <typename F>
00226 struct signature<boost::function<F> >
00227 {
00228 typedef F type;
00229 };
00230
00239 template <typename F>
00240 struct result_type
00241 {
00242 typedef typename boost::function_types::result_type<typename signature<F>::type>::type type;
00243 };
00244
00245 namespace detail
00246 {
00247
00248
00249
00250 template<typename T>
00251 struct remove_cv_ref
00252 : boost::remove_cv< typename boost::remove_reference<T>::type >
00253 { };
00254
00255
00256
00257
00258
00259
00260
00261
00262 template< typename F,
00263 class From = typename boost::mpl::begin< boost::function_types::parameter_types<typename signature<F>::type> >::type,
00264 class To = typename boost::mpl::end< boost::function_types::parameter_types<typename signature<F>::type> >::type>
00265 struct invoker
00266 {
00267
00268 template<typename Args, typename ArgStream>
00269 static inline
00270 typename result_type<F>::type
00271 apply(F func, ArgStream & astream, Args const & args)
00272 {
00273 typedef typename remove_cv_ref<typename boost::mpl::deref<From>::type>::type arg_type;
00274 typedef typename boost::mpl::next<From>::type next_iter_type;
00275
00276 return invoker<F, next_iter_type, To>::apply(
00277 func, astream, boost::fusion::push_back(args, get_next_arg<arg_type>(astream)) );
00278 }
00279 };
00280
00281
00282 template<typename F, class To>
00283 struct invoker<F,To,To>
00284 {
00285 template<typename Args, typename ArgStream>
00286 static inline
00287 typename result_type<F>::type
00288 apply(F func, ArgStream &, Args const & args)
00289 {
00290 return boost::fusion::invoke(func, args);
00291 }
00292 };
00293
00294 }
00295
00296
00304 template <typename F, typename ArgStream>
00305 typename result_type<F>::type
00306 call(F f, ArgStream & astream)
00307 {
00308 return detail::invoker<F>::template apply(f, astream, boost::fusion::nil());
00309 }
00310
00316 template <class T, typename F, typename ArgStream>
00317 typename result_type<F>::type
00318 call(T * that, F f, ArgStream & astream)
00319 {
00320
00321
00322 boost::fusion::nil args;
00323 return detail::invoker<F,
00324 typename boost::mpl::next< typename boost::mpl::begin< boost::function_types::parameter_types<typename signature<F>::type, boost::add_pointer<boost::mpl::placeholders::_> > >::type>::type,
00325 typename boost::mpl::end< boost::function_types::parameter_types<typename signature<F>::type, boost::add_pointer<boost::mpl::placeholders::_> > >::type>
00326 ::template apply(f, astream, boost::fusion::push_back(args, that));
00327 }
00328
00329
00338 template <typename ArgStreamFirst, typename ArgStreamSecond>
00339 struct chain
00340 {
00341 template <class ArgStream>
00342 bool eof(ArgStream * as)
00343 {
00344 return detail::eof_check(as);
00345 }
00346
00347 typedef ArgStreamFirst first_type;
00348 typedef ArgStreamSecond second_type;
00349 ArgStreamFirst * first;
00350 ArgStreamSecond * second;
00351
00352 chain(ArgStreamFirst & first_stream, ArgStreamSecond & second_stream)
00353 :
00354 first(&first_stream),
00355 second(&second_stream)
00356 {
00357 }
00358
00359 template <typename T>
00360 T get_next_arg()
00361 {
00362 if (!eof(first))
00363 {
00364 try
00365 {
00366 return first->get_next_arg<T>();
00367 }
00368 catch(arg_stream::no_more_args &)
00369 {
00370 first = 0;
00371 }
00372 }
00373
00374 return second->get_next_arg<T>();
00375 }
00376
00377 bool eof() const
00378 {
00379 return eof(first) && eof(second);
00380 }
00381 };
00382
00383 template <typename S1, typename S2>
00384 struct traits<chain<S1, S2> >
00385 {
00386 static const bool has_eof_memberfunction = true;
00387 };
00388
00392 template <typename ArgStreamFirst, typename ArgStreamSecond>
00393 chain<ArgStreamFirst, ArgStreamSecond> make_chain(ArgStreamFirst & first_stream, ArgStreamSecond & second_stream)
00394 {
00395 return chain<ArgStreamFirst, ArgStreamSecond>(first_stream, second_stream);
00396 }
00397
00401 struct nonarg
00402 {
00403 bool eof()
00404 {
00405 return true;
00406 }
00407
00408 template <typename R>
00409 R get_next_arg()
00410 {
00411 throw arg_stream::no_more_args();
00412
00413 return *(R*)32;
00414 }
00415 };
00416
00417 template<>
00418 struct traits<nonarg>
00419 {
00420 static const bool has_eof_memberfunction = true;
00421 };
00422
00427 template <typename T>
00428 struct single
00429 {
00430 typedef T value_type;
00431
00432 T value;
00433 unsigned int repeat;
00434
00435 single(typename boost::add_reference<T const>::type t, unsigned int count = 1) : value(t), repeat(count)
00436 {
00437 }
00438
00439 bool eof()
00440 {
00441 return repeat == 0;
00442 }
00443
00444 template <typename R>
00445 R convert_or_throw(value_type & value, typename boost::enable_if<boost::is_convertible<value_type, R> >::type * dummy = 0)
00446 {
00447 return R(value);
00448 }
00449 template <typename R>
00450 R convert_or_throw(value_type & value, typename boost::disable_if<boost::is_convertible<value_type, R> >::type * dummy = 0)
00451 {
00452 throw adobe::bad_cast();
00453 return *(R*)value;
00454 }
00455
00456 template <typename R>
00457 R get_next_arg()
00458 {
00459 if (repeat)
00460 {
00461 repeat--;
00462 }
00463 else
00464 {
00465 throw arg_stream::no_more_args();
00466 }
00467
00468 return convert_or_throw<R>(value);
00469 }
00470 };
00471
00472 template<typename T>
00473 struct traits<single<T> >
00474 {
00475 static const bool has_eof_memberfunction = true;
00476 };
00477
00478 template <typename ArgStream, typename Transformer>
00479 struct with_transform
00480 {
00481 ADOBE_HAS_TEMPLATE1_IMPL(arg_stream_inverse_lookup);
00482
00483 template <typename Class>
00484 struct has_inverse_lookup
00485 {
00486 static const bool value = ADOBE_HAS_TEMPLATE1(Class, arg_stream_inverse_lookup);
00487 };
00488
00489 template <typename Class, typename R, bool>
00490 struct has_entry_if_has_inverse_lookup
00491 {
00492 static const bool value = false;
00493 };
00494 template <typename Class, typename R>
00495 struct has_entry_if_has_inverse_lookup<Class, R, true>
00496 {
00497 static const bool value = has_type_type<typename Class::template arg_stream_inverse_lookup<R> >::value;
00498 };
00499
00500 template <typename Class, typename R>
00501 struct has_transform
00502 {
00503 static const bool value = has_entry_if_has_inverse_lookup<Class, R, has_inverse_lookup<Class>::value>::value;
00504 };
00505
00506 typedef ArgStream value_type;
00507 typedef ArgStream arg_stream_type;
00508 typedef Transformer transformer_type;
00509
00510 ArgStream & argstream;
00511 Transformer & transformer;
00512
00513 with_transform(ArgStream & as, Transformer & trans) : argstream(as), transformer(trans)
00514 {
00515 }
00516
00517 bool eof()
00518 {
00519 return detail::eof_check(argstream);
00520 }
00521
00522 template <typename R>
00523 R transforming_get(typename boost::enable_if<has_transform<Transformer, R> >::type * dummy = 0)
00524 {
00525 typedef typename Transformer::template arg_stream_inverse_lookup<R>::type Rfrom;
00526 return transformer.template arg_stream_transform<R>(arg_stream::get_next_arg<Rfrom>(argstream));
00527 }
00528 template <typename R>
00529 R transforming_get(typename boost::disable_if<has_transform<Transformer, R> >::type * dummy = 0)
00530 {
00531 return arg_stream::get_next_arg<R>(argstream);
00532 }
00533
00534 template <typename R>
00535 R get_next_arg()
00536 {
00537 return transforming_get<R>();
00538 }
00539 };
00540
00541 template <typename ArgStream, typename Transformer>
00542 with_transform<ArgStream, Transformer> make_transforming(ArgStream & as, Transformer & transformer)
00543 {
00544 return with_transform<ArgStream, Transformer>(as, transformer);
00545 }
00546
00547 }
00548 }
00549
00550
00551 #endif // include_guard