]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
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 | // | |
146 | template <class T> | |
147 | inline extract<T>::extract(PyObject* o) | |
148 | : base(o) | |
149 | { | |
150 | } | |
151 | ||
152 | template <class T> | |
153 | inline extract<T>::extract(api::object const& o) | |
154 | : base(o.ptr()) | |
155 | { | |
156 | } | |
157 | ||
158 | namespace 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 |