summaryrefslogtreecommitdiff
path: root/src/emc/rs274ngc/array1.hh
blob: 0a589a2999c002e1619fb68e70aa61b2ccb47dca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2004 Roman Yakovenko.
// 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 __array_1_pyplusplus_hpp__
#define __array_1_pyplusplus_hpp__

#include "boost/python.hpp"
#include "boost/mpl/if.hpp"
#include "boost/type_traits/is_same.hpp"
#include "boost/type_traits/is_fundamental.hpp"
#include "boost/python/converter/registry.hpp"

#include <iostream>

//1 - dimension
namespace pyplusplus{ namespace containers{ namespace static_sized{

inline void
raise_on_out_of_range( long unsigned int size, long unsigned int index ){
    if( size <= index ){
        throw std::out_of_range("index out of range");
    }
}

namespace details{

template<class T>
struct is_immutable{
    BOOST_STATIC_CONSTANT(
        bool
        , value = ( boost::is_same< T, std::string >::value )
                  || ( boost::is_same< T, std::wstring >::value )
                  || ( boost::is_fundamental< T >::value )
                  || ( boost::is_enum< T >::value )
    );

};

template<class T>
bool is_registered(){
    namespace bpl = boost::python;
    bpl::handle<> class_obj( bpl::objects::registered_class_object( bpl::type_id< T >()));
    return class_obj.get() ? true : false;
}

template< class T >
void register_alias( const char* name ){
    namespace bpl = boost::python;
    bpl::handle<> class_obj( bpl::objects::registered_class_object( bpl::type_id< T >()));
    boost::python::scope().attr( name ) = bpl::object( class_obj );
}

}//details

template< class TItemType, long unsigned int size >
struct const_array_1_t{

    typedef BOOST_DEDUCED_TYPENAME boost::call_traits<const TItemType>::param_type param_type;

    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
            details::is_immutable<TItemType>::value
            , TItemType
            , param_type
        >::type reference_type;

    const_array_1_t( TItemType const * const data )
    : m_data( data ){
        if( !data ){
            throw std::runtime_error( "const_array_1_t: pointer to null has been recieved." );
        }
    }

    long unsigned int len() const {
        return size;
    }

    reference_type item_ref( long unsigned int index ) const{
        raise_on_out_of_range( size, index );
        return m_data[index];
    }

private:

    TItemType const * m_data;

};

template< class TItemType, long unsigned int size >
struct array_1_t{

    typedef BOOST_DEDUCED_TYPENAME boost::call_traits<const TItemType>::param_type param_type;

    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
            details::is_immutable<TItemType>::value
            , TItemType
            , param_type
        >::type reference_type;

    array_1_t( TItemType * data )
    : m_data( data ){
        if( !data ){
            throw std::runtime_error( "array_1_t: pointer to null has been recieved." );
        }
    }

    long unsigned int len() const {
        return size;
    }

    reference_type item_ref( long unsigned int index ) const{
        raise_on_out_of_range( size, index );
        return m_data[index];
    }

    void
    set_item( long unsigned int index, reference_type new_value ){
        raise_on_out_of_range( size, index );
        m_data[index] = new_value;
    }

private:

    TItemType* m_data;

};

template< class TItemType
          , long unsigned int size
          , typename CallPolicies=boost::python::default_call_policies >
struct register_const_array_1{
    register_const_array_1(const char* name){
        namespace bpl = boost::python;
        typedef const_array_1_t< TItemType, size > wrapper_t;

        if( details::is_registered< wrapper_t >() ){
            details::register_alias< wrapper_t >( name );
        }
        else{
            bpl::class_< wrapper_t >( name, bpl::no_init )
                .def( "__getitem__"
                      , &wrapper_t::item_ref
                      , ( bpl::arg("index") )
                      , CallPolicies() )
                .def( "__len__", &wrapper_t::len );
        }
    }
};

template< class TItemType
          , long unsigned int size
          , typename CallPolicies=boost::python::default_call_policies >
struct register_array_1{
    register_array_1(const char* name){
        namespace bpl = boost::python;
        typedef array_1_t< TItemType, size > wrapper_t;
        if( details::is_registered< wrapper_t >() ){
            details::register_alias< wrapper_t >( name );
        }
        else{
            bpl::class_< wrapper_t >( name, bpl::no_init )
                .def( "__getitem__"
                      , &wrapper_t::item_ref
                      , ( bpl::arg("index") )
                      , CallPolicies() )
                .def( "__setitem__"
                      , &wrapper_t::set_item
                      , ( bpl::arg("index"), bpl::arg("value") )
                      , CallPolicies()  )
                .def( "__len__", &wrapper_t::len );
        }
    }
};

} /*pyplusplus*/ } /*containers*/ } /*static_sized*/


#endif//__array_1_pyplusplus_hpp__