accessor.h
Go to the documentation of this file.
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     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 //    const Package& package() const { return message_.package(); }
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       // size() should return the size of the vector in the given instance
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 } // namespace cpp_introspection
00175 
00176 #endif // CPP_INTROSPECTION_ACCESSOR_H


cpp_introspection
Author(s): Johannes Meyer
autogenerated on Wed Aug 26 2015 11:11:00