source: NonGTP/Boost/boost/python/suite/indexing/vector_indexing_suite.hpp @ 857

Revision 857, 7.4 KB checked in by igarcia, 18 years ago (diff)
Line 
1//  (C) Copyright Joel de Guzman 2003.
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 VECTOR_INDEXING_SUITE_JDG20036_HPP
7# define VECTOR_INDEXING_SUITE_JDG20036_HPP
8
9# include <boost/python/suite/indexing/indexing_suite.hpp>
10# include <boost/python/suite/indexing/container_utils.hpp>
11# include <boost/python/iterator.hpp>
12
13namespace boost { namespace python {
14           
15    // Forward declaration
16    template <class Container, bool NoProxy, class DerivedPolicies>
17    class vector_indexing_suite;
18   
19    namespace detail
20    {
21        template <class Container, bool NoProxy>
22        class final_vector_derived_policies
23            : public vector_indexing_suite<Container,
24                NoProxy, final_vector_derived_policies<Container, NoProxy> > {};
25    }
26
27    // The vector_indexing_suite class is a predefined indexing_suite derived
28    // class for wrapping std::vector (and std::vector like) classes. It provides
29    // all the policies required by the indexing_suite (see indexing_suite).
30    // Example usage:
31    //
32    //  class X {...};
33    //
34    //  ...
35    //
36    //      class_<std::vector<X> >("XVec")
37    //          .def(vector_indexing_suite<std::vector<X> >())
38    //      ;
39    //
40    // By default indexed elements are returned by proxy. This can be
41    // disabled by supplying *true* in the NoProxy template parameter.
42    //
43    template <
44        class Container,
45        bool NoProxy = false,
46        class DerivedPolicies
47            = detail::final_vector_derived_policies<Container, NoProxy> >
48    class vector_indexing_suite
49        : public indexing_suite<Container, DerivedPolicies, NoProxy>
50    {
51    public:
52   
53        typedef typename Container::value_type data_type;
54        typedef typename Container::value_type key_type;
55        typedef typename Container::size_type index_type;
56        typedef typename Container::size_type size_type;
57        typedef typename Container::difference_type difference_type;
58       
59        template <class Class>
60        static void
61        extension_def(Class& cl)
62        {
63            cl
64                .def("append", &base_append)
65                .def("extend", &base_extend)
66            ;
67        }
68       
69        static
70        typename mpl::if_<
71            is_class<data_type>
72          , data_type&
73          , data_type
74        >::type
75        get_item(Container& container, index_type i)
76        {
77            return container[i];
78        }
79
80        static object
81        get_slice(Container& container, index_type from, index_type to)
82        {
83            if (from > to)
84                return object(Container());
85            return object(Container(container.begin()+from, container.begin()+to));
86        }
87
88        static void
89        set_item(Container& container, index_type i, data_type const& v)
90        {
91            container[i] = v;
92        }
93
94        static void
95        set_slice(Container& container, index_type from,
96            index_type to, data_type const& v)
97        {
98            if (from > to) {
99                return;
100            }
101            else {
102                container.erase(container.begin()+from, container.begin()+to);
103                container.insert(container.begin()+from, v);
104            }
105        }
106
107        template <class Iter>
108        static void
109        set_slice(Container& container, index_type from,
110            index_type to, Iter first, Iter last)
111        {
112            if (from > to) {
113                container.insert(container.begin()+from, first, last);
114            }
115            else {
116                container.erase(container.begin()+from, container.begin()+to);
117                container.insert(container.begin()+from, first, last);
118            }
119        }
120
121        static void
122        delete_item(Container& container, index_type i)
123        {
124            container.erase(container.begin()+i);
125        }
126       
127        static void
128        delete_slice(Container& container, index_type from, index_type to)
129        {
130            if (from > to) {
131                // A null-op.
132                return;
133            }
134            container.erase(container.begin()+from, container.begin()+to);
135        }
136       
137        static size_t
138        size(Container& container)
139        {
140            return container.size();
141        }
142       
143        static bool
144        contains(Container& container, key_type const& key)
145        {
146            return std::find(container.begin(), container.end(), key)
147                != container.end();
148        }
149       
150        static index_type
151        get_min_index(Container& container)
152        {
153            return 0;
154        }
155
156        static index_type
157        get_max_index(Container& container)
158        {
159            return container.size();
160        }
161     
162        static bool
163        compare_index(Container& container, index_type a, index_type b)
164        {
165            return a < b;
166        }
167       
168        static index_type
169        convert_index(Container& container, PyObject* i_)
170        {
171            extract<long> i(i_);
172            if (i.check())
173            {
174                long index = i();
175                if (index < 0)
176                    index += DerivedPolicies::size(container);
177                if (index >= long(container.size()) || index < 0)
178                {
179                    PyErr_SetString(PyExc_IndexError, "Index out of range");
180                    throw_error_already_set();
181                }
182                return index;
183            }
184           
185            PyErr_SetString(PyExc_TypeError, "Invalid index type");
186            throw_error_already_set();
187            return index_type();
188        }
189     
190        static void
191        append(Container& container, data_type const& v)
192        {
193            container.push_back(v);
194        }
195       
196        template <class Iter>
197        static void
198        extend(Container& container, Iter first, Iter last)
199        {
200            container.insert(container.end(), first, last);
201        }
202       
203    private:
204   
205        static void
206        base_append(Container& container, object v)
207        {
208            extract<data_type&> elem(v);
209            // try if elem is an exact Data
210            if (elem.check())
211            {
212                DerivedPolicies::append(container, elem());
213            }
214            else
215            {
216                //  try to convert elem to data_type
217                extract<data_type> elem(v);
218                if (elem.check())
219                {
220                    DerivedPolicies::append(container, elem());
221                }
222                else
223                {
224                    PyErr_SetString(PyExc_TypeError,
225                        "Attempting to append an invalid type");
226                    throw_error_already_set();
227                }
228            }
229        }
230       
231        static void
232        base_extend(Container& container, object v)
233        {
234            std::vector<data_type> temp;
235            container_utils::extend_container(temp, v);
236            DerivedPolicies::extend(container, temp.begin(), temp.end());
237        }
238    };
239       
240}} // namespace boost::python
241
242#endif // VECTOR_INDEXING_SUITE_JDG20036_HPP
Note: See TracBrowser for help on using the repository browser.