*** empty log message ***
[luabind.git] / luabind / scope.hpp
blob74860e553b2b7d403b53b74afbb0dd5bd6076f3e
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
27 #include <vector>
28 #include <string>
29 #include <stack>
31 #include <luabind/detail/ref.hpp>
33 namespace luabind
35 namespace detail
37 struct scoped_sequence;
39 struct scoped_object
41 scoped_object() {}
42 virtual ~scoped_object() {}
44 virtual void commit(lua_State*) = 0;
45 virtual scoped_object* clone() = 0;
47 scoped_sequence operator,(const scoped_object& rhs) const;
50 struct scoped_sequence : scoped_object
52 scoped_sequence(scoped_object* a, scoped_object* b)
54 #ifndef NDEBUG
55 m_cloned = false;
56 #endif
57 this->objects.push_back(a);
58 this->objects.push_back(b);
61 scoped_sequence()
63 #ifndef NDEBUG
64 m_cloned = false;
65 #endif
68 virtual ~scoped_sequence()
70 for (std::vector<scoped_object*>
71 ::const_iterator i = this->objects.begin()
72 ; i != this->objects.end()
73 ; ++i)
75 scoped_object* ptr = *i;
76 delete ptr;
80 scoped_sequence& operator,(const scoped_object& rhs)
82 objects.push_back(const_cast<scoped_object&>(rhs).clone());
83 return *this;
86 virtual scoped_object* clone()
88 scoped_sequence* copy = new scoped_sequence();
89 copy->objects.swap(this->objects);
91 assert(!m_cloned && "You cannot register the scoped_object twice");
92 #ifndef NDEBUG
93 m_cloned = true;
94 #endif
95 return copy;
98 virtual void commit(lua_State* L)
100 assert(!m_cloned && "You cannot register the scoped_object twice");
102 for (std::vector<scoped_object*>
103 ::const_iterator i = this->objects.begin()
104 ; i != this->objects.end()
105 ; ++i)
107 scoped_object* ptr = *i;
108 ptr->commit(L);
110 #ifndef NDEBUG
111 m_cloned = false;
112 #endif
116 private:
117 #ifndef NDEBUG
118 bool m_cloned;
119 #endif
120 mutable std::vector<scoped_object*> objects;
124 inline scoped_sequence scoped_object::operator,(const scoped_object& rhs) const
126 return scoped_sequence(const_cast<scoped_object*>(this)->clone(), const_cast<scoped_object&>(rhs).clone());
131 struct scope_stack
133 std::stack<int> scopes;
135 static int gc(lua_State* L)
137 scope_stack* scopes = static_cast<scope_stack*>(
138 lua_touserdata(L, -1)
141 assert(scopes->scopes.size() == 0);
143 scopes->~scope_stack();
145 return 0;
148 static int top(lua_State* L)
150 lua_pushstring(L, "__luabind_scope_stack");
151 lua_gettable(L, LUA_REGISTRYINDEX);
153 scope_stack* scopes = static_cast<scope_stack*>(
154 lua_touserdata(L, -1)
157 lua_pop(L, 1);
159 return scopes->scopes.top();
162 static void push(lua_State* L)
164 lua_pushstring(L, "__luabind_scope_stack");
165 lua_gettable(L, LUA_REGISTRYINDEX);
167 scope_stack* scopes = static_cast<scope_stack*>(
168 lua_touserdata(L, -1)
171 lua_pop(L, 1);
173 scopes->scopes.push(detail::ref(L));
176 static void pop(lua_State* L)
178 lua_pushstring(L, "__luabind_scope_stack");
179 lua_gettable(L, LUA_REGISTRYINDEX);
181 scope_stack* scopes = static_cast<scope_stack*>(
182 lua_touserdata(L, -1)
185 lua_pop(L, 1);
187 int n = scopes->scopes.top();
188 scopes->scopes.pop();
189 detail::unref(L, n);
193 class scope : public detail::scoped_object
195 public:
197 static void init(lua_State* L)
199 lua_pushstring(L, "__luabind_scope_stack");
200 lua_gettable(L, LUA_REGISTRYINDEX);
202 scope_stack* scopes = static_cast<scope_stack*>(
203 lua_touserdata(L, -1)
206 lua_pop(L, 1);
208 if (scopes == 0)
210 scopes = static_cast<scope_stack*>(
211 lua_newuserdata(L, sizeof(scope_stack))
214 lua_pushstring(L, "__luabind_scope_stack");
215 lua_pushvalue(L, -2);
216 lua_settable(L, LUA_REGISTRYINDEX);
218 new (scopes) scope_stack();
220 lua_newtable(L);
221 lua_pushstring(L, "__gc");
222 lua_pushcclosure(L, scope_stack::gc, 0);
223 lua_settable(L, -3);
224 lua_setmetatable(L, -2);
226 lua_pop(L, 1);
230 scope(const char* name)
231 : m_name(name)
233 #ifndef NDEBUG
234 m_cloned = false;
235 #endif
238 ~scope()
240 for (std::vector<detail::scoped_object*>::iterator
241 i = m_children.begin(); i != m_children.end(); ++i)
243 delete *i;
247 scope& operator[](const detail::scoped_object& x)
249 detail::scoped_object* ptr = &const_cast<detail::scoped_object&>(x);
250 m_children.push_back(ptr->clone());
251 return *this;
254 virtual detail::scoped_object* clone()
256 assert(!m_cloned && "cannot register the same namespace twice");
257 #ifndef NDEBUG
258 m_cloned = true;
259 #endif
260 std::vector<detail::scoped_object*> tmp;
261 tmp.swap(this->m_children);
262 scope* copy = new scope(m_name);
263 copy->m_children.swap(tmp);
264 return copy;
267 virtual void commit(lua_State* L)
269 assert(!m_cloned && "cannot register the same namespace twice");
270 #ifndef NDEBUG
271 m_cloned = true;
272 #endif
273 init(L);
275 detail::getref(L, scope_stack::top(L)); // get current scope
276 lua_pushstring(L, m_name);
277 lua_gettable(L, -2);
278 lua_remove(L, -2); // remove scope
280 if (lua_isnil(L, -1))
282 lua_pop(L, 1);
284 lua_newtable(L);
285 detail::getref(L, scope_stack::top(L));
286 lua_pushstring(L, m_name);
287 lua_pushvalue(L, -3);
288 lua_settable(L, -3);
289 lua_pop(L, 1);
292 scope_stack::push(L);
294 for (std::vector<detail::scoped_object*>
295 ::const_iterator i = m_children.begin()
296 ; i != m_children.end()
297 ; ++i)
299 detail::scoped_object* ptr = *i;
300 ptr->commit(L);
301 delete ptr;
304 #ifndef NDEBUG
305 m_children.clear();
306 #endif
308 scope_stack::pop(L);
311 private:
312 #ifndef NDEBUG
313 bool m_cloned;
314 #endif
315 mutable std::vector<detail::scoped_object*> m_children;
316 const char* m_name;
325 class module_proxy
327 public:
329 module_proxy(lua_State* L, const char* name)
330 : m_state(L)
331 , m_name(name)
333 scope::init(L);
336 void operator[](const detail::scoped_object& x) const
338 lua_State* L = m_state;
339 if (m_name)
341 lua_pushstring(L, m_name);
342 lua_gettable(L, LUA_GLOBALSINDEX);
343 if (lua_isnil(L, -1))
345 lua_pop(L, 1);
346 // see if the table already exists
347 lua_newtable(L);
348 lua_pushstring(L, m_name);
349 lua_pushvalue(L, -2);
350 lua_settable(L, LUA_GLOBALSINDEX);
353 else
355 lua_pushvalue(L, LUA_GLOBALSINDEX);
358 scope_stack::push(L);
360 detail::scoped_object* ptr = &const_cast<detail::scoped_object&>(x);
361 ptr->commit(L);
363 scope_stack::pop(L);
366 private:
368 lua_State* m_state;
369 const char* m_name;
373 inline module_proxy module(lua_State* L) { return module_proxy(L,0); }
374 inline module_proxy module(lua_State* L, const char* name) { return module_proxy(L, name); }
376 typedef scope namespace_;
379 #endif // LUABIND_SCOPE_HPP_INCLUDED