760 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			760 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //  (C) Copyright Joel de Guzman 2003. | ||
|  | //  Distributed under the Boost Software License, Version 1.0. (See | ||
|  | //  accompanying file LICENSE_1_0.txt or copy at | ||
|  | //  http://www.boost.org/LICENSE_1_0.txt) | ||
|  | 
 | ||
|  | #ifndef INDEXING_SUITE_DETAIL_JDG20036_HPP | ||
|  | # define INDEXING_SUITE_DETAIL_JDG20036_HPP | ||
|  | 
 | ||
|  | # include <boost/python/extract.hpp> | ||
|  | # include <boost/scoped_ptr.hpp> | ||
|  | # include <boost/get_pointer.hpp> | ||
|  | # include <boost/detail/binary_search.hpp> | ||
|  | # include <boost/numeric/conversion/cast.hpp> | ||
|  | # include <boost/type_traits/is_pointer.hpp> | ||
|  | # include <vector> | ||
|  | # include <map> | ||
|  | #include <iostream> | ||
|  | 
 | ||
|  | namespace boost { namespace python { namespace detail { | ||
|  | 
 | ||
|  | #if defined(NDEBUG) | ||
|  | #define BOOST_PYTHON_INDEXING_CHECK_INVARIANT | ||
|  | #else | ||
|  | #define BOOST_PYTHON_INDEXING_CHECK_INVARIANT check_invariant() | ||
|  | #endif | ||
|  |      | ||
|  |     template <class Proxy> | ||
|  |     struct compare_proxy_index | ||
|  |     { | ||
|  |         //  This functor compares a proxy and an index. | ||
|  |         //  This is used by proxy_group::first_proxy to | ||
|  |         //  get first proxy with index i. | ||
|  |                  | ||
|  |         template <class Index> | ||
|  |         bool operator()(PyObject* prox, Index i) const | ||
|  |         { | ||
|  |             typedef typename Proxy::policies_type policies_type; | ||
|  |             Proxy& proxy = extract<Proxy&>(prox)(); | ||
|  |             return policies_type:: | ||
|  |                 compare_index(proxy.get_container(), proxy.get_index(), i); | ||
|  |         } | ||
|  |     };         | ||
|  |   | ||
|  |     //  The proxy_group class holds a vector of container element | ||
|  |     //  proxies. First, what is a container element proxy? A container  | ||
|  |     //  element proxy acts like a smart pointer holding a reference to  | ||
|  |     //  a container and an index (see container_element, for details).  | ||
|  |     // | ||
|  |     //  The proxies are held in a vector always sorted by its index. | ||
|  |     //  Various functions manage the addition, removal and searching | ||
|  |     //  of proxies from the vector. | ||
|  |     // | ||
|  |     template <class Proxy> | ||
|  |     class proxy_group | ||
|  |     { | ||
|  |     public: | ||
|  |      | ||
|  |         typedef typename std::vector<PyObject*>::const_iterator const_iterator; | ||
|  |         typedef typename std::vector<PyObject*>::iterator iterator; | ||
|  |         typedef typename Proxy::index_type index_type; | ||
|  |         typedef typename Proxy::policies_type policies_type; | ||
|  |          | ||
|  |         iterator | ||
|  |         first_proxy(index_type i) | ||
|  |         { | ||
|  |             // Return the first proxy with index <= i | ||
|  |             return boost::detail::lower_bound( | ||
|  |                 proxies.begin(), proxies.end(),  | ||
|  |                 i, compare_proxy_index<Proxy>()); | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         remove(Proxy& proxy) | ||
|  |         { | ||
|  |             // Remove a proxy | ||
|  |             for (iterator iter = first_proxy(proxy.get_index()); | ||
|  |                 iter != proxies.end(); ++iter) | ||
|  |             { | ||
|  |                 if (&extract<Proxy&>(*iter)() == &proxy) | ||
|  |                 { | ||
|  |                     proxies.erase(iter); | ||
|  |                     break; | ||
|  |                 } | ||
|  |             } | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         add(PyObject* prox) | ||
|  |         { | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // Add a proxy | ||
|  |             proxies.insert( | ||
|  |                 first_proxy(extract<Proxy&>(prox)().get_index()), prox); | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         erase(index_type i, mpl::false_) | ||
|  |         { | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // Erase the proxy with index i  | ||
|  |             replace(i, i+1, 0); | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         erase(index_type i, mpl::true_) | ||
|  |         { | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // Erase the proxy with index i  | ||
|  |              | ||
|  |             iterator iter = first_proxy(i); | ||
|  |             extract<Proxy&> p(*iter); | ||
|  |              | ||
|  |             if (iter != proxies.end() && p().get_index() == i) | ||
|  |             { | ||
|  |                 extract<Proxy&> p(*iter); | ||
|  |                 p().detach(); | ||
|  |                 proxies.erase(iter); | ||
|  |             } | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         erase(index_type from, index_type to) | ||
|  |         { | ||
|  |             // note: this cannot be called when container is not sliceable | ||
|  |              | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // Erase all proxies with indexes from..to  | ||
|  |             replace(from, to, 0); | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         replace( | ||
|  |             index_type from,  | ||
|  |             index_type to,  | ||
|  |             typename std::vector<PyObject*>::size_type len) | ||
|  |         { | ||
|  |             // note: this cannot be called when container is not sliceable | ||
|  | 
 | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // Erase all proxies with indexes from..to. | ||
|  |             // Adjust the displaced indexes such that the | ||
|  |             // final effect is that we have inserted *len* | ||
|  |             // number of proxies in the vacated region. This | ||
|  |             // procedure involves adjusting the indexes of  | ||
|  |             // the proxies. | ||
|  |              | ||
|  |             iterator left = first_proxy(from); | ||
|  |             iterator right = proxies.end(); // we'll adjust this later | ||
|  |              | ||
|  |             for (iterator iter = left; iter != right; ++iter) | ||
|  |             { | ||
|  |                 if (extract<Proxy&>(*iter)().get_index() > to) | ||
|  |                 { | ||
|  |                     right = iter; // adjust right | ||
|  |                     break; | ||
|  |                 } | ||
|  |                 extract<Proxy&> p(*iter); | ||
|  |                 p().detach(); | ||
|  |             } | ||
|  |              | ||
|  |             typename std::vector<PyObject*>::size_type  | ||
|  |                 offset = left-proxies.begin(); | ||
|  |             proxies.erase(left, right); | ||
|  |             right = proxies.begin()+offset; | ||
|  | 
 | ||
|  |             while (right != proxies.end()) | ||
|  |             { | ||
|  |                 typedef typename Proxy::container_type::difference_type difference_type; | ||
|  |                 extract<Proxy&> p(*right); | ||
|  |                 p().set_index( | ||
|  |                     extract<Proxy&>(*right)().get_index()  | ||
|  |                     - (difference_type(to) - from - len) | ||
|  |                 ); | ||
|  |                      | ||
|  |                 ++right; | ||
|  |             } | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |         } | ||
|  |          | ||
|  |         PyObject* | ||
|  |         find(index_type i) | ||
|  |         { | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // Find the proxy with *exact* index i. | ||
|  |             // Return 0 (null) if no proxy with the  | ||
|  |             // given index is found. | ||
|  |             iterator iter = first_proxy(i); | ||
|  |             if (iter != proxies.end() | ||
|  |                 && extract<Proxy&>(*iter)().get_index() == i) | ||
|  |             { | ||
|  |                 BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |                 return *iter; | ||
|  |             } | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             return 0; | ||
|  |         } | ||
|  | 
 | ||
|  |         typename std::vector<PyObject*>::size_type  | ||
|  |         size() const | ||
|  |         { | ||
|  |             BOOST_PYTHON_INDEXING_CHECK_INVARIANT; | ||
|  |             // How many proxies are there so far? | ||
|  |             return proxies.size(); | ||
|  |         }  | ||
|  | 
 | ||
|  |     private: | ||
|  | 
 | ||
|  | #if !defined(NDEBUG) | ||
|  |         void | ||
|  |         check_invariant() const | ||
|  |         { | ||
|  |             for (const_iterator i = proxies.begin(); i != proxies.end(); ++i) | ||
|  |             { | ||
|  |                 if ((*i)->ob_refcnt <= 0) | ||
|  |                 { | ||
|  |                     PyErr_SetString(PyExc_RuntimeError,  | ||
|  |                         "Invariant: Proxy vector in an inconsistent state"); | ||
|  |                     throw_error_already_set(); | ||
|  |                 } | ||
|  |                  | ||
|  |                 if (i+1 != proxies.end()) | ||
|  |                 { | ||
|  |                     if (extract<Proxy&>(*(i+1))().get_index() == | ||
|  |                         extract<Proxy&>(*(i))().get_index()) | ||
|  |                     { | ||
|  |                         PyErr_SetString(PyExc_RuntimeError,  | ||
|  |                             "Invariant: Proxy vector in an inconsistent state (duplicate proxy)"); | ||
|  |                         throw_error_already_set(); | ||
|  |                     } | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | #endif | ||
|  |          | ||
|  |         std::vector<PyObject*> proxies; | ||
|  |     }; | ||
|  |              | ||
|  |     // proxy_links holds a map of Container pointers (keys) | ||
|  |     // with proxy_group(s) (data). Various functions manage  | ||
|  |     // the addition, removal and searching of proxies from  | ||
|  |     // the map. | ||
|  |     // | ||
|  |     template <class Proxy, class Container> | ||
|  |     class proxy_links | ||
|  |     { | ||
|  |     public: | ||
|  |      | ||
|  |         typedef std::map<Container*, proxy_group<Proxy> > links_t; | ||
|  |         typedef typename Proxy::index_type index_type; | ||
|  | 
 | ||
|  |         void | ||
|  |         remove(Proxy& proxy) | ||
|  |         { | ||
|  |             // Remove a proxy. | ||
|  |             typename links_t::iterator r = links.find(&proxy.get_container()); | ||
|  |             if (r != links.end()) | ||
|  |             { | ||
|  |                 r->second.remove(proxy); | ||
|  |                 if (r->second.size() == 0) | ||
|  |                     links.erase(r); | ||
|  |             } | ||
|  |         } | ||
|  |          | ||
|  |         void | ||
|  |         add(PyObject* prox, Container& container) | ||
|  |         { | ||
|  |             // Add a proxy | ||
|  |             links[&container].add(prox); | ||
|  |         } | ||
|  |          | ||
|  |         template <class NoSlice> | ||
|  |         void erase(Container& container, index_type i, NoSlice no_slice) | ||
|  |         { | ||
|  |             // Erase the proxy with index i  | ||
|  |             typename links_t::iterator r = links.find(&container); | ||
|  |             if (r != links.end()) | ||
|  |             { | ||
|  |                 r->second.erase(i, no_slice); | ||
|  |                 if (r->second.size() == 0) | ||
|  |                     links.erase(r); | ||
|  |             } | ||
|  |         } | ||
|  |          | ||
|  |         void | ||
|  |         erase(Container& container, index_type from, index_type to) | ||
|  |         { | ||
|  |             // Erase all proxies with indexes from..to  | ||
|  |             typename links_t::iterator r = links.find(&container); | ||
|  |             if (r != links.end()) | ||
|  |             { | ||
|  |                 r->second.erase(from, to); | ||
|  |                 if (r->second.size() == 0) | ||
|  |                     links.erase(r); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         void | ||
|  |         replace( | ||
|  |             Container& container,  | ||
|  |             index_type from, index_type to, index_type len) | ||
|  |         { | ||
|  |             // Erase all proxies with indexes from..to. | ||
|  |             // Adjust the displaced indexes such that the | ||
|  |             // final effect is that we have inserted *len* | ||
|  |             // number of proxies in the vacated region. This | ||
|  |             // procedure involves adjusting the indexes of  | ||
|  |             // the proxies. | ||
|  | 
 | ||
|  |             typename links_t::iterator r = links.find(&container); | ||
|  |             if (r != links.end()) | ||
|  |             { | ||
|  |                 r->second.replace(from, to, len); | ||
|  |                 if (r->second.size() == 0) | ||
|  |                     links.erase(r); | ||
|  |             } | ||
|  |         } | ||
|  |          | ||
|  |         PyObject* | ||
|  |         find(Container& container, index_type i) | ||
|  |         { | ||
|  |             // Find the proxy with *exact* index i. | ||
|  |             // Return 0 (null) if no proxy with the given  | ||
|  |             // index is found. | ||
|  |             typename links_t::iterator r = links.find(&container); | ||
|  |             if (r != links.end()) | ||
|  |                 return r->second.find(i); | ||
|  |             return 0; | ||
|  |         } | ||
|  | 
 | ||
|  |     private: | ||
|  |      | ||
|  |         links_t links; | ||
|  |     }; | ||
|  |      | ||
|  |     // container_element is our container proxy class. | ||
|  |     // This class acts like a smart pointer to a container | ||
|  |     // element. The class holds an index and a reference to | ||
|  |     // a container. Dereferencing the smart pointer will | ||
|  |     // retrieve the nth (index) element from the container. | ||
|  |     // | ||
|  |     // A container_element can also be detached from the | ||
|  |     // container. In such a detached state, the container_element | ||
|  |     // holds a copy of the nth (index) element, which it  | ||
|  |     // returns when dereferenced. | ||
|  |     // | ||
|  |     template <class Container, class Index, class Policies> | ||
|  |     class container_element | ||
|  |     { | ||
|  |     public: | ||
|  |      | ||
|  |         typedef Index index_type; | ||
|  |         typedef Container container_type; | ||
|  |         typedef typename Policies::data_type element_type; | ||
|  |         typedef Policies policies_type; | ||
|  |         typedef container_element<Container, Index, Policies> self_t; | ||
|  |         typedef proxy_group<self_t> links_type; | ||
|  |          | ||
|  |         container_element(object container, Index index) | ||
|  |             : ptr() | ||
|  |             , container(container) | ||
|  |             , index(index) | ||
|  |         { | ||
|  |         } | ||
|  |              | ||
|  |         container_element(container_element const& ce) | ||
|  |           : ptr(ce.ptr.get() == 0 ? 0 : new element_type(*ce.ptr.get())) | ||
|  |           , container(ce.container) | ||
|  |           , index(ce.index) | ||
|  |         { | ||
|  |         } | ||
|  | 
 | ||
|  |         ~container_element() | ||
|  |         { | ||
|  |             if (!is_detached()) | ||
|  |                 get_links().remove(*this); | ||
|  |         } | ||
|  |                        | ||
|  |         element_type& operator*() const | ||
|  |         { | ||
|  |             if (is_detached()) | ||
|  |                 return *get_pointer(ptr); | ||
|  |             return Policies::get_item(get_container(), index); | ||
|  |         } | ||
|  |          | ||
|  |         element_type* get() const | ||
|  |         { | ||
|  |             if (is_detached()) | ||
|  |                 return get_pointer(ptr); | ||
|  |             return &Policies::get_item(get_container(), index); | ||
|  |         } | ||
|  |          | ||
|  |         void | ||
|  |         detach() | ||
|  |         { | ||
|  |             if (!is_detached()) | ||
|  |             { | ||
|  |                 ptr.reset( | ||
|  |                     new element_type( | ||
|  |                         Policies::get_item(get_container(), index))); | ||
|  |                 container = object(); // free container. reset it to None | ||
|  |             } | ||
|  |         } | ||
|  |          | ||
|  |         bool | ||
|  |         is_detached() const | ||
|  |         { | ||
|  |             return get_pointer(ptr) != 0; | ||
|  |         } | ||
|  | 
 | ||
|  |         Container&  | ||
|  |         get_container() const | ||
|  |         { | ||
|  |             return extract<Container&>(container)(); | ||
|  |         } | ||
|  |          | ||
|  |         Index  | ||
|  |         get_index() const | ||
|  |         { | ||
|  |             return index; | ||
|  |         } | ||
|  | 
 | ||
|  |         void  | ||
|  |         set_index(Index i) | ||
|  |         { | ||
|  |             index = i; | ||
|  |         } | ||
|  |   | ||
|  |         static proxy_links<self_t, Container>& | ||
|  |         get_links() | ||
|  |         { | ||
|  |             // All container_element(s) maintain links to | ||
|  |             // its container in a global map (see proxy_links). | ||
|  |             // This global "links" map is a singleton. | ||
|  |              | ||
|  |             static proxy_links<self_t, Container> links; | ||
|  |             return links; // singleton | ||
|  |         } | ||
|  | 
 | ||
|  |     private: | ||
|  |              | ||
|  |         container_element& operator=(container_element const& ce); | ||
|  | 
 | ||
|  |         scoped_ptr<element_type> ptr; | ||
|  |         object container; | ||
|  |         Index index; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template < | ||
|  |           class Container | ||
|  |         , class DerivedPolicies | ||
|  |         , class ContainerElement | ||
|  |         , class Index | ||
|  |     > | ||
|  |     struct no_proxy_helper | ||
|  |     {                 | ||
|  |         static void | ||
|  |         register_container_element() | ||
|  |         {  | ||
|  |         } | ||
|  | 
 | ||
|  |         template <class DataType>  | ||
|  |         static object | ||
|  |         base_get_item_helper(DataType const& p, mpl::true_) | ||
|  |         {  | ||
|  |             return object(ptr(p)); | ||
|  |         } | ||
|  | 
 | ||
|  |         template <class DataType>  | ||
|  |         static object | ||
|  |         base_get_item_helper(DataType const& x, mpl::false_) | ||
|  |         {  | ||
|  |             return object(x); | ||
|  |         } | ||
|  | 
 | ||
|  |         static object | ||
|  |         base_get_item_(back_reference<Container&> const& container, PyObject* i) | ||
|  |         {  | ||
|  |             return base_get_item_helper( | ||
|  |                 DerivedPolicies::get_item( | ||
|  |                     container.get(), DerivedPolicies:: | ||
|  |                         convert_index(container.get(), i)) | ||
|  |               , is_pointer<BOOST_DEDUCED_TYPENAME Container::value_type>() | ||
|  |             ); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void | ||
|  |         base_replace_indexes( | ||
|  |             Container& /*container*/, Index /*from*/,  | ||
|  |             Index /*to*/, Index /*n*/) | ||
|  |         { | ||
|  |         } | ||
|  | 
 | ||
|  |         template <class NoSlice> | ||
|  |         static void | ||
|  |         base_erase_index( | ||
|  |             Container& /*container*/, Index /*i*/, NoSlice /*no_slice*/) | ||
|  |         { | ||
|  |         } | ||
|  |          | ||
|  |         static void | ||
|  |         base_erase_indexes(Container& /*container*/, Index /*from*/, Index /*to*/) | ||
|  |         { | ||
|  |         } | ||
|  |     };             | ||
|  |            | ||
|  |     template < | ||
|  |           class Container | ||
|  |         , class DerivedPolicies | ||
|  |         , class ContainerElement | ||
|  |         , class Index | ||
|  |     > | ||
|  |     struct proxy_helper | ||
|  |     {         | ||
|  |         static void | ||
|  |         register_container_element() | ||
|  |         {  | ||
|  |             register_ptr_to_python<ContainerElement>(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static object | ||
|  |         base_get_item_(back_reference<Container&> const& container, PyObject* i) | ||
|  |         {  | ||
|  |             // Proxy | ||
|  |             Index idx = DerivedPolicies::convert_index(container.get(), i); | ||
|  | 
 | ||
|  |             if (PyObject* shared =  | ||
|  |                 ContainerElement::get_links().find(container.get(), idx)) | ||
|  |             { | ||
|  |                 handle<> h(python::borrowed(shared)); | ||
|  |                 return object(h); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 object prox(ContainerElement(container.source(), idx)); | ||
|  |                 ContainerElement:: | ||
|  |                     get_links().add(prox.ptr(), container.get()); | ||
|  |                 return prox; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         static void | ||
|  |         base_replace_indexes( | ||
|  |             Container& container, Index from,  | ||
|  |             Index to, Index n) | ||
|  |         { | ||
|  |             ContainerElement::get_links().replace(container, from, to, n); | ||
|  |         } | ||
|  |          | ||
|  |         template <class NoSlice> | ||
|  |         static void | ||
|  |         base_erase_index( | ||
|  |             Container& container, Index i, NoSlice no_slice) | ||
|  |         { | ||
|  |             ContainerElement::get_links().erase(container, i, no_slice); | ||
|  |         } | ||
|  |          | ||
|  |         static void | ||
|  |         base_erase_indexes( | ||
|  |             Container& container, Index from, Index to) | ||
|  |         { | ||
|  |             ContainerElement::get_links().erase(container, from, to); | ||
|  |         } | ||
|  |     };         | ||
|  |      | ||
|  |     template < | ||
|  |           class Container | ||
|  |         , class DerivedPolicies | ||
|  |         , class ProxyHandler | ||
|  |         , class Data | ||
|  |         , class Index | ||
|  |     > | ||
|  |     struct slice_helper | ||
|  |     {         | ||
|  |         static object  | ||
|  |         base_get_slice(Container& container, PySliceObject* slice) | ||
|  |         {  | ||
|  |             Index from, to; | ||
|  |             base_get_slice_data(container, slice, from, to); | ||
|  |             return DerivedPolicies::get_slice(container, from, to); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void | ||
|  |         base_get_slice_data( | ||
|  |             Container& container, PySliceObject* slice, Index& from_, Index& to_) | ||
|  |         { | ||
|  |             if (Py_None != slice->step) { | ||
|  |                 PyErr_SetString( PyExc_IndexError, "slice step size not supported."); | ||
|  |                 throw_error_already_set(); | ||
|  |             } | ||
|  | 
 | ||
|  |             Index min_index = DerivedPolicies::get_min_index(container); | ||
|  |             Index max_index = DerivedPolicies::get_max_index(container); | ||
|  |              | ||
|  |             if (Py_None == slice->start) { | ||
|  |                 from_ = min_index; | ||
|  |             } | ||
|  |             else { | ||
|  |                 long from = extract<long>( slice->start); | ||
|  |                 if (from < 0) // Negative slice index | ||
|  |                     from += max_index; | ||
|  |                 if (from < 0) // Clip lower bounds to zero | ||
|  |                     from = 0; | ||
|  |                 from_ = boost::numeric_cast<Index>(from); | ||
|  |                 if (from_ > max_index) // Clip upper bounds to max_index. | ||
|  |                     from_ = max_index; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (Py_None == slice->stop) { | ||
|  |                 to_ = max_index; | ||
|  |             } | ||
|  |             else { | ||
|  |                 long to = extract<long>( slice->stop); | ||
|  |                 if (to < 0) | ||
|  |                     to += max_index; | ||
|  |                 if (to < 0) | ||
|  |                     to = 0; | ||
|  |                 to_ = boost::numeric_cast<Index>(to); | ||
|  |                 if (to_ > max_index) | ||
|  |                     to_ = max_index; | ||
|  |             } | ||
|  |         }         | ||
|  |     | ||
|  |         static void  | ||
|  |         base_set_slice(Container& container, PySliceObject* slice, PyObject* v) | ||
|  |         { | ||
|  |             Index from, to; | ||
|  |             base_get_slice_data(container, slice, from, to); | ||
|  |              | ||
|  |             extract<Data&> elem(v); | ||
|  |             // try if elem is an exact Data | ||
|  |             if (elem.check()) | ||
|  |             { | ||
|  |                 ProxyHandler::base_replace_indexes(container, from, to, 1); | ||
|  |                 DerivedPolicies::set_slice(container, from, to, elem()); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 //  try to convert elem to Data | ||
|  |                 extract<Data> elem(v); | ||
|  |                 if (elem.check()) | ||
|  |                 { | ||
|  |                     ProxyHandler::base_replace_indexes(container, from, to, 1); | ||
|  |                     DerivedPolicies::set_slice(container, from, to, elem()); | ||
|  |                 } | ||
|  |                 else | ||
|  |                 { | ||
|  |                     //  Otherwise, it must be a list or some container | ||
|  |                     handle<> l_(python::borrowed(v)); | ||
|  |                     object l(l_); | ||
|  |      | ||
|  |                     std::vector<Data> temp; | ||
|  |                     for (int i = 0; i < l.attr("__len__")(); i++) | ||
|  |                     { | ||
|  |                         object elem(l[i]); | ||
|  |                         extract<Data const&> x(elem); | ||
|  |                         //  try if elem is an exact Data type | ||
|  |                         if (x.check()) | ||
|  |                         { | ||
|  |                             temp.push_back(x()); | ||
|  |                         } | ||
|  |                         else | ||
|  |                         { | ||
|  |                             //  try to convert elem to Data type | ||
|  |                             extract<Data> x(elem); | ||
|  |                             if (x.check()) | ||
|  |                             { | ||
|  |                                 temp.push_back(x()); | ||
|  |                             } | ||
|  |                             else | ||
|  |                             { | ||
|  |                                 PyErr_SetString(PyExc_TypeError,  | ||
|  |                                     "Invalid sequence element"); | ||
|  |                                 throw_error_already_set(); | ||
|  |                             } | ||
|  |                         } | ||
|  |                     }           | ||
|  |                    | ||
|  |                     ProxyHandler::base_replace_indexes(container, from, to,  | ||
|  |                         temp.end()-temp.begin()); | ||
|  |                     DerivedPolicies::set_slice(container, from, to,  | ||
|  |                         temp.begin(), temp.end()); | ||
|  |                 } | ||
|  |             }             | ||
|  |         } | ||
|  |          | ||
|  |         static void  | ||
|  |         base_delete_slice(Container& container, PySliceObject* slice) | ||
|  |         {  | ||
|  |             Index from, to; | ||
|  |             base_get_slice_data(container, slice, from, to); | ||
|  |             ProxyHandler::base_erase_indexes(container, from, to); | ||
|  |             DerivedPolicies::delete_slice(container, from, to); | ||
|  |         }   | ||
|  |     }; | ||
|  |      | ||
|  |     template < | ||
|  |           class Container | ||
|  |         , class DerivedPolicies | ||
|  |         , class ProxyHandler | ||
|  |         , class Data | ||
|  |         , class Index | ||
|  |     > | ||
|  |     struct no_slice_helper | ||
|  |     {         | ||
|  |         static void | ||
|  |         slicing_not_suported() | ||
|  |         { | ||
|  |             PyErr_SetString(PyExc_RuntimeError, "Slicing not supported"); | ||
|  |             throw_error_already_set(); | ||
|  |         } | ||
|  |          | ||
|  |         static object  | ||
|  |         base_get_slice(Container& /*container*/, PySliceObject* /*slice*/) | ||
|  |         {  | ||
|  |             slicing_not_suported(); | ||
|  |             return object(); | ||
|  |         } | ||
|  |     | ||
|  |         static void  | ||
|  |         base_set_slice(Container& /*container*/, PySliceObject* /*slice*/, PyObject* /*v*/) | ||
|  |         { | ||
|  |             slicing_not_suported(); | ||
|  |         } | ||
|  |          | ||
|  |         static void  | ||
|  |         base_delete_slice(Container& /*container*/, PySliceObject* /*slice*/) | ||
|  |         {  | ||
|  |             slicing_not_suported(); | ||
|  |         }   | ||
|  |     }; | ||
|  | 
 | ||
|  | #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP | ||
|  | }} // namespace python::detail | ||
|  | #endif | ||
|  | 
 | ||
|  |     template <class Container, class Index, class Policies> | ||
|  |     inline typename Policies::data_type*  | ||
|  |     get_pointer( | ||
|  |         python::detail::container_element<Container, Index, Policies> const& p) | ||
|  |     { | ||
|  |         // Get the pointer of a container_element smart pointer | ||
|  |         return p.get(); | ||
|  |     } | ||
|  | 
 | ||
|  | #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP | ||
|  |     // Don't hide these other get_pointer overloads | ||
|  |     using boost::python::get_pointer; | ||
|  |     using boost::get_pointer; | ||
|  | }} // namespace python::detail | ||
|  | #endif | ||
|  | 
 | ||
|  | } // namespace boost | ||
|  | 
 | ||
|  | #endif // INDEXING_SUITE_DETAIL_JDG20036_HPP |