Orocos Real-Time Toolkit  2.5.0
CreateSequence.hpp
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  CreateSequence.hpp
00003 
00004                         CreateSequence.hpp -  description
00005                            -------------------
00006     begin                : Tue September 07 2010
00007     copyright            : (C) 2010 The SourceWorks
00008     email                : peter@thesourceworks.com
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #ifndef ORO_CREATESEQUENCE_HPP_
00040 #define ORO_CREATESEQUENCE_HPP_
00041 
00042 #include <boost/fusion/include/cons.hpp>
00043 #include <boost/fusion/include/front.hpp>
00044 #include <boost/fusion/include/vector.hpp>
00045 
00046 #include <vector>
00047 #include <boost/mpl/front.hpp>
00048 #include <boost/mpl/pop_front.hpp>
00049 #include <boost/mpl/print.hpp>
00050 // The fusion <--> MPL link header
00051 #include <boost/fusion/mpl.hpp>
00052 #include <boost/utility/enable_if.hpp>
00053 
00054 #include "DataSource.hpp"
00055 #include "Exceptions.hpp"
00056 #include "../FactoryExceptions.hpp"
00057 #include "mystd.hpp"
00058 
00059 #include <iostream>
00060 
00061 namespace RTT
00062 {
00063     namespace internal
00064     {
00065         namespace bf = boost::fusion;
00066         namespace mpl = boost::mpl;
00067 
00068 
00069         template <class T> struct incomplete;
00070 
00075         template<class Seq, class Data, class Enable = void >
00076         struct GetArgument {
00077             Data operator()(Seq s) { bf::front(s)->evaluate(); return Data(bf::front(s)->rvalue()); /* front(s) is a DataSource<Data> */}
00078         }; // normal type
00079 
00083         template<class Seq, class Data>
00084         struct GetArgument<Seq, Data, typename boost::enable_if< is_pure_reference<Data> >::type> {
00085             Data operator()(Seq s) { return Data(bf::front(s)->set() ); /* Case of reference.*/ }
00086         }; // shared_ptr type
00087 
00092         template<class Seq, class Data, class Enable = void >
00093         struct AssignHelper {
00094             static void set( Seq seq, Data in) { bf::front(seq)->set( bf::front(in) ); }
00095         }; // normal type
00096 
00097         template<class Seq, class Data>
00098         struct AssignHelper<Seq, Data, typename boost::enable_if< boost::is_pointer<typename mpl::front<Data>::type> >::type> {
00099             static void set(Seq , Data ) {} // nop
00100         }; // shared_ptr type
00101 
00105         template<class T>
00106         struct UpdateHelper {
00107             static void update(typename DataSource<typename remove_cr<T>::type >::shared_ptr) {}
00108         };
00109 
00110         template<class T>
00111         struct UpdateHelper<T&> {
00112             static void update(typename DataSource<typename remove_cr<T>::type >::shared_ptr s) { s->updated(); }
00113         };
00114 
00119         struct create_sequence_helper {
00120             template<class ds_arg_type, class ds_type>
00121             static ds_type sources(std::vector<base::DataSourceBase::shared_ptr>::const_iterator front, int argnbr, std::string const& tname )
00122             {
00123                 typedef typename ds_type::element_type element_type;
00124 
00125                 ds_type a =
00126                     boost::dynamic_pointer_cast< element_type >( DataSourceTypeInfo<ds_arg_type>::getTypeInfo()->convert(*front) );
00127                 if ( ! a ) {
00128                     //cout << typeid(DataSource<ds_arg_type>).name() << endl;
00129                     ORO_THROW_OR_RETURN(wrong_types_of_args_exception( argnbr, tname, (*front)->getType() ), ds_type());
00130                     //ORO_THROW_OR_RETURN(wrong_types_of_args_exception( argnbr, typeid(DataSource<ds_arg_type>).name(), typeid(front).name() ), type());
00131                 }
00132                 return a;
00133             }
00134 
00135             template<class ds_arg_type, class ads_type>
00136             static ads_type assignable(std::vector<base::DataSourceBase::shared_ptr>::const_iterator front, int argnbr, std::string const& tname )
00137             {
00138                 typedef typename ads_type::element_type element_type;
00139 
00140                 ads_type a =
00141                     boost::dynamic_pointer_cast< AssignableDataSource<ds_arg_type> >( *front ); // note: no conversion done, must be same type.
00142                 if ( ! a ) {
00143                     ORO_THROW_OR_RETURN(wrong_types_of_args_exception( argnbr, tname, (*front)->getType() ), ads_type());
00144                 }
00145                 return a;
00146             }
00147         };
00148 
00149         template<class List, int size>
00150         struct create_sequence_impl;
00151 
00180         template<class List>
00181         struct create_sequence: public create_sequence_impl<List, mpl::size<
00182                 List>::value>
00183         {
00184         };
00185 
00186         template<class List, int size>
00187         struct create_sequence_impl
00188         {
00192             typedef create_sequence<typename mpl::pop_front<List>::type> tail;
00193 
00197             typedef typename mpl::front<List>::type arg_type;
00198 
00202             typedef typename remove_cr<arg_type>::type ds_arg_type;
00203 
00207             typedef typename mpl::if_<typename is_pure_reference<arg_type>::type,
00208                     typename AssignableDataSource< ds_arg_type >::shared_ptr,
00209                     typename DataSource<ds_arg_type>::shared_ptr>::type ds_type;
00210 
00211             typedef typename AssignableDataSource< ds_arg_type >::shared_ptr ads_type;
00212 
00217             typedef typename tail::type tail_type;
00218 
00222             typedef bf::cons<ds_type, tail_type> type;
00223 
00224             typedef typename tail::atype atail_type;
00225             typedef bf::cons<ads_type, atail_type> atype;
00226 
00227             typedef typename tail::data_type arg_tail_type;
00228 
00232             typedef bf::cons<arg_type, arg_tail_type> data_type;
00233 
00242             static type sources(std::vector<base::DataSourceBase::shared_ptr>::const_iterator args, int argnbr = 1 )
00243             {
00244                 std::vector<base::DataSourceBase::shared_ptr>::const_iterator next = args;
00245                 return bf::cons<ds_type, tail_type>
00246                     (create_sequence_helper::sources<ds_arg_type, ds_type>(args, argnbr, DataSourceTypeInfo<arg_type>::getType()),
00247                      tail::sources( ++next, argnbr + 1));
00248             }
00249 
00258             static atype assignable(std::vector<base::DataSourceBase::shared_ptr>::const_iterator args, int argnbr = 1 )
00259             {
00260                 std::vector<base::DataSourceBase::shared_ptr>::const_iterator next = args;
00261                 return atype(
00262                         create_sequence_helper::assignable<ds_arg_type, ads_type>(args, argnbr, DataSourceTypeInfo<arg_type>::getType()),
00263                         tail::assignable(++next, argnbr + 1));
00264             }
00265 
00272             static data_type data(const type& seq) {
00273                 return data_type( GetArgument<type,arg_type>()(seq), tail::data( bf::pop_front(seq) ) );
00274             }
00275 
00282             static void set(const data_type& in, const atype& seq) {
00283                 AssignHelper<atype, data_type>::set(seq, in);
00284                 return tail::set( bf::pop_front(in), bf::pop_front(seq) );
00285             }
00286 
00292             static void update(const type&seq) {
00293                 UpdateHelper<arg_type>::update( bf::front(seq) );
00294                 return tail::update( bf::pop_front(seq) );
00295             }
00296 
00304             static type copy(const type& seq, std::map<
00305                               const base::DataSourceBase*,
00306                               base::DataSourceBase*>& alreadyCloned) {
00307                 return type( bf::front(seq)->copy(alreadyCloned), tail::copy( bf::pop_front(seq), alreadyCloned ) );
00308             }
00309 
00317             static const types::TypeInfo* GetTypeInfo(int i) {
00318                 if ( i <= 0 || i > size)
00319                     return 0;
00320                 if ( i == 1 ) {
00321                     return DataSourceTypeInfo<arg_type>::getTypeInfo();
00322                 } else {
00323                     return tail::GetTypeInfo(i-1);
00324                 }
00325             }
00326 
00334             static std::string GetType(int i) {
00335                 if ( i <= 0 || i > size)
00336                     return "na";
00337                 if ( i == 1 ) {
00338                     return DataSourceTypeInfo<arg_type>::getType();
00339                 } else {
00340                     return tail::GetType(i-1);
00341                 }
00342             }
00343 };
00344 
00345         template<class List>
00346         struct create_sequence_impl<List, 1> // mpl list of one
00347         {
00348             typedef typename mpl::front<List>::type arg_type;
00349             typedef typename remove_cr<arg_type>::type ds_arg_type;
00350             typedef bf::cons<arg_type> data_type;
00351 
00355             typedef typename mpl::if_<typename is_pure_reference<arg_type>::type,
00356                     typename AssignableDataSource< ds_arg_type >::shared_ptr,
00357                     typename DataSource<ds_arg_type>::shared_ptr>::type ds_type;
00358             typedef typename AssignableDataSource< ds_arg_type >::shared_ptr ads_type;
00359 
00360 
00361             // the result sequence type is a cons of the last argument in the vector.
00362             typedef bf::cons<ds_type> type;
00363 
00364             typedef bf::cons<ads_type> atype;
00365 
00366             static type sources(std::vector<base::DataSourceBase::shared_ptr>::const_iterator front, int argnbr = 1)
00367             {
00368                 return type(
00369                         create_sequence_helper::sources<ds_arg_type, ds_type>(front, argnbr, DataSourceTypeInfo<arg_type>::getType()));
00370             }
00371 
00372             static atype assignable(std::vector<base::DataSourceBase::shared_ptr>::const_iterator args, int argnbr = 1)
00373             {
00374                 return atype(
00375                         create_sequence_helper::assignable<ds_arg_type, ads_type>(args, argnbr, DataSourceTypeInfo<arg_type>::getType()));
00376             }
00377 
00384             static data_type data(const type& seq) {
00385                 return data_type( GetArgument<type,arg_type>()(seq) );
00386             }
00387 
00388             static void update(const type&seq) {
00389                 UpdateHelper<arg_type>::update( bf::front(seq) );
00390                 return;
00391             }
00392 
00393             static void set(const data_type& in, const atype& seq) {
00394                 AssignHelper<atype, data_type>::set(seq, in);
00395             }
00396 
00404             static type copy(const type& seq, std::map<
00405                               const base::DataSourceBase*,
00406                               base::DataSourceBase*>& alreadyCloned) {
00407                 return type( bf::front(seq)->copy(alreadyCloned) );
00408             }
00409 
00410             static const types::TypeInfo* GetTypeInfo(int i) {
00411                 if ( i != 1)
00412                     return 0;
00413                 return DataSource<ds_arg_type>::GetTypeInfo();
00414             }
00415             static std::string GetType(int i) {
00416                 if ( i != 1)
00417                     return "na";
00418                 return DataSourceTypeInfo<arg_type>::getType();
00419             }
00420         };
00421 
00422         template<class List>
00423         struct create_sequence_impl<List, 0> // empty mpl list
00424         {
00425             typedef bf::vector<> data_type;
00426 
00427             // the result sequence type is a cons of the last argument in the vector.
00428             typedef bf::vector<> type;
00429 
00430             typedef bf::vector<> atype;
00431 
00432             static type sources(std::vector<base::DataSourceBase::shared_ptr>::const_iterator args, int argnbr = 0)
00433             {
00434                 return type();
00435             }
00436 
00437             static atype assignable(std::vector<base::DataSourceBase::shared_ptr>::const_iterator args, int argnbr = 0)
00438             {
00439                 return atype();
00440             }
00441 
00448             static data_type data(const type& seq) {
00449                 return data_type();
00450             }
00451 
00452             static void update(const type&seq) {
00453                 return;
00454             }
00455 
00456             static void set(const data_type& in, const atype& seq) {
00457                 return;
00458             }
00459 
00460 
00468             static type copy(const type& seq, std::map<
00469                               const base::DataSourceBase*,
00470                               base::DataSourceBase*>& alreadyCloned) {
00471                 return type();
00472             }
00473             static const types::TypeInfo* GetTypeInfo(int i) {
00474                 return 0;
00475             }
00476             static std::string GetType(int i) {
00477                 return "na";
00478             }
00479         };
00480     }
00481 }
00482 
00483 #endif /* ORO_CREATESEQUENCE_HPP_ */