| // Copyright (c) Microsoft. All rights reserved. | |
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
| #pragma once | |
| #include <boost/python/suite/indexing/vector_indexing_suite.hpp> | |
| namespace bond | |
| { | |
| namespace python | |
| { | |
| // Indexing suite equivalent to boost::python::vector_indexing_suite but for | |
| // containers that don't support random access iterator. | |
| template <typename T, bool NoProxy, typename DerivedPolicies> | |
| class list_indexing_suite; | |
| namespace detail | |
| { | |
| template <typename T, bool NoProxy> | |
| class final_list_derived_policies | |
| : public bond::python::list_indexing_suite< | |
| T, | |
| NoProxy, | |
| final_list_derived_policies<T, NoProxy> > | |
| {}; | |
| } | |
| template < | |
| typename T, | |
| bool NoProxy = false, | |
| typename DerivedPolicies = detail::final_list_derived_policies<T, NoProxy> | |
| > | |
| class list_indexing_suite | |
| : public boost::python::vector_indexing_suite<T, NoProxy, DerivedPolicies> | |
| { | |
| typedef boost::python::vector_indexing_suite<T, NoProxy, DerivedPolicies> base; | |
| public: | |
| typedef typename base::data_type data_type; | |
| typedef typename base::index_type index_type; | |
| typedef typename base::key_type key_type; | |
| static | |
| typename std::conditional< | |
| std::is_class<data_type>::value, | |
| data_type&, | |
| data_type | |
| >::type | |
| get_item(T& list, index_type i) | |
| { | |
| return *advance(list.begin(), i); | |
| } | |
| static void | |
| set_item(T& list, index_type i, data_type const& v) | |
| { | |
| *advance(list.begin(), i) = v; | |
| } | |
| static void | |
| delete_item(T& list, index_type i) | |
| { | |
| list.erase(advance(list.begin(), i)); | |
| } | |
| static boost::python::object | |
| get_slice(T& list, index_type from, index_type to) | |
| { | |
| if (from > to) | |
| return boost::python::object(T()); | |
| auto s = slice(list, from, to); | |
| return boost::python::object(T(s.first, s.second)); | |
| } | |
| static void | |
| set_slice(T& list, index_type from, index_type to, data_type const& v) | |
| { | |
| if (to >= from) | |
| { | |
| auto s = slice(list, from, to); | |
| list.erase(s.first, s.second); | |
| list.insert(advance(list.begin(), from), v); | |
| } | |
| } | |
| template <typename Iter> | |
| static void | |
| set_slice(T& list, index_type from, | |
| index_type to, Iter first, Iter last) | |
| { | |
| if (to >= from) | |
| { | |
| auto s = slice(list, from, to); | |
| list.erase(s.first, s.second); | |
| list.insert(advance(list.begin(), from), first, last); | |
| } | |
| } | |
| static void | |
| delete_slice(T& list, index_type from, index_type to) | |
| { | |
| if (to >= from) | |
| { | |
| auto s = slice(list, from, to); | |
| list.erase(s.first, s.second); | |
| } | |
| } | |
| private: | |
| static | |
| typename T::iterator | |
| advance(typename T::iterator it, typename T::difference_type i) | |
| { | |
| return std::advance(it, i), it; | |
| } | |
| static | |
| std::pair<typename T::iterator, typename T::iterator> | |
| slice(T& list, index_type from, index_type to) | |
| { | |
| BOOST_ASSERT(to >= from); | |
| std::pair<typename T::iterator, typename T::iterator> s; | |
| s.first = list.begin(); | |
| std::advance(s.first, from); | |
| s.second = s.first; | |
| std::advance(s.second, to - from); | |
| return s; | |
| } | |
| }; | |
| } // namespace python | |
| } // namespace bond |