Merge branch '0.7.1'
[luabind.git] / src / class.cpp
blobafcdd938f2e715c5c4ece5f93acd8c84c0c90462
1 // Copyright (c) 2004 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #include <luabind/lua_include.hpp>
25 #include <luabind/config.hpp>
26 #include <luabind/class.hpp>
27 #include <luabind/nil.hpp>
29 #include <cstring>
30 #include <iostream>
32 namespace luabind
34 LUABIND_API detail::nil_type nil;
37 namespace luabind { namespace detail {
39 struct class_registration : registration
41 class_registration(char const* name);
43 void register_(lua_State* L) const;
45 const char* m_name;
47 // datamembers, some members may be readonly, and
48 // only have a getter function
49 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
50 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
52 // the operators in lua
53 mutable std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
54 mutable std::map<const char*, int, detail::ltstr> m_static_constants;
56 mutable std::vector<class_base::base_desc> m_bases;
57 mutable detail::construct_rep m_constructor;
59 void(*m_destructor)(void*);
60 void(*m_const_holder_destructor)(void*);
62 void*(*m_extractor)(void*);
63 const void*(*m_const_extractor)(void*);
65 void(*m_const_converter)(void*,void*);
67 void(*m_construct_holder)(void*, void*);
68 void(*m_construct_const_holder)(void*, void*);
70 void(*m_default_construct_holder)(void*);
71 void(*m_default_construct_const_holder)(void*);
73 void(*m_adopt_fun)(void*);
75 int m_holder_size;
76 int m_holder_alignment;
78 LUABIND_TYPE_INFO m_type;
79 LUABIND_TYPE_INFO m_holder_type;
80 LUABIND_TYPE_INFO m_const_holder_type;
82 scope m_scope;
83 scope m_members;
84 scope m_default_members;
87 class_registration::class_registration(char const* name)
89 m_name = name;
92 void class_registration::register_(lua_State* L) const
94 LUABIND_CHECK_STACK(L);
96 assert(lua_type(L, -1) == LUA_TTABLE);
98 lua_pushstring(L, m_name);
100 detail::class_rep* crep;
102 detail::class_registry* r = detail::class_registry::get_registry(L);
103 // create a class_rep structure for this class.
104 // allocate it within lua to let lua collect it on
105 // lua_close(). This is better than allocating it
106 // as a static, since it will then be destructed
107 // when the program exits instead.
108 // warning: we assume that lua will not
109 // move the userdata memory.
110 lua_newuserdata(L, sizeof(detail::class_rep));
111 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
113 new(crep) detail::class_rep(
114 m_type
115 , m_name
117 , m_destructor
118 , m_const_holder_destructor
119 , m_holder_type
120 , m_const_holder_type
121 , m_extractor
122 , m_const_extractor
123 , m_const_converter
124 , m_construct_holder
125 , m_construct_const_holder
126 , m_default_construct_holder
127 , m_default_construct_const_holder
128 , m_adopt_fun
129 , m_holder_size
130 , m_holder_alignment);
132 // register this new type in the class registry
133 r->add_class(m_type, crep);
134 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
136 // if we have a held type
137 // we have to register it in the class-table
138 // but only for the base class, if it already
139 // exists, we don't have to register it
140 detail::class_rep* c = r->find_class(m_holder_type);
141 if (c == 0)
143 r->add_class(m_holder_type, crep);
144 r->add_class(m_const_holder_type, crep);
148 // constructors
149 m_constructor.swap(crep->m_constructor);
151 crep->m_getters.swap(m_getters);
152 crep->m_setters.swap(m_setters);
154 for (int i = 0; i < detail::number_of_operators; ++i)
155 crep->m_operators[i].swap(m_operators[i]);
157 crep->m_static_constants.swap(m_static_constants);
159 detail::class_registry* registry = detail::class_registry::get_registry(L);
161 crep->get_default_table(L);
162 m_scope.register_(L);
163 m_default_members.register_(L);
164 lua_pop(L, 1);
166 crep->get_table(L);
167 m_members.register_(L);
168 lua_pop(L, 1);
170 for (std::vector<class_base::base_desc>::iterator i = m_bases.begin();
171 i != m_bases.end(); ++i)
173 LUABIND_CHECK_STACK(L);
175 // the baseclass' class_rep structure
176 detail::class_rep* bcrep = registry->find_class(i->type);
178 detail::class_rep::base_info base;
179 base.pointer_offset = i->ptr_offset;
180 base.base = bcrep;
182 crep->add_base_class(base);
184 // copy base class table
185 crep->get_table(L);
186 bcrep->get_table(L);
187 lua_pushnil(L);
189 while (lua_next(L, -2))
191 lua_pushvalue(L, -2); // copy key
192 lua_gettable(L, -5);
194 if (!lua_isnil(L, -1))
196 lua_pop(L, 2);
197 continue;
200 lua_pop(L, 1);
201 lua_pushvalue(L, -2); // copy key
202 lua_insert(L, -2);
204 lua_settable(L, -5);
206 lua_pop(L, 2);
208 // copy base class detaults table
209 crep->get_default_table(L);
210 bcrep->get_default_table(L);
211 lua_pushnil(L);
213 while (lua_next(L, -2))
215 lua_pushvalue(L, -2); // copy key
216 lua_gettable(L, -5);
218 if (!lua_isnil(L, -1))
220 lua_pop(L, 2);
221 continue;
224 lua_pop(L, 1);
225 lua_pushvalue(L, -2); // copy key
226 lua_insert(L, -2);
228 lua_settable(L, -5);
230 lua_pop(L, 2);
234 lua_settable(L, -3);
237 // -- interface ---------------------------------------------------------
239 class_base::class_base(char const* name)
240 : scope(std::auto_ptr<registration>(
241 m_registration = new class_registration(name))
246 void class_base::init(
247 LUABIND_TYPE_INFO type_id
248 , LUABIND_TYPE_INFO holder_type
249 , LUABIND_TYPE_INFO const_holder_type
250 , void*(*extractor)(void*)
251 , const void*(*const_extractor)(void*)
252 , void(*const_converter_)(void*,void*)
253 , void(*holder_constructor_)(void*,void*)
254 , void(*const_holder_constructor_)(void*,void*)
255 , void(*holder_default_constructor_)(void*)
256 , void(*const_holder_default_constructor_)(void*)
257 , void(*adopt_fun)(void*)
258 , void(*destructor)(void*)
259 , void(*const_holder_destructor)(void*)
260 , int holder_size
261 , int holder_alignment)
263 m_registration->m_type = type_id;
264 m_registration->m_holder_type = holder_type;
265 m_registration->m_const_holder_type = const_holder_type;
266 m_registration->m_extractor = extractor;
267 m_registration->m_const_extractor = const_extractor;
268 m_registration->m_const_converter = const_converter_;
269 m_registration->m_construct_holder = holder_constructor_;
270 m_registration->m_construct_const_holder = const_holder_constructor_;
271 m_registration->m_default_construct_holder = holder_default_constructor_;
272 m_registration->m_default_construct_const_holder = const_holder_default_constructor_;
273 m_registration->m_destructor = destructor;
274 m_registration->m_const_holder_destructor = const_holder_destructor;
275 m_registration->m_adopt_fun = adopt_fun;
276 m_registration->m_holder_size = holder_size;
277 m_registration->m_holder_alignment = holder_alignment;
280 void class_base::add_getter(
281 const char* name, const boost::function2<int, lua_State*, int>& g)
283 detail::class_rep::callback c;
284 c.func = g;
285 c.pointer_offset = 0;
287 const char* key = name;
288 m_registration->m_getters[key] = c;
291 #ifdef LUABIND_NO_ERROR_CHECKING
292 void class_base::add_setter(
293 const char* name
294 , const boost::function2<int, lua_State*, int>& s)
295 #else
296 void class_base::add_setter(
297 const char* name
298 , const boost::function2<int, lua_State*, int>& s
299 , int (*match)(lua_State*, int)
300 , void (*get_sig_ptr)(lua_State*, std::string&))
301 #endif
303 detail::class_rep::callback c;
304 c.func = s;
305 c.pointer_offset = 0;
307 #ifndef LUABIND_NO_ERROR_CHECKING
308 c.match = match;
309 c.sig = get_sig_ptr;
310 #endif
313 const char* key = name;
314 m_registration->m_setters[key] = c;
317 void class_base::add_base(const base_desc& b)
319 m_registration->m_bases.push_back(b);
322 void class_base::add_constructor(const detail::construct_rep::overload_t& o)
324 m_registration->m_constructor.overloads.push_back(o);
327 void class_base::add_member(registration* member)
329 std::auto_ptr<registration> ptr(member);
330 m_registration->m_members.operator,(scope(ptr));
333 void class_base::add_default_member(registration* member)
335 std::auto_ptr<registration> ptr(member);
336 m_registration->m_default_members.operator,(scope(ptr));
339 #ifndef LUABIND_NO_ERROR_CHECKING
340 void class_base::add_operator(
341 int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*)
342 , void(*sig)(lua_State*, std::string&), int arity)
343 #else
344 void class_base::add_operator(
345 int op_id, int(*func)(lua_State*)
346 , int(*matcher)(lua_State*), int arity)
347 #endif
349 detail::class_rep::operator_callback o;
350 o.set_fun(func);
351 o.set_match_fun(matcher);
352 o.set_arity(arity);
354 #ifndef LUABIND_NO_ERROR_CHECKING
356 o.set_sig_fun(sig);
358 #endif
359 m_registration->m_operators[op_id].push_back(o);
362 const char* class_base::name() const
364 return m_registration->m_name;
367 void class_base::add_static_constant(const char* name, int val)
369 m_registration->m_static_constants[name] = val;
372 void class_base::add_inner_scope(scope& s)
374 m_registration->m_scope.operator,(s);
377 template<class T>
378 void add_custom_name(T i, std::string& s) {}
380 void add_custom_name(std::type_info const* i, std::string& s)
382 s += " [";
383 s += i->name();
384 s += "]";
387 std::string get_class_name(lua_State* L, LUABIND_TYPE_INFO i)
389 std::string ret;
391 assert(L);
393 class_registry* r = class_registry::get_registry(L);
394 class_rep* crep = r->find_class(i);
396 if (crep == 0)
398 ret = "custom";
399 add_custom_name(i, ret);
401 else
403 if (LUABIND_TYPE_INFO_EQUAL(i, crep->holder_type()))
405 ret += "smart_ptr<";
406 ret += crep->name();
407 ret += ">";
409 else if (LUABIND_TYPE_INFO_EQUAL(i, crep->const_holder_type()))
411 ret += "smart_ptr<const ";
412 ret += crep->name();
413 ret += ">";
415 else
417 ret += crep->name();
420 return ret;
423 }} // namespace luabind::detail