$search
00001 //================================================================================================= 00002 // Copyright (c) 2012, Johannes Meyer, TU Darmstadt 00003 // All rights reserved. 00004 00005 // Redistribution and use in source and binary forms, with or without 00006 // modification, are permitted provided that the following conditions are met: 00007 // * Redistributions of source code must retain the above copyright 00008 // notice, this list of conditions and the following disclaimer. 00009 // * Redistributions in binary form must reproduce the above copyright 00010 // notice, this list of conditions and the following disclaimer in the 00011 // documentation and/or other materials provided with the distribution. 00012 // * Neither the name of the Flight Systems and Automatic Control group, 00013 // TU Darmstadt, nor the names of its contributors may be used to 00014 // endorse or promote products derived from this software without 00015 // specific prior written permission. 00016 00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 //================================================================================================= 00028 00029 #ifndef CPP_INTROSPECTION_ACCESSOR_H 00030 #define CPP_INTROSPECTION_ACCESSOR_H 00031 00032 #include <introspection/message_template.h> 00033 #include <introspection/field.h> 00034 #include <introspection/field_traits.h> 00035 00036 #include <boost/type_traits.hpp> 00037 #include <boost/utility/enable_if.hpp> 00038 #include <boost/mpl/if.hpp> 00039 00040 namespace cpp_introspection { 00041 00042 class AccessorBase {}; 00043 00044 template <typename T> 00045 class Accessor : public AccessorBase, public MessageTemplate<typename boost::remove_const<T>::type> { 00046 public: 00047 using MessageTemplate<typename boost::remove_const<T>::type>::MessageType; 00048 typedef typename boost::is_const<T>::type is_const; 00049 00050 private: 00051 const Message& message_; 00052 boost::shared_ptr<T> instance_; 00053 V_Field fields_; 00054 M_Field fields_by_name_; 00055 00056 public: 00057 Accessor(const Message& message, const boost::shared_ptr<T>& instance) 00058 : message_(message) 00059 , instance_(instance) 00060 { 00061 fields_.reserve(message.size()); 00062 for(Message::const_iterator field = message.begin(); field != message.end(); ++field) { 00063 FieldPtr access = (*field)->access(*this); 00064 fields_.push_back(access); 00065 fields_by_name_[access->getName()] = access; 00066 } 00067 } 00068 virtual ~Accessor() {} 00069 00070 bool hasInstance() const { return instance_.get(); } 00071 VoidPtr getInstance() const { return is_const::value ? VoidPtr() : boost::const_pointer_cast<void>(getConstInstance()); } 00072 VoidConstPtr getConstInstance() const { return boost::shared_static_cast<void const>(instance_); } 00073 00074 T& instance() const { return *instance_; } 00075 00076 const char *getName() const { return message_.getName(); } 00077 00078 // const Package& package() const { return message_.package(); } 00079 const V_Field& fields() const { return fields_; } 00080 FieldWPtr field(const std::string& name) const { return fields_by_name_.at(name); } 00081 const V_FieldName& getFieldNames() const { return message_.getFieldNames(); } 00082 00083 void serialize(ros::serialization::OStream& stream, const VoidConstPtr&) const { message_.serialize(stream, getConstInstance()); } 00084 ros::SerializedMessage serialize(const VoidConstPtr&) const { return message_.serialize(getConstInstance()); } 00085 std::size_t serializationLength(const VoidConstPtr&) const { return message_.serializationLength(getConstInstance()); } 00086 VoidPtr deserialize(ros::serialization::IStream& stream, const VoidPtr&) const { return is_const::value ? VoidPtr() : message_.deserialize(stream, getInstance()); } 00087 00088 00089 private: 00090 template <typename FieldType> 00091 class FieldAccess : public FieldType { 00092 private: 00093 const Accessor& accessor_; 00094 mutable V_Message expanded_; 00095 typedef typename boost::mpl::if_<boost::is_const<T>, const typename FieldType::field_type, typename FieldType::field_type>::type field_type; 00096 typedef typename boost::mpl::if_<boost::is_const<T>, const typename FieldType::value_type, typename FieldType::value_type>::type value_type; 00097 00098 public: 00099 FieldAccess(const FieldType& field, const Accessor& accessor) : FieldType(field), accessor_(accessor), expanded_(size()) {} 00100 virtual ~FieldAccess() {} 00101 00102 const Accessor& accessor() const { return accessor_; } 00103 00104 using FieldType::reference; 00105 field_type& reference() const { return reference(accessor().instance()); } 00106 value_type& reference(std::size_t i) const { return reference(accessor().instance(), i); } 00107 bool hasInstance() const { return true; } 00108 00109 // size() should return the size of the vector in the given instance 00110 std::size_t size() const { return field_traits::size<typename FieldType::field_type>::value(reference()); } 00111 bool empty() const { return field_traits::size<typename FieldType::field_type>::empty(reference()); } 00112 void resize(std::size_t new_size) const { field_traits::size<typename FieldType::field_type>::resize(reference(), new_size); expanded_.resize(size()); } 00113 std::size_t capacity() const { return field_traits::size<typename FieldType::field_type>::capacity(reference()); } 00114 00115 boost::any get(std::size_t i) const { return boost::any(reference(i)); } 00116 void setAny(const boost::any& value, std::size_t i) const { reference(i) = boost::any_cast<typename FieldType::value_type>(value); } 00117 00118 MessagePtr expand(std::size_t i) const { 00119 if (i >= expanded_.size()) expanded_.resize(size()); 00120 if (i >= expanded_.size()) return MessagePtr(); 00121 if (expanded_[i]) return expanded_[i]; 00122 00123 MessagePtr message(messageByTypeId(this->getTypeId())); 00124 if (!message) { 00125 ROS_WARN_NAMED("cpp_introspection", "failed to expand field %s of type %s (unknown type)", FieldType::getName(), FieldType::getDataType()); 00126 return MessagePtr(); 00127 } 00128 expanded_[i] = message->introspect(&reference(i)); 00129 return expanded_[i]; 00130 } 00131 }; 00132 00133 public: 00134 template <class FieldType> static FieldPtr access(const FieldType& field, AccessorBase& accessor) { 00135 return FieldPtr(new FieldAccess<FieldType>(field, static_cast<Accessor&>(accessor))); 00136 } 00137 }; 00138 00139 namespace { 00140 struct null_deleter { void operator()(void const *) const { } }; 00141 } 00142 00143 template <typename T> 00144 MessagePtr MessageTemplate<T>::introspect(void *instance) const 00145 { 00146 return introspect(VoidPtr(instance, null_deleter())); 00147 } 00148 00149 template <typename T> 00150 MessagePtr MessageTemplate<T>::introspect(const VoidPtr& instance) const 00151 { 00152 boost::shared_ptr<T> x(boost::shared_static_cast<T>(instance)); 00153 if (!x) return MessagePtr(); 00154 return MessagePtr(new Accessor<T>(*this, x)); 00155 } 00156 00157 template <typename T> 00158 MessagePtr MessageTemplate<T>::introspect(void const *instance) const 00159 { 00160 return introspect(VoidConstPtr(instance, null_deleter())); 00161 } 00162 00163 template <typename T> 00164 MessagePtr MessageTemplate<T>::introspect(const VoidConstPtr& instance) const 00165 { 00166 boost::shared_ptr<T const> x(boost::shared_static_cast<T const>(instance)); 00167 if (!x) return MessagePtr(); 00168 return MessagePtr(new Accessor<T const>(*this, x)); 00169 } 00170 00171 } // namespace cpp_introspection 00172 00173 #endif // CPP_INTROSPECTION_ACCESSOR_H