iterator_policy.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. #ifndef LUABIND_ITERATOR_POLICY__071111_HPP
  5. # define LUABIND_ITERATOR_POLICY__071111_HPP
  6. # include <luabind/config.hpp>
  7. # include <luabind/detail/policy.hpp>
  8. # include <luabind/detail/convert_to_lua.hpp>
  9. namespace luabind { namespace detail {
  10. template <class Iterator>
  11. struct iterator
  12. {
  13. static int next(lua_State* L)
  14. {
  15. iterator* self = static_cast<iterator*>(
  16. lua_touserdata(L, lua_upvalueindex(1)));
  17. if (self->first != self->last)
  18. {
  19. convert_to_lua(L, *self->first);
  20. ++self->first;
  21. }
  22. else
  23. {
  24. lua_pushnil(L);
  25. }
  26. return 1;
  27. }
  28. static int destroy(lua_State* L)
  29. {
  30. iterator* self = static_cast<iterator*>(lua_touserdata(L, 1));
  31. self->~iterator();
  32. return 0;
  33. }
  34. iterator(Iterator first, Iterator last)
  35. : first(first)
  36. , last(last)
  37. {}
  38. Iterator first;
  39. Iterator last;
  40. };
  41. template <class Iterator>
  42. int make_range(lua_State* L, Iterator first, Iterator last)
  43. {
  44. void* storage = lua_newuserdata(L, sizeof(iterator<Iterator>));
  45. lua_newtable(L);
  46. lua_pushcclosure(L, iterator<Iterator>::destroy, 0);
  47. lua_setfield(L, -2, "__gc");
  48. lua_setmetatable(L, -2);
  49. lua_pushcclosure(L, iterator<Iterator>::next, 1);
  50. new (storage) iterator<Iterator>(first, last);
  51. return 1;
  52. }
  53. template <class Container>
  54. int make_range(lua_State* L, Container& container)
  55. {
  56. return make_range(L, container.begin(), container.end());
  57. }
  58. struct iterator_converter
  59. {
  60. typedef iterator_converter type;
  61. template <class Container>
  62. void apply(lua_State* L, Container& container)
  63. {
  64. make_range(L, container);
  65. }
  66. template <class Container>
  67. void apply(lua_State* L, Container const& container)
  68. {
  69. make_range(L, container);
  70. }
  71. };
  72. struct iterator_policy : conversion_policy<0>
  73. {
  74. static void precall(lua_State*, index_map const&)
  75. {}
  76. static void postcall(lua_State*, index_map const&)
  77. {}
  78. template <class T, class Direction>
  79. struct apply
  80. {
  81. typedef iterator_converter type;
  82. };
  83. };
  84. }} // namespace luabind::detail
  85. namespace luabind { namespace {
  86. LUABIND_ANONYMOUS_FIX detail::policy_cons<
  87. detail::iterator_policy, detail::null_type> return_stl_iterator;
  88. }} // namespace luabind::unnamed
  89. #endif // LUABIND_ITERATOR_POLICY__071111_HPP