GCC Code Coverage Report


Directory: ./
File: bindings/python/crocoddyl/utils/set_indexing_suite.hpp
Date: 2025-06-03 08:14:12
Exec Total Coverage
Lines: 0 67 0.0%
Functions: 0 19 0.0%
Branches: 0 44 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 ✗ static void extension_def(Class& class_) {
61 ✗ class_.def("add", &function<DerivedPolicies::add>)
62 ✗ .def("remove", &function<DerivedPolicies::remove>)
63 ✗ .def("discard", &function<DerivedPolicies::discard>)
64 ✗ .def("clear", &DerivedPolicies::clear);
65 ✗ }
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_
171