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     };
00327 
00328     template< class T>
00329     struct AlwaysAssignChecker
00330         : public std::binary_function<T, T, bool>
00331     {
00332         bool operator()(const T&, const T& ) const
00333         {
00334             return true;
00335         }
00336     };
00337 
00338     template< class T>
00339     struct SizeAssignChecker
00340         : public std::binary_function<T, T, bool>
00341     {
00342         bool operator()(const T& v1, const T& v2) const
00343         {
00344             // v2 may be assigned to v1 if it has sufficient capacity.
00345             return v1.capacity() >= v2.size();
00346         }
00347     };
00348 
00349     // check the validity of an index
00350     template< class T>
00351     struct ArrayIndexChecker
00352         : public std::binary_function< T, int, bool>
00353     {
00354         bool operator()(const T& v, int i ) const
00355         {
00356             return i > -1 && i < (int)(v.size());
00357         }
00358     };
00359 
00360 #if 0
00361   // check the validity of an index
00362     template< class T>
00363     struct MultiVectorIndexChecker
00364         : public std::binary_function< T, int, bool>
00365     {
00366         bool operator()(const T& v, int i ) const
00367         {
00368             return i > -1 && i < T::size;
00369         }
00370     };
00371 #endif
00372 
00373   // check the validity of a fixed range index
00374     template< class T, int Range>
00375     struct RangeIndexChecker
00376         : public std::binary_function< T, int, bool>
00377     {
00378         bool operator()(const T& v, int i ) const
00379         {
00380             return i > -1 && i < Range;
00381         }
00382     };
00383 
00387     template<typename T, typename IndexType, typename SetType, typename IPred, typename APred, bool has_ostream>
00388     class TemplateContainerTypeInfo
00389         : public TemplateTypeInfo<T,has_ostream>
00390     {
00391         typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type _T;
00392     public:
00393         using TypeInfo::buildConstant;
00394         using TypeInfo::buildVariable;
00395 
00396         TemplateContainerTypeInfo(std::string name)
00397             : TemplateTypeInfo<T, has_ostream>(name) {}
00398 
00399         AttributeBase* buildVariable(std::string name) const
00400         {
00401             // no sizehint, but _do_ check IPred.
00402             return new Attribute<T>( name, new detail::UnboundDataSource<IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<_T> > >() );
00403         }
00404 
00405         DataSourceBase::shared_ptr buildValue() const
00406         {
00407             return new IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<_T> >();
00408         }
00409 
00410         AttributeBase* buildVariable(std::string name,int size) const
00411         {
00412             // if a sizehint is given, create a TaskIndexContainerVariable instead,
00413             // which checks capacities.
00414             _T t_init(size, SetType());
00415 
00416             return new Attribute<T>( name, new detail::UnboundDataSource<IndexedValueDataSource<T, IndexType, SetType, IPred, APred> >( t_init ) );
00417         }
00418     };
00419 
00423     template<typename T, typename IndexType, typename SetType, typename IPred, typename APred, bool has_ostream>
00424     class TemplateIndexTypeInfo
00425         : public TemplateTypeInfo<T,has_ostream>
00426     {
00427         typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type _T;
00428     public:
00429         using TypeInfo::buildConstant;
00430         using TypeInfo::buildVariable;
00431 
00432         TemplateIndexTypeInfo(std::string name)
00433             : TemplateTypeInfo<T, has_ostream>(name) {}
00434 
00435         AttributeBase* buildVariable(std::string name) const
00436         {
00437             // no sizehint, but _do_ check IPred.
00438             return new Attribute<T>( name, new detail::UnboundDataSource<IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<T> > >() );
00439         }
00440 
00441         DataSourceBase::shared_ptr buildValue() const
00442         {
00443             Logger::log() <<Logger::Debug << "Building Indexable value of "<< this->getTypeName()<<Logger::endl;
00444             return new IndexedValueDataSource<T, IndexType, SetType, IPred, AlwaysAssignChecker<T> >();
00445         }
00446 
00447     };
00448 
00449     namespace detail
00450     {
00456         template<class Signature, int>
00457         struct TemplateConstructor;
00458 
00459         template<class S>
00460         struct TemplateConstructor<S,1>
00461             : public TypeBuilder,
00462               public FunctorFactoryPart1<DataSourceBase*, DataSourceArgsMethod<S> >
00463         {
00464             typedef typename boost::function_traits<S>::result_type result_type;
00465             typedef typename boost::function_traits<S>::arg1_type arg1_type;
00466 
00467             bool automatic;
00468             template<class FInit>
00469             TemplateConstructor( FInit f, bool autom)
00470                 : FunctorFactoryPart1<DataSourceBase*, DataSourceArgsMethod<S> >(f ),
00471                 automatic(autom)
00472             {}
00473 
00474             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00475                 // these checks are necessary because produce(args) calls convert, which could lead to endless loops.
00476                 // detect same type converion.
00477                 if ( args.size() == 1 && args[0]->getTypeInfo() == DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00478                     return args[0];
00479                 }
00480                 // detect invalid type conversion.
00481                 if ( args.size() == 1 && args[0]->getTypeInfo() != DataSourceTypeInfo<arg1_type>::getTypeInfo() ) {
00482                     return DataSourceBase::shared_ptr();
00483                 }
00484                 try {
00485                     return this->produce( args );
00486                 } catch ( ... ) {
00487                 }
00488                 return DataSourceBase::shared_ptr();
00489             }
00490 
00491             virtual DataSourceBase::shared_ptr convert(DataSourceBase::shared_ptr arg) const {
00492                 // these checks are necessary because produce(args) calls convert, which could lead to endless loops.
00493                 // detect same type converion.
00494                 if ( arg->getTypeInfo() == DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00495                     return arg;
00496                 }
00497                 // detect invalid type conversion.
00498                 if ( arg->getTypeInfo() != DataSourceTypeInfo<arg1_type>::getTypeInfo() ) {
00499                     return DataSourceBase::shared_ptr();
00500                 }
00501                 // from now on, it should always succeed.
00502                 std::vector<DataSourceBase::shared_ptr> args;
00503                 args.push_back(arg);
00504                 DataSourceBase::shared_ptr ret = this->build(args);
00505                 if (ret && !automatic)
00506                     log(Warning) << "Conversion from " << arg->getTypeName() << " to " << ret->getTypeName() <<endlog();
00507                 return ret;
00508             }
00509         };
00510 
00511         template<class S>
00512         struct TemplateConstructor<S,2>
00513             : public TypeBuilder,
00514               public FunctorFactoryPart2<DataSourceBase*, DataSourceArgsMethod<S> >
00515         {
00516             template<class FInit>
00517             TemplateConstructor( FInit f, bool autom)
00518                 : FunctorFactoryPart2<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00519             {}
00520 
00521             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00522                 try {
00523                     return this->produce( args );
00524                 } catch ( ... ) {
00525                 }
00526                 return DataSourceBase::shared_ptr();
00527             }
00528 
00529         };
00530 
00531         template<class S>
00532         struct TemplateConstructor<S,3>
00533             : public TypeBuilder,
00534               public FunctorFactoryPart3<DataSourceBase*, DataSourceArgsMethod<S> >
00535         {
00536             template<class FInit>
00537             TemplateConstructor( FInit f, bool autom)
00538                 : FunctorFactoryPart3<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00539             {}
00540 
00541             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00542                 try {
00543                     return this->produce( args );
00544                 } catch ( ... ) {
00545                 }
00546                 return DataSourceBase::shared_ptr();
00547             }
00548 
00549         };
00550 
00551         template<class S>
00552         struct TemplateConstructor<S,4>
00553             : public TypeBuilder,
00554               public FunctorFactoryPart4<DataSourceBase*, DataSourceArgsMethod<S> >
00555         {
00556             template<class FInit>
00557             TemplateConstructor( FInit f, bool autom)
00558                 : FunctorFactoryPart4<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00559             {}
00560 
00561             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00562                 try {
00563                     return this->produce( args );
00564                 } catch ( ... ) {
00565                 }
00566                 return DataSourceBase::shared_ptr();
00567             }
00568 
00569         };
00570 
00571         template<class S>
00572         struct TemplateConstructor<S,6>
00573             : public TypeBuilder,
00574               public FunctorFactoryPart6<DataSourceBase*, DataSourceArgsMethod<S> >
00575         {
00576             template<class FInit>
00577             TemplateConstructor( FInit f, bool autom)
00578                 : FunctorFactoryPart6<DataSourceBase*, DataSourceArgsMethod<S> >(f )
00579             {}
00580 
00581             virtual DataSourceBase::shared_ptr build(const std::vector<DataSourceBase::shared_ptr>& args) const {
00582                 try {
00583                     return this->produce( args );
00584                 } catch ( ... ) {
00585                 }
00586                 return DataSourceBase::shared_ptr();
00587             }
00588 
00589         };
00590     }
00591 
00599     template<class Function>
00600     TypeBuilder* newConstructor( Function* foo, bool automatic = false ) {
00601         return new detail::TemplateConstructor<Function, boost::function_traits<Function>::arity>(foo, automatic);
00602     }
00603 
00612     template<class Object>
00613     TypeBuilder* newConstructor( Object obj, bool automatic = false) {
00614         return new detail::TemplateConstructor<typename Object::Signature, boost::function_traits<typename Object::Signature>::arity>(obj, automatic);
00615     }
00616 }
00617 
00618 #endif

Generated on Tue Aug 25 14:17:23 2009 for Orocos Real-Time Toolkit by  doxygen 1.5.8