MYNT-EYE-S-SDK/wrappers/python/third_party/array/array_indexing_suite.hpp

143 lines
4.0 KiB
C++
Raw Normal View History

2018-05-20 04:25:30 +03:00
// From Praetorian's answer here: http://stackoverflow.com/a/27560620
#include <boost/python.hpp>
#include <boost/python/suite/indexing/indexing_suite.hpp>
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <type_traits>
// Forward declaration
template <typename Array, bool NoProxy, typename DerivedPolicies>
class array_indexing_suite;
namespace detail {
template <typename Array, bool NoProxy>
struct final_array_derived_policies
: array_indexing_suite<Array, NoProxy,
final_array_derived_policies<Array, NoProxy>> {};
} /* namespace detail */
template <typename Array,
bool NoProxy = std::is_arithmetic<typename Array::value_type>::value,
typename DerivedPolicies =
detail::final_array_derived_policies<Array, NoProxy>>
class array_indexing_suite
: public boost::python::indexing_suite<Array, DerivedPolicies, NoProxy> {
public:
typedef typename Array::value_type data_type;
typedef typename Array::value_type key_type;
typedef typename Array::size_type index_type;
typedef typename Array::size_type size_type;
typedef typename Array::difference_type difference_type;
static data_type &get_item(Array &arr, index_type i) {
return arr[i];
}
static void set_item(Array &arr, index_type i, data_type const &v) {
arr[i] = v;
}
static void delete_item(Array & /*arr*/, index_type /*i*/) {
::PyErr_SetString(::PyExc_TypeError, "Cannot delete array item");
boost::python::throw_error_already_set();
}
static size_type size(Array &arr) {
return arr.size();
}
static bool contains(Array &arr, key_type const &key) {
return std::find(arr.cbegin(), arr.cend(), key) != arr.cend();
}
static index_type get_min_index(Array &) {
return 0;
}
static index_type get_max_index(Array &arr) {
return arr.size();
}
static bool compare_index(Array &, index_type a, index_type b) {
return a < b;
}
static index_type convert_index(Array &arr, PyObject *i_) {
boost::python::extract<long> i(i_);
if (i.check()) {
long index = i();
if (index < 0) {
index += static_cast<decltype(index)>(DerivedPolicies::size(arr));
}
if ((index >= long(arr.size())) || (index < 0)) {
::PyErr_SetString(::PyExc_IndexError, "Index out of range");
boost::python::throw_error_already_set();
}
return index;
}
::PyErr_SetString(::PyExc_TypeError, "Invalid index type");
boost::python::throw_error_already_set();
return index_type();
}
static boost::python::object get_slice(
Array &arr, index_type from, index_type to) {
if (from > to) {
return boost::python::object(Array());
}
return boost::python::object(Array(arr.begin() + from, arr.begin() + to));
}
static void set_slice(
Array &arr, index_type from, index_type to, data_type const &v) {
if (from > to) {
return;
} else if (to > arr.size()) {
::PyErr_SetString(::PyExc_IndexError, "Index out of range");
boost::python::throw_error_already_set();
} else {
std::fill(arr.begin() + from, arr.begin() + to, v);
}
}
template <typename Iter>
static void set_slice(
Array &arr, index_type from, index_type to, Iter first, Iter last) {
auto num_items = std::distance(first, last);
if ((from + num_items) > arr.size()) {
::PyErr_SetString(::PyExc_IndexError, "Index out of range");
boost::python::throw_error_already_set();
return;
}
if (from > to) {
std::copy(first, last, arr.begin() + from);
} else {
if (static_cast<decltype(num_items)>(to - from) != num_items) {
::PyErr_SetString(::PyExc_TypeError, "Array length is immutable");
boost::python::throw_error_already_set();
return;
}
std::copy(first, last, arr.begin() + from);
}
}
static void delete_slice(
Array & /*arr*/, index_type /*from*/, index_type /*to*/) {
::PyErr_SetString(::PyExc_TypeError, "Cannot delete array item(s)");
boost::python::throw_error_already_set();
}
};