| // (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 VECTOR_INDEXING_SUITE_JDG20036_HPP |
| # define VECTOR_INDEXING_SUITE_JDG20036_HPP |
| |
| # include <boost/python/suite/indexing/indexing_suite.hpp> |
| # include <boost/python/suite/indexing/container_utils.hpp> |
| # include <boost/python/iterator.hpp> |
| |
| namespace boost { namespace python { |
| |
| // Forward declaration |
| template <class Container, bool NoProxy, class DerivedPolicies> |
| class vector_indexing_suite; |
| |
| namespace detail |
| { |
| template <class Container, bool NoProxy> |
| class final_vector_derived_policies |
| : public vector_indexing_suite<Container, |
| NoProxy, final_vector_derived_policies<Container, NoProxy> > {}; |
| } |
| |
| // The vector_indexing_suite class is a predefined indexing_suite derived |
| // class for wrapping std::vector (and std::vector like) classes. It provides |
| // all the policies required by the indexing_suite (see indexing_suite). |
| // Example usage: |
| // |
| // class X {...}; |
| // |
| // ... |
| // |
| // class_<std::vector<X> >("XVec") |
| // .def(vector_indexing_suite<std::vector<X> >()) |
| // ; |
| // |
| // By default indexed elements are returned by proxy. This can be |
| // disabled by supplying *true* in the NoProxy template parameter. |
| // |
| template < |
| class Container, |
| bool NoProxy = false, |
| class DerivedPolicies |
| = detail::final_vector_derived_policies<Container, NoProxy> > |
| class vector_indexing_suite |
| : public indexing_suite<Container, DerivedPolicies, NoProxy> |
| { |
| public: |
| |
| typedef typename Container::value_type data_type; |
| typedef typename Container::value_type key_type; |
| typedef typename Container::size_type index_type; |
| typedef typename Container::size_type size_type; |
| typedef typename Container::difference_type difference_type; |
| |
| template <class Class> |
| static void |
| extension_def(Class& cl) |
| { |
| cl |
| .def("append", &base_append) |
| .def("extend", &base_extend) |
| ; |
| } |
| |
| static |
| typename mpl::if_< |
| is_class<data_type> |
| , data_type& |
| , data_type |
| >::type |
| get_item(Container& container, index_type i) |
| { |
| return container[i]; |
| } |
| |
| static object |
| get_slice(Container& container, index_type from, index_type to) |
| { |
| if (from > to) |
| return object(Container()); |
| return object(Container(container.begin()+from, container.begin()+to)); |
| } |
| |
| static void |
| set_item(Container& container, index_type i, data_type const& v) |
| { |
| container[i] = v; |
| } |
| |
| static void |
| set_slice(Container& container, index_type from, |
| index_type to, data_type const& v) |
| { |
| if (from > to) { |
| return; |
| } |
| else { |
| container.erase(container.begin()+from, container.begin()+to); |
| container.insert(container.begin()+from, v); |
| } |
| } |
| |
| template <class Iter> |
| static void |
| set_slice(Container& container, index_type from, |
| index_type to, Iter first, Iter last) |
| { |
| if (from > to) { |
| container.insert(container.begin()+from, first, last); |
| } |
| else { |
| container.erase(container.begin()+from, container.begin()+to); |
| container.insert(container.begin()+from, first, last); |
| } |
| } |
| |
| static void |
| delete_item(Container& container, index_type i) |
| { |
| container.erase(container.begin()+i); |
| } |
| |
| static void |
| delete_slice(Container& container, index_type from, index_type to) |
| { |
| if (from > to) { |
| // A null-op. |
| return; |
| } |
| container.erase(container.begin()+from, container.begin()+to); |
| } |
| |
| static size_t |
| size(Container& container) |
| { |
| return container.size(); |
| } |
| |
| static bool |
| contains(Container& container, key_type const& key) |
| { |
| return std::find(container.begin(), container.end(), key) |
| != container.end(); |
| } |
| |
| static index_type |
| get_min_index(Container& /*container*/) |
| { |
| return 0; |
| } |
| |
| static index_type |
| get_max_index(Container& container) |
| { |
| return container.size(); |
| } |
| |
| static bool |
| compare_index(Container& /*container*/, index_type a, index_type b) |
| { |
| return a < b; |
| } |
| |
| static index_type |
| convert_index(Container& container, PyObject* i_) |
| { |
| extract<long> i(i_); |
| if (i.check()) |
| { |
| long index = i(); |
| if (index < 0) |
| index += DerivedPolicies::size(container); |
| if (index >= long(container.size()) || index < 0) |
| { |
| PyErr_SetString(PyExc_IndexError, "Index out of range"); |
| throw_error_already_set(); |
| } |
| return index; |
| } |
| |
| PyErr_SetString(PyExc_TypeError, "Invalid index type"); |
| throw_error_already_set(); |
| return index_type(); |
| } |
| |
| static void |
| append(Container& container, data_type const& v) |
| { |
| container.push_back(v); |
| } |
| |
| template <class Iter> |
| static void |
| extend(Container& container, Iter first, Iter last) |
| { |
| container.insert(container.end(), first, last); |
| } |
| |
| private: |
| |
| static void |
| base_append(Container& container, object v) |
| { |
| extract<data_type&> elem(v); |
| // try if elem is an exact Data |
| if (elem.check()) |
| { |
| DerivedPolicies::append(container, elem()); |
| } |
| else |
| { |
| // try to convert elem to data_type |
| extract<data_type> elem(v); |
| if (elem.check()) |
| { |
| DerivedPolicies::append(container, elem()); |
| } |
| else |
| { |
| PyErr_SetString(PyExc_TypeError, |
| "Attempting to append an invalid type"); |
| throw_error_already_set(); |
| } |
| } |
| } |
| |
| static void |
| base_extend(Container& container, object v) |
| { |
| std::vector<data_type> temp; |
| container_utils::extend_container(temp, v); |
| DerivedPolicies::extend(container, temp.begin(), temp.end()); |
| } |
| }; |
| |
| }} // namespace boost::python |
| |
| #endif // VECTOR_INDEXING_SUITE_JDG20036_HPP |