Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 SequenceTypeInfo.hpp 00003 00004 SequenceTypeInfo.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_SEQUENCE_TYPE_INFO_BASE_HPP 00040 #define ORO_SEQUENCE_TYPE_INFO_BASE_HPP 00041 00042 #include "PrimitiveTypeInfo.hpp" 00043 #include "SequenceConstructor.hpp" 00044 #include "TemplateConstructor.hpp" 00045 #include "PropertyComposition.hpp" 00046 #include "PropertyDecomposition.hpp" 00047 #include "../internal/FusedFunctorDataSource.hpp" 00048 #include "../internal/DataSourceGenerator.hpp" 00049 #include <boost/lexical_cast.hpp> 00050 00051 namespace RTT 00052 { 00053 namespace types 00054 { 00060 template<class T> 00061 int get_capacity(T const& cont) 00062 { 00063 return cont.capacity(); 00064 } 00065 00071 template<class T> 00072 int get_size(T const& cont) 00073 { 00074 return cont.size(); 00075 } 00076 00084 template<class T> 00085 typename T::reference get_container_item(T & cont, int index) 00086 { 00087 if (index >= (int) (cont.size()) || index < 0) 00088 return internal::NA<typename T::reference>::na(); 00089 return cont[index]; 00090 } 00091 00099 template<class T> 00100 typename T::value_type get_container_item_copy(const T & cont, int index) 00101 { 00102 if (index >= (int) (cont.size()) || index < 0) 00103 return internal::NA<typename T::value_type>::na(); 00104 return cont[index]; 00105 } 00106 00115 bool get_container_item(std::vector<bool> & cont, int index); 00116 bool get_container_item_copy(const std::vector<bool> & cont, int index); 00117 00125 template<typename T> 00126 class SequenceTypeInfoBase 00127 { 00128 public: 00129 SequenceTypeInfoBase(TypeInfo* tbase) 00130 { 00131 tbase->addConstructor( new SequenceBuilder<T>() ); 00132 tbase->addConstructor( newConstructor( sequence_ctor<T>() ) ); 00133 tbase->addConstructor( newConstructor( sequence_ctor2<T>() ) ); 00134 } 00135 00136 ~SequenceTypeInfoBase() {} 00137 00138 base::AttributeBase* buildVariable(std::string name,int size) const 00139 { 00140 // if a sizehint is given 00141 T t_init(size, typename T::value_type() ); 00142 00143 return new Attribute<T>( name, new internal::UnboundDataSource<internal::ValueDataSource<T> >( t_init ) ); 00144 } 00145 00146 bool resize(base::DataSourceBase::shared_ptr arg, int size) const 00147 { 00148 if (arg->isAssignable()) { 00149 typename internal::AssignableDataSource<T>::shared_ptr asarg = internal::AssignableDataSource<T>::narrow( arg.get() ); 00150 asarg->set().resize( size ); 00151 asarg->updated(); 00152 return true; 00153 } 00154 return false; 00155 } 00156 00160 bool composeType( base::DataSourceBase::shared_ptr dssource, base::DataSourceBase::shared_ptr dsresult) const { 00161 const internal::DataSource<PropertyBag>* pb = dynamic_cast< const internal::DataSource<PropertyBag>* > (dssource.get() ); 00162 if ( !pb ) 00163 return false; 00164 typename internal::AssignableDataSource<T>::shared_ptr ads = boost::dynamic_pointer_cast< internal::AssignableDataSource<T> >( dsresult ); 00165 if ( !ads ) 00166 return false; 00167 00168 PropertyBag const& source = pb->rvalue(); 00169 typename internal::AssignableDataSource<T>::reference_t result = ads->set(); 00170 00171 // take into account sequences: 00172 base::PropertyBase* sz = source.find("Size"); 00173 if (!sz) 00174 sz = source.find("size"); 00175 if (sz) 00176 { 00177 internal::DataSource<int>::shared_ptr sz_ds = internal::DataSource<int>::narrow(sz->getDataSource().get()); 00178 if (sz_ds) 00179 result.resize( sz_ds->get() ); 00180 } 00181 else 00182 { 00183 // no size found, inform parent of number of elements to come: 00184 result.resize( source.size() ); 00185 } 00186 // recurse into items of this sequence: 00187 PropertyBag target( source.getType() ); 00188 PropertyBag decomp; 00189 internal::ReferenceDataSource<T> rds(result); 00190 rds.ref(); // prevent dealloc. 00191 // we compose each item in this sequence and then update result with target's result. 00192 // 1. each child is composed into target (this is a recursive thing) 00193 // 2. we decompose result one-level deep and 'refresh' it with the composed children of step 1. 00194 if ( composePropertyBag(source, target) && typeDecomposition( &rds, decomp, false) && ( decomp.getType() == target.getType() ) && refreshProperties(decomp, target, true) ) { 00195 assert(result.size() == source.size()); 00196 assert(source.size() == target.size()); 00197 assert(source.size() == decomp.size()); 00198 ads->updated(); 00199 Logger::log() <<Logger::Debug<<"Successfuly composed type from "<< source.getType() <<Logger::endl; 00200 return true; 00201 } 00202 return false; 00203 } 00204 00208 base::DataSourceBase::shared_ptr decomposeType(base::DataSourceBase::shared_ptr source) const 00209 { 00210 return base::DataSourceBase::shared_ptr(); 00211 } 00212 00213 00214 std::vector<std::string> getMemberNames() const { 00215 // only discover the parts of this struct: 00216 std::vector<std::string> result; 00217 result.push_back("size"); 00218 result.push_back("capacity"); 00219 return result; 00220 } 00221 00222 base::DataSourceBase::shared_ptr getMember(base::DataSourceBase::shared_ptr item, const std::string& name) const { 00223 // the only thing we do is to check for an integer in name, otherwise, assume a part (size/capacity) is accessed: 00224 try { 00225 unsigned int indx = boost::lexical_cast<unsigned int>(name); 00226 // @todo could also return a direct reference to item indx using another DS type that respects updated(). 00227 return getMember( item, new internal::ConstantDataSource<int>(indx)); 00228 } catch(...) {} 00229 00230 return getMember( item, new internal::ConstantDataSource<std::string>(name) ); 00231 } 00232 00233 base::DataSourceBase::shared_ptr getMember(base::DataSourceBase::shared_ptr item, 00234 base::DataSourceBase::shared_ptr id) const { 00235 // discover if user gave us a part name or index: 00236 typename internal::DataSource<int>::shared_ptr id_indx = internal::DataSource<int>::narrow( internal::DataSourceTypeInfo<int>::getTypeInfo()->convert(id).get() ); 00237 typename internal::DataSource<std::string>::shared_ptr id_name = internal::DataSource<std::string>::narrow( id.get() ); 00238 if ( id_name ) { 00239 if ( id_name->get() == "size" ) { 00240 try { 00241 return internal::newFunctorDataSource(&get_size<T>, internal::GenerateDataSource()(item.get()) ); 00242 } catch(...) {} 00243 } 00244 if ( id_name->get() == "capacity" ) { 00245 try { 00246 return internal::newFunctorDataSource(&get_capacity<T>, internal::GenerateDataSource()(item.get()) ); 00247 } catch(...) {} 00248 } 00249 } 00250 00251 if ( id_indx ) { 00252 try { 00253 if ( item->isAssignable() ) 00254 return internal::newFunctorDataSource(&get_container_item<T>, internal::GenerateDataSource()(item.get(), id_indx.get() ) ); 00255 else 00256 return internal::newFunctorDataSource(&get_container_item_copy<T>, internal::GenerateDataSource()(item.get(), id_indx.get() ) ); 00257 } catch(...) {} 00258 } 00259 if (id_name) { 00260 log(Error) << "SequenceTypeInfo: No such member : " << id_name->get() << endlog(); 00261 } 00262 if (id_indx) { 00263 log(Error) << "SequenceTypeInfo: Invalid index : " << id_indx->get() <<":"<< id_indx->getTypeName() << endlog(); 00264 } 00265 if ( !id_name && ! id_indx) 00266 log(Error) << "SequenceTypeInfo: Not a member or index : " << id <<":"<< id->getTypeName() << endlog(); 00267 return base::DataSourceBase::shared_ptr(); 00268 } 00269 }; 00270 } 00271 } 00272 00273 #endif