Michele De Stefano's C++ Utilities
container_operators.hpp
Go to the documentation of this file.
1 // container_operators.hpp
2 //
3 // Copyright (c) 2014 - Michele De Stefano (micdestefano@users.sourceforge.net)
4 //
5 // Distributed under the MIT License (See accompanying file LICENSE)
6 
7 #ifndef MDS_UTILS_PYTHON_CONTAINER_OPERATORS_HPP_INCLUDED
8 #define MDS_UTILS_PYTHON_CONTAINER_OPERATORS_HPP_INCLUDED
9 
14 #include <boost/numeric/conversion/cast.hpp>
15 
34 namespace mds_utils {
35  namespace python {
36 
37 
57 template<class Derived>
59 
60 
76  Obj py_get_item(const Obj &idx) {
77 
78  using namespace boost;
79 
80  Derived &self(static_cast<Derived&>(*this));
81 
82  Py_ssize_t nel(numeric_cast<Py_ssize_t>(self.get_nel()));
83 
84  if (PySlice_Check(idx)) {
85 
86  Py_ssize_t start(0),stop(0),step(0),slen(0);
87 
88  PySlice_GetIndicesEx(
89  reinterpret_cast<PySliceObject*>(static_cast<PyObject*>(idx)),
90  self.get_nel(),&start,&stop,&step,&slen);
91 
92  List l;
93 
94  Py_ssize_t k,i,ind;
95 
96  for (k = 0,ind = i = start;k < slen;++k,i += step,ind = i) {
97  if (ind < 0) ind += nel;
98  if (ind < 0 || ind >= nel) {
99  throw index_error("Index out of range");
100  }
101  l.append(self.get_el_at(ind));
102  }
103 
104  return l;
105  } else {
106 
107  Py_ssize_t i = get<Py_ssize_t>(idx);
108  if (i < 0) i += nel;
109  if (i < 0 || i >= nel) {
110  throw index_error("Index out of range");
111  }
112 
113  return to_python(self.get_el_at(i));
114  }
115 
116  }
117 
118 };
119 
120 
143 template<class Derived>
145 
158  void py_set_item(const Obj& idx,const Obj& val) {
159 
160  using namespace boost;
161 
162  Derived &self(static_cast<Derived&>(*this));
163 
164  Py_ssize_t nel(numeric_cast<Py_ssize_t>(self.get_nel()));
165 
166  if (PySlice_Check(idx)) {
167 
168  if (!PySequence_Check(val)) {
169  throw std::invalid_argument("The value to be set is not a sequence");
170  }
171 
172  Py_ssize_t start(0),stop(0),step(0),slen(0);
173 
174  PySlice_GetIndicesEx(
175  reinterpret_cast<PySliceObject*>(static_cast<PyObject*>(idx)),
176  self.get_nel(),&start,&stop,&step,&slen);
177 
178  Py_ssize_t len_val(PySequence_Length(val));
179 
180  if (len_val != slen) {
181  throw std::invalid_argument("The rhs has not the same dimensions as the lhs.");
182  }
183 
184  Py_ssize_t k,i,ind;
185 
186  for (k = 0,ind = i = start;k < slen;++k,i += step,ind = i) {
187  if (ind < 0) ind += nel;
188  if (ind < 0 || ind >= nel) {
189  throw index_error("Index out of range");
190  }
191 
192  Obj py_val(PySequence_GetItem(val,k));
193 
194  py_val.get_ownership();
195 
196  self.set_el_at(ind,
197  get<typename Derived::value_type>(py_val));
198  }
199 
200  } else {
201 
202  Py_ssize_t i = get<Py_ssize_t>(idx);
203  if (i < 0) i += nel;
204  if (i < 0 || i >= nel) {
205  throw index_error("Index out of range");
206  }
207 
208  self.set_el_at(i,get<typename Derived::value_type>(val));
209  }
210 
211  }
212 
213 };
214 
215 
216 
217  } // namespace python
218 } // namespace mds_utils
219 
220 #endif
Obj py_get_item(const Obj &idx)
Manages container read access through Python indices and slices.
Contains a wrapper class for the Python list datatype.
PyObject * to_python(void)
Converts a value into a Python object.
Adds support for random access operator (i.e. square brackets) to a class that has to be exposed to t...
Main namespace of all Michele De Stefano&#39;s C++ utilities.
Definition: endian.hpp:30
Adds support for random get/set access operator (i.e. square brackets) to a class that has to be expo...
Utilities and workarounds for all the extension codes.
Wraps a Python list.
Definition: list.hpp:47
Exception used for detecting and raising IndexError Python exceptions.
Definition: exception.hpp:40
void get_ownership()
Used in place of incref, when the wrapped PyObject* was increfed already.
Definition: obj.hpp:380
void py_set_item(const Obj &idx, const Obj &val)
Manages container write access through Python indices and slices.
List & append(const T &val)
Appends an element to the list.
Definition: list.hpp:127
Contains new C++ exceptions created specifically for interoperation with Python.
Utilities for converting data from/to Python.
This is a simple wrapper around the PyObject* datatype.
Definition: obj.hpp:68