fixed leaking lua-references as reported by Tom Spilman.
[luabind.git] / src / object.cpp
blob89ea4b32dbda7ee6ce7ceda3c435052ca5273976
1 // Copyright (c) 2003 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/luabind.hpp>
28 #include <luabind/detail/implicit_cast.hpp>
30 using namespace luabind::detail;
32 namespace luabind
34 namespace detail
38 // *************************************
39 // PROXY OBJECT
41 #define LUABIND_PROXY_ASSIGNMENT_OPERATOR(rhs)\
42 proxy_object& proxy_object::operator=(const rhs& p) \
43 { \
44 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state"); \
45 lua_State* L = lua_state(); \
46 m_obj->pushvalue(); \
47 m_key.get(L);\
48 p.pushvalue(); \
49 lua_settable(L, -3); \
50 lua_pop(L, 1); \
51 return *this; \
54 LUABIND_PROXY_ASSIGNMENT_OPERATOR(object)
55 LUABIND_PROXY_ASSIGNMENT_OPERATOR(proxy_object)
56 LUABIND_PROXY_ASSIGNMENT_OPERATOR(proxy_raw_object)
57 LUABIND_PROXY_ASSIGNMENT_OPERATOR(proxy_array_object)
59 #undef LUABIND_PROXY_ASSIGNMENT_OPERATOR
61 void proxy_object::pushvalue() const
63 assert((m_key.is_valid()) && "you cannot call pushvalue() on an uninitialized object");
65 lua_State* L = m_obj->lua_state();
66 m_obj->pushvalue();
67 m_key.get(L);
68 lua_gettable(L, -2);
69 // remove the table and leave the value on top of the stack
70 lua_remove(L, -2);
73 void proxy_object::set() const
75 lua_State* L = lua_state();
76 m_obj->pushvalue();
77 m_key.get(L);
78 lua_pushvalue(L, -3);
79 lua_settable(L, -3);
80 // pop table and value
81 lua_pop(L, 2);
86 // *************************************
87 // PROXY ARRAY OBJECT
91 #define LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(rhs)\
92 proxy_array_object& proxy_array_object::operator=(const rhs& p) \
93 { \
94 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state"); \
95 lua_State* L = lua_state(); \
96 m_obj->pushvalue(); \
97 p.pushvalue(); \
98 lua_rawseti(L, -2, m_key); \
99 lua_pop(L, 1); \
100 return *this; \
103 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(object)
104 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(proxy_object)
105 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(proxy_raw_object)
106 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(proxy_array_object)
108 #undef LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR
110 void proxy_array_object::pushvalue() const
112 // you are trying to dereference an invalid object
113 assert((m_key != LUA_NOREF) && "you cannot call pushvalue() on an uninitialized object");
115 lua_State* L = m_obj->lua_state();
116 m_obj->pushvalue();
117 lua_rawgeti(L, -1, m_key);
118 lua_remove(L, -2);
121 void proxy_array_object::set() const
123 lua_State* L = lua_state();
124 m_obj->pushvalue();
125 lua_pushvalue(L, -2);
126 lua_rawseti(L, -2, m_key);
127 // pop table and value
128 lua_pop(L, 2);
132 // *************************************
133 // PROXY RAW OBJECT
136 #define LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(rhs)\
137 proxy_raw_object& proxy_raw_object::operator=(const rhs& p) \
139 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state"); \
140 lua_State* L = lua_state(); \
141 m_obj->pushvalue(); \
142 m_key.get(L);\
143 p.pushvalue(); \
144 lua_rawset(L, -3); \
145 lua_pop(L, 1); \
146 return *this; \
149 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(object)
150 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(proxy_object)
151 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(proxy_raw_object)
152 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(proxy_array_object)
154 #undef LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR
156 void proxy_raw_object::pushvalue() const
158 assert((m_key.is_valid()) && "you cannot call pushvalue() on an uninitiallized object");
160 lua_State* L = lua_state();
161 m_obj->pushvalue();
162 m_key.get(L);
163 lua_rawget(L, -2);
164 // remove the table and leave the value on top of the stack
165 lua_remove(L, -2);
168 void proxy_raw_object::set() const
170 lua_State* L = lua_state();
171 m_obj->pushvalue();
172 m_key.get(L);
173 lua_pushvalue(L, -3);
174 lua_rawset(L, -3);
175 // pop table and value
176 lua_pop(L, 2);
179 } // detail
181 #define LUABIND_DECLARE_OPERATOR(MACRO)\
182 MACRO(object, object) \
183 MACRO(object, detail::proxy_object) \
184 MACRO(object, detail::proxy_array_object) \
185 MACRO(object, detail::proxy_raw_object) \
186 MACRO(detail::proxy_object, object) \
187 MACRO(detail::proxy_object, detail::proxy_object) \
188 MACRO(detail::proxy_object, detail::proxy_array_object) \
189 MACRO(detail::proxy_object, detail::proxy_raw_object) \
190 MACRO(detail::proxy_array_object, object) \
191 MACRO(detail::proxy_array_object, detail::proxy_object) \
192 MACRO(detail::proxy_array_object, detail::proxy_array_object) \
193 MACRO(detail::proxy_array_object, detail::proxy_raw_object) \
194 MACRO(detail::proxy_raw_object, object) \
195 MACRO(detail::proxy_raw_object, detail::proxy_object) \
196 MACRO(detail::proxy_raw_object, detail::proxy_array_object) \
197 MACRO(detail::proxy_raw_object, detail::proxy_raw_object)
200 // *****************************
201 // OPERATOR ==
205 #define LUABIND_EQUALITY_OPERATOR(lhs_t, rhs_t)\
206 bool operator==(const lhs_t& lhs, const rhs_t& rhs) \
208 if (!lhs.is_valid()) return false; \
209 if (!rhs.is_valid()) return false; \
210 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot compare objects from different lua states"); \
211 lua_State* L = lhs.lua_state(); \
212 lhs.pushvalue(); \
213 rhs.pushvalue(); \
214 bool result = lua_equal(L, -1, -2) != 0; \
215 lua_pop(L, 2); \
216 return result; \
219 LUABIND_DECLARE_OPERATOR(LUABIND_EQUALITY_OPERATOR)
221 #undef LUABIND_EQUALITY_OPERATOR
224 // *****************************
225 // OPERATOR =
227 #define LUABIND_ASSIGNMENT_OPERATOR(rhs)\
228 object& object::operator=(const rhs& o) const \
230 m_state = o.lua_state(); \
231 o.pushvalue(); \
232 set(); \
233 return const_cast<luabind::object&>(*this); \
236 LUABIND_ASSIGNMENT_OPERATOR(object)
237 LUABIND_ASSIGNMENT_OPERATOR(proxy_object)
238 LUABIND_ASSIGNMENT_OPERATOR(proxy_array_object)
239 LUABIND_ASSIGNMENT_OPERATOR(proxy_raw_object)
243 // *****************************
244 // OPERATOR ==
248 #define LUABIND_LESSTHAN_OPERATOR(lhs_t, rhs_t)\
249 bool operator<(const lhs_t& lhs, const rhs_t& rhs) \
251 if (!lhs.is_valid()) return false; \
252 if (!rhs.is_valid()) return false; \
253 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot compare objects from different lua states"); \
254 lua_State* L = lhs.lua_state(); \
255 lhs.pushvalue(); \
256 rhs.pushvalue(); \
257 bool result = lua_lessthan(L, -1, -2) != 0; \
258 lua_pop(L, 2); \
259 return result; \
262 LUABIND_DECLARE_OPERATOR(LUABIND_LESSTHAN_OPERATOR)
264 #undef LUABIND_LESSTHAN_OPERATOR
266 #define LUABIND_LESSOREQUAL_OPERATOR(lhs_t, rhs_t)\
267 bool operator<=(const lhs_t& lhs, const rhs_t& rhs) \
269 if (!lhs.is_valid()) return false; \
270 if (!rhs.is_valid()) return false; \
271 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot compare objects from different lua states"); \
272 lua_State* L = lhs.lua_state(); \
273 lhs.pushvalue(); \
274 rhs.pushvalue(); \
275 bool result1 = lua_lessthan(L, -1, -2) != 0; \
276 bool result2 = lua_equal(L, -1, -2) != 0; \
277 lua_pop(L, 2); \
278 return result1 || result2; \
281 LUABIND_DECLARE_OPERATOR(LUABIND_LESSOREQUAL_OPERATOR)
283 #undef LUABIND_LESSOREQUAL_OPERATOR
285 #undef LUABIND_GREATERTHAN_OPERATOR
288 #undef LUABIND_DECLARE_OPERATOR