• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright David Abrahams 2002.
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 EXTRACT_DWA200265_HPP
6 # define EXTRACT_DWA200265_HPP
7 
8 # include <boost/python/detail/prefix.hpp>
9 
10 # include <boost/python/converter/object_manager.hpp>
11 # include <boost/python/converter/from_python.hpp>
12 # include <boost/python/converter/rvalue_from_python_data.hpp>
13 # include <boost/python/converter/registered.hpp>
14 # include <boost/python/converter/registered_pointee.hpp>
15 
16 # include <boost/python/object_core.hpp>
17 # include <boost/python/refcount.hpp>
18 
19 # include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
20 # include <boost/python/detail/void_ptr.hpp>
21 # include <boost/python/detail/void_return.hpp>
22 # include <boost/call_traits.hpp>
23 
24 #if BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900)
25 # define BOOST_EXTRACT_WORKAROUND ()
26 #else
27 # define BOOST_EXTRACT_WORKAROUND
28 #endif
29 
30 namespace boost { namespace python {
31 
32 namespace api
33 {
34   class object;
35 }
36 
37 namespace converter
38 {
39   template <class Ptr>
40   struct extract_pointer
41   {
42       typedef Ptr result_type;
43       extract_pointer(PyObject*);
44 
45       bool check() const;
46       Ptr operator()() const;
47 
48    private:
49       PyObject* m_source;
50       void* m_result;
51   };
52 
53   template <class Ref>
54   struct extract_reference
55   {
56       typedef Ref result_type;
57       extract_reference(PyObject*);
58 
59       bool check() const;
60       Ref operator()() const;
61 
62    private:
63       PyObject* m_source;
64       void* m_result;
65   };
66 
67   template <class T>
68   struct extract_rvalue : private noncopyable
69   {
70       typedef typename mpl::if_<
71           python::detail::copy_ctor_mutates_rhs<T>
72         , T&
73         , typename call_traits<T>::param_type
74       >::type result_type;
75 
76       extract_rvalue(PyObject*);
77 
78       bool check() const;
79       result_type operator()() const;
80    private:
81       PyObject* m_source;
82       mutable rvalue_from_python_data<T> m_data;
83   };
84 
85   template <class T>
86   struct extract_object_manager
87   {
88       typedef T result_type;
89       extract_object_manager(PyObject*);
90 
91       bool check() const;
92       result_type operator()() const;
93    private:
94       PyObject* m_source;
95   };
96 
97   template <class T>
98   struct select_extract
99   {
100       BOOST_STATIC_CONSTANT(
101           bool, obj_mgr = is_object_manager<T>::value);
102 
103       BOOST_STATIC_CONSTANT(
104           bool, ptr = is_pointer<T>::value);
105 
106       BOOST_STATIC_CONSTANT(
107           bool, ref = is_reference<T>::value);
108 
109       typedef typename mpl::if_c<
110           obj_mgr
111           , extract_object_manager<T>
112           , typename mpl::if_c<
113               ptr
114               , extract_pointer<T>
115               , typename mpl::if_c<
116                   ref
117                   , extract_reference<T>
118                   , extract_rvalue<T>
119                 >::type
120             >::type
121          >::type type;
122   };
123 }
124 
125 template <class T>
126 struct extract
127     : converter::select_extract<T>::type
128 {
129  private:
130     typedef typename converter::select_extract<T>::type base;
131  public:
132     typedef typename base::result_type result_type;
133 
operator result_typeboost::python::extract134     operator result_type() const
135     {
136         return (*this)();
137     }
138 
139     extract(PyObject*);
140     extract(api::object const&);
141 };
142 
143 //
144 // Implementations
145 //
146 template <class T>
extract(PyObject * o)147 inline extract<T>::extract(PyObject* o)
148     : base(o)
149 {
150 }
151 
152 template <class T>
extract(api::object const & o)153 inline extract<T>::extract(api::object const& o)
154     : base(o.ptr())
155 {
156 }
157 
158 namespace converter
159 {
160   template <class T>
extract_rvalue(PyObject * x)161   inline extract_rvalue<T>::extract_rvalue(PyObject* x)
162       : m_source(x)
163       , m_data(
164           (rvalue_from_python_stage1)(x, registered<T>::converters)
165           )
166   {
167   }
168 
169   template <class T>
170   inline bool
check() const171   extract_rvalue<T>::check() const
172   {
173       return m_data.stage1.convertible;
174   }
175 
176   template <class T>
177   inline typename extract_rvalue<T>::result_type
operator ()() const178   extract_rvalue<T>::operator()() const
179   {
180       return *(T*)(
181           // Only do the stage2 conversion once
182           m_data.stage1.convertible ==  m_data.storage.bytes
183              ? m_data.storage.bytes
184              : (rvalue_from_python_stage2)(m_source, m_data.stage1, registered<T>::converters)
185           );
186   }
187 
188   template <class Ref>
extract_reference(PyObject * obj)189   inline extract_reference<Ref>::extract_reference(PyObject* obj)
190       : m_source(obj)
191       , m_result(
192           (get_lvalue_from_python)(obj, registered<Ref>::converters)
193           )
194   {
195   }
196 
197   template <class Ref>
check() const198   inline bool extract_reference<Ref>::check() const
199   {
200       return m_result != 0;
201   }
202 
203   template <class Ref>
operator ()() const204   inline Ref extract_reference<Ref>::operator()() const
205   {
206       if (m_result == 0)
207           (throw_no_reference_from_python)(m_source, registered<Ref>::converters);
208 
209       return python::detail::void_ptr_to_reference(m_result, (Ref(*)())0);
210   }
211 
212   template <class Ptr>
extract_pointer(PyObject * obj)213   inline extract_pointer<Ptr>::extract_pointer(PyObject* obj)
214       : m_source(obj)
215       , m_result(
216           obj == Py_None ? 0 : (get_lvalue_from_python)(obj, registered_pointee<Ptr>::converters)
217           )
218   {
219   }
220 
221   template <class Ptr>
check() const222   inline bool extract_pointer<Ptr>::check() const
223   {
224       return m_source == Py_None || m_result != 0;
225   }
226 
227   template <class Ptr>
operator ()() const228   inline Ptr extract_pointer<Ptr>::operator()() const
229   {
230       if (m_result == 0 && m_source != Py_None)
231           (throw_no_pointer_from_python)(m_source, registered_pointee<Ptr>::converters);
232 
233       return Ptr(m_result);
234   }
235 
236   template <class T>
extract_object_manager(PyObject * obj)237   inline extract_object_manager<T>::extract_object_manager(PyObject* obj)
238       : m_source(obj)
239   {
240   }
241 
242   template <class T>
check() const243   inline bool extract_object_manager<T>::check() const
244   {
245       return object_manager_traits<T>::check(m_source);
246   }
247 
248   template <class T>
operator ()() const249   inline T extract_object_manager<T>::operator()() const
250   {
251       return T(
252           object_manager_traits<T>::adopt(python::incref(m_source))
253           );
254   }
255 }
256 
257 }} // namespace boost::python::converter
258 
259 #endif // EXTRACT_DWA200265_HPP
260