231 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			231 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								// Copyright David Abrahams 2002.
							 | 
						||
| 
								 | 
							
								// Distributed under 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 ITERATOR_DWA2002510_HPP
							 | 
						||
| 
								 | 
							
								# define ITERATOR_DWA2002510_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/python/detail/prefix.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/python/class.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/python/return_value_policy.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/python/return_by_value.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/python/handle.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/python/make_function.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/python/object/iterator_core.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/python/object/class_detail.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/python/object/function_object.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/mpl/vector/vector10.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/mpl/if.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/python/detail/raw_pyobject.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/type.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/type_traits/is_same.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/type_traits/add_reference.hpp>
							 | 
						||
| 
								 | 
							
								# include <boost/type_traits/add_const.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# include <boost/detail/iterator.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost { namespace python { namespace objects {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// CallPolicies for the next() method of iterators. We don't want
							 | 
						||
| 
								 | 
							
								// users to have to explicitly specify that the references returned by
							 | 
						||
| 
								 | 
							
								// iterators are copied, so we just replace the result_converter from
							 | 
						||
| 
								 | 
							
								// the default_iterator_call_policies with a permissive one which
							 | 
						||
| 
								 | 
							
								// always copies the result.
							 | 
						||
| 
								 | 
							
								typedef return_value_policy<return_by_value> default_iterator_call_policies;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Instantiations of these are wrapped to produce Python iterators.
							 | 
						||
| 
								 | 
							
								template <class NextPolicies, class Iterator>
							 | 
						||
| 
								 | 
							
								struct iterator_range
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    iterator_range(object sequence, Iterator start, Iterator finish);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    typedef boost::detail::iterator_traits<Iterator> traits_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    struct next
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        typedef typename mpl::if_<
							 | 
						||
| 
								 | 
							
								            is_reference<
							 | 
						||
| 
								 | 
							
								                typename traits_t::reference
							 | 
						||
| 
								 | 
							
								            >
							 | 
						||
| 
								 | 
							
								          , typename traits_t::reference
							 | 
						||
| 
								 | 
							
								          , typename traits_t::value_type
							 | 
						||
| 
								 | 
							
								        >::type result_type;
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        result_type
							 | 
						||
| 
								 | 
							
								        operator()(iterator_range<NextPolicies,Iterator>& self)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (self.m_start == self.m_finish)
							 | 
						||
| 
								 | 
							
								                stop_iteration_error();
							 | 
						||
| 
								 | 
							
								            return *self.m_start++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
							 | 
						||
| 
								 | 
							
								        // CWPro8 has a codegen problem when this is an empty class
							 | 
						||
| 
								 | 
							
								        int garbage;
							 | 
						||
| 
								 | 
							
								# endif 
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    typedef next next_fn;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    object m_sequence; // Keeps the sequence alive while iterating.
							 | 
						||
| 
								 | 
							
								    Iterator m_start;
							 | 
						||
| 
								 | 
							
								    Iterator m_finish;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace detail
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // Get a Python class which contains the given iterator and
							 | 
						||
| 
								 | 
							
								  // policies, creating it if necessary. Requires: NextPolicies is
							 | 
						||
| 
								 | 
							
								  // default-constructible.
							 | 
						||
| 
								 | 
							
								  template <class Iterator, class NextPolicies>
							 | 
						||
| 
								 | 
							
								  object demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies())
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								      typedef iterator_range<NextPolicies,Iterator> range_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Check the registry. If one is already registered, return it.
							 | 
						||
| 
								 | 
							
								      handle<> class_obj(
							 | 
						||
| 
								 | 
							
								          objects::registered_class_object(python::type_id<range_>()));
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								      if (class_obj.get() != 0)
							 | 
						||
| 
								 | 
							
								          return object(class_obj);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      typedef typename range_::next_fn next_fn;
							 | 
						||
| 
								 | 
							
								      typedef typename next_fn::result_type result_type;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      return class_<range_>(name, no_init)
							 | 
						||
| 
								 | 
							
								          .def("__iter__", identity_function())
							 | 
						||
| 
								 | 
							
								          .def(
							 | 
						||
| 
								 | 
							
								#if PY_VERSION_HEX >= 0x03000000
							 | 
						||
| 
								 | 
							
								              "__next__"
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								              "next"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            , make_function(
							 | 
						||
| 
								 | 
							
								                next_fn()
							 | 
						||
| 
								 | 
							
								              , policies
							 | 
						||
| 
								 | 
							
								              , mpl::vector2<result_type,range_&>()
							 | 
						||
| 
								 | 
							
								            ));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // A function object which builds an iterator_range.
							 | 
						||
| 
								 | 
							
								  template <
							 | 
						||
| 
								 | 
							
								      class Target
							 | 
						||
| 
								 | 
							
								    , class Iterator
							 | 
						||
| 
								 | 
							
								    , class Accessor1
							 | 
						||
| 
								 | 
							
								    , class Accessor2
							 | 
						||
| 
								 | 
							
								    , class NextPolicies
							 | 
						||
| 
								 | 
							
								  >
							 | 
						||
| 
								 | 
							
								  struct py_iter_
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								      py_iter_(Accessor1 const& get_start, Accessor2 const& get_finish)
							 | 
						||
| 
								 | 
							
								        : m_get_start(get_start)
							 | 
						||
| 
								 | 
							
								        , m_get_finish(get_finish)
							 | 
						||
| 
								 | 
							
								      {}
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      // Extract an object x of the Target type from the first Python
							 | 
						||
| 
								 | 
							
								      // argument, and invoke get_start(x)/get_finish(x) to produce
							 | 
						||
| 
								 | 
							
								      // iterators, which are used to construct a new iterator_range<>
							 | 
						||
| 
								 | 
							
								      // object that gets wrapped into a Python iterator.
							 | 
						||
| 
								 | 
							
								      iterator_range<NextPolicies,Iterator>
							 | 
						||
| 
								 | 
							
								      operator()(back_reference<Target&> x) const
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								          // Make sure the Python class is instantiated.
							 | 
						||
| 
								 | 
							
								          detail::demand_iterator_class("iterator", (Iterator*)0, NextPolicies());
							 | 
						||
| 
								 | 
							
								          
							 | 
						||
| 
								 | 
							
								          return iterator_range<NextPolicies,Iterator>(
							 | 
						||
| 
								 | 
							
								              x.source()
							 | 
						||
| 
								 | 
							
								            , m_get_start(x.get())
							 | 
						||
| 
								 | 
							
								            , m_get_finish(x.get())
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								   private:
							 | 
						||
| 
								 | 
							
								      Accessor1 m_get_start;
							 | 
						||
| 
								 | 
							
								      Accessor2 m_get_finish;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
							 | 
						||
| 
								 | 
							
								  inline object make_iterator_function(
							 | 
						||
| 
								 | 
							
								      Accessor1 const& get_start
							 | 
						||
| 
								 | 
							
								    , Accessor2 const& get_finish
							 | 
						||
| 
								 | 
							
								    , NextPolicies const& /*next_policies*/
							 | 
						||
| 
								 | 
							
								    , Iterator const& (*)()
							 | 
						||
| 
								 | 
							
								    , boost::type<Target>*
							 | 
						||
| 
								 | 
							
								    , int
							 | 
						||
| 
								 | 
							
								  )
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								      return make_function(
							 | 
						||
| 
								 | 
							
								          py_iter_<Target,Iterator,Accessor1,Accessor2,NextPolicies>(get_start, get_finish)
							 | 
						||
| 
								 | 
							
								        , default_call_policies()
							 | 
						||
| 
								 | 
							
								        , mpl::vector2<iterator_range<NextPolicies,Iterator>, back_reference<Target&> >()
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
							 | 
						||
| 
								 | 
							
								  inline object make_iterator_function(
							 | 
						||
| 
								 | 
							
								      Accessor1 const& get_start
							 | 
						||
| 
								 | 
							
								    , Accessor2 const& get_finish
							 | 
						||
| 
								 | 
							
								    , NextPolicies const& next_policies
							 | 
						||
| 
								 | 
							
								    , Iterator& (*)()
							 | 
						||
| 
								 | 
							
								    , boost::type<Target>*
							 | 
						||
| 
								 | 
							
								    , ...)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								      return make_iterator_function(
							 | 
						||
| 
								 | 
							
								          get_start
							 | 
						||
| 
								 | 
							
								        , get_finish
							 | 
						||
| 
								 | 
							
								        , next_policies
							 | 
						||
| 
								 | 
							
								        , (Iterator const&(*)())0
							 | 
						||
| 
								 | 
							
								        , (boost::type<Target>*)0
							 | 
						||
| 
								 | 
							
								        , 0
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Create a Python callable object which accepts a single argument
							 | 
						||
| 
								 | 
							
								// convertible to the C++ Target type and returns a Python
							 | 
						||
| 
								 | 
							
								// iterator. The Python iterator uses get_start(x) and get_finish(x)
							 | 
						||
| 
								 | 
							
								// (where x is an instance of Target) to produce begin and end
							 | 
						||
| 
								 | 
							
								// iterators for the range, and an instance of NextPolicies is used as
							 | 
						||
| 
								 | 
							
								// CallPolicies for the Python iterator's next() function. 
							 | 
						||
| 
								 | 
							
								template <class Target, class NextPolicies, class Accessor1, class Accessor2>
							 | 
						||
| 
								 | 
							
								inline object make_iterator_function(
							 | 
						||
| 
								 | 
							
								    Accessor1 const& get_start
							 | 
						||
| 
								 | 
							
								  , Accessor2 const& get_finish
							 | 
						||
| 
								 | 
							
								  , NextPolicies const& next_policies
							 | 
						||
| 
								 | 
							
								  , boost::type<Target>* = 0
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    typedef typename Accessor1::result_type iterator;
							 | 
						||
| 
								 | 
							
								    typedef typename add_const<iterator>::type iterator_const;
							 | 
						||
| 
								 | 
							
								    typedef typename add_reference<iterator_const>::type iterator_cref;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								    return detail::make_iterator_function(
							 | 
						||
| 
								 | 
							
								        get_start
							 | 
						||
| 
								 | 
							
								      , get_finish
							 | 
						||
| 
								 | 
							
								      , next_policies
							 | 
						||
| 
								 | 
							
								      , (iterator_cref(*)())0
							 | 
						||
| 
								 | 
							
								      , (boost::type<Target>*)0
							 | 
						||
| 
								 | 
							
								      , 0
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// implementation
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								template <class NextPolicies, class Iterator>
							 | 
						||
| 
								 | 
							
								inline iterator_range<NextPolicies,Iterator>::iterator_range(
							 | 
						||
| 
								 | 
							
								    object sequence, Iterator start, Iterator finish)
							 | 
						||
| 
								 | 
							
								    : m_sequence(sequence), m_start(start), m_finish(finish)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}}} // namespace boost::python::objects
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif // ITERATOR_DWA2002510_HPP
							 |