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
)
60 this->objects
.push_back(a
);
61 this->objects
.push_back(b
);
71 virtual ~scoped_sequence()
73 for (std::vector
<scoped_object
*>
74 ::const_iterator i
= this->objects
.begin()
75 ; i
!= this->objects
.end()
78 scoped_object
* ptr
= *i
;
83 scoped_sequence
& operator,(const scoped_object
& rhs
)
85 objects
.push_back(const_cast<scoped_object
&>(rhs
).clone());
89 virtual scoped_object
* clone()
91 scoped_sequence
* copy
= new scoped_sequence();
92 copy
->objects
.swap(this->objects
);
94 assert(!m_cloned
&& "You cannot register the scoped_object twice");
101 virtual void commit(lua_State
* L
)
103 assert(!m_cloned
&& "You cannot register the scoped_object twice");
105 for (std::vector
<scoped_object
*>
106 ::const_iterator i
= this->objects
.begin()
107 ; i
!= this->objects
.end()
110 scoped_object
* ptr
= *i
;
123 mutable std::vector
<scoped_object
*> objects
;
127 inline scoped_sequence
scoped_object::operator,(const scoped_object
& rhs
) const
129 return scoped_sequence(const_cast<scoped_object
*>(this)->clone(), const_cast<scoped_object
&>(rhs
).clone());
136 std::stack
<int> scopes
;
138 static int gc(lua_State
* L
)
140 scope_stack
* scopes
= static_cast<scope_stack
*>(
141 lua_touserdata(L
, -1)
144 assert(scopes
->scopes
.size() == 1);
146 int top
= scopes
->scopes
.top();
147 scopes
->scopes
.pop();
149 detail::unref(L
, top
);
151 scopes
->~scope_stack();
156 static int top(lua_State
* L
)
158 lua_pushstring(L
, "__luabind_scope_stack");
159 lua_gettable(L
, LUA_REGISTRYINDEX
);
161 scope_stack
* scopes
= static_cast<scope_stack
*>(
162 lua_touserdata(L
, -1)
167 return scopes
->scopes
.top();
170 static void push(lua_State
* L
)
172 lua_pushstring(L
, "__luabind_scope_stack");
173 lua_gettable(L
, LUA_REGISTRYINDEX
);
175 scope_stack
* scopes
= static_cast<scope_stack
*>(
176 lua_touserdata(L
, -1)
181 scopes
->scopes
.push(detail::ref(L
));
184 static void pop(lua_State
* L
)
186 lua_pushstring(L
, "__luabind_scope_stack");
187 lua_gettable(L
, LUA_REGISTRYINDEX
);
189 scope_stack
* scopes
= static_cast<scope_stack
*>(
190 lua_touserdata(L
, -1)
195 int n
= scopes
->scopes
.top();
196 scopes
->scopes
.pop();
201 class scope
: public detail::scoped_object
205 static void init(lua_State
* L
)
207 lua_pushstring(L
, "__luabind_scope_stack");
208 lua_gettable(L
, LUA_REGISTRYINDEX
);
210 scope_stack
* scopes
= static_cast<scope_stack
*>(
211 lua_touserdata(L
, -1)
218 scopes
= static_cast<scope_stack
*>(
219 lua_newuserdata(L
, sizeof(scope_stack
))
222 lua_pushstring(L
, "__luabind_scope_stack");
223 lua_pushvalue(L
, -2);
224 lua_settable(L
, LUA_REGISTRYINDEX
);
226 new (scopes
) scope_stack();
228 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
229 scopes
->scopes
.push(detail::ref(L
));
232 lua_pushstring(L
, "__gc");
233 lua_pushcclosure(L
, scope_stack::gc
, 0);
235 lua_setmetatable(L
, -2);
241 scope(lua_State
* L
, const char* name
)
251 scope(const char* name
)
262 for (std::vector
<detail::scoped_object
*>
263 ::const_iterator i
= m_children
.begin()
264 ; i
!= m_children
.end()
267 detail::scoped_object
* ptr
= *i
;
272 scope
& operator[](const detail::scoped_object
& x
)
274 m_children
.push_back(const_cast<detail::scoped_object
&>(x
).clone());
278 this->commit(m_state
);
280 for (std::vector
<detail::scoped_object
*>
281 ::const_iterator i
= m_children
.begin()
282 ; i
!= m_children
.end()
285 detail::scoped_object
* ptr
= *i
;
295 virtual detail::scoped_object
* clone()
297 assert(!m_cloned
&& "cannot register the same namespace twice");
301 std::vector
<detail::scoped_object
*> tmp
;
302 tmp
.swap(this->m_children
);
303 scope
* copy
= new scope(m_name
.c_str());
304 copy
->m_children
.swap(tmp
);
308 virtual void commit(lua_State
* L
)
310 assert(!m_cloned
&& "cannot register the same namespace twice");
316 detail::getref(L
, scope_stack::top(L
)); // get current scope
317 lua_pushstring(L
, m_name
.c_str());
319 lua_remove(L
, -2); // remove scope
321 if (lua_isnil(L
, -1))
326 detail::getref(L
, scope_stack::top(L
));
327 lua_pushstring(L
, m_name
.c_str());
328 lua_pushvalue(L
, -3);
333 scope_stack::push(L
);
335 for (std::vector
<detail::scoped_object
*>
336 ::const_iterator i
= m_children
.begin()
337 ; i
!= m_children
.end()
340 detail::scoped_object
* ptr
= *i
;
351 mutable std::vector
<detail::scoped_object
*> m_children
;
356 typedef scope namespace_
;
359 #endif // LUABIND_SCOPE_HPP_INCLUDED