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)
4
5 #ifndef LUABIND_INHERITANCE_090217_HPP
6 # define LUABIND_INHERITANCE_090217_HPP
7
8 # include <luabind/typeid.hpp>
9
10 # include <boost/scoped_ptr.hpp>
11
12 # include <cassert>
13 # include <limits>
14 # include <map>
15 # include <memory>
16 # include <vector>
17
18
19 namespace luabind { namespace detail {
20
21 LUABIND_API extern char classid_map_tag;
22 LUABIND_API extern char class_map_tag;
23 extern char cast_graph_tag; // Not used in headers, thus no LUABIND_API.
24
25 typedef void*(*cast_function)(void*);
26 typedef std::size_t class_id;
27
28 class_id const unknown_class = (std::numeric_limits<class_id>::max)();
29
30 class class_rep;
31
32 class LUABIND_API cast_graph
33 {
34 public:
35 cast_graph();
36 ~cast_graph();
37
38 // `src` and `p` here describe the *most derived* object. This means that
39 // for a polymorphic type, the pointer must be cast with
40 // dynamic_cast<void*> before being passed in here, and `src` has to
41 // match typeid(*p).
42 std::pair<void*, int> cast(
43 void* p, class_id src, class_id target
44 , class_id dynamic_id, void const* dynamic_ptr) const;
45 void insert(class_id src, class_id target, cast_function cast);
46
47 private:
48 class impl;
49 boost::scoped_ptr<impl> m_impl;
50 };
51
52 // Maps a type_id to a class_id. Note that this actually partitions the
53 // id-space into two, using one half for "local" ids; ids that are used only as
54 // keys into the conversion cache. This is needed because we need a unique key
55 // even for types that hasn't been registered explicitly.
56 class LUABIND_API class_id_map
57 {
58 public:
59 class_id_map();
60
61 class_id get(type_id const& type) const;
62 class_id get_local(type_id const& type);
63 void put(class_id id, type_id const& type);
64
65 private:
66 typedef std::map<type_id, class_id> map_type;
67 map_type m_classes;
68 class_id m_local_id;
69
70 static class_id const local_id_base;
71 };
72
class_id_map()73 inline class_id_map::class_id_map()
74 : m_local_id(local_id_base)
75 {}
76
get(type_id const & type) const77 inline class_id class_id_map::get(type_id const& type) const
78 {
79 map_type::const_iterator i = m_classes.find(type);
80 if (i == m_classes.end() || i->second >= local_id_base)
81 return unknown_class;
82 return i->second;
83 }
84
get_local(type_id const & type)85 inline class_id class_id_map::get_local(type_id const& type)
86 {
87 std::pair<map_type::iterator, bool> result = m_classes.insert(
88 std::make_pair(type, 0));
89
90 if (result.second)
91 result.first->second = m_local_id++;
92
93 assert(m_local_id >= local_id_base);
94
95 return result.first->second;
96 }
97
put(class_id id,type_id const & type)98 inline void class_id_map::put(class_id id, type_id const& type)
99 {
100 assert(id < local_id_base);
101
102 std::pair<map_type::iterator, bool> result = m_classes.insert(
103 std::make_pair(type, 0));
104
105 assert(
106 result.second
107 || result.first->second == id
108 || result.first->second >= local_id_base
109 );
110
111 result.first->second = id;
112 }
113
114 class class_map
115 {
116 public:
117 class_rep* get(class_id id) const;
118 void put(class_id id, class_rep* cls);
119
120 private:
121 std::vector<class_rep*> m_classes;
122 };
123
get(class_id id) const124 inline class_rep* class_map::get(class_id id) const
125 {
126 if (id >= m_classes.size())
127 return 0;
128 return m_classes[id];
129 }
130
put(class_id id,class_rep * cls)131 inline void class_map::put(class_id id, class_rep* cls)
132 {
133 if (id >= m_classes.size())
134 m_classes.resize(id + 1);
135 m_classes[id] = cls;
136 }
137
138 template <class S, class T>
139 struct static_cast_
140 {
executeluabind::detail::static_cast_141 static void* execute(void* p)
142 {
143 return static_cast<T*>(static_cast<S*>(p));
144 }
145 };
146
147 template <class S, class T>
148 struct dynamic_cast_
149 {
executeluabind::detail::dynamic_cast_150 static void* execute(void* p)
151 {
152 return dynamic_cast<T*>(static_cast<S*>(p));
153 }
154 };
155
156 // Thread safe class_id allocation.
157 LUABIND_API class_id allocate_class_id(type_id const& cls);
158
159 template <class T>
160 struct registered_class
161 {
162 static class_id const id;
163 };
164
165 template <class T>
166 class_id const registered_class<T>::id = allocate_class_id(typeid(T));
167
168 template <class T>
169 struct registered_class<T const>
170 : registered_class<T>
171 {};
172
173 }} // namespace luabind::detail
174
175 #endif // LUABIND_INHERITANCE_090217_HPP
176