New inheritance graph code.
[luabind.git] / luabind / detail / inheritance.hpp
blob70859150d9644c4d3d734dd616a606d6add98975
1 // Copyright Daniel Wallin 2009. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef LUABIND_INHERITANCE_090217_HPP
6 # define LUABIND_INHERITANCE_090217_HPP
8 # include <cassert>
9 # include <limits>
10 # include <map>
11 # include <memory>
12 # include <vector>
13 # include <luabind/typeid.hpp>
15 namespace luabind { namespace detail {
17 typedef void*(*cast_function)(void*);
18 typedef std::size_t class_id;
20 class_id const unknown_class = std::numeric_limits<class_id>::max();
22 class class_rep;
24 class LUABIND_API cast_graph
26 public:
27 cast_graph();
28 ~cast_graph();
30 // `src` and `p` here describe the *most derived* object. This means that
31 // for a polymorphic type, the pointer must be cast with
32 // dynamic_cast<void*> before being passed in here, and `src` has to
33 // match typeid(*p).
34 std::pair<void*, std::size_t> cast(
35 void* p, class_id src, class_id target
36 , class_id dynamic_id, void const* dynamic_ptr) const;
37 void insert(class_id src, class_id target, cast_function cast);
39 private:
40 class impl;
41 std::auto_ptr<impl> m_impl;
44 // Maps a type_id to a class_id. Note that this..
45 class class_id_map
47 public:
48 class_id get(type_id const& type) const;
49 class_id get_local(type_id const& type);
50 void put(class_id id, type_id const& type);
52 private:
53 typedef std::map<type_id, class_id> map_type;
54 map_type m_classes;
57 inline class_id class_id_map::get(type_id const& type) const
59 map_type::const_iterator i = m_classes.find(type);
60 if (i == m_classes.end() || i->second > unknown_class / 2)
61 return unknown_class;
62 return i->second;
65 inline class_id class_id_map::get_local(type_id const& type)
67 std::pair<map_type::iterator, bool> result = m_classes.insert(
68 std::make_pair(type, 0));
70 if (result.second)
71 result.first->second = unknown_class - m_classes.size();
73 return result.first->second;
76 inline void class_id_map::put(class_id id, type_id const& type)
78 std::pair<map_type::iterator, bool> result = m_classes.insert(
79 std::make_pair(type, id));
80 assert(result.second || result.first->second == id);
81 (void)result;
84 class class_map
86 public:
87 class_rep* get(class_id id) const;
88 void put(class_id id, class_rep* cls);
90 private:
91 std::vector<class_rep*> m_classes;
94 inline class_rep* class_map::get(class_id id) const
96 if (id >= m_classes.size())
97 return 0;
98 return m_classes[id];
101 inline void class_map::put(class_id id, class_rep* cls)
103 if (id >= m_classes.size())
104 m_classes.resize(id + 1);
105 m_classes[id] = cls;
108 template <class S, class T>
109 struct static_cast_
111 static void* execute(void* p)
113 return static_cast<T*>(static_cast<S*>(p));
117 template <class S, class T>
118 struct dynamic_cast_
120 static void* execute(void* p)
122 return dynamic_cast<T*>(static_cast<S*>(p));
126 // Thread safe class_id allocation.
127 LUABIND_API class_id allocate_class_id();
129 template <class T>
130 struct registered_class
132 static class_id const id;
135 template <class T>
136 class_id const registered_class<T>::id = allocate_class_id();
138 template <class T>
139 struct registered_class<T const>
140 : registered_class<T>
143 }} // namespace luabind::detail
145 #endif // LUABIND_INHERITANCE_090217_HPP