From 8f88d054647d529663194a39982cf0b7520dd322 Mon Sep 17 00:00:00 2001 From: Daniel Wallin Date: Sun, 11 Nov 2007 22:41:29 +0000 Subject: [PATCH] fixed #54. Rewrote `iterator_policy.hpp`. Now properly destroys iterators. The downside is that it's less efficient. --- luabind/iterator_policy.hpp | 235 +++++++++++++++++++++----------------------- 1 file changed, 114 insertions(+), 121 deletions(-) rewrite luabind/iterator_policy.hpp (99%) diff --git a/luabind/iterator_policy.hpp b/luabind/iterator_policy.hpp dissimilarity index 99% index ce50190..ad43d2a 100755 --- a/luabind/iterator_policy.hpp +++ b/luabind/iterator_policy.hpp @@ -1,121 +1,114 @@ -// Copyright (c) 2003 Daniel Wallin and Arvid Norberg - -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. - - -#ifndef LUABIND_ITERATOR_POLICY_HPP_INCLUDED -#define LUABIND_ITERATOR_POLICY_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace luabind { namespace detail -{ - template - struct iterator_state - { - typedef iterator_state self_t; - - static int step(lua_State* L) - { - self_t& state = *static_cast(lua_touserdata(L, lua_upvalueindex(1))); - - if (state.start == state.end) - { - lua_pushnil(L); - } - else - { - convert_to_lua(L, *state.start); - ++state.start; - } - - return 1; - } - - iterator_state(const Iter& s, const Iter& e) - : start(s) - , end(e) - {} - - Iter start; - Iter end; - }; - - struct iterator_converter - { - typedef boost::mpl::bool_ is_value_converter; - typedef iterator_converter type; - - template - void apply(lua_State* L, const T& c) - { - typedef typename T::const_iterator iter_t; - typedef iterator_state state_t; - - // note that this should be destructed, for now.. just hope that iterator - // is a pod - void* iter = lua_newuserdata(L, sizeof(state_t)); - new (iter) state_t(c.begin(), c.end()); - lua_pushcclosure(L, state_t::step, 1); - } - - template - void apply(lua_State* L, T& c) - { - typedef typename T::iterator iter_t; - typedef iterator_state state_t; - - // note that this should be destructed, for now.. just hope that iterator - // is a pod - void* iter = lua_newuserdata(L, sizeof(state_t)); - new (iter) state_t(c.begin(), c.end()); - lua_pushcclosure(L, state_t::step, 1); - } - }; - - struct iterator_policy : conversion_policy<0> - { - static void precall(lua_State*, const index_map&) {} - static void postcall(lua_State*, const index_map&) {} - - template - struct apply - { - typedef iterator_converter type; - }; - }; - -}} - -namespace luabind -{ - namespace - { - LUABIND_ANONYMOUS_FIX detail::policy_cons return_stl_iterator; - } -} - -#endif // LUABIND_ITERATOR_POLICY_HPP_INCLUDED - +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_ITERATOR_POLICY__071111_HPP +# define LUABIND_ITERATOR_POLICY__071111_HPP + +# include +# include +# include + +namespace luabind { namespace detail { + +template +struct iterator +{ + static int next(lua_State* L) + { + iterator* self = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + + if (self->first != self->last) + { + convert_to_lua(L, *self->first); + ++self->first; + } + else + { + lua_pushnil(L); + } + + return 1; + } + + static int destroy(lua_State* L) + { + iterator* self = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + self->~iterator(); + return 0; + } + + iterator(Iterator first, Iterator last) + : first(first) + , last(last) + {} + + Iterator first; + Iterator last; +}; + +template +int make_range(lua_State* L, Iterator first, Iterator last) +{ + void* storage = lua_newuserdata(L, sizeof(iterator)); + lua_newtable(L); + lua_pushcclosure(L, iterator::destroy, 0); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + lua_pushcclosure(L, iterator::next, 1); + new (storage) iterator(first, last); + return 1; +} + +template +int make_range(lua_State* L, Container& container) +{ + return make_range(L, container.begin(), container.end()); +} + +struct iterator_converter +{ + typedef boost::mpl::bool_ is_value_converter; + typedef iterator_converter type; + + template + void apply(lua_State* L, Container& container) + { + make_range(L, container); + } + + template + void apply(lua_State* L, Container const& container) + { + make_range(L, container); + } +}; + +struct iterator_policy : conversion_policy<0> +{ + static void precall(lua_State*, index_map const&) + {} + + static void postcall(lua_State*, index_map const&) + {} + + template + struct apply + { + typedef iterator_converter type; + }; +}; + +}} // namespace luabind::detail + +namespace luabind { namespace { + +LUABIND_ANONYMOUS_FIX detail::policy_cons< + detail::iterator_policy, detail::null_type> return_stl_iterator; + +}} // namespace luabind::unnamed + +#endif // LUABIND_ITERATOR_POLICY__071111_HPP + -- 2.11.4.GIT