6 #ifndef INDEXING_SUITE_DETAIL_JDG20036_HPP 7 # define INDEXING_SUITE_DETAIL_JDG20036_HPP 9 # include <boost/python/extract.hpp> 10 # include <boost/scoped_ptr.hpp> 11 # include <boost/get_pointer.hpp> 12 # include <boost/detail/binary_search.hpp> 13 # include <boost/numeric/conversion/cast.hpp> 14 # include <boost/type_traits/is_pointer.hpp> 19 namespace boost {
namespace python {
namespace detail {
22 #define BOOST_PYTHON_INDEXING_CHECK_INVARIANT 24 #define BOOST_PYTHON_INDEXING_CHECK_INVARIANT check_invariant() 27 template <
class Proxy>
34 template <
class Index>
37 typedef typename Proxy::policies_type policies_type;
38 Proxy&
proxy = extract<Proxy&>(prox)();
39 return policies_type::
40 compare_index(proxy.get_container(), proxy.get_index(), i);
53 template <
class Proxy>
67 return boost::detail::lower_bound(
68 proxies.begin(), proxies.end(),
76 for (iterator iter = first_proxy(
proxy.get_index());
77 iter != proxies.end(); ++iter)
79 if (&extract<Proxy&>(*iter)() == &
proxy)
94 first_proxy(extract<Proxy&>(prox)().get_index()), prox);
99 erase(index_type i, mpl::false_)
113 iterator iter = first_proxy(i);
114 extract<Proxy&> p(*iter);
116 if (iter != proxies.end() && p().get_index() == i)
118 extract<Proxy&> p(*iter);
126 erase(index_type from, index_type to)
132 replace(from, to, 0);
140 typename std::vector<PyObject*>::size_type len)
152 iterator
left = first_proxy(from);
153 iterator
right = proxies.end();
155 for (iterator iter = left; iter !=
right; ++iter)
157 if (extract<Proxy&>(*iter)().get_index() > to)
162 extract<Proxy&> p(*iter);
166 typename std::vector<PyObject*>::size_type
167 offset = left-proxies.begin();
168 proxies.erase(left, right);
169 right = proxies.begin()+offset;
171 while (right != proxies.end())
173 typedef typename Proxy::container_type::difference_type difference_type;
174 extract<Proxy&> p(*right);
176 extract<Proxy&>(*right)().get_index()
177 - (difference_type(to) - from - len)
192 iterator iter = first_proxy(i);
193 if (iter != proxies.end()
194 && extract<Proxy&>(*iter)().get_index() == i)
203 typename std::vector<PyObject*>::size_type
208 return proxies.size();
217 for (const_iterator i = proxies.begin(); i != proxies.end(); ++i)
219 if ((*i)->ob_refcnt <= 0)
221 PyErr_SetString(PyExc_RuntimeError,
222 "Invariant: Proxy vector in an inconsistent state");
223 throw_error_already_set();
226 if (i+1 != proxies.end())
228 if (extract<Proxy&>(*(i+1))().get_index() ==
229 extract<Proxy&>(*(i))().get_index())
231 PyErr_SetString(PyExc_RuntimeError,
232 "Invariant: Proxy vector in an inconsistent state (duplicate proxy)");
233 throw_error_already_set();
248 template <
class Proxy,
class Container>
253 typedef std::map<Container*, proxy_group<Proxy> >
links_t;
261 if (r != links.end())
263 r->second.remove(
proxy);
264 if (r->second.size() == 0)
270 add(PyObject* prox, Container& container)
273 links[&container].add(prox);
276 template <
class NoSlice>
277 void erase(Container& container, index_type i, NoSlice no_slice)
281 if (r != links.end())
283 r->second.erase(i, no_slice);
284 if (r->second.size() == 0)
290 erase(Container& container, index_type from, index_type to)
294 if (r != links.end())
296 r->second.erase(from, to);
297 if (r->second.size() == 0)
304 Container& container,
305 index_type from, index_type to, index_type len)
315 if (r != links.end())
317 r->second.replace(from, to, len);
318 if (r->second.size() == 0)
324 find(Container& container, index_type i)
330 if (r != links.end())
331 return r->second.find(i);
351 template <
class Container,
class Index,
class Policies>
365 , container(container)
371 : ptr(ce.ptr.
get() == 0 ? 0 : new element_type(*ce.ptr.
get()))
372 , container(ce.container)
380 get_links().remove(*
this);
387 return Policies::get_item(get_container(), index);
390 element_type*
get()
const 394 return &Policies::get_item(get_container(), index);
404 Policies::get_item(get_container(), index)));
405 container = object();
418 return extract<Container&>(container)();
448 scoped_ptr<element_type>
ptr;
455 ,
class DerivedPolicies
456 ,
class ContainerElement
466 template <
class DataType>
470 return object(ptr(p));
473 template <
class DataType>
483 return base_get_item_helper(
484 DerivedPolicies::get_item(
485 container.get(), DerivedPolicies::
486 convert_index(container.get(), i))
487 , is_pointer<BOOST_DEDUCED_TYPENAME Container::value_type>()
493 Container& container, Index from,
498 template <
class NoSlice>
501 Container& container, Index i, NoSlice no_slice)
513 ,
class DerivedPolicies
514 ,
class ContainerElement
522 register_ptr_to_python<ContainerElement>();
529 Index idx = DerivedPolicies::convert_index(container.get(), i);
531 if (PyObject* shared =
532 ContainerElement::get_links().find(container.get(), idx))
534 handle<> h(python::borrowed(shared));
539 object prox(ContainerElement(container.source(), idx));
541 get_links().add(prox.ptr(), container.get());
548 Container& container, Index from,
551 ContainerElement::get_links().replace(container, from, to, n);
554 template <
class NoSlice>
557 Container& container, Index i, NoSlice no_slice)
559 ContainerElement::get_links().erase(container, i, no_slice);
564 Container& container, Index from, Index to)
566 ContainerElement::get_links().erase(container, from, to);
572 ,
class DerivedPolicies
583 base_get_slice_data(container, slice, from, to);
584 return DerivedPolicies::get_slice(container, from, to);
589 Container& container, PySliceObject* slice, Index& from_, Index& to_)
591 if (Py_None != slice->step) {
592 PyErr_SetString( PyExc_IndexError,
"slice step size not supported.");
593 throw_error_already_set();
596 Index min_index = DerivedPolicies::get_min_index(container);
597 Index max_index = DerivedPolicies::get_max_index(container);
599 if (Py_None == slice->start) {
603 long from = extract<long>( slice->start);
608 from_ = boost::numeric_cast<Index>(from);
609 if (from_ > max_index)
613 if (Py_None == slice->stop) {
617 long to = extract<long>( slice->stop);
622 to_ = boost::numeric_cast<Index>(to);
632 base_get_slice_data(container, slice, from, to);
634 extract<Data&> elem(v);
638 ProxyHandler::base_replace_indexes(container, from, to, 1);
639 DerivedPolicies::set_slice(container, from, to, elem());
644 extract<Data> elem(v);
647 ProxyHandler::base_replace_indexes(container, from, to, 1);
648 DerivedPolicies::set_slice(container, from, to, elem());
653 handle<> l_(python::borrowed(v));
656 std::vector<Data> temp;
657 for (
int i = 0; i < l.attr(
"__len__")(); i++)
660 extract<Data const&>
x(elem);
669 extract<Data>
x(elem);
676 PyErr_SetString(PyExc_TypeError,
677 "Invalid sequence element");
678 throw_error_already_set();
683 ProxyHandler::base_replace_indexes(container, from, to,
684 temp.end()-temp.begin());
685 DerivedPolicies::set_slice(container, from, to,
686 temp.begin(), temp.end());
695 base_get_slice_data(container, slice, from, to);
696 ProxyHandler::base_erase_indexes(container, from, to);
697 DerivedPolicies::delete_slice(container, from, to);
703 ,
class DerivedPolicies
713 PyErr_SetString(PyExc_RuntimeError,
"Slicing not supported");
714 throw_error_already_set();
720 slicing_not_suported();
727 slicing_not_suported();
733 slicing_not_suported();
737 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 741 template <
class Container,
class Index,
class Policies>
742 inline typename Policies::data_type*
750 #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 759 #endif // INDEXING_SUITE_DETAIL_JDG20036_HPP
container_element< Container, Index, Policies > self_t
static void base_delete_slice(Container &container, PySliceObject *slice)
void check_invariant() const
Proxy::index_type index_type
std::vector< PyObject * > proxies
static void register_container_element()
bool operator()(PyObject *prox, Index i) const
void replace(Container &container, index_type from, index_type to, index_type len)
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
std::vector< PyObject * >::const_iterator const_iterator
element_type * get() const
void add(PyObject *prox, Container &container)
static void base_set_slice(Container &container, PySliceObject *slice, PyObject *v)
proxy_group< self_t > links_type
static void base_erase_index(Container &container, Index i, NoSlice no_slice)
container_element(container_element const &ce)
void erase(index_type from, index_type to)
Policies::data_type element_type
void erase(Container &container, index_type i, NoSlice no_slice)
Policies::data_type * get_pointer(python::detail::container_element< Container, Index, Policies > const &p)
static object base_get_item_helper(DataType const &x, mpl::false_)
element_type & operator*() const
static proxy_links< self_t, Container > & get_links()
PyObject * find(index_type i)
void erase(index_type i, mpl::true_)
static void base_erase_indexes(Container &container, Index from, Index to)
static void base_set_slice(Container &container, PySliceObject *slice, PyObject *v)
static void slicing_not_suported()
Encloses LArSoft data product proxy objects and utilities.See this doxygen module for an introduction...
static void base_erase_index(Container &container, Index i, NoSlice no_slice)
void erase(Container &container, index_type from, index_type to)
static void base_replace_indexes(Container &container, Index from, Index to, Index n)
static void base_erase_indexes(Container &container, Index from, Index to)
container_element(object container, Index index)
void erase(index_type i, mpl::false_)
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
std::vector< PyObject * >::iterator iterator
static void base_delete_slice(Container &container, PySliceObject *slice)
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
static object base_get_item_helper(DataType const &p, mpl::true_)
iterator first_proxy(index_type i)
static object base_get_item_(back_reference< Container & > const &container, PyObject *i)
static void base_replace_indexes(Container &container, Index from, Index to, Index n)
static object base_get_slice(Container &container, PySliceObject *slice)
PyObject * find(Container &container, index_type i)
Container & get_container() const
void replace(index_type from, index_type to, typename std::vector< PyObject * >::size_type len)
std::map< Container *, proxy_group< Proxy > > links_t
static void base_get_slice_data(Container &container, PySliceObject *slice, Index &from_, Index &to_)
std::vector< PyObject * >::size_type size() const
static void register_container_element()
static object base_get_item_(back_reference< Container & > const &container, PyObject *i)
Proxy::policies_type policies_type
Proxy::index_type index_type
#define BOOST_PYTHON_INDEXING_CHECK_INVARIANT
scoped_ptr< element_type > ptr
static object base_get_slice(Container &container, PySliceObject *slice)