diff options
Diffstat (limited to 'boost/python/suite/indexing/vector_indexing_suite.hpp')
-rw-r--r-- | boost/python/suite/indexing/vector_indexing_suite.hpp | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/boost/python/suite/indexing/vector_indexing_suite.hpp b/boost/python/suite/indexing/vector_indexing_suite.hpp new file mode 100644 index 0000000000..34c29ecc6f --- /dev/null +++ b/boost/python/suite/indexing/vector_indexing_suite.hpp @@ -0,0 +1,242 @@ +// (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 |