Crazy Eddie's GUI System  ${CEGUI_VERSION}
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
slice_handler.hpp
1 // This file has been generated by Py++.
2 
3 // -*- mode:c++ -*-
4 //
5 // Header file slice_handler.hpp
6 //
7 // Copyright (c) 2003 Raoul M. Gough
8 //
9 // Use, modification and distribution is subject to the Boost Software
10 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
11 // at http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // History
14 // =======
15 // 2003/ 9/ 9 rmg File creation
16 // 2008/12/08 Roman Change indexing suite layout
17 // 2009/01/30 Roman patch from Maik Beckmann was applied - fixes error:
18 // // error: no class template named 'extract_return_type'
19 // $Id: slice_handler.hpp,v 1.1.2.10 2003/11/24 16:35:52 raoulgough Exp $
20 //
21 
22 #ifndef BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
23 #define BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
24 
25 #include <boost/python/handle.hpp>
26 #include <boost/python/object.hpp>
27 #include <boost/python/list.hpp>
28 #include <boost/python/extract.hpp>
29 #include <boost/python/make_function.hpp>
30 #include <boost/mpl/apply.hpp>
31 #include <algorithm>
32 
33 #include <indexing_suite/slice.hpp>
34 #include <indexing_suite/python_iterator.hpp>
35 
36 namespace boost { namespace python { namespace indexing {
37  template<class Algorithms, class Policy>
39  {
40  static boost::python::object make_getitem (Policy const &);
41  static boost::python::object make_setitem (Policy const &);
42  static boost::python::object make_delitem (Policy const &);
43  static boost::python::object make_extend (Policy const &);
44 
45  private:
46  typedef typename Algorithms::container container;
47  typedef typename Algorithms::reference reference;
48  typedef typename Algorithms::slice_helper slice_helper;
49 
50  static boost::python::list get_slice (container &, slice);
51  static void set_slice (container &, slice, boost::python::object);
52  static void del_slice (container &, slice);
53  static void extend (container &, boost::python::object);
54  };
55 
56  namespace detail {
57  template<typename Policy>
59  {
60  // This class overrides the Policy's postcall function and
61  // result_conveter to handle the list returned from get_slice.
62  // The Policy's result_converter is removed, since it gets
63  // applied within get_slice. Our postcall override applies the
64  // original postcall to each element of the Python list returned
65  // from get_slice.
66 
67  typedef boost::python::default_result_converter result_converter;
68  typedef typename Policy::argument_package argument_package;
69 
70  template<class Sig> struct extract_return_type :
71  Policy::template extract_return_type<Sig> { };
72 
73  postcall_override (Policy const &p);
74 
75  bool precall (PyObject *args);
76  PyObject* postcall (PyObject *args, PyObject *result);
77 
78  private:
79  Policy m_base;
80  };
81  }
82 
84  // Return a function object that implements the slice version of __getitem__
86 
87  template<class Algorithms, class Policy>
88  boost::python::object
90  ::make_getitem (Policy const &policy)
91  {
92  return
93  boost::python::make_function(
94  get_slice, detail::postcall_override<Policy> (policy));
95  }
96 
98  // Return a function object that implements the slice version of __setitem__
100 
101  template<class Algorithms, class Policy>
102  boost::python::object
103  slice_handler<Algorithms, Policy>
104  ::make_setitem (Policy const &policy)
105  {
106  // should we try to get funky with policy::precall?
107  return boost::python::make_function (set_slice, policy);
108  }
109 
111  // Return a function object that implements the slice version of __delitem__
113 
114  template<class Algorithms, class Policy>
115  boost::python::object
116  slice_handler<Algorithms, Policy>
117  ::make_delitem (Policy const &policy)
118  {
119  // should we try to get funky with policy::precall?
120  return boost::python::make_function (del_slice, policy);
121  }
122 
124  // Return a function object that implements extend
126 
127  template<class Algorithms, class Policy>
128  boost::python::object
129  slice_handler<Algorithms, Policy>
130  ::make_extend (Policy const &policy)
131  {
132  // should we try to get funky with policy::precall?
133  return boost::python::make_function (extend, policy);
134  }
135 
136  namespace detail {
138  // postcall_override constructor
140 
141  template<class Policy>
142  postcall_override<Policy>::postcall_override (Policy const &p)
143  : m_base (p)
144  {
145  }
146 
148  // precall forwarder
150 
151  template<class Policy>
152  bool postcall_override<Policy>::precall (PyObject *args)
153  {
154  return m_base.precall (args);
155  }
156 
158  // Apply base postcall to each element of the list returend by get_slice
160 
161  template<class Policy>
162  PyObject *
163  postcall_override<Policy>::postcall (PyObject *args, PyObject *result)
164  {
165  int size = PyList_Size (result);
166 
167  for (int count = 0; count < size; ++count)
168  {
169  m_base.postcall (args, PyList_GetItem (result, count));
170  }
171 
172  return result;
173  }
174  } // namespace detail
175 
177  // Implementation for the slice version of __getitem__
179 
180  template<class Algorithms, class Policy>
181  boost::python::list
182  slice_handler<Algorithms, Policy>
183  ::get_slice (container &c, slice sl)
184  {
185  typedef typename Policy::result_converter converter_type;
186  typedef typename Algorithms::reference reference;
187 
188  typename boost::mpl::apply1<converter_type, reference>::type
189  converter;
190 
191  boost::python::list result;
192 
193  slice_helper helper (Algorithms::make_slice_helper (c, sl));
194 
195  while (helper.next())
196  {
197  // Apply the result converter (only) to each element before
198  // appending. postcall is done in postcall_override
199 
200  result.append (boost::python::handle<> (converter (helper.current())));
201  }
202 
203  return result;
204  }
205 
207  // Implementation for the slice version of __setitem__
209 
210  template<class Algorithms, class Policy>
211  void
212  slice_handler<Algorithms, Policy>
213  ::set_slice (container &c, slice sl, boost::python::object values)
214  {
215  python_iterator value_iter (values);
216 
217  // Try two kinds of extractors - the first is more efficient (using
218  // a reference to existing object, if possible and sensible) and the
219  // second allowing implicit conversions.
220 
221  typedef boost::python::extract<
222  BOOST_DEDUCED_TYPENAME Algorithms::value_param> extractor1;
223 
224  typedef boost::python::extract<
225  BOOST_DEDUCED_TYPENAME Algorithms::value_type> extractor2;
226 
227  // Note: any error during this operation will probably leave the
228  // container partially updated. This can occur (for example) if the
229  // replacement sequence is of a different length to the original
230  // slice and the container does not support insertion/deletion.
231  // This could be prevented if the length of the replacement sequence
232  // is known in advance (via __len__, for example) but not otherwise.
233 
234  slice_helper write_helper (Algorithms::make_slice_helper (c, sl));
235 
236  // Overwrite and/or insert elements
237  while (value_iter.next())
238  {
239  extractor1 ex1 (value_iter.current());
240 
241  if (ex1.check())
242  {
243  write_helper.write (ex1);
244  }
245 
246  else
247  {
248  write_helper.write (extractor2 (value_iter.current()));
249  }
250  }
251 
252  if (write_helper.next())
253  {
254  // We've run out of elements to read, but write_helper is not
255  // finished. Erase the remaining element(s) in the slice
256  write_helper.erase_remaining();
257  }
258  }
259 
261  // Implementation for the slice version of __delitem__
263 
264  template<class Algorithms, class Policy>
265  void
266  slice_handler<Algorithms, Policy>
267  ::del_slice (container &c, slice sl)
268  {
269  slice_helper helper (Algorithms::make_slice_helper (c, sl));
270 
271  if (helper.next())
272  {
273  helper.erase_remaining();
274  }
275  }
276 
278  // Implementation of extend
280 
281  template<class Algorithms, class Policy>
282  void
283  slice_handler<Algorithms, Policy>
284  ::extend (container &c, boost::python::object values)
285  {
286  // Set up a slice at the tail end of the container, and use
287  // set_slice to do all the hard work.
288 
289  boost::python::object length
290  ((boost::python::handle<>
291  (PyLong_FromLong (Algorithms::size (c)))));
292 
293  slice sl
294  ((boost::python::handle<>
295  (PySlice_New
296  (length.ptr(),
297  boost::python::object().ptr(),
298  boost::python::object().ptr()))));
299 
300  set_slice (c, sl, values);
301  }
302 } } }
303 
304 #endif // BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
305 
306 
307 
Definition: python_CEGUI.h:11
Definition: slice.hpp:31
Definition: slice_handler.hpp:38