Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/python/object/iterator.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef ITERATOR_DWA2002510_HPP
0006 # define ITERATOR_DWA2002510_HPP
0007 
0008 # include <boost/python/detail/prefix.hpp>
0009 # include <boost/python/detail/type_traits.hpp>
0010 
0011 # include <boost/python/class.hpp>
0012 # include <boost/python/return_value_policy.hpp>
0013 # include <boost/python/return_by_value.hpp>
0014 # include <boost/python/handle.hpp>
0015 # include <boost/python/make_function.hpp>
0016 
0017 # include <boost/python/object/iterator_core.hpp>
0018 # include <boost/python/object/class_detail.hpp>
0019 # include <boost/python/object/function_object.hpp>
0020 
0021 # include <boost/mpl/vector/vector10.hpp>
0022 # include <boost/mpl/if.hpp>
0023 
0024 # include <boost/python/detail/raw_pyobject.hpp>
0025 
0026 # include <boost/type.hpp>
0027 
0028 # include <iterator>
0029 
0030 namespace boost { namespace python { namespace objects {
0031 
0032 // CallPolicies for the next() method of iterators. We don't want
0033 // users to have to explicitly specify that the references returned by
0034 // iterators are copied, so we just replace the result_converter from
0035 // the default_iterator_call_policies with a permissive one which
0036 // always copies the result.
0037 typedef return_value_policy<return_by_value> default_iterator_call_policies;
0038 
0039 // Instantiations of these are wrapped to produce Python iterators.
0040 template <class NextPolicies, class Iterator>
0041 struct iterator_range
0042 {
0043     iterator_range(object sequence, Iterator start, Iterator finish);
0044 
0045     typedef std::iterator_traits<Iterator> traits_t;
0046 
0047     struct next
0048     {
0049         typedef typename mpl::if_<
0050             is_reference<
0051                 typename traits_t::reference
0052             >
0053           , typename traits_t::reference
0054           , typename traits_t::value_type
0055         >::type result_type;
0056         
0057         result_type
0058         operator()(iterator_range<NextPolicies,Iterator>& self)
0059         {
0060             if (self.m_start == self.m_finish)
0061                 stop_iteration_error();
0062             return *self.m_start++;
0063         }
0064 
0065 # if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
0066         // CWPro8 has a codegen problem when this is an empty class
0067         int garbage;
0068 # endif 
0069     };
0070     
0071     typedef next next_fn;
0072     
0073     object m_sequence; // Keeps the sequence alive while iterating.
0074     Iterator m_start;
0075     Iterator m_finish;
0076 };
0077 
0078 namespace detail
0079 {
0080   // Get a Python class which contains the given iterator and
0081   // policies, creating it if necessary. Requires: NextPolicies is
0082   // default-constructible.
0083   template <class Iterator, class NextPolicies>
0084   object demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies())
0085   {
0086       typedef iterator_range<NextPolicies,Iterator> range_;
0087 
0088       // Check the registry. If one is already registered, return it.
0089       handle<> class_obj(
0090           objects::registered_class_object(python::type_id<range_>()));
0091         
0092       if (class_obj.get() != 0)
0093           return object(class_obj);
0094 
0095       typedef typename range_::next_fn next_fn;
0096       typedef typename next_fn::result_type result_type;
0097       
0098       return class_<range_>(name, no_init)
0099           .def("__iter__", identity_function())
0100           .def(
0101 #if PY_VERSION_HEX >= 0x03000000
0102               "__next__"
0103 #else
0104               "next"
0105 #endif
0106             , make_function(
0107                 next_fn()
0108               , policies
0109               , mpl::vector2<result_type,range_&>()
0110             ));
0111   }
0112 
0113   // A function object which builds an iterator_range.
0114   template <
0115       class Target
0116     , class Iterator
0117     , class Accessor1
0118     , class Accessor2
0119     , class NextPolicies
0120   >
0121   struct py_iter_
0122   {
0123       py_iter_(Accessor1 const& get_start, Accessor2 const& get_finish)
0124         : m_get_start(get_start)
0125         , m_get_finish(get_finish)
0126       {}
0127       
0128       // Extract an object x of the Target type from the first Python
0129       // argument, and invoke get_start(x)/get_finish(x) to produce
0130       // iterators, which are used to construct a new iterator_range<>
0131       // object that gets wrapped into a Python iterator.
0132       iterator_range<NextPolicies,Iterator>
0133       operator()(back_reference<Target&> x) const
0134       {
0135           // Make sure the Python class is instantiated.
0136           detail::demand_iterator_class("iterator", (Iterator*)0, NextPolicies());
0137           
0138           return iterator_range<NextPolicies,Iterator>(
0139               x.source()
0140             , m_get_start(x.get())
0141             , m_get_finish(x.get())
0142           );
0143       }
0144    private:
0145       Accessor1 m_get_start;
0146       Accessor2 m_get_finish;
0147   };
0148 
0149   template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
0150   inline object make_iterator_function(
0151       Accessor1 const& get_start
0152     , Accessor2 const& get_finish
0153     , NextPolicies const& /*next_policies*/
0154     , Iterator const& (*)()
0155     , boost::type<Target>*
0156     , int
0157   )
0158   {
0159       return make_function(
0160           py_iter_<Target,Iterator,Accessor1,Accessor2,NextPolicies>(get_start, get_finish)
0161         , default_call_policies()
0162         , mpl::vector2<iterator_range<NextPolicies,Iterator>, back_reference<Target&> >()
0163       );
0164   }
0165 
0166   template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
0167   inline object make_iterator_function(
0168       Accessor1 const& get_start
0169     , Accessor2 const& get_finish
0170     , NextPolicies const& next_policies
0171     , Iterator& (*)()
0172     , boost::type<Target>*
0173     , ...)
0174   {
0175       return make_iterator_function(
0176           get_start
0177         , get_finish
0178         , next_policies
0179         , (Iterator const&(*)())0
0180         , (boost::type<Target>*)0
0181         , 0
0182       );
0183   }
0184 
0185 }
0186 
0187 // Create a Python callable object which accepts a single argument
0188 // convertible to the C++ Target type and returns a Python
0189 // iterator. The Python iterator uses get_start(x) and get_finish(x)
0190 // (where x is an instance of Target) to produce begin and end
0191 // iterators for the range, and an instance of NextPolicies is used as
0192 // CallPolicies for the Python iterator's next() function. 
0193 template <class Target, class NextPolicies, class Accessor1, class Accessor2>
0194 inline object make_iterator_function(
0195     Accessor1 const& get_start
0196   , Accessor2 const& get_finish
0197   , NextPolicies const& next_policies
0198   , boost::type<Target>* = 0
0199 )
0200 {
0201     typedef typename Accessor1::result_type iterator;
0202     typedef typename boost::python::detail::add_const<iterator>::type iterator_const;
0203     typedef typename boost::python::detail::add_lvalue_reference<iterator_const>::type iterator_cref;
0204       
0205     return detail::make_iterator_function(
0206         get_start
0207       , get_finish
0208       , next_policies
0209       , (iterator_cref(*)())0
0210       , (boost::type<Target>*)0
0211       , 0
0212     );
0213 }
0214 
0215 //
0216 // implementation
0217 //
0218 template <class NextPolicies, class Iterator>
0219 inline iterator_range<NextPolicies,Iterator>::iterator_range(
0220     object sequence, Iterator start, Iterator finish)
0221     : m_sequence(sequence), m_start(start), m_finish(finish)
0222 {
0223 }
0224 
0225 }}} // namespace boost::python::objects
0226 
0227 #endif // ITERATOR_DWA2002510_HPP