*** empty log message ***
[luabind.git] / src / class.cpp
blob7c1d16abbbbb5bba5cdfd0121c2978f307f8de62
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>
28 namespace luabind { namespace detail {
30 struct class_registration : registration
32 class_registration(char const* name);
34 void register_(lua_State* L) const;
36 const char* m_name;
38 mutable std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
40 // datamembers, some members may be readonly, and
41 // only have a getter function
42 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
43 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
45 // the operators in lua
46 mutable std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
47 mutable std::map<const char*, int, detail::ltstr> m_static_constants;
49 mutable std::vector<class_base::base_desc> m_bases;
50 mutable detail::construct_rep m_constructor;
52 void(*m_destructor)(void*);
53 void(*m_const_holder_destructor)(void*);
55 void*(*m_extractor)(void*);
56 const void*(*m_const_extractor)(void*);
58 void(*m_const_converter)(void*,void*);
60 void(*m_construct_holder)(void*, void*);
61 void(*m_construct_const_holder)(void*, void*);
63 void(*m_default_construct_holder)(void*);
64 void(*m_default_construct_const_holder)(void*);
66 int m_holder_size;
67 int m_holder_alignment;
69 LUABIND_TYPE_INFO m_type;
70 LUABIND_TYPE_INFO m_holder_type;
71 LUABIND_TYPE_INFO m_const_holder_type;
73 scope m_scope;
76 class_registration::class_registration(char const* name)
78 m_name = name;
81 void class_registration::register_(lua_State* L) const
83 lua_pushstring(L, m_name);
85 detail::class_rep* crep;
87 detail::class_registry* r = detail::class_registry::get_registry(L);
88 // create a class_rep structure for this class.
89 // allocate it within lua to let lua collect it on
90 // lua_close(). This is better than allocating it
91 // as a static, since it will then be destructed
92 // when the program exits instead.
93 // warning: we assume that lua will not
94 // move the userdata memory.
95 lua_newuserdata(L, sizeof(detail::class_rep));
96 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
98 new(crep) detail::class_rep(
99 m_type
100 , m_name
102 , m_destructor
103 , m_const_holder_destructor
104 , m_holder_type
105 , m_const_holder_type
106 , m_extractor
107 , m_const_extractor
108 , m_const_converter
109 , m_construct_holder
110 , m_construct_const_holder
111 , m_default_construct_holder
112 , m_default_construct_const_holder
113 , m_holder_size
114 , m_holder_alignment);
116 // register this new type in the class registry
117 r->add_class(m_type, crep);
118 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
120 // if we have a held type
121 // we have to register it in the class-table
122 // but only for the base class, if it already
123 // exists, we don't have to register it
124 detail::class_rep* c = r->find_class(m_holder_type);
125 if (c == 0)
127 r->add_class(m_holder_type, crep);
128 r->add_class(m_const_holder_type, crep);
132 // constructors
133 m_constructor.swap(crep->m_constructor);
135 crep->m_getters.swap(m_getters);
136 crep->m_setters.swap(m_setters);
138 for(int i = 0; i < detail::number_of_operators; ++i)
139 crep->m_operators[i].swap(m_operators[i]);
141 crep->m_static_constants.swap(m_static_constants);
143 // here!
144 // crep->m_methods = m_methods;
146 for (std::vector<class_base::base_desc>::iterator i = m_bases.begin();
147 i != m_bases.end();
148 ++i)
150 detail::class_registry* r = detail::class_registry::get_registry(L);
152 // the baseclass' class_rep structure
153 detail::class_rep* bcrep = r->find_class(i->type);
155 detail::class_rep::base_info base;
156 base.pointer_offset = i->ptr_offset;
157 base.base = bcrep;
159 crep->add_base_class(base);
161 typedef std::map<const char*, detail::method_rep, detail::ltstr> methods_t;
163 for (methods_t::const_iterator i
164 = bcrep->m_methods.begin()
165 ; i != bcrep->m_methods.end()
166 ; ++i)
168 detail::method_rep& m = m_methods[i->first];
170 typedef std::vector<detail::overload_rep> overloads_t;
172 for (overloads_t::const_iterator j
173 = i->second.overloads().begin()
174 ; j != i->second.overloads().end()
175 ; ++j)
177 detail::overload_rep o = *j;
178 o.add_offset(base.pointer_offset);
179 m.add_overload(o);
183 // copy base class table
184 detail::getref(L, crep->table_ref());
185 detail::getref(L, bcrep->table_ref());
186 lua_pushnil(L);
188 while (lua_next(L, -2))
190 lua_pushvalue(L, -2); // copy key
191 lua_insert(L, -2);
192 lua_settable(L, -5);
195 lua_pop(L, 2);
198 crep->m_methods = m_methods;
200 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
201 = crep->m_methods.begin(); i != crep->m_methods.end(); ++i)
203 i->second.crep = crep;
206 // add methods
207 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
208 = m_methods.begin(); i != m_methods.end(); ++i)
210 detail::getref(L, crep->table_ref());
211 lua_pushstring(L, i->first);
212 lua_pushnil(L);
213 lua_settable(L, -3);
214 lua_pop(L, 1);
216 crep->add_method(L, i->first, crep->m_methods[i->first]);
217 i->second.crep = crep;
220 m_methods.clear();
222 detail::getref(L, crep->table_ref());
223 m_scope.register_(L);
224 lua_pop(L, 1);
226 lua_settable(L, -3);
229 // -- interface ---------------------------------------------------------
231 class_base::class_base(char const* name)
232 : scope(std::auto_ptr<registration>(
233 m_registration = new class_registration(name))
238 void class_base::init(
239 LUABIND_TYPE_INFO type_
240 , LUABIND_TYPE_INFO holder_type
241 , LUABIND_TYPE_INFO const_holder_type
242 , void*(*extractor)(void*)
243 , const void*(*const_extractor)(void*)
244 , void(*const_converter_)(void*,void*)
245 , void(*holder_constructor_)(void*,void*)
246 , void(*const_holder_constructor_)(void*,void*)
247 , void(*holder_default_constructor_)(void*)
248 , void(*const_holder_default_constructor_)(void*)
249 , void(*destructor)(void*)
250 , void(*const_holder_destructor)(void*)
251 , int holder_size
252 , int holder_alignment)
254 m_registration->m_type = type_;
255 m_registration->m_holder_type = holder_type;
256 m_registration->m_const_holder_type = const_holder_type;
257 m_registration->m_extractor = extractor;
258 m_registration->m_const_extractor = const_extractor;
259 m_registration->m_const_converter = const_converter_;
260 m_registration->m_construct_holder = holder_constructor_;
261 m_registration->m_construct_const_holder = const_holder_constructor_;
262 m_registration->m_default_construct_holder = holder_default_constructor_;
263 m_registration->m_default_construct_const_holder = const_holder_default_constructor_;
264 m_registration->m_destructor = destructor;
265 m_registration->m_const_holder_destructor = const_holder_destructor;
266 m_registration->m_holder_size = holder_size;
267 m_registration->m_holder_alignment = holder_alignment;
270 void class_base::add_getter(
271 const char* name, const boost::function2<int, lua_State*, int>& g)
273 detail::class_rep::callback c;
274 c.func = g;
275 c.pointer_offset = 0;
277 const char* key = name;
278 m_registration->m_getters[key] = c;
281 #ifdef LUABIND_NO_ERROR_CHECKING
282 void class_base::add_setter(
283 const char* name
284 , const boost::function2<int, lua_State*, int>& s)
285 #else
286 void class_base::add_setter(
287 const char* name
288 , const boost::function2<int, lua_State*, int>& s
289 , int (*match)(lua_State*, int)
290 , void (*get_sig_ptr)(lua_State*, std::string&))
291 #endif
293 detail::class_rep::callback c;
294 c.func = s;
295 c.pointer_offset = 0;
297 #ifndef LUABIND_NO_ERROR_CHECKING
298 c.match = match;
299 c.sig = get_sig_ptr;
300 #endif
303 const char* key = name;
304 m_registration->m_setters[key] = c;
307 void class_base::add_base(const base_desc& b)
309 m_registration->m_bases.push_back(b);
312 void class_base::add_constructor(const detail::construct_rep::overload_t& o)
314 m_registration->m_constructor.overloads.push_back(o);
317 void class_base::add_method(const char* name, const detail::overload_rep& o)
319 detail::method_rep& method = m_registration->m_methods[name];
320 method.name = name;
321 method.add_overload(o);
322 method.crep = 0;
325 #ifndef LUABIND_NO_ERROR_CHECKING
326 void class_base::add_operator(
327 int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*)
328 , void(*sig)(lua_State*, std::string&), int arity)
329 #else
330 void class_base::add_operator(
331 int op_id, int(*func)(lua_State*)
332 , int(*matcher)(lua_State*), int arity)
333 #endif
335 detail::class_rep::operator_callback o;
336 o.set_fun(func);
337 o.set_match_fun(matcher);
338 o.set_arity(arity);
340 #ifndef LUABIND_NO_ERROR_CHECKING
342 o.set_sig_fun(sig);
344 #endif
345 m_registration->m_operators[op_id].push_back(o);
348 const char* class_base::name() const
350 return m_registration->m_name;
353 void class_base::add_static_constant(const char* name, int val)
355 m_registration->m_static_constants[name] = val;
358 void class_base::add_inner_scope(scope& s)
360 m_registration->m_scope.operator,(s);
363 std::string get_class_name(lua_State* L, LUABIND_TYPE_INFO i)
365 std::string ret;
366 class_registry* r = class_registry::get_registry(L);
367 class_rep* crep = r->find_class(i);
369 if (crep == 0)
371 ret = "custom";
373 else
375 if (LUABIND_TYPE_INFO_EQUAL(i, crep->holder_type()))
377 ret += "smart_ptr<";
378 ret += crep->name();
379 ret += ">";
381 else if (LUABIND_TYPE_INFO_EQUAL(i, crep->const_holder_type()))
383 ret += "smart_ptr<const ";
384 ret += crep->name();
385 ret += ">";
387 else
389 ret += crep->name();
392 return ret;
395 }} // namespace luabind::detail