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