LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
vector_indexing_suite.hpp
Go to the documentation of this file.
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 
13 namespace boost { namespace python {
14 
15  // Forward declaration
16  template <class Container, bool NoProxy, class DerivedPolicies>
18 
19  namespace detail
20  {
21  template <class Container, bool NoProxy>
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
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;
237  DerivedPolicies::extend(container, temp.begin(), temp.end());
238  }
239  };
240 
241 }} // namespace boost::python
242 
243 #endif // VECTOR_INDEXING_SUITE_JDG20036_HPP
static void delete_slice(Container &container, index_type from, index_type to)
static void set_item(Container &container, index_type i, data_type const &v)
static void append(Container &container, data_type const &v)
Container::difference_type difference_type
void extend_container(Container &container, object l)
static void delete_item(Container &container, index_type i)
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
static void set_slice(Container &container, index_type from, index_type to, data_type const &v)
static index_type convert_index(Container &container, PyObject *i_)
static size_t size(Container &container)
static index_type get_max_index(Container &container)
static bool contains(Container &container, key_type const &key)
static object get_slice(Container &container, index_type from, index_type to)
static mpl::if_< is_class< data_type >, data_type &, data_type >::type get_item(Container &container, index_type i)
static index_type get_min_index(Container &container)
static bool compare_index(Container &container, index_type a, index_type b)
static void extend(Container &container, Iter first, Iter last)
static void set_slice(Container &container, index_type from, index_type to, Iter first, Iter last)