revised scope documentation and added smart pointer documentation.
[luabind.git] / luabind / scope.hpp
blobfac0d1af84678a1065bb71f9a56a88dc0053cdc5
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()
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 #ifndef NDEBUG
58 m_cloned = false;
59 #endif
60 this->objects.push_back(a);
61 this->objects.push_back(b);
64 scoped_sequence()
66 #ifndef NDEBUG
67 m_cloned = false;
68 #endif
71 virtual ~scoped_sequence()
73 for (std::vector<scoped_object*>
74 ::const_iterator i = this->objects.begin()
75 ; i != this->objects.end()
76 ; ++i)
78 scoped_object* ptr = *i;
79 delete ptr;
83 scoped_sequence& operator,(const scoped_object& rhs)
85 objects.push_back(const_cast<scoped_object&>(rhs).clone());
86 return *this;
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");
95 #ifndef NDEBUG
96 m_cloned = true;
97 #endif
98 return copy;
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()
108 ; ++i)
110 scoped_object* ptr = *i;
111 ptr->commit(L);
113 #ifndef NDEBUG
114 m_cloned = false;
115 #endif
119 private:
120 #ifndef NDEBUG
121 bool m_cloned;
122 #endif
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());
134 struct scope_stack
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();
153 return 0;
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)
165 lua_pop(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)
179 lua_pop(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)
193 lua_pop(L, 1);
195 int n = scopes->scopes.top();
196 scopes->scopes.pop();
197 detail::unref(L, n);
201 class scope : public detail::scoped_object
203 public:
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)
214 lua_pop(L, 1);
216 if (scopes == 0)
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));
231 lua_newtable(L);
232 lua_pushstring(L, "__gc");
233 lua_pushcclosure(L, scope_stack::gc, 0);
234 lua_settable(L, -3);
235 lua_setmetatable(L, -2);
237 lua_pop(L, 1);
241 scope(lua_State* L, const char* name)
242 : m_state(L)
243 , m_name(name)
245 #ifndef NDEBUG
246 m_cloned = false;
247 #endif
248 init(L);
251 scope(const char* name)
252 : m_state(0)
253 , m_name(name)
255 #ifndef NDEBUG
256 m_cloned = false;
257 #endif
260 virtual ~scope()
262 for (std::vector<detail::scoped_object*>
263 ::const_iterator i = m_children.begin()
264 ; i != m_children.end()
265 ; ++i)
267 detail::scoped_object* ptr = *i;
268 delete ptr;
272 scope& operator[](const detail::scoped_object& x)
274 m_children.push_back(const_cast<detail::scoped_object&>(x).clone());
276 if (m_state)
278 this->commit(m_state);
280 for (std::vector<detail::scoped_object*>
281 ::const_iterator i = m_children.begin()
282 ; i != m_children.end()
283 ; ++i)
285 detail::scoped_object* ptr = *i;
286 delete ptr;
289 m_children.clear();
292 return *this;
295 virtual detail::scoped_object* clone()
297 assert(!m_cloned && "cannot register the same namespace twice");
298 #ifndef NDEBUG
299 m_cloned = true;
300 #endif
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);
305 return copy;
308 virtual void commit(lua_State* L)
310 assert(!m_cloned && "cannot register the same namespace twice");
311 #ifndef NDEBUG
312 m_cloned = true;
313 #endif
314 init(L);
316 detail::getref(L, scope_stack::top(L)); // get current scope
317 lua_pushstring(L, m_name.c_str());
318 lua_gettable(L, -2);
319 lua_remove(L, -2); // remove scope
321 if (lua_isnil(L, -1))
323 lua_pop(L, 1);
325 lua_newtable(L);
326 detail::getref(L, scope_stack::top(L));
327 lua_pushstring(L, m_name.c_str());
328 lua_pushvalue(L, -3);
329 lua_settable(L, -3);
330 lua_pop(L, 1);
333 scope_stack::push(L);
335 for (std::vector<detail::scoped_object*>
336 ::const_iterator i = m_children.begin()
337 ; i != m_children.end()
338 ; ++i)
340 detail::scoped_object* ptr = *i;
341 ptr->commit(L);
344 scope_stack::pop(L);
347 private:
348 #ifndef NDEBUG
349 bool m_cloned;
350 #endif
351 mutable std::vector<detail::scoped_object*> m_children;
352 lua_State* m_state;
353 std::string m_name;
356 typedef scope namespace_;
359 #endif // LUABIND_SCOPE_HPP_INCLUDED