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     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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


cpp_introspection
Author(s): Johannes Meyer
autogenerated on Tue Jan 8 2013 17:30:47