source: trunk/environments/g4py/source/boost/vector_indexing_suite.hpp@ 1349

Last change on this file since 1349 was 1337, checked in by garnier, 15 years ago

tag geant4.9.4 beta 1 + modifs locales

File size: 7.1 KB
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 "indexing_suite.hpp"
10# include "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("push_back", &base_append)
66 .def("extend", &base_extend)
67 ;
68 }
69
70 static
71 typename mpl::if_<
72 is_class<data_type>
73 , data_type&
74 , data_type
75 >::type
76 get_item(Container& container, index_type i)
77 {
78 return container[i];
79 }
80
81 static object
82 get_slice(Container& container, index_type from, index_type to)
83 {
84 if (from > to)
85 return object(Container());
86 return object(Container(container.begin()+from, container.begin()+to));
87 }
88
89 static void
90 set_item(Container& container, index_type i, data_type const& v)
91 {
92 container[i] = v;
93 }
94
95 static void
96 set_slice(Container& container, index_type from,
97 index_type to, data_type const& v)
98 {
99 if (from > to) {
100 return;
101 }
102 else {
103 container.erase(container.begin()+from, container.begin()+to);
104 container.insert(container.begin()+from, v);
105 }
106 }
107
108 template <class Iter>
109 static void
110 set_slice(Container& container, index_type from,
111 index_type to, Iter first, Iter last)
112 {
113 if (from > to) {
114 container.insert(container.begin()+from, first, last);
115 }
116 else {
117 container.erase(container.begin()+from, container.begin()+to);
118 container.insert(container.begin()+from, first, last);
119 }
120 }
121
122 static void
123 delete_item(Container& container, index_type i)
124 {
125 container.erase(container.begin()+i);
126 }
127
128 static void
129 delete_slice(Container& container, index_type from, index_type to)
130 {
131 if (from > to) {
132 // A null-op.
133 return;
134 }
135 container.erase(container.begin()+from, container.begin()+to);
136 }
137
138 static size_t
139 size(Container& container)
140 {
141 return container.size();
142 }
143
144 static bool
145 contains(Container& container, key_type const& key)
146 {
147 return std::find(container.begin(), container.end(), key)
148 != container.end();
149 }
150
151 static index_type
152 get_min_index(Container& container)
153 {
154 return 0;
155 }
156
157 static index_type
158 get_max_index(Container& container)
159 {
160 return container.size();
161 }
162
163 static bool
164 compare_index(Container& container, index_type a, index_type b)
165 {
166 return a < b;
167 }
168
169 static index_type
170 convert_index(Container& container, PyObject* i_)
171 {
172 extract<long> i(i_);
173 if (i.check())
174 {
175 long index = i();
176 if (index < 0)
177 index += DerivedPolicies::size(container);
178 if (index >= long(container.size()) || index < 0)
179 {
180 PyErr_SetString(PyExc_IndexError, "Index out of range");
181 throw_error_already_set();
182 }
183 return index;
184 }
185
186 PyErr_SetString(PyExc_TypeError, "Invalid index type");
187 throw_error_already_set();
188 return index_type();
189 }
190
191 static void
192 append(Container& container, data_type const& v)
193 {
194 container.push_back(v);
195 }
196
197 template <class Iter>
198 static void
199 extend(Container& container, Iter first, Iter last)
200 {
201 container.insert(container.end(), first, last);
202 }
203
204 private:
205
206 static void
207 base_append(Container& container, object v)
208 {
209 extract<data_type&> elem(v);
210 // try if elem is an exact Data
211 if (elem.check())
212 {
213 DerivedPolicies::append(container, elem());
214 }
215 else
216 {
217 // try to convert elem to data_type
218 extract<data_type> elem(v);
219 if (elem.check())
220 {
221 DerivedPolicies::append(container, elem());
222 }
223 else
224 {
225 PyErr_SetString(PyExc_TypeError,
226 "Attempting to append an invalid type");
227 throw_error_already_set();
228 }
229 }
230 }
231
232 static void
233 base_extend(Container& container, object v)
234 {
235 std::vector<data_type> temp;
236 container_utils::extend_container(temp, v);
237 DerivedPolicies::extend(container, temp.begin(), temp.end());
238 }
239 };
240
241}} // namespace boost::python
242
243#endif // VECTOR_INDEXING_SUITE_JDG20036_HPP
Note: See TracBrowser for help on using the repository browser.