Go to the documentation of this file.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 #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
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
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 }
00172
00173 #endif // CPP_INTROSPECTION_ACCESSOR_H