Package pyplusplus :: Package code_repository :: Module return_range

Source Code for Module pyplusplus.code_repository.return_range

  1  # Copyright 2004-2008 Roman Yakovenko. 
  2  # Distributed under the Boost Software License, Version 1.0. (See 
  3  # accompanying file LICENSE_1_0.txt or copy at 
  4  # http://www.boost.org/LICENSE_1_0.txt) 
  5   
  6  """ 
  7  This file contains C++ code - "return_range" call policies 
  8  """ 
  9   
 10  from pyplusplus.decl_wrappers import call_policies 
 11   
 12  namespace = "pyplusplus::call_policies" 
 13   
 14  file_name = call_policies.return_range_t.HEADER_FILE 
 15   
 16  code = \ 
 17  """// Copyright 2004-2008 Roman Yakovenko. 
 18  // Distributed under the Boost Software License, Version 1.0. (See 
 19  // accompanying file LICENSE_1_0.txt or copy at 
 20  // http://www.boost.org/LICENSE_1_0.txt) 
 21   
 22  #ifndef return_range_pyplusplus_hpp__ 
 23  #define return_range_pyplusplus_hpp__ 
 24   
 25  #include "boost/python.hpp" 
 26  #include "boost/mpl/int.hpp" 
 27  #include "boost/function.hpp" 
 28  #include "boost/python/suite/indexing/iterator_range.hpp" 
 29  #include "boost/python/object/class_detail.hpp" 
 30  #include "boost/type_traits/is_same.hpp" 
 31  namespace pyplusplus{ namespace call_policies{ 
 32   
 33  namespace bpl = boost::python; 
 34   
 35  namespace detail{   
 36   
 37  struct return_raw_data_ref{ 
 38       
 39      template <class T>  
 40      struct apply{ 
 41   
 42          BOOST_STATIC_ASSERT( boost::is_pointer<T>::value ); 
 43           
 44          struct type{ 
 45              static bool convertible() 
 46              { return true; } 
 47   
 48              PyObject*  
 49              operator()( T return_value) const{  
 50                  if( !return_value ){ 
 51                      return bpl::detail::none(); 
 52                  } 
 53                  else{ 
 54                      typedef typename boost::remove_pointer< T >::type value_type; 
 55                      typedef typename boost::remove_const< value_type >::type non_const_value_type; 
 56                      non_const_value_type* data = const_cast<non_const_value_type*>( return_value ); 
 57                      return PyCObject_FromVoidPtr( data, NULL );  
 58                  } 
 59              } 
 60          }; 
 61   
 62      }; 
 63   
 64  }; 
 65   
 66  } //detail 
 67       
 68  template < typename TGetSize, typename TValueType, typename TValuePolicies=bpl::default_call_policies >  
 69  struct return_range : bpl::default_call_policies{ 
 70   
 71      typedef return_range< TGetSize, TValueType, TValuePolicies > this_type; 
 72   
 73  public: 
 74   
 75      typedef typename detail::return_raw_data_ref result_converter; 
 76       
 77      typedef TValueType value_type; 
 78      typedef TGetSize get_size_type; 
 79      typedef TValuePolicies value_policies_type; 
 80       
 81      typedef bpl::indexing::iterator_range<value_type*> range_type; 
 82   
 83      template <class ArgumentPackage> 
 84      static PyObject* postcall(ArgumentPackage const& args, PyObject* result){ 
 85          if( result == bpl::detail::none() ){ 
 86              return result; 
 87          } 
 88          if( !PyCObject_Check( result ) ){ 
 89              throw std::runtime_error( "Internal error: expected to get PyCObject" ); 
 90          } 
 91          value_type* raw_data = reinterpret_cast<value_type*>( PyCObject_AsVoidPtr( result ) ); 
 92          Py_DECREF(result);//we don't need result anymore 
 93           
 94          bpl::tuple args_w( bpl::handle<>( bpl::borrowed( args ) ) ); 
 95   
 96          register_range_class_on_demand(); 
 97           
 98          get_size_type get_size; 
 99          range_type the_range( raw_data, raw_data + get_size( args_w ) ); 
100           
101          bpl::object range_obj( the_range ); 
102           
103          return bpl::incref( range_obj.ptr() ); 
104      } 
105  private: 
106   
107      static void register_range_class( boost::mpl::true_ ){ 
108          //register range class with default call policies 
109          bpl::class_<range_type>( "_impl_details_range_iterator_",  bpl::init<value_type*, value_type*>() ) 
110              .def(bpl::indexing::container_suite<range_type>() ); 
111      } 
112       
113      static void register_range_class( boost::mpl::false_ ){ 
114          //register range class with non default call policies 
115          unsigned long const methods_mask  
116              = bpl::indexing::all_methods  
117                & ~( bpl::indexing::reorder_methods |  bpl::indexing::search_methods ) ; 
118   
119          typedef bpl::indexing::iterator_range_suite< range_type, methods_mask > suite_type; 
120          bpl::class_<range_type>( "_impl_details_range_iterator_",  bpl::init<value_type*, value_type*>() ) 
121              .def( suite_type::with_policies( value_policies_type() ) ); 
122      } 
123   
124      static void register_range_class_on_demand(){ 
125          //Check the registry. If the class doesn't exist, register it. 
126          bpl::handle<> class_obj( 
127              bpl::objects::registered_class_object(bpl::type_id<range_type>())); 
128           
129          if( class_obj.get() == 0 ){ 
130              register_range_class( boost::is_same< bpl::default_call_policies, value_policies_type>() ); 
131          } 
132      } 
133   
134  }; 
135   
136  } /*pyplusplus*/ } /*call_policies*/ 
137   
138   
139  #endif//return_range_pyplusplus_hpp__ 
140   
141  """ 
142