/ src / emc / rs274ngc / array1.hh
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__