array1.hh
1 // Copyright 2004 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 #ifndef __array_1_pyplusplus_hpp__ 7 #define __array_1_pyplusplus_hpp__ 8 9 #ifndef BOOST_PYTHON_MAX_ARITY 10 #define BOOST_PYTHON_MAX_ARITY 4 11 #endif 12 #include <boost/python/iterator.hpp> 13 #include <boost/python/enum.hpp> 14 #include <boost/python/object.hpp> 15 #include <boost/python/scope.hpp> 16 #include <boost/python/converter/registry.hpp> 17 #include <stdexcept> 18 #include <type_traits> 19 20 #include <iostream> 21 22 //1 - dimension 23 namespace pyplusplus{ namespace containers{ namespace static_sized{ 24 25 inline void 26 raise_on_out_of_range( long unsigned int size, long unsigned int index ){ 27 if( size <= index ){ 28 throw std::out_of_range("index out of range"); 29 } 30 } 31 32 namespace details{ 33 34 template<class T> 35 struct is_immutable{ 36 enum { value = 37 ( std::is_same< T, std::string >::value ) 38 || ( std::is_same< T, std::wstring >::value ) 39 || ( std::is_fundamental< T >::value ) 40 || ( std::is_enum< T >::value ) }; 41 }; 42 43 template<class T> 44 bool is_registered(){ 45 namespace bpl = boost::python; 46 bpl::handle<> class_obj( bpl::objects::registered_class_object( bpl::type_id< T >())); 47 return class_obj.get() ? true : false; 48 } 49 50 template< class T > 51 void register_alias( const char* name ){ 52 namespace bpl = boost::python; 53 bpl::handle<> class_obj( bpl::objects::registered_class_object( bpl::type_id< T >())); 54 boost::python::scope().attr( name ) = bpl::object( class_obj ); 55 } 56 57 }//details 58 59 template< class TItemType, long unsigned int size > 60 struct const_array_1_t{ 61 62 typedef BOOST_DEDUCED_TYPENAME boost::call_traits<const TItemType>::param_type param_type; 63 64 typedef typename std::conditional< 65 details::is_immutable<TItemType>::value 66 , TItemType 67 , param_type 68 >::type reference_type; 69 70 const_array_1_t( TItemType const * const data ) 71 : m_data( data ){ 72 if( !data ){ 73 throw std::runtime_error( "const_array_1_t: pointer to null has been received." ); 74 } 75 } 76 77 long unsigned int len() const { 78 return size; 79 } 80 81 reference_type item_ref( long unsigned int index ) const{ 82 raise_on_out_of_range( size, index ); 83 return m_data[index]; 84 } 85 86 private: 87 88 TItemType const * m_data; 89 90 }; 91 92 template< class TItemType, long unsigned int size > 93 struct array_1_t{ 94 95 typedef BOOST_DEDUCED_TYPENAME boost::call_traits<const TItemType>::param_type param_type; 96 97 typedef typename std::conditional< 98 details::is_immutable<TItemType>::value 99 , TItemType 100 , param_type 101 >::type reference_type; 102 103 array_1_t( TItemType * data ) 104 : m_data( data ){ 105 if( !data ){ 106 throw std::runtime_error( "array_1_t: pointer to null has been received." ); 107 } 108 } 109 110 long unsigned int len() const { 111 return size; 112 } 113 114 reference_type item_ref( long unsigned int index ) const{ 115 raise_on_out_of_range( size, index ); 116 return m_data[index]; 117 } 118 119 void 120 set_item( long unsigned int index, reference_type new_value ){ 121 raise_on_out_of_range( size, index ); 122 m_data[index] = new_value; 123 } 124 125 private: 126 127 TItemType* m_data; 128 129 }; 130 131 template< class TItemType 132 , long unsigned int size 133 , typename CallPolicies=boost::python::default_call_policies > 134 struct register_const_array_1{ 135 register_const_array_1(const char* name){ 136 namespace bpl = boost::python; 137 typedef const_array_1_t< TItemType, size > wrapper_t; 138 139 if( details::is_registered< wrapper_t >() ){ 140 details::register_alias< wrapper_t >( name ); 141 } 142 else{ 143 bpl::class_< wrapper_t >( name, bpl::no_init ) 144 .def( "__getitem__" 145 , &wrapper_t::item_ref 146 , ( bpl::arg("index") ) 147 , CallPolicies() ) 148 .def( "__len__", &wrapper_t::len ); 149 } 150 } 151 }; 152 153 template< class TItemType 154 , long unsigned int size 155 , typename CallPolicies=boost::python::default_call_policies > 156 struct register_array_1{ 157 register_array_1(const char* name){ 158 namespace bpl = boost::python; 159 typedef array_1_t< TItemType, size > wrapper_t; 160 if( details::is_registered< wrapper_t >() ){ 161 details::register_alias< wrapper_t >( name ); 162 } 163 else{ 164 bpl::class_< wrapper_t >( name, bpl::no_init ) 165 .def( "__getitem__" 166 , &wrapper_t::item_ref 167 , ( bpl::arg("index") ) 168 , CallPolicies() ) 169 .def( "__setitem__" 170 , &wrapper_t::set_item 171 , ( bpl::arg("index"), bpl::arg("value") ) 172 , CallPolicies() ) 173 .def( "__len__", &wrapper_t::len ); 174 } 175 } 176 }; 177 178 } /*pyplusplus*/ } /*containers*/ } /*static_sized*/ 179 180 181 #endif//__array_1_pyplusplus_hpp__