TemplateTypeInfo.hpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 19 14:11:26 CET 2004  Types.hpp
00003 
00004                         Types.hpp -  description
00005                            -------------------
00006     begin                : Mon January 19 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
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 #ifndef ORO_TEMPLATE_TYPEINFO_HPP
00039 #define ORO_TEMPLATE_TYPEINFO_HPP
00040 
00041 #include "Types.hpp"
00042 #include "Property.hpp"
00043 #include "Attribute.hpp"
00044 #include "Logger.hpp"
00045 #include <ostream>
00046 #include "FunctorFactory.hpp"
00047 #include "DataSourceArgsMethod.hpp"
00048 
00049 #include <boost/type_traits/function_traits.hpp>
00050 #include "boost/function_types/function_type.hpp"
00051 #include "boost/function_types/function_type_signature.hpp"
00052 
00053 #include "rtt-config.h"
00054 
00055 namespace RTT
00056 {
00057     namespace detail {
00058         template<typename T, bool b_value>
00059         struct TypeStreamSelector;
00060         template<typename T>
00061         struct TypeStreamSelector<T,true>
00062         {
00063             static std::ostream& write(std::ostream& os, T t)
00064             {
00065 #ifdef OS_HAVE_STREAMS
00066                 os << t;
00067 #endif
00068                 return os;
00069             }
00070             static std::istream& read(std::istream& os, T& t)
00071             {
00072 #ifdef OS_HAVE_STREAMS
00073                 os >> t;
00074 #endif
00075                 return os;
00076             }
00077         };
00078         template<typename T>
00079         struct TypeStreamSelector<T,false>
00080         {
00081             static std::ostream& write(std::ostream& os, T)
00082             {
00083                 return os;
00084             }
00085             static std::istream& read(std::istream& os, T& )
00086             {
00087                 return os;
00088             }
00089         };
00090     }
00091 
00160     template<typename T, bool use_ostream = false> //, typename ParamT = T>
00161     class TemplateTypeInfo
00162         : public TypeInfo
00163     {
00164         const std::string tname;
00165     public:
00166         using TypeInfo::buildConstant;
00167         using TypeInfo::buildVariable;
00168 
00172         typedef T UserType;
00176         typedef typename Property<T>::DataSourceType PropertyType;
00177 
00185         TemplateTypeInfo(std::string name)
00186             : tname(name)
00187         {
00188             // Install the type info object for T.
00189             if ( detail::DataSourceTypeInfo<T>::value_type_info::TypeInfoObject != 0) {
00190                 Logger::log() << Logger::Warning << "Overriding TypeInfo for '"
00191                               << detail::DataSourceTypeInfo<T>::value_type_info::TypeInfoObject->getTypeName()
00192                               << "'." << Logger::endl;
00193             }
00194             detail::DataSourceTypeInfo<T>::value_type_info::TypeInfoObject = this;
00195 
00196         }
00197 
00198         AttributeBase* buildConstant(std::string name, DataSourceBase::shared_ptr dsb) const
00199         {
00200             typename DataSource<PropertyType>::shared_ptr res =
00201                 AdaptDataSource<PropertyType>()( detail::DataSourceTypeInfo<PropertyType>::getTypeInfo()->convert(dsb));
00202             if ( res ) {
00203                 res->get();
00204                 Logger::log() << Logger::Info << "Building "<<tname<<" Constant '"<<name<<"' with value "<< dsb->getTypeInfo()->toString(dsb) <<Logger::endl;
00205                 return new Constant<PropertyType>( name, res->value() );
00206             }
00207             else
00208                 return 0;
00209         }
00210 
00211         AttributeBase* buildVariable(std::string name) const
00212         {
00213             // A variable starts its life as unbounded.
00214             Logger::log() << Logger::Debug << "Building variable '"<<name <<"' of type " << tname <<Logger::endl;
00215             return new Attribute<T>( name, new detail::UnboundDataSource<ValueDataSource<T> >() );
00216         }
00217 
00218         AttributeBase* buildAttribute( std::string name, DataSourceBase::shared_ptr in) const
00219         {
00220             typename AssignableDataSource<PropertyType>::shared_ptr ds;
00221             if ( !in )
00222                 ds = new ValueDataSource<PropertyType>();
00223             else
00224                 ds = AssignableDataSource<PropertyType>::narrow( in.get() );
00225             if (!ds)
00226                 return 0;
00227             // A variable starts its life as unbounded.
00228             Logger::log() << Logger::Debug << "Building Attribute '"<< name <<"' of type " << tname <<Logger::endl;
00229             return new Attribute<PropertyType>( name, ds.get() );
00230         }
00231 
00232         AttributeBase* buildAlias(std::string name, DataSourceBase::shared_ptr in ) const
00233         {
00234             typename DataSource<T>::shared_ptr ds = AdaptDataSource<T>()( detail::DataSourceTypeInfo<T>::getTypeInfo()->convert(in) );
00235             if ( ! ds )
00236                 return 0;
00237             return new Alias<T>( name, ds );
00238         }
00239 
00240         virtual const std::string& getTypeName() const { return tname; }
00241 
00242         virtual PropertyBase* buildProperty(const std::string& name, const std::string& desc, DataSourceBase::shared_ptr source = 0) const {
00243             if (source) {
00244                typename AssignableDataSource<PropertyType>::shared_ptr ad
00245                     = AdaptAssignableDataSource<PropertyType>()( source );
00246                 if (ad)
00247                     return new Property<PropertyType>(name, desc, ad );
00248                 // else ?
00249             }
00250             return new Property<PropertyType>(name, desc);
00251         }
00252 
00253         virtual DataSourceBase::shared_ptr buildValue() const {
00254             return new ValueDataSource<PropertyType>();
00255         }
00256 
00257         virtual std::ostream& write( std::ostream& os, DataSourceBase::shared_ptr in ) const {
00258             typename DataSource<T>::shared_ptr d = AdaptDataSource<T>()( in );
00259             if ( d && use_ostream )
00260                 detail::TypeStreamSelector<T, use_ostream>::write( os, d->value() );
00261             else {
00262 #ifdef OS_HAVE_STREAMS
00263                 std::string output = std::string("(")+ in->getTypeName() +")";
00264                 os << output;
00265 #endif
00266             }
00267             return os;
00268             //return os << "("<< tname <<")"
00269         }
00270 
00271         virtual std::istream& read( std::istream& os, DataSourceBase::shared_ptr out ) const {
00272             typename AssignableDataSource<T>::shared_ptr d = AdaptAssignableDataSource<T>()( out );
00273             if ( d && use_ostream ) {
00274                 detail::TypeStreamSelector<T, use_ostream>::read( os, d->set() );
00275                 d->updated(); // because use of set().
00276             }
00277             return os;
00278         }
00279 
00280         virtual bool decomposeType( DataSourceBase::shared_ptr source, PropertyBag& targetbag ) const {
00281             // Extract typed values
00282             typename DataSource<PropertyType>::shared_ptr ds = AdaptDataSource<PropertyType>()( source.get() );
00283             if ( !ds )
00284                 return false; // happens in the case of 'unknown type'
00285             // Try user's function.
00286             return decomposeTypeImpl( ds->get(), targetbag );
00287         }
00288 
00292         virtual bool decomposeTypeImpl( typename AssignableDataSource<T>::const_reference_t source, PropertyBag& targetbag ) const {
00293             return false;
00294         }
00295 
00296         virtual bool composeType( DataSourceBase::shared_ptr source, DataSourceBase::shared_ptr result) const {
00297             // First, try a plain update.
00298             if ( result->update( source.get() ) )
00299                 return true;
00300 
00301             // Did not work, maybe the type needs to be composed.
00302             const DataSource<PropertyBag>* pb = dynamic_cast< const DataSource<PropertyBag>* > (source.get() );
00303             if ( !pb )
00304                 return false;
00305             typename AssignableDataSource<PropertyType>::shared_ptr ads = AdaptAssignableDataSource<PropertyType>()( result.get() );
00306             if ( !ads )
00307                 return false;
00308 
00309             if ( composeTypeImpl( pb->value(), ads->set() ) )
00310                 ads->updated();
00311             else {
00312                 Logger::log() <<Logger::Debug<<"Failed to compose from "<< source->getTypeName() <<Logger::endl;
00313                 return false;
00314             }
00315             Logger::log() <<Logger::Debug<<"Successfuly composed type from "<< source->getTypeName() <<Logger::endl;
00316             return true;
00317         }
00318 
00322         virtual bool composeTypeImpl(const PropertyBag& source,  typename AssignableDataSource<T>::reference_t result) const {
00323             return false;
00324         }
00325         
00326         std::string getTypeIdName() const { return typeid(T).name(); }
00327 
00328     };
00329 
00330     template< class T>
00331     struct AlwaysAssignChecker
00332         : public std::binary_function<T, T, bool>
00333     {
00334         bool operator()(const T&, const T& ) const
00335         {
00336             return true;
00337         }
00338     };
00339 
00340     template< class T>
00341     struct SizeAssignChecker
00342         : public std::binary_function<T, T, bool>
00343     {
00344         bool operator()(const T& v1, const T& v2) const
00345         {
00346             // v2 may be assigned to v1 if it has sufficient capacity.
00347             return v1.capacity() >= v2.size();
00348         }
00349     };
00350 
00351     // check the validity of an index
00352     template< class T>
00353     struct ArrayIndexChecker
00354         : public std::binary_function< T, int, bool>
00355     {
00356         bool operator()(const T& v, int i ) const
00357         {
00358             return i > -1 && i < (int)(v.size());
00359         }
00360     };
00361 
00362 #if 0
00363   // check the validity of an index
00364     template< class T>
00365     struct MultiVectorIndexChecker
00366         : public std::binary_function< T, int, bool>
00367     {
00368         bool operator()(const T& v, int i ) const
00369         {
00370             return i > -1 && i < T::size;
00371         }
00372     };
00373 #endif
00374 
00375   // check the validity of a fixed range index
00376     template< class T, int Range>
00377     struct RangeIndexChecker
00378         : public std::binary_function< T, int, bool>
00379     {
00380         bool operator()(const T& v, int i ) const
00381         {
00382             return i > -1 && i < Range;
00383         }
00384     };
00385 
00389     template<typename T, typename IndexType, typename SetType, typename IPred, typename APred, bool has_ostream>
00390     class TemplateContainerTypeInfo
00391         : public TemplateTypeInfo<T,has_ostream>
00392     {
00393         typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type _T;
00394     public:
00395         using TemplateTypeInfo<T,has_ostream>::buildConstant;
00396         using TemplateTypeInfo<T,has_ostream>::buildVariable;
00397 
00398         TemplateContainerTypeInfo(std::string name)
00399             : TemplateTypeInfo<T, has_ostream>(name) {}
00400 
00401         AttributeBase* buildVariable(std::string name) const
00402         {
00403             // no sizehint, but _do_ check IPred.
00404             return new Attribute<T>( name, new detail::UnboundDataSource<IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<_T> > >() );
00405         }
00406 
00407         DataSourceBase::shared_ptr buildValue() const
00408         {
00409             return new IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<_T> >();
00410         }
00411 
00412         AttributeBase* buildVariable(std::string name,int size) const
00413         {
00414             // if a sizehint is given, create a TaskIndexContainerVariable instead,
00415             // which checks capacities.
00416             _T t_init(size, SetType());
00417 
00418             return new Attribute<T>( name, new detail::UnboundDataSource<IndexedValueDataSource<T, IndexType, SetType, IPred, APred> >( t_init ) );
00419         }
00420     };
00421 
00425     template<typename T, typename IndexType, typename SetType, typename IPred, typename APred, bool has_ostream>
00426     class TemplateIndexTypeInfo
00427         : public TemplateTypeInfo<T,has_ostream>
00428     {
00429         typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type _T;
00430     public:
00431         using TemplateTypeInfo<T,has_ostream>::buildConstant;
00432         using TemplateTypeInfo<T,has_ostream>::buildVariable;
00433 
00434         TemplateIndexTypeInfo(std::string name)
00435             : TemplateTypeInfo<T, has_ostream>(name) {}
00436 
00437         AttributeBase* buildVariable(std::string name) const
00438         {
00439             // no sizehint, but _do_ check IPred.
00440             return new Attribute<T>( name, new detail::UnboundDataSource<IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<T> > >() );
00441         }
00442 
00443         DataSourceBase::shared_ptr buildValue() const
00444         {
00445             Logger::log() <<Logger::Debug << "Building Indexable value of "<< this->getTypeName()<<Logger::endl;
00446             return new IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<T> >();
00447         }
00448 
00449     };
00450 
00451     namespace detail
00452     {
00458         template<class Signature, int>
00459         struct TemplateConstructor;
00460 
00461         template<class S>
00462         struct TemplateConstructor<S,1>
00463             : public TypeBuilder,
00464               public FunctorFactoryPart1<DataSourceBase*, DataSourceArgsMethod<S> >
00465         {
00466             typedef typename boost::function_traits<S>::result_type result_type;
00467             typedef typename boost::function_traits<S>::arg1_type arg1_type;
00468 
00469             bool automatic;
00470             template<class FInit>
00471             TemplateConstructor( FInit f, bool autom)
00472                 : FunctorFactoryPart1<DataSourceBase*, DataSourceArgsMethod<S> >(f ),
00473                 automatic(autom)
00474             {}
00475 
00476             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00477                 // these checks are necessary because produce(args) calls convert, which could lead to endless loops.
00478                 // detect same type converion.
00479                 if ( args.size() == 1 && args[0]->getTypeInfo() == DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00480                     return args[0];
00481                 }
00482                 // detect invalid type conversion.
00483                 if ( args.size() == 1 && args[0]->getTypeInfo() != DataSourceTypeInfo<arg1_type>::getTypeInfo() ) {
00484                     return DataSourceBase::shared_ptr();
00485                 }
00486                 try {
00487                     return this->produce( args );
00488                 } catch ( ... ) {
00489                 }
00490                 return DataSourceBase::shared_ptr();
00491             }
00492 
00493             virtual DataSourceBase::shared_ptr convert(DataSourceBase::shared_ptr arg) const {
00494                 // these checks are necessary because produce(args) calls convert, which could lead to endless loops.
00495                 // detect same type converion.
00496                 if ( arg->getTypeInfo() == DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00497                     return arg;
00498                 }
00499                 // detect invalid type conversion.
00500                 if ( arg->getTypeInfo() != DataSourceTypeInfo<arg1_type>::getTypeInfo() ) {
00501                     return DataSourceBase::shared_ptr();
00502                 }
00503                 // from now on, it should always succeed.
00504                 std::vector<DataSourceBase::shared_ptr> args;
00505                 args.push_back(arg);
00506                 DataSourceBase::shared_ptr ret = this->build(args);
00507                 if (ret && !automatic)
00508                     log(Warning) << "Conversion from " << arg->getTypeName() << " to " << ret->getTypeName() <<endlog();
00509                 return ret;
00510             }
00511         };
00512 
00513         template<class S>
00514         struct TemplateConstructor<S,2>
00515             : public TypeBuilder,
00516               public FunctorFactoryPart2<DataSourceBase*, DataSourceArgsMethod<S> >
00517         {
00518             template<class FInit>
00519             TemplateConstructor( FInit f, bool autom)
00520                 : FunctorFactoryPart2<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00521             {}
00522 
00523             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00524                 try {
00525                     return this->produce( args );
00526                 } catch ( ... ) {
00527                 }
00528                 return DataSourceBase::shared_ptr();
00529             }
00530 
00531         };
00532 
00533         template<class S>
00534         struct TemplateConstructor<S,3>
00535             : public TypeBuilder,
00536               public FunctorFactoryPart3<DataSourceBase*, DataSourceArgsMethod<S> >
00537         {
00538             template<class FInit>
00539             TemplateConstructor( FInit f, bool autom)
00540                 : FunctorFactoryPart3<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00541             {}
00542 
00543             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00544                 try {
00545                     return this->produce( args );
00546                 } catch ( ... ) {
00547                 }
00548                 return DataSourceBase::shared_ptr();
00549             }
00550 
00551         };
00552 
00553         template<class S>
00554         struct TemplateConstructor<S,4>
00555             : public TypeBuilder,
00556               public FunctorFactoryPart4<DataSourceBase*, DataSourceArgsMethod<S> >
00557         {
00558             template<class FInit>
00559             TemplateConstructor( FInit f, bool autom)
00560                 : FunctorFactoryPart4<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00561             {}
00562 
00563             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00564                 try {
00565                     return this->produce( args );
00566                 } catch ( ... ) {
00567                 }
00568                 return DataSourceBase::shared_ptr();
00569             }
00570 
00571         };
00572 
00573         template<class S>
00574         struct TemplateConstructor<S,6>
00575             : public TypeBuilder,
00576               public FunctorFactoryPart6<DataSourceBase*, DataSourceArgsMethod<S> >
00577         {
00578             template<class FInit>
00579             TemplateConstructor( FInit f, bool autom)
00580                 : FunctorFactoryPart6<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00581             {}
00582 
00583             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00584                 try {
00585                     return this->produce( args );
00586                 } catch ( ... ) {
00587                 }
00588                 return DataSourceBase::shared_ptr();
00589             }
00590 
00591         };
00592     }
00593 
00601     template<class Function>
00602     TypeBuilder* newConstructor( Function* foo, bool automatic = false ) {
00603         return new detail::TemplateConstructor<Function, boost::function_traits<Function>::arity>(foo, automatic);
00604     }
00605 
00614     template<class Object>
00615     TypeBuilder* newConstructor( Object obj, bool automatic = false) {
00616         return new detail::TemplateConstructor<typename Object::Signature, boost::function_traits<typename Object::Signature>::arity>(obj, automatic);
00617     }
00618 }
00619 
00620 #endif
Generated on Thu Dec 23 13:22:38 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3