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.
24 #ifndef LUABIND_SCOPE_HPP_INCLUDED
25 #define LUABIND_SCOPE_HPP_INCLUDED
31 #include <luabind/detail/ref.hpp>
37 struct scoped_sequence
;
45 virtual ~scoped_object() {}
47 virtual void commit(lua_State
*) = 0;
48 virtual scoped_object
* clone() = 0;
50 scoped_sequence
operator,(const scoped_object
& rhs
) const;
53 struct scoped_sequence
: scoped_object
55 scoped_sequence(scoped_object
* a
, scoped_object
* b
)
57 this->objects
.push_back(a
);
58 this->objects
.push_back(b
);
63 virtual ~scoped_sequence()
65 for (std::vector
<scoped_object
*>
66 ::const_iterator i
= this->objects
.begin()
67 ; i
!= this->objects
.end()
70 scoped_object
* ptr
= *i
;
75 scoped_sequence
& operator,(const scoped_object
& rhs
)
77 objects
.push_back(const_cast<scoped_object
&>(rhs
).clone());
81 virtual scoped_object
* clone()
83 scoped_sequence
* copy
= new scoped_sequence();
84 copy
->objects
.swap(this->objects
);
88 virtual void commit(lua_State
* L
)
90 for (std::vector
<scoped_object
*>
91 ::const_iterator i
= this->objects
.begin()
92 ; i
!= this->objects
.end()
95 scoped_object
* ptr
= *i
;
100 mutable std::vector
<scoped_object
*> objects
;
103 inline scoped_sequence
scoped_object::operator,(const scoped_object
& rhs
) const
105 return scoped_sequence(const_cast<scoped_object
*>(this)->clone(), const_cast<scoped_object
&>(rhs
).clone());
111 std::stack
<int> scopes
;
113 static int gc(lua_State
* L
)
115 scope_stack
* scopes
= static_cast<scope_stack
*>(
116 lua_touserdata(L
, -1)
119 assert(scopes
->scopes
.size() == 1);
121 int top
= scopes
->scopes
.top();
122 scopes
->scopes
.pop();
124 detail::unref(L
, top
);
126 scopes
->~scope_stack();
131 static int top(lua_State
* L
)
133 lua_pushstring(L
, "__luabind_scope_stack");
134 lua_gettable(L
, LUA_REGISTRYINDEX
);
136 scope_stack
* scopes
= static_cast<scope_stack
*>(
137 lua_touserdata(L
, -1)
142 return scopes
->scopes
.top();
145 static void push(lua_State
* L
)
147 lua_pushstring(L
, "__luabind_scope_stack");
148 lua_gettable(L
, LUA_REGISTRYINDEX
);
150 scope_stack
* scopes
= static_cast<scope_stack
*>(
151 lua_touserdata(L
, -1)
156 scopes
->scopes
.push(detail::ref(L
));
159 static void pop(lua_State
* L
)
161 lua_pushstring(L
, "__luabind_scope_stack");
162 lua_gettable(L
, LUA_REGISTRYINDEX
);
164 scope_stack
* scopes
= static_cast<scope_stack
*>(
165 lua_touserdata(L
, -1)
170 int n
= scopes
->scopes
.top();
171 scopes
->scopes
.pop();
176 class scope
: public detail::scoped_object
180 static void init(lua_State
* L
)
182 lua_pushstring(L
, "__luabind_scope_stack");
183 lua_gettable(L
, LUA_REGISTRYINDEX
);
185 scope_stack
* scopes
= static_cast<scope_stack
*>(
186 lua_touserdata(L
, -1)
193 scopes
= static_cast<scope_stack
*>(
194 lua_newuserdata(L
, sizeof(scope_stack
))
197 lua_pushstring(L
, "__luabind_scope_stack");
198 lua_pushvalue(L
, -2);
199 lua_settable(L
, LUA_REGISTRYINDEX
);
201 new (scopes
) scope_stack();
203 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
204 scopes
->scopes
.push(detail::ref(L
));
207 lua_pushstring(L
, "__gc");
208 lua_pushcclosure(L
, scope_stack::gc
, 0);
210 lua_setmetatable(L
, -2);
216 scope(lua_State
* L
, const char* name
)
223 scope(const char* name
)
231 for (std::vector
<detail::scoped_object
*>
232 ::const_iterator i
= m_children
.begin()
233 ; i
!= m_children
.end()
236 detail::scoped_object
* ptr
= *i
;
241 scope
& operator[](detail::scoped_object
& x
)
243 m_children
.push_back(x
.clone());
247 this->commit(m_state
);
249 for (std::vector
<detail::scoped_object
*>
250 ::const_iterator i
= m_children
.begin()
251 ; i
!= m_children
.end()
254 detail::scoped_object
* ptr
= *i
;
264 virtual detail::scoped_object
* clone()
266 std::vector
<detail::scoped_object
*> tmp
;
267 tmp
.swap(this->m_children
);
268 scope
* copy
= new scope(m_name
.c_str());
269 copy
->m_children
.swap(tmp
);
273 virtual void commit(lua_State
* L
)
277 detail::getref(L
, scope_stack::top(L
)); // get current scope
278 lua_pushstring(L
, m_name
.c_str());
280 lua_remove(L
, -2); // remove scope
282 if (lua_isnil(L
, -1))
287 detail::getref(L
, scope_stack::top(L
));
288 lua_pushstring(L
, m_name
.c_str());
289 lua_pushvalue(L
, -3);
294 scope_stack::push(L
);
296 for (std::vector
<detail::scoped_object
*>
297 ::const_iterator i
= m_children
.begin()
298 ; i
!= m_children
.end()
301 detail::scoped_object
* ptr
= *i
;
310 mutable std::vector
<detail::scoped_object
*> m_children
;
315 typedef scope namespace_
;
318 #endif // LUABIND_SCOPE_HPP_INCLUDED