1 // Copyright Daniel Wallin 2007. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5 #ifndef LUABIND_ITERATOR_POLICY_071111_HPP
6 # define LUABIND_ITERATOR_POLICY_071111_HPP
7
8 # include <luabind/config.hpp> // for LUABIND_ANONYMOUS_FIX
9 # include <luabind/detail/convert_to_lua.hpp> // for convert_to_lua
10 # include <luabind/detail/policy.hpp> // for index_map, etc
11
12 # include <new> // for operator new
13
14 namespace luabind { namespace detail {
15
16 struct null_type;
17
18 template <class Iterator>
19 struct iterator
20 {
nextluabind::detail::iterator21 static int next(lua_State* L)
22 {
23 iterator* self = static_cast<iterator*>(
24 lua_touserdata(L, lua_upvalueindex(1)));
25
26 if (self->first != self->last)
27 {
28 convert_to_lua(L, *self->first);
29 ++self->first;
30 }
31 else
32 {
33 lua_pushnil(L);
34 }
35
36 return 1;
37 }
38
destroyluabind::detail::iterator39 static int destroy(lua_State* L)
40 {
41 iterator* self = static_cast<iterator*>(lua_touserdata(L, 1));
42 self->~iterator();
43 (void)self; // MSVC warns about self not being referenced.
44 return 0;
45 }
46
iteratorluabind::detail::iterator47 iterator(Iterator first_, Iterator last_)
48 : first(first_)
49 , last(last_)
50 {}
51
52 Iterator first;
53 Iterator last;
54 };
55
56 template <class Iterator>
make_range(lua_State * L,Iterator first,Iterator last)57 int make_range(lua_State* L, Iterator first, Iterator last)
58 {
59 void* storage = lua_newuserdata(L, sizeof(iterator<Iterator>));
60 lua_createtable(L, 0, 1);
61 lua_pushcclosure(L, iterator<Iterator>::destroy, 0);
62 lua_setfield(L, -2, "__gc");
63 lua_setmetatable(L, -2);
64 lua_pushcclosure(L, iterator<Iterator>::next, 1);
65 new (storage) iterator<Iterator>(first, last);
66 return 1;
67 }
68
69 template <class Container>
make_range(lua_State * L,Container & container)70 int make_range(lua_State* L, Container& container)
71 {
72 return make_range(L, container.begin(), container.end());
73 }
74
75 struct iterator_converter
76 {
77 typedef iterator_converter type;
78
79 template <class Container>
applyluabind::detail::iterator_converter80 void apply(lua_State* L, Container& container)
81 {
82 make_range(L, container);
83 }
84
85 template <class Container>
applyluabind::detail::iterator_converter86 void apply(lua_State* L, Container const& container)
87 {
88 make_range(L, container);
89 }
90 };
91
92 struct iterator_policy : conversion_policy<0>
93 {
precallluabind::detail::iterator_policy94 static void precall(lua_State*, index_map const&)
95 {}
96
postcallluabind::detail::iterator_policy97 static void postcall(lua_State*, index_map const&)
98 {}
99
100 template <class T, class Direction>
101 struct apply
102 {
103 typedef iterator_converter type;
104 };
105 };
106
107 }} // namespace luabind::detail
108
109 namespace luabind {
110
111 detail::policy_cons<detail::iterator_policy, detail::null_type> const
112 return_stl_iterator = {};
113
114 namespace detail
115 {
ignore_unused_return_stl_iterator()116 inline void ignore_unused_return_stl_iterator()
117 {
118 (void)return_stl_iterator;
119 }
120 }
121
122 } // namespace luabind
123
124 #endif // LUABIND_ITERATOR_POLICY__071111_HPP
125