243 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			243 lines
		
	
	
		
			7.4 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 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 |