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 PackagePtr package() const { return message_.package(); }
00077 const char* getPackageName() const { return message_.getPackageName(); }
00078
00079 const char *getName() const { return message_.getName(); }
00080
00081
00082 const V_Field& fields() const { return fields_; }
00083 FieldWPtr field(const std::string& name) const { return fields_by_name_.at(name); }
00084 const V_FieldName& getFieldNames() const { return message_.getFieldNames(); }
00085
00086 void serialize(ros::serialization::OStream& stream, const VoidConstPtr&) const { message_.serialize(stream, getConstInstance()); }
00087 ros::SerializedMessage serialize(const VoidConstPtr&) const { return message_.serialize(getConstInstance()); }
00088 std::size_t serializationLength(const VoidConstPtr&) const { return message_.serializationLength(getConstInstance()); }
00089 VoidPtr deserialize(ros::serialization::IStream& stream, const VoidPtr&) const { return is_const::value ? VoidPtr() : message_.deserialize(stream, getInstance()); }
00090
00091
00092 private:
00093 template <typename FieldType>
00094 class FieldAccess : public FieldType {
00095 private:
00096 const Accessor& accessor_;
00097 mutable V_Message expanded_;
00098 typedef typename boost::mpl::if_<boost::is_const<T>, const typename FieldType::field_type, typename FieldType::field_type>::type field_type;
00099 typedef typename boost::mpl::if_<boost::is_const<T>, const typename FieldType::value_type, typename FieldType::value_type>::type value_type;
00100
00101 public:
00102 FieldAccess(const FieldType& field, const Accessor& accessor) : FieldType(field), accessor_(accessor), expanded_(size()) {}
00103 virtual ~FieldAccess() {}
00104
00105 const Accessor& accessor() const { return accessor_; }
00106
00107 using FieldType::reference;
00108 field_type& reference() const { return reference(accessor().instance()); }
00109 value_type& reference(std::size_t i) const { return reference(accessor().instance(), i); }
00110 bool hasInstance() const { return true; }
00111
00112
00113 std::size_t size() const { return field_traits::size<typename FieldType::field_type>::value(reference()); }
00114 bool empty() const { return field_traits::size<typename FieldType::field_type>::empty(reference()); }
00115 void resize(std::size_t new_size) const { field_traits::size<typename FieldType::field_type>::resize(reference(), new_size); expanded_.resize(size()); }
00116 std::size_t capacity() const { return field_traits::size<typename FieldType::field_type>::capacity(reference()); }
00117
00118 boost::any get(std::size_t i) const { return boost::any(reference(i)); }
00119 void setAny(const boost::any& value, std::size_t i) const { reference(i) = boost::any_cast<typename FieldType::value_type>(value); }
00120
00121 MessagePtr expand(std::size_t i) const {
00122 if (i >= expanded_.size()) expanded_.resize(size());
00123 if (i >= expanded_.size()) return MessagePtr();
00124 if (expanded_[i]) return expanded_[i];
00125
00126 MessagePtr message(messageByTypeId(this->getTypeId()));
00127 if (!message) {
00128 ROS_WARN_NAMED("cpp_introspection", "failed to expand field %s of type %s (unknown type)", FieldType::getName(), FieldType::getDataType());
00129 return MessagePtr();
00130 }
00131 expanded_[i] = message->introspect(&reference(i));
00132 return expanded_[i];
00133 }
00134 };
00135
00136 public:
00137 template <class FieldType> static FieldPtr access(const FieldType& field, AccessorBase& accessor) {
00138 return FieldPtr(new FieldAccess<FieldType>(field, static_cast<Accessor&>(accessor)));
00139 }
00140 };
00141
00142 namespace {
00143 struct null_deleter { void operator()(void const *) const { } };
00144 }
00145
00146 template <typename T>
00147 MessagePtr MessageTemplate<T>::introspect(void *instance) const
00148 {
00149 return introspect(VoidPtr(instance, null_deleter()));
00150 }
00151
00152 template <typename T>
00153 MessagePtr MessageTemplate<T>::introspect(const VoidPtr& instance) const
00154 {
00155 boost::shared_ptr<T> x(boost::shared_static_cast<T>(instance));
00156 if (!x) return MessagePtr();
00157 return MessagePtr(new Accessor<T>(*this, x));
00158 }
00159
00160 template <typename T>
00161 MessagePtr MessageTemplate<T>::introspect(void const *instance) const
00162 {
00163 return introspect(VoidConstPtr(instance, null_deleter()));
00164 }
00165
00166 template <typename T>
00167 MessagePtr MessageTemplate<T>::introspect(const VoidConstPtr& instance) const
00168 {
00169 boost::shared_ptr<T const> x(boost::shared_static_cast<T const>(instance));
00170 if (!x) return MessagePtr();
00171 return MessagePtr(new Accessor<T const>(*this, x));
00172 }
00173
00174 }
00175
00176 #endif // CPP_INTROSPECTION_ACCESSOR_H