00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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>
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
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
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
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
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
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();
00276 }
00277 return os;
00278 }
00279
00280 virtual bool decomposeType( DataSourceBase::shared_ptr source, PropertyBag& targetbag ) const {
00281
00282 typename DataSource<PropertyType>::shared_ptr ds = AdaptDataSource<PropertyType>()( source.get() );
00283 if ( !ds )
00284 return false;
00285
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
00298 if ( result->update( source.get() ) )
00299 return true;
00300
00301
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
00347 return v1.capacity() >= v2.size();
00348 }
00349 };
00350
00351
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
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
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
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
00415
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
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
00478
00479 if ( args.size() == 1 && args[0]->getTypeInfo() == DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00480 return args[0];
00481 }
00482
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
00495
00496 if ( arg->getTypeInfo() == DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00497 return arg;
00498 }
00499
00500 if ( arg->getTypeInfo() != DataSourceTypeInfo<arg1_type>::getTypeInfo() ) {
00501 return DataSourceBase::shared_ptr();
00502 }
00503
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