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>
59 typedef typename std::vector<PyObject*>::iterator
iterator;
67 return boost::detail::lower_bound(
68 proxies.begin(), proxies.end(),
77 iter != proxies.end(); ++iter)
79 if (&extract<Proxy&>(*iter)() == &proxy)
94 first_proxy(extract<Proxy&>(prox)().get_index()), prox);
114 extract<Proxy&>
p(*iter);
116 if (iter != proxies.end() &&
p().get_index() == i)
118 extract<Proxy&>
p(*iter);
140 typename std::vector<PyObject*>::size_type
len)
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)
193 if (iter != proxies.end()
194 && extract<Proxy&>(*iter)().get_index() == i)
203 typename std::vector<PyObject*>::size_type
208 return proxies.size();
215 check_invariant()
const
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();
240 std::vector<PyObject*> proxies;
248 template <
class Proxy,
class Container>
253 typedef std::map<Container*, proxy_group<Proxy> >
links_t;
260 typename links_t::iterator
r = links.find(&proxy.get_container());
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>
280 typename links_t::iterator
r = links.find(&container);
281 if (r != links.end())
283 r->second.erase(i, no_slice);
284 if (r->second.size() == 0)
293 typename links_t::iterator
r = links.find(&container);
294 if (r != links.end())
296 r->second.erase(from, to);
297 if (r->second.size() == 0)
304 Container& container,
314 typename links_t::iterator
r = links.find(&container);
315 if (r != links.end())
317 r->second.replace(from, to, len);
318 if (r->second.size() == 0)
329 typename links_t::iterator
r = links.find(&container);
330 if (r != links.end())
331 return r->second.find(i);
351 template <
class Container,
class Index,
class Policies>
365 , container(container)
372 , container(ce.container)
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>
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
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);
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());
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();
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