1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 #pragma once 5 6 #include <boost/python/suite/indexing/vector_indexing_suite.hpp> 7 8 namespace bond 9 { 10 namespace python 11 { 12 13 // Indexing suite equivalent to boost::python::vector_indexing_suite but for 14 // containers that don't support random access iterator. 15 16 template <typename T, bool NoProxy, typename DerivedPolicies> 17 class list_indexing_suite; 18 19 namespace detail 20 { 21 template <typename T, bool NoProxy> 22 class final_list_derived_policies 23 : public bond::python::list_indexing_suite< 24 T, 25 NoProxy, 26 final_list_derived_policies<T, NoProxy> > 27 {}; 28 } 29 30 template < 31 typename T, 32 bool NoProxy = false, 33 typename DerivedPolicies = detail::final_list_derived_policies<T, NoProxy> 34 > 35 class list_indexing_suite 36 : public boost::python::vector_indexing_suite<T, NoProxy, DerivedPolicies> 37 { 38 typedef boost::python::vector_indexing_suite<T, NoProxy, DerivedPolicies> base; 39 public: 40 typedef typename base::data_type data_type; 41 typedef typename base::index_type index_type; 42 typedef typename base::key_type key_type; 43 44 static 45 typename std::conditional< 46 std::is_class<data_type>::value, 47 data_type&, 48 data_type 49 >::type get_item(T & list,index_type i)50 get_item(T& list, index_type i) 51 { 52 return *advance(list.begin(), i); 53 } 54 55 static void set_item(T & list,index_type i,data_type const & v)56 set_item(T& list, index_type i, data_type const& v) 57 { 58 *advance(list.begin(), i) = v; 59 } 60 61 static void delete_item(T & list,index_type i)62 delete_item(T& list, index_type i) 63 { 64 list.erase(advance(list.begin(), i)); 65 } 66 67 static boost::python::object get_slice(T & list,index_type from,index_type to)68 get_slice(T& list, index_type from, index_type to) 69 { 70 if (from > to) 71 return boost::python::object(T()); 72 73 auto s = slice(list, from, to); 74 return boost::python::object(T(s.first, s.second)); 75 } 76 77 static void set_slice(T & list,index_type from,index_type to,data_type const & v)78 set_slice(T& list, index_type from, index_type to, data_type const& v) 79 { 80 if (to >= from) 81 { 82 auto s = slice(list, from, to); 83 list.erase(s.first, s.second); 84 list.insert(advance(list.begin(), from), v); 85 } 86 } 87 88 template <typename Iter> 89 static void set_slice(T & list,index_type from,index_type to,Iter first,Iter last)90 set_slice(T& list, index_type from, 91 index_type to, Iter first, Iter last) 92 { 93 if (to >= from) 94 { 95 auto s = slice(list, from, to); 96 list.erase(s.first, s.second); 97 list.insert(advance(list.begin(), from), first, last); 98 } 99 } 100 101 static void delete_slice(T & list,index_type from,index_type to)102 delete_slice(T& list, index_type from, index_type to) 103 { 104 if (to >= from) 105 { 106 auto s = slice(list, from, to); 107 list.erase(s.first, s.second); 108 } 109 } 110 111 private: 112 static 113 typename T::iterator advance(typename T::iterator it,typename T::difference_type i)114 advance(typename T::iterator it, typename T::difference_type i) 115 { 116 return std::advance(it, i), it; 117 } 118 119 static 120 std::pair<typename T::iterator, typename T::iterator> slice(T & list,index_type from,index_type to)121 slice(T& list, index_type from, index_type to) 122 { 123 BOOST_ASSERT(to >= from); 124 125 std::pair<typename T::iterator, typename T::iterator> s; 126 127 s.first = list.begin(); 128 std::advance(s.first, from); 129 130 s.second = s.first; 131 std::advance(s.second, to - from); 132 133 return s; 134 } 135 }; 136 137 } // namespace python 138 139 } // namespace bond 140