moved some headers out of detail/
[luabind.git] / src / class.cpp
blob9c97759c6987f95a2c1bc8ada514186f3ba0e1b6
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 #define LUABIND_BUILDING
27 #include <luabind/config.hpp>
28 #include <luabind/class.hpp>
30 namespace luabind { namespace detail {
32 struct class_registration : registration
34 class_registration(char const* name);
36 void register_(lua_State* L) const;
38 const char* m_name;
40 mutable std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
42 // datamembers, some members may be readonly, and
43 // only have a getter function
44 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
45 mutable std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
47 // the operators in lua
48 mutable std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
49 mutable std::map<const char*, int, detail::ltstr> m_static_constants;
51 mutable std::vector<class_base::base_desc> m_bases;
52 mutable detail::construct_rep m_constructor;
54 void(*m_destructor)(void*);
55 void(*m_const_holder_destructor)(void*);
57 void*(*m_extractor)(void*);
58 const void*(*m_const_extractor)(void*);
60 void(*m_const_converter)(void*,void*);
62 void(*m_construct_holder)(void*, void*);
63 void(*m_construct_const_holder)(void*, void*);
65 int m_holder_size;
66 int m_holder_alignment;
68 LUABIND_TYPE_INFO m_type;
69 LUABIND_TYPE_INFO m_holder_type;
70 LUABIND_TYPE_INFO m_const_holder_type;
72 #ifndef LUABIND_DONT_COPY_STRINGS
73 // the maps that contains char pointers points into
74 // this vector of strings.
75 mutable std::vector<char*> m_strings;
76 #endif
77 scope m_scope;
80 class_registration::class_registration(char const* name)
82 #ifndef LUABIND_DONT_COPY_STRINGS
83 m_strings.push_back(detail::dup_string(name));
84 m_name = m_strings.back();
85 #else
86 m_name = name;
87 #endif
90 void class_registration::register_(lua_State* L) const
92 lua_pushstring(L, m_name);
94 detail::class_rep* crep;
96 detail::class_registry* r = detail::class_registry::get_registry(L);
97 // create a class_rep structure for this class.
98 // allocate it within lua to let lua collect it on
99 // lua_close(). This is better than allocating it
100 // as a static, since it will then be destructed
101 // when the program exits instead.
102 // warning: we assume that lua will not
103 // move the userdata memory.
104 lua_newuserdata(L, sizeof(detail::class_rep));
105 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
107 new(crep) detail::class_rep(
108 m_type
109 , m_name
111 , m_destructor
112 , m_const_holder_destructor
113 , m_holder_type
114 , m_const_holder_type
115 , m_extractor
116 , m_const_extractor
117 , m_const_converter
118 , m_construct_holder
119 , m_construct_const_holder
120 , m_holder_size
121 , m_holder_alignment);
123 // register this new type in the class registry
124 r->add_class(m_type, crep);
125 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
127 // if we have a held type
128 // we have to register it in the class-table
129 // but only for the base class, if it already
130 // exists, we don't have to register it
131 detail::class_rep* c = r->find_class(m_holder_type);
132 if (c == 0)
134 r->add_class(m_holder_type, crep);
135 r->add_class(m_const_holder_type, crep);
139 // constructors
140 m_constructor.swap(crep->m_constructor);
142 #ifndef LUABIND_DONT_COPY_STRINGS
143 assert(crep->m_strings.empty() && "Internal error");
144 crep->m_strings.swap(m_strings);
145 #endif
147 crep->m_getters.swap(m_getters);
148 crep->m_setters.swap(m_setters);
150 for(int i = 0; i < detail::number_of_operators; ++i)
151 crep->m_operators[i].swap(m_operators[i]);
153 crep->m_static_constants.swap(m_static_constants);
155 // here!
156 // crep->m_methods = m_methods;
158 for (std::vector<class_base::base_desc>::iterator i = m_bases.begin();
159 i != m_bases.end();
160 ++i)
162 detail::class_registry* r = detail::class_registry::get_registry(L);
164 // the baseclass' class_rep structure
165 detail::class_rep* bcrep = r->find_class(i->type);
167 detail::class_rep::base_info base;
168 base.pointer_offset = i->ptr_offset;
169 base.base = bcrep;
171 crep->add_base_class(base);
173 typedef std::map<const char*, detail::method_rep, detail::ltstr> methods_t;
175 for (methods_t::const_iterator i
176 = bcrep->m_methods.begin()
177 ; i != bcrep->m_methods.end()
178 ; ++i)
180 detail::method_rep& m = m_methods[i->first];
182 typedef std::vector<detail::overload_rep> overloads_t;
184 for (overloads_t::const_iterator j
185 = i->second.overloads().begin()
186 ; j != i->second.overloads().end()
187 ; ++j)
189 detail::overload_rep o = *j;
190 o.add_offset(base.pointer_offset);
191 m.add_overload(o);
195 // copy base class table
196 detail::getref(L, crep->table_ref());
197 detail::getref(L, bcrep->table_ref());
198 lua_pushnil(L);
200 while (lua_next(L, -2))
202 lua_pushvalue(L, -2); // copy key
203 lua_insert(L, -2);
204 lua_settable(L, -5);
207 lua_pop(L, 2);
210 crep->m_methods = m_methods;
212 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
213 = crep->m_methods.begin(); i != crep->m_methods.end(); ++i)
215 i->second.crep = crep;
218 // add methods
219 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
220 = m_methods.begin(); i != m_methods.end(); ++i)
222 detail::getref(L, crep->table_ref());
223 lua_pushstring(L, i->first);
224 lua_pushnil(L);
225 lua_settable(L, -3);
226 lua_pop(L, 1);
228 crep->add_method(L, i->first, crep->m_methods[i->first]);
229 i->second.crep = crep;
232 m_methods.clear();
234 detail::getref(L, crep->table_ref());
235 m_scope.register_(L);
236 lua_pop(L, 1);
238 lua_settable(L, -3);
241 // -- interface ---------------------------------------------------------
243 class_base::class_base(char const* name)
244 : scope(std::auto_ptr<registration>(
245 m_registration = new class_registration(name))
250 void class_base::init(
251 LUABIND_TYPE_INFO type_
252 , LUABIND_TYPE_INFO holder_type
253 , LUABIND_TYPE_INFO const_holder_type
254 , void*(*extractor)(void*)
255 , const void*(*const_extractor)(void*)
256 , void(*const_converter_)(void*,void*)
257 , void(*holder_constructor_)(void*,void*)
258 , void(*const_holder_constructor_)(void*,void*)
259 , void(*destructor)(void*)
260 , void(*const_holder_destructor)(void*)
261 , int holder_size
262 , int holder_alignment)
264 m_registration->m_type = type_;
265 m_registration->m_holder_type = holder_type;
266 m_registration->m_const_holder_type = const_holder_type;
267 m_registration->m_extractor = extractor;
268 m_registration->m_const_extractor = const_extractor;
269 m_registration->m_const_converter = const_converter_;
270 m_registration->m_construct_holder = holder_constructor_;
271 m_registration->m_construct_const_holder = const_holder_constructor_;
272 m_registration->m_destructor = destructor;
273 m_registration->m_const_holder_destructor = const_holder_destructor;
274 m_registration->m_holder_size = holder_size;
275 m_registration->m_holder_alignment = holder_alignment;
278 void class_base::add_getter(
279 const char* name, const boost::function2<int, lua_State*, int>& g)
281 detail::class_rep::callback c;
282 c.func = g;
283 c.pointer_offset = 0;
285 #ifndef LUABIND_DONT_COPY_STRINGS
286 char* key = detail::dup_string(name);
287 m_registration->m_strings.push_back(key);
288 #else
289 const char* key = name;
290 #endif
291 m_registration->m_getters[key] = c;
294 #ifdef LUABIND_NO_ERROR_CHECKING
295 void class_base::add_setter(
296 const char* name
297 , const boost::function2<int, lua_State*, int>& s)
298 #else
299 void class_base::add_setter(
300 const char* name
301 , const boost::function2<int, lua_State*, int>& s
302 , int (*match)(lua_State*, int)
303 , void (*get_sig_ptr)(lua_State*, std::string&))
304 #endif
306 detail::class_rep::callback c;
307 c.func = s;
308 c.pointer_offset = 0;
310 #ifndef LUABIND_NO_ERROR_CHECKING
311 c.match = match;
312 c.sig = get_sig_ptr;
313 #endif
315 #ifndef LUABIND_DONT_COPY_STRINGS
316 char* key = detail::dup_string(name);
317 m_registration->m_strings.push_back(key);
318 #else
319 const char* key = name;
320 #endif
321 m_registration->m_setters[key] = c;
324 void class_base::add_base(const base_desc& b)
326 m_registration->m_bases.push_back(b);
329 void class_base::add_constructor(const detail::construct_rep::overload_t& o)
331 m_registration->m_constructor.overloads.push_back(o);
334 void class_base::add_method(const char* name, const detail::overload_rep& o)
336 #ifdef LUABIND_DONT_COPY_STRINGS
337 detail::method_rep& method = m_registration->m_methods[name];
338 method.name = name;
339 #else
340 m_registration->m_strings.push_back(detail::dup_string(name));
341 detail::method_rep& method = m_registration->m_methods[
342 m_registration->m_strings.back()];
343 method.name = m_registration->m_strings.back();
344 #endif
345 method.add_overload(o);
346 method.crep = 0;
349 #ifndef LUABIND_NO_ERROR_CHECKING
350 void class_base::add_operator(
351 int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*)
352 , void(*sig)(lua_State*, std::string&), int arity)
353 #else
354 void class_base::add_operator(
355 int op_id, int(*func)(lua_State*)
356 , int(*matcher)(lua_State*), int arity)
357 #endif
359 detail::class_rep::operator_callback o;
360 o.set_fun(func);
361 o.set_match_fun(matcher);
362 o.set_arity(arity);
364 #ifndef LUABIND_NO_ERROR_CHECKING
366 o.set_sig_fun(sig);
368 #endif
369 m_registration->m_operators[op_id].push_back(o);
372 const char* class_base::name() const
374 return m_registration->m_name;
377 void class_base::add_static_constant(const char* name, int val)
379 m_registration->m_static_constants[name] = val;
382 void class_base::add_inner_scope(scope& s)
384 m_registration->m_scope.operator,(s);
387 }} // namespace luabind::detail