// Copyright Daniel Wallin 2009. Use, modification and distribution is // subject to the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef LUABIND_INHERITANCE_090217_HPP # define LUABIND_INHERITANCE_090217_HPP # include # include # include # include # include # include # include namespace luabind { namespace detail { typedef void*(*cast_function)(void*); typedef std::size_t class_id; class_id const unknown_class = (std::numeric_limits::max)(); class class_rep; class LUABIND_API cast_graph { public: cast_graph(); ~cast_graph(); // `src` and `p` here describe the *most derived* object. This means that // for a polymorphic type, the pointer must be cast with // dynamic_cast before being passed in here, and `src` has to // match typeid(*p). std::pair cast( void* p, class_id src, class_id target , class_id dynamic_id, void const* dynamic_ptr) const; void insert(class_id src, class_id target, cast_function cast); private: class impl; boost::scoped_ptr m_impl; }; // Maps a type_id to a class_id. Note that this actually partitions the // id-space into two, using one half for "local" ids; ids that are used only as // keys into the conversion cache. This is needed because we need a unique key // even for types that hasn't been registered explicitly. class LUABIND_API class_id_map { public: class_id_map(); class_id get(type_id const& type) const; class_id get_local(type_id const& type); void put(class_id id, type_id const& type); private: typedef std::map map_type; map_type m_classes; class_id m_local_id; static class_id const local_id_base; }; inline class_id_map::class_id_map() : m_local_id(local_id_base) {} inline class_id class_id_map::get(type_id const& type) const { map_type::const_iterator i = m_classes.find(type); if (i == m_classes.end() || i->second >= local_id_base) return unknown_class; return i->second; } inline class_id class_id_map::get_local(type_id const& type) { std::pair result = m_classes.insert( std::make_pair(type, 0)); if (result.second) result.first->second = m_local_id++; assert(m_local_id >= local_id_base); return result.first->second; } inline void class_id_map::put(class_id id, type_id const& type) { assert(id < local_id_base); std::pair result = m_classes.insert( std::make_pair(type, 0)); assert( result.second || result.first->second == id || result.first->second >= local_id_base ); result.first->second = id; } class class_map { public: class_rep* get(class_id id) const; void put(class_id id, class_rep* cls); private: std::vector m_classes; }; inline class_rep* class_map::get(class_id id) const { if (id >= m_classes.size()) return 0; return m_classes[id]; } inline void class_map::put(class_id id, class_rep* cls) { if (id >= m_classes.size()) m_classes.resize(id + 1); m_classes[id] = cls; } template struct static_cast_ { static void* execute(void* p) { return static_cast(static_cast(p)); } }; template struct dynamic_cast_ { static void* execute(void* p) { return dynamic_cast(static_cast(p)); } }; // Thread safe class_id allocation. LUABIND_API class_id allocate_class_id(type_id const& cls); template struct registered_class { static class_id const id; }; template class_id const registered_class::id = allocate_class_id(typeid(T)); template struct registered_class : registered_class {}; }} // namespace luabind::detail #endif // LUABIND_INHERITANCE_090217_HPP