• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 namespace 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
extension_def(Class & cl)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
get_item(Container & container,index_type i)75         get_item(Container& container, index_type i)
76         {
77             return container[i];
78         }
79 
80         static object
get_slice(Container & container,index_type from,index_type to)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
set_item(Container & container,index_type i,data_type const & v)89         set_item(Container& container, index_type i, data_type const& v)
90         {
91             container[i] = v;
92         }
93 
94         static void
set_slice(Container & container,index_type from,index_type to,data_type const & v)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
set_slice(Container & container,index_type from,index_type to,Iter first,Iter last)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
delete_item(Container & container,index_type i)122         delete_item(Container& container, index_type i)
123         {
124             container.erase(container.begin()+i);
125         }
126 
127         static void
delete_slice(Container & container,index_type from,index_type to)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
size(Container & container)138         size(Container& container)
139         {
140             return container.size();
141         }
142 
143         static bool
contains(Container & container,key_type const & key)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
get_min_index(Container &)151         get_min_index(Container& /*container*/)
152         {
153             return 0;
154         }
155 
156         static index_type
get_max_index(Container & container)157         get_max_index(Container& container)
158         {
159             return container.size();
160         }
161 
162         static bool
compare_index(Container &,index_type a,index_type b)163         compare_index(Container& /*container*/, index_type a, index_type b)
164         {
165             return a < b;
166         }
167 
168         static index_type
convert_index(Container & container,PyObject * i_)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
append(Container & container,data_type const & v)191         append(Container& container, data_type const& v)
192         {
193             container.push_back(v);
194         }
195 
196         template <class Iter>
197         static void
extend(Container & container,Iter first,Iter last)198         extend(Container& container, Iter first, Iter last)
199         {
200             container.insert(container.end(), first, last);
201         }
202 
203     private:
204 
205         static void
base_append(Container & container,object v)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
base_extend(Container & container,object v)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
243