Reimplemented build system.
[luabind.git] / src / class.cpp
blob1c5e457ed571d24f6426d3c0553b60623b6b13b2
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 method_name
41 method_name(char const* n): name(n) {}
42 bool operator()(method_rep const& o) const
43 { return std::strcmp(o.name, name) == 0; }
44 char const* name;
47 struct class_registration : registration
49 class_registration(char const* name);
51 void register_(lua_State* L) const;
53 const char* m_name;
55 mutable std::list<detail::method_rep> m_methods;
57 // datamembers, some members may be readonly, and
58 // only have a getter function
59 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
60 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
62 // the operators in lua
63 mutable std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
64 mutable std::map<const char*, int, detail::ltstr> m_static_constants;
66 mutable std::vector<class_base::base_desc> m_bases;
67 mutable detail::construct_rep m_constructor;
69 void(*m_destructor)(void*);
70 void(*m_const_holder_destructor)(void*);
72 void*(*m_extractor)(void*);
73 const void*(*m_const_extractor)(void*);
75 void(*m_const_converter)(void*,void*);
77 void(*m_construct_holder)(void*, void*);
78 void(*m_construct_const_holder)(void*, void*);
80 void(*m_default_construct_holder)(void*);
81 void(*m_default_construct_const_holder)(void*);
83 void(*m_adopt_fun)(void*);
85 int m_holder_size;
86 int m_holder_alignment;
88 LUABIND_TYPE_INFO m_type;
89 LUABIND_TYPE_INFO m_holder_type;
90 LUABIND_TYPE_INFO m_const_holder_type;
92 scope m_scope;
95 class_registration::class_registration(char const* name)
97 m_name = name;
100 void class_registration::register_(lua_State* L) const
102 LUABIND_CHECK_STACK(L);
104 assert(lua_type(L, -1) == LUA_TTABLE);
106 lua_pushstring(L, m_name);
108 detail::class_rep* crep;
110 detail::class_registry* r = detail::class_registry::get_registry(L);
111 // create a class_rep structure for this class.
112 // allocate it within lua to let lua collect it on
113 // lua_close(). This is better than allocating it
114 // as a static, since it will then be destructed
115 // when the program exits instead.
116 // warning: we assume that lua will not
117 // move the userdata memory.
118 lua_newuserdata(L, sizeof(detail::class_rep));
119 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
121 new(crep) detail::class_rep(
122 m_type
123 , m_name
125 , m_destructor
126 , m_const_holder_destructor
127 , m_holder_type
128 , m_const_holder_type
129 , m_extractor
130 , m_const_extractor
131 , m_const_converter
132 , m_construct_holder
133 , m_construct_const_holder
134 , m_default_construct_holder
135 , m_default_construct_const_holder
136 , m_adopt_fun
137 , m_holder_size
138 , m_holder_alignment);
140 // register this new type in the class registry
141 r->add_class(m_type, crep);
142 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
144 // if we have a held type
145 // we have to register it in the class-table
146 // but only for the base class, if it already
147 // exists, we don't have to register it
148 detail::class_rep* c = r->find_class(m_holder_type);
149 if (c == 0)
151 r->add_class(m_holder_type, crep);
152 r->add_class(m_const_holder_type, crep);
156 // constructors
157 m_constructor.swap(crep->m_constructor);
159 crep->m_getters.swap(m_getters);
160 crep->m_setters.swap(m_setters);
162 for (int i = 0; i < detail::number_of_operators; ++i)
163 crep->m_operators[i].swap(m_operators[i]);
165 crep->m_static_constants.swap(m_static_constants);
167 typedef std::list<detail::method_rep> methods_t;
169 detail::class_registry* registry = detail::class_registry::get_registry(L);
171 for (std::vector<class_base::base_desc>::iterator i = m_bases.begin();
172 i != m_bases.end(); ++i)
174 LUABIND_CHECK_STACK(L);
176 // the baseclass' class_rep structure
177 detail::class_rep* bcrep = registry->find_class(i->type);
179 detail::class_rep::base_info base;
180 base.pointer_offset = i->ptr_offset;
181 base.base = bcrep;
183 crep->add_base_class(base);
185 // copy base class table
186 crep->get_table(L);
187 bcrep->get_table(L);
188 lua_pushnil(L);
190 while (lua_next(L, -2))
192 lua_pushvalue(L, -2); // copy key
193 lua_insert(L, -2);
194 lua_settable(L, -5);
196 lua_pop(L, 2);
198 // copy base class detaults table
199 crep->get_default_table(L);
200 bcrep->get_default_table(L);
201 lua_pushnil(L);
203 while (lua_next(L, -2))
205 lua_pushvalue(L, -2); // copy key
206 lua_insert(L, -2);
207 lua_settable(L, -5);
209 lua_pop(L, 2);
213 // add methods
214 for (std::list<detail::method_rep>::iterator i
215 = m_methods.begin(); i != m_methods.end(); ++i)
217 LUABIND_CHECK_STACK(L);
218 crep->add_method(*i);
221 crep->register_methods(L);
223 m_methods.clear();
225 crep->get_default_table(L);
226 m_scope.register_(L);
227 lua_pop(L, 1);
229 lua_settable(L, -3);
232 // -- interface ---------------------------------------------------------
234 class_base::class_base(char const* name)
235 : scope(std::auto_ptr<registration>(
236 m_registration = new class_registration(name))
241 void class_base::init(
242 LUABIND_TYPE_INFO type_id
243 , LUABIND_TYPE_INFO holder_type
244 , LUABIND_TYPE_INFO const_holder_type
245 , void*(*extractor)(void*)
246 , const void*(*const_extractor)(void*)
247 , void(*const_converter_)(void*,void*)
248 , void(*holder_constructor_)(void*,void*)
249 , void(*const_holder_constructor_)(void*,void*)
250 , void(*holder_default_constructor_)(void*)
251 , void(*const_holder_default_constructor_)(void*)
252 , void(*adopt_fun)(void*)
253 , void(*destructor)(void*)
254 , void(*const_holder_destructor)(void*)
255 , int holder_size
256 , int holder_alignment)
258 m_registration->m_type = type_id;
259 m_registration->m_holder_type = holder_type;
260 m_registration->m_const_holder_type = const_holder_type;
261 m_registration->m_extractor = extractor;
262 m_registration->m_const_extractor = const_extractor;
263 m_registration->m_const_converter = const_converter_;
264 m_registration->m_construct_holder = holder_constructor_;
265 m_registration->m_construct_const_holder = const_holder_constructor_;
266 m_registration->m_default_construct_holder = holder_default_constructor_;
267 m_registration->m_default_construct_const_holder = const_holder_default_constructor_;
268 m_registration->m_destructor = destructor;
269 m_registration->m_const_holder_destructor = const_holder_destructor;
270 m_registration->m_adopt_fun = adopt_fun;
271 m_registration->m_holder_size = holder_size;
272 m_registration->m_holder_alignment = holder_alignment;
275 void class_base::add_getter(
276 const char* name, const boost::function2<int, lua_State*, int>& g)
278 detail::class_rep::callback c;
279 c.func = g;
280 c.pointer_offset = 0;
282 const char* key = name;
283 m_registration->m_getters[key] = c;
286 #ifdef LUABIND_NO_ERROR_CHECKING
287 void class_base::add_setter(
288 const char* name
289 , const boost::function2<int, lua_State*, int>& s)
290 #else
291 void class_base::add_setter(
292 const char* name
293 , const boost::function2<int, lua_State*, int>& s
294 , int (*match)(lua_State*, int)
295 , void (*get_sig_ptr)(lua_State*, std::string&))
296 #endif
298 detail::class_rep::callback c;
299 c.func = s;
300 c.pointer_offset = 0;
302 #ifndef LUABIND_NO_ERROR_CHECKING
303 c.match = match;
304 c.sig = get_sig_ptr;
305 #endif
308 const char* key = name;
309 m_registration->m_setters[key] = c;
312 void class_base::add_base(const base_desc& b)
314 m_registration->m_bases.push_back(b);
317 void class_base::add_constructor(const detail::construct_rep::overload_t& o)
319 m_registration->m_constructor.overloads.push_back(o);
322 void class_base::add_method(const char* name, const detail::overload_rep& o)
324 typedef std::list<detail::method_rep> methods_t;
326 methods_t::iterator m = std::find_if(
327 m_registration->m_methods.begin()
328 , m_registration->m_methods.end()
329 , method_name(name));
330 if (m == m_registration->m_methods.end())
332 m_registration->m_methods.push_back(method_rep());
333 m = m_registration->m_methods.end();
334 std::advance(m, -1);
335 m->name = name;
338 m->add_overload(o);
339 m->crep = 0;
342 #ifndef LUABIND_NO_ERROR_CHECKING
343 void class_base::add_operator(
344 int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*)
345 , void(*sig)(lua_State*, std::string&), int arity)
346 #else
347 void class_base::add_operator(
348 int op_id, int(*func)(lua_State*)
349 , int(*matcher)(lua_State*), int arity)
350 #endif
352 detail::class_rep::operator_callback o;
353 o.set_fun(func);
354 o.set_match_fun(matcher);
355 o.set_arity(arity);
357 #ifndef LUABIND_NO_ERROR_CHECKING
359 o.set_sig_fun(sig);
361 #endif
362 m_registration->m_operators[op_id].push_back(o);
365 const char* class_base::name() const
367 return m_registration->m_name;
370 void class_base::add_static_constant(const char* name, int val)
372 m_registration->m_static_constants[name] = val;
375 void class_base::add_inner_scope(scope& s)
377 m_registration->m_scope.operator,(s);
380 template<class T>
381 void add_custom_name(T i, std::string& s) {}
383 void add_custom_name(std::type_info const* i, std::string& s)
385 s += " [";
386 s += i->name();
387 s += "]";
390 std::string get_class_name(lua_State* L, LUABIND_TYPE_INFO i)
392 std::string ret;
394 assert(L);
396 class_registry* r = class_registry::get_registry(L);
397 class_rep* crep = r->find_class(i);
399 if (crep == 0)
401 ret = "custom";
402 add_custom_name(i, ret);
404 else
406 if (LUABIND_TYPE_INFO_EQUAL(i, crep->holder_type()))
408 ret += "smart_ptr<";
409 ret += crep->name();
410 ret += ">";
412 else if (LUABIND_TYPE_INFO_EQUAL(i, crep->const_holder_type()))
414 ret += "smart_ptr<const ";
415 ret += crep->name();
416 ret += ">";
418 else
420 ret += crep->name();
423 return ret;
426 }} // namespace luabind::detail