*** empty log message ***
[luabind.git] / src / object.cpp
blob81e974770d9c81f1193787a74c8c4485633d304c
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 extern "C"
25 #include "lua.h"
28 #include <luabind/luabind.hpp>
29 #include <luabind/detail/implicit_cast.hpp>
31 using namespace luabind::detail;
33 namespace luabind
35 namespace detail
39 // *************************************
40 // PROXY OBJECT
42 #define LUABIND_PROXY_ASSIGNMENT_OPERATOR(rhs)\
43 proxy_object& proxy_object::operator=(const rhs& p) \
44 { \
45 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state"); \
46 lua_State* L = lua_state(); \
47 m_obj->pushvalue(); \
48 detail::getref(L, m_key_ref); \
49 p.pushvalue(); \
50 lua_settable(L, -3); \
51 lua_pop(L, 1); \
52 return *this; \
55 LUABIND_PROXY_ASSIGNMENT_OPERATOR(object)
56 LUABIND_PROXY_ASSIGNMENT_OPERATOR(proxy_object)
57 LUABIND_PROXY_ASSIGNMENT_OPERATOR(proxy_raw_object)
58 LUABIND_PROXY_ASSIGNMENT_OPERATOR(proxy_array_object)
60 #undef LUABIND_PROXY_ASSIGNMENT_OPERATOR
62 void proxy_object::pushvalue() const
64 assert((m_key_ref != LUA_NOREF) && "you cannot call pushvalue() on an uninitialized object");
66 lua_State* L = m_obj->lua_state();
67 m_obj->pushvalue();
68 detail::getref(L, m_key_ref);
69 lua_gettable(L, -2);
70 // remove the table and leave the value on top of the stack
71 lua_remove(L, -2);
74 void proxy_object::set() const
76 lua_State* L = lua_state();
77 m_obj->pushvalue();
78 detail::getref(L, m_key_ref);
79 lua_pushvalue(L, -3);
80 lua_settable(L, -3);
81 // pop table and value
82 lua_pop(L, 2);
87 // *************************************
88 // PROXY ARRAY OBJECT
92 #define LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(rhs)\
93 proxy_array_object& proxy_array_object::operator=(const rhs& p) \
94 { \
95 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state"); \
96 lua_State* L = lua_state(); \
97 m_obj->pushvalue(); \
98 p.pushvalue(); \
99 lua_rawseti(L, -2, m_key); \
100 lua_pop(L, 1); \
101 return *this; \
104 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(object)
105 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(proxy_object)
106 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(proxy_raw_object)
107 LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR(proxy_array_object)
109 #undef LUABIND_ARRAY_PROXY_ASSIGNMENT_OPERATOR
111 void proxy_array_object::pushvalue() const
113 // you are trying to dereference an invalid object
114 assert((m_key != LUA_NOREF) && "you cannot call pushvalue() on an uninitialized object");
116 lua_State* L = m_obj->lua_state();
117 m_obj->pushvalue();
118 lua_rawgeti(L, -1, m_key);
119 lua_remove(L, -2);
122 void proxy_array_object::set() const
124 lua_State* L = lua_state();
125 m_obj->pushvalue();
126 lua_pushvalue(L, -2);
127 lua_rawseti(L, -2, m_key);
128 // pop table and value
129 lua_pop(L, 2);
133 // *************************************
134 // PROXY RAW OBJECT
137 #define LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(rhs)\
138 proxy_raw_object& proxy_raw_object::operator=(const rhs& p) \
140 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state"); \
141 lua_State* L = lua_state(); \
142 m_obj->pushvalue(); \
143 detail::getref(L, m_key_ref); \
144 p.pushvalue(); \
145 lua_rawset(L, -3); \
146 lua_pop(L, 1); \
147 return *this; \
150 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(object)
151 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(proxy_object)
152 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(proxy_raw_object)
153 LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR(proxy_array_object)
155 #undef LUABIND_RAW_PROXY_ASSIGNMENT_OPERATOR
157 void proxy_raw_object::pushvalue() const
159 assert((m_key_ref != LUA_NOREF) && "you cannot call pushvalue() on an uninitiallized object");
161 lua_State* L = lua_state();
162 m_obj->pushvalue();
163 detail::getref(L, m_key_ref);
164 lua_rawget(L, -2);
165 // remove the table and leave the value on top of the stack
166 lua_remove(L, -2);
169 void proxy_raw_object::set() const
171 lua_State* L = lua_state();
172 m_obj->pushvalue();
173 detail::getref(L, m_key_ref);
174 lua_pushvalue(L, -3);
175 lua_rawset(L, -3);
176 // pop table and value
177 lua_pop(L, 2);
180 } // detail
182 #define LUABIND_DECLARE_OPERATOR(MACRO)\
183 MACRO(object, object) \
184 MACRO(object, detail::proxy_object) \
185 MACRO(object, detail::proxy_array_object) \
186 MACRO(object, detail::proxy_raw_object) \
187 MACRO(detail::proxy_object, object) \
188 MACRO(detail::proxy_object, detail::proxy_object) \
189 MACRO(detail::proxy_object, detail::proxy_array_object) \
190 MACRO(detail::proxy_object, detail::proxy_raw_object) \
191 MACRO(detail::proxy_array_object, object) \
192 MACRO(detail::proxy_array_object, detail::proxy_object) \
193 MACRO(detail::proxy_array_object, detail::proxy_array_object) \
194 MACRO(detail::proxy_array_object, detail::proxy_raw_object) \
195 MACRO(detail::proxy_raw_object, object) \
196 MACRO(detail::proxy_raw_object, detail::proxy_object) \
197 MACRO(detail::proxy_raw_object, detail::proxy_array_object) \
198 MACRO(detail::proxy_raw_object, detail::proxy_raw_object)
201 // *****************************
202 // OPERATOR ==
206 #define LUABIND_EQUALITY_OPERATOR(lhs_t, rhs_t)\
207 bool operator==(const lhs_t& lhs, const rhs_t& rhs) \
209 if (!lhs.is_valid()) return false; \
210 if (!rhs.is_valid()) return false; \
211 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot compare objects from different lua states"); \
212 lua_State* L = lhs.lua_state(); \
213 lhs.pushvalue(); \
214 rhs.pushvalue(); \
215 bool result = lua_equal(L, -1, -2) != 0; \
216 lua_pop(L, 2); \
217 return result; \
220 LUABIND_DECLARE_OPERATOR(LUABIND_EQUALITY_OPERATOR)
222 #undef LUABIND_EQUALITY_OPERATOR
225 // *****************************
226 // OPERATOR =
228 #define LUABIND_ASSIGNMENT_OPERATOR(rhs)\
229 object& object::operator=(const rhs& o) const \
231 m_state = o.lua_state(); \
232 o.pushvalue(); \
233 set(); \
234 return const_cast<luabind::object&>(*this); \
237 LUABIND_ASSIGNMENT_OPERATOR(object)
238 LUABIND_ASSIGNMENT_OPERATOR(proxy_object)
239 LUABIND_ASSIGNMENT_OPERATOR(proxy_array_object)
240 LUABIND_ASSIGNMENT_OPERATOR(proxy_raw_object)
244 // *****************************
245 // OPERATOR ==
249 #define LUABIND_LESSTHAN_OPERATOR(lhs_t, rhs_t)\
250 bool operator<(const lhs_t& lhs, const rhs_t& rhs) \
252 if (!lhs.is_valid()) return false; \
253 if (!rhs.is_valid()) return false; \
254 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot compare objects from different lua states"); \
255 lua_State* L = lhs.lua_state(); \
256 lhs.pushvalue(); \
257 rhs.pushvalue(); \
258 bool result = lua_lessthan(L, -1, -2) != 0; \
259 lua_pop(L, 2); \
260 return result; \
263 LUABIND_DECLARE_OPERATOR(LUABIND_LESSTHAN_OPERATOR)
265 #undef LUABIND_LESSTHAN_OPERATOR
267 #define LUABIND_LESSOREQUAL_OPERATOR(lhs_t, rhs_t)\
268 bool operator<=(const lhs_t& lhs, const rhs_t& rhs) \
270 if (!lhs.is_valid()) return false; \
271 if (!rhs.is_valid()) return false; \
272 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot compare objects from different lua states"); \
273 lua_State* L = lhs.lua_state(); \
274 lhs.pushvalue(); \
275 rhs.pushvalue(); \
276 bool result1 = lua_lessthan(L, -1, -2) != 0; \
277 bool result2 = lua_equal(L, -1, -2) != 0; \
278 lua_pop(L, 2); \
279 return result1 || result2; \
282 LUABIND_DECLARE_OPERATOR(LUABIND_LESSOREQUAL_OPERATOR)
284 #undef LUABIND_LESSOREQUAL_OPERATOR
286 #undef LUABIND_GREATERTHAN_OPERATOR
289 #undef LUABIND_DECLARE_OPERATOR