vector_indexing_suite.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // (C) Copyright Joel de Guzman 2003.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef VECTOR_INDEXING_SUITE_JDG20036_HPP
  6. # define VECTOR_INDEXING_SUITE_JDG20036_HPP
  7. # include <boost/python/suite/indexing/indexing_suite.hpp>
  8. # include <boost/python/suite/indexing/container_utils.hpp>
  9. # include <boost/python/iterator.hpp>
  10. namespace boost { namespace python {
  11. // Forward declaration
  12. template <class Container, bool NoProxy, class DerivedPolicies>
  13. class vector_indexing_suite;
  14. namespace detail
  15. {
  16. template <class Container, bool NoProxy>
  17. class final_vector_derived_policies
  18. : public vector_indexing_suite<Container,
  19. NoProxy, final_vector_derived_policies<Container, NoProxy> > {};
  20. }
  21. // The vector_indexing_suite class is a predefined indexing_suite derived
  22. // class for wrapping std::vector (and std::vector like) classes. It provides
  23. // all the policies required by the indexing_suite (see indexing_suite).
  24. // Example usage:
  25. //
  26. // class X {...};
  27. //
  28. // ...
  29. //
  30. // class_<std::vector<X> >("XVec")
  31. // .def(vector_indexing_suite<std::vector<X> >())
  32. // ;
  33. //
  34. // By default indexed elements are returned by proxy. This can be
  35. // disabled by supplying *true* in the NoProxy template parameter.
  36. //
  37. template <
  38. class Container,
  39. bool NoProxy = false,
  40. class DerivedPolicies
  41. = detail::final_vector_derived_policies<Container, NoProxy> >
  42. class vector_indexing_suite
  43. : public indexing_suite<Container, DerivedPolicies, NoProxy>
  44. {
  45. public:
  46. typedef typename Container::value_type data_type;
  47. typedef typename Container::value_type key_type;
  48. typedef typename Container::size_type index_type;
  49. typedef typename Container::size_type size_type;
  50. typedef typename Container::difference_type difference_type;
  51. template <class Class>
  52. static void
  53. extension_def(Class& cl)
  54. {
  55. cl
  56. .def("append", &base_append)
  57. .def("extend", &base_extend)
  58. ;
  59. }
  60. static
  61. typename mpl::if_<
  62. is_class<data_type>
  63. , data_type&
  64. , data_type
  65. >::type
  66. get_item(Container& container, index_type i)
  67. {
  68. return container[i];
  69. }
  70. static object
  71. get_slice(Container& container, index_type from, index_type to)
  72. {
  73. if (from > to)
  74. return object(Container());
  75. return object(Container(container.begin()+from, container.begin()+to));
  76. }
  77. static void
  78. set_item(Container& container, index_type i, data_type const& v)
  79. {
  80. container[i] = v;
  81. }
  82. static void
  83. set_slice(Container& container, index_type from,
  84. index_type to, data_type const& v)
  85. {
  86. if (from > to) {
  87. return;
  88. }
  89. else {
  90. container.erase(container.begin()+from, container.begin()+to);
  91. container.insert(container.begin()+from, v);
  92. }
  93. }
  94. template <class Iter>
  95. static void
  96. set_slice(Container& container, index_type from,
  97. index_type to, Iter first, Iter last)
  98. {
  99. if (from > to) {
  100. container.insert(container.begin()+from, first, last);
  101. }
  102. else {
  103. container.erase(container.begin()+from, container.begin()+to);
  104. container.insert(container.begin()+from, first, last);
  105. }
  106. }
  107. static void
  108. delete_item(Container& container, index_type i)
  109. {
  110. container.erase(container.begin()+i);
  111. }
  112. static void
  113. delete_slice(Container& container, index_type from, index_type to)
  114. {
  115. if (from > to) {
  116. // A null-op.
  117. return;
  118. }
  119. container.erase(container.begin()+from, container.begin()+to);
  120. }
  121. static size_t
  122. size(Container& container)
  123. {
  124. return container.size();
  125. }
  126. static bool
  127. contains(Container& container, key_type const& key)
  128. {
  129. return std::find(container.begin(), container.end(), key)
  130. != container.end();
  131. }
  132. static index_type
  133. get_min_index(Container& /*container*/)
  134. {
  135. return 0;
  136. }
  137. static index_type
  138. get_max_index(Container& container)
  139. {
  140. return container.size();
  141. }
  142. static bool
  143. compare_index(Container& /*container*/, index_type a, index_type b)
  144. {
  145. return a < b;
  146. }
  147. static index_type
  148. convert_index(Container& container, PyObject* i_)
  149. {
  150. extract<long> i(i_);
  151. if (i.check())
  152. {
  153. long index = i();
  154. if (index < 0)
  155. index += DerivedPolicies::size(container);
  156. if (index >= long(container.size()) || index < 0)
  157. {
  158. PyErr_SetString(PyExc_IndexError, "Index out of range");
  159. throw_error_already_set();
  160. }
  161. return index;
  162. }
  163. PyErr_SetString(PyExc_TypeError, "Invalid index type");
  164. throw_error_already_set();
  165. return index_type();
  166. }
  167. static void
  168. append(Container& container, data_type const& v)
  169. {
  170. container.push_back(v);
  171. }
  172. template <class Iter>
  173. static void
  174. extend(Container& container, Iter first, Iter last)
  175. {
  176. container.insert(container.end(), first, last);
  177. }
  178. private:
  179. static void
  180. base_append(Container& container, object v)
  181. {
  182. extract<data_type&> elem(v);
  183. // try if elem is an exact Data
  184. if (elem.check())
  185. {
  186. DerivedPolicies::append(container, elem());
  187. }
  188. else
  189. {
  190. // try to convert elem to data_type
  191. extract<data_type> elem(v);
  192. if (elem.check())
  193. {
  194. DerivedPolicies::append(container, elem());
  195. }
  196. else
  197. {
  198. PyErr_SetString(PyExc_TypeError,
  199. "Attempting to append an invalid type");
  200. throw_error_already_set();
  201. }
  202. }
  203. }
  204. static void
  205. base_extend(Container& container, object v)
  206. {
  207. std::vector<data_type> temp;
  208. container_utils::extend_container(temp, v);
  209. DerivedPolicies::extend(container, temp.begin(), temp.end());
  210. }
  211. };
  212. }} // namespace boost::python
  213. #endif // VECTOR_INDEXING_SUITE_JDG20036_HPP