GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bindings/python/crocoddyl/utils/set_indexing_suite.hpp Lines: 6 57 10.5 %
Date: 2024-02-13 11:12:33 Branches: 0 48 0.0 %

Line Branch Exec Source
1
///////////////////////////////////////////////////////////////////////////////
2
// BSD 3-Clause License
3
//
4
// Copyright (C) 2022, University of Edinburgh
5
// Copyright note valid unless otherwise stated in individual files.
6
// All rights reserved.
7
///////////////////////////////////////////////////////////////////////////////
8
9
#ifndef BINDINGS_PYTHON_CROCODDYL_UTILS_SET_INDEXING_SUITE_HPP_
10
#define BINDINGS_PYTHON_CROCODDYL_UTILS_SET_INDEXING_SUITE_HPP_
11
12
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
13
14
namespace crocoddyl {
15
namespace python {
16
17
template <typename Container, bool NoProxy, typename DerivedPolicies>
18
class set_indexing_suite;
19
20
namespace detail {
21
template <typename Container, bool NoProxy>
22
class final_set_derived_policies
23
    : public crocoddyl::python::set_indexing_suite<
24
          Container, NoProxy, final_set_derived_policies<Container, NoProxy> > {
25
};
26
}  // namespace detail
27
28
// The set_indexing_suite class is a predefined indexing_suite derived
29
// class for wrapping std::set (and std::set like) classes. It provides
30
// all the policies required by the indexing_suite (see indexing_suite).
31
// Example usage:
32
//
33
//  class X {...};
34
//
35
//  ...
36
//
37
//      class_<std::set<X> >("XSet")
38
//          .def(set_indexing_suite<std::set<X> >())
39
//      ;
40
//
41
// By default indexed elements are returned by proxy. This can be
42
// disabled by supplying *true* in the NoProxy template parameter.
43
//
44
template <typename Container, bool NoProxy = false,
45
          typename DerivedPolicies =
46
              detail::final_set_derived_policies<Container, NoProxy> >
47
class set_indexing_suite
48
    : public boost::python::vector_indexing_suite<Container, NoProxy,
49
                                                  DerivedPolicies> {
50
  typedef boost::python::vector_indexing_suite<Container, NoProxy,
51
                                               DerivedPolicies>
52
      base;
53
54
 public:
55
  typedef typename base::data_type data_type;
56
  typedef typename base::index_type index_type;
57
  typedef typename base::key_type key_type;
58
59
  template <class Class>
60
10
  static void extension_def(Class& class_) {
61
10
    class_.def("add", &function<DerivedPolicies::add>)
62
10
        .def("remove", &function<DerivedPolicies::remove>)
63
10
        .def("discard", &function<DerivedPolicies::discard>)
64
10
        .def("clear", &DerivedPolicies::clear);
65
10
  }
66
67
  static bool contains(Container& container, key_type const& key) {
68
    return container.find(key) != container.end();
69
  }
70
71
  static void add(Container& container, data_type const& v) {
72
    container.insert(v);
73
  }
74
75
  static void discard(Container& container, data_type const& v) {
76
    container.erase(v);
77
  }
78
79
  static void remove(Container& container, data_type const& v) {
80
    if (!container.erase(v)) {
81
      PyErr_SetString(PyExc_KeyError, "Element doesn't exist");
82
      boost::python::throw_error_already_set();
83
    }
84
  }
85
86
  static void clear(Container& container) { container.clear(); }
87
88
  static data_type get_item(Container& container, index_type i) {
89
    return *std::next(container.begin(), i);
90
  }
91
92
  static void set_item(Container&, index_type, data_type const&) {
93
    not_supported();
94
  }
95
96
  static void delete_item(Container& container, index_type i) {
97
    container.erase(advance(container.begin(), i));
98
  }
99
100
  static boost::python::object get_slice(Container& container, index_type from,
101
                                         index_type to) {
102
    if (from > to) return boost::python::object(Container());
103
104
    auto s = slice(container, from, to);
105
    return boost::python::object(Container(s.first, s.second));
106
  }
107
108
  static void set_slice(Container&, index_type, index_type, data_type const&) {
109
    not_supported();
110
  }
111
112
  template <typename Iter>
113
  static void set_slice(Container&, index_type, index_type, Iter, Iter) {
114
    not_supported();
115
  }
116
117
  static void delete_slice(Container& container, index_type from,
118
                           index_type to) {
119
    if (to >= from) {
120
      auto s = slice(container, from, to);
121
      container.erase(s.first, s.second);
122
    }
123
  }
124
125
 private:
126
  static typename Container::iterator advance(
127
      typename Container::iterator it, typename Container::difference_type i) {
128
    return std::advance(it, i), it;
129
  }
130
131
  static std::pair<typename Container::iterator, typename Container::iterator>
132
  slice(Container& container, index_type from, index_type to) {
133
    BOOST_ASSERT(to >= from);
134
    std::pair<typename Container::iterator, typename Container::iterator> s;
135
    s.first = container.begin();
136
    std::advance(s.first, from);
137
    s.second = s.first;
138
    std::advance(s.second, to - from);
139
    return s;
140
  }
141
142
  template <void (*fn)(Container&, data_type const&)>
143
  static void function(Container& container, const boost::python::object v) {
144
    using namespace boost::python;
145
    extract<data_type&> elemRef(v);
146
147
    if (elemRef.check()) {
148
      fn(container, elemRef());
149
    } else {
150
      extract<data_type> elem(v);
151
      if (elem.check()) {
152
        fn(container, elem());
153
      } else {
154
        PyErr_SetString(PyExc_TypeError, "Invalid type");
155
        throw_error_already_set();
156
      }
157
    }
158
  }
159
160
  static void not_supported() {
161
    PyErr_SetString(PyExc_TypeError,
162
                    "__setitem__ not supported for set object");
163
    boost::python::throw_error_already_set();
164
  }
165
};
166
167
}  // namespace python
168
}  // namespace crocoddyl
169
170
#endif  // BINDINGS_PYTHON_CROCODDYL_UTILS_SET_INDEXING_SUITE_HPP_