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
30namespace boost { namespace python {
31
32namespace api
33{
34 class object;
35}
36
37namespace 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
125template <class T>
126struct 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
134 operator result_type() const
135 {
136 return (*this)();
137 }
138
139 extract(PyObject*);
140 extract(api::object const&);
141};
142
143//
144// Implementations
145//
146template <class T>
147inline extract<T>::extract(PyObject* o)
148 : base(o)
149{
150}
151
152template <class T>
153inline extract<T>::extract(api::object const& o)
154 : base(o.ptr())
155{
156}
157
158namespace converter
159{
160 template <class T>
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
171 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
178 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>
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>
198 inline bool extract_reference<Ref>::check() const
199 {
200 return m_result != 0;
201 }
202
203 template <class Ref>
204 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>
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>
222 inline bool extract_pointer<Ptr>::check() const
223 {
224 return m_source == Py_None || m_result != 0;
225 }
226
227 template <class Ptr>
228 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>
237 inline extract_object_manager<T>::extract_object_manager(PyObject* obj)
238 : m_source(obj)
239 {
240 }
241
242 template <class T>
243 inline bool extract_object_manager<T>::check() const
244 {
245 return object_manager_traits<T>::check(m_source);
246 }
247
248 template <class T>
249 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

source code of boost/boost/python/extract.hpp