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>
28 struct compare_proxy_index
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>
352 class container_element
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
459 struct no_proxy_helper
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
708 struct no_slice_helper
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*
744 python::detail::container_element<Container, Index, Policies>
const&
p)
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)
Proxy::index_type index_type
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)
std::vector< PyObject * >::const_iterator const_iterator
element_type * get() const
void add(PyObject *prox, Container &container)
Policies::data_type * get_pointer(python::detail::container_element< Container, Index, Policies > const &p)
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)
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()
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)
#define BOOST_PYTHON_INDEXING_CHECK_INVARIANT
container_element(object container, Index index)
void erase(index_type i, mpl::false_)
std::vector< PyObject * >::iterator iterator
static void base_delete_slice(Container &container, PySliceObject *slice)
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
static object base_get_slice(Container &container, PySliceObject *slice)