• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #if !defined(BOOST_PP_IS_ITERATING)
2 
3 // Copyright David Abrahams 2001.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 
8 # ifndef POINTER_HOLDER_DWA20011215_HPP
9 #  define POINTER_HOLDER_DWA20011215_HPP
10 
11 # include <boost/get_pointer.hpp>
12 #  include <boost/type.hpp>
13 
14 #  include <boost/python/instance_holder.hpp>
15 #  include <boost/python/object/inheritance_query.hpp>
16 #  include <boost/python/object/forward.hpp>
17 
18 #  include <boost/python/pointee.hpp>
19 #  include <boost/python/type_id.hpp>
20 
21 #  include <boost/python/detail/wrapper_base.hpp>
22 #  include <boost/python/detail/force_instantiate.hpp>
23 #  include <boost/python/detail/preprocessor.hpp>
24 # include <boost/python/detail/type_traits.hpp>
25 
26 
27 #  include <boost/mpl/if.hpp>
28 #  include <boost/mpl/apply.hpp>
29 
30 #  include <boost/preprocessor/comma_if.hpp>
31 #  include <boost/preprocessor/iterate.hpp>
32 #  include <boost/preprocessor/repeat.hpp>
33 #  include <boost/preprocessor/debug/line.hpp>
34 #  include <boost/preprocessor/enum_params.hpp>
35 #  include <boost/preprocessor/repetition/enum_binary_params.hpp>
36 
37 #  include <boost/detail/workaround.hpp>
38 
39 namespace boost { namespace python {
40 
41 template <class T> class wrapper;
42 
43 }}
44 
45 
46 namespace boost { namespace python { namespace objects {
47 
48 #define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) objects::do_unforward(a##n,0)
49 
50 template <class Pointer, class Value>
51 struct pointer_holder : instance_holder
52 {
53     typedef Value value_type;
54 
55     pointer_holder(Pointer);
56 
57     // Forward construction to the held object
58 
59 #  define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/pointer_holder.hpp>, 1))
60 #  include BOOST_PP_ITERATE()
61 
62  private: // types
63 
64  private: // required holder implementation
65     void* holds(type_info, bool null_ptr_only);
66 
67     template <class T>
holds_wrappedboost::python::objects::pointer_holder68     inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p)
69     {
70         return python::type_id<T>() == dst_t ? p : 0;
71     }
72 
holds_wrappedboost::python::objects::pointer_holder73     inline void* holds_wrapped(type_info, ...)
74     {
75         return 0;
76     }
77 
78  private: // data members
79     Pointer m_p;
80 };
81 
82 template <class Pointer, class Value>
83 struct pointer_holder_back_reference : instance_holder
84 {
85  private:
86     typedef typename python::pointee<Pointer>::type held_type;
87  public:
88     typedef Value value_type;
89 
90     // Not sure about this one -- can it work? The source object
91     // undoubtedly does not carry the correct back reference pointer.
92     pointer_holder_back_reference(Pointer);
93 
94     // Forward construction to the held object
95 #  define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/pointer_holder.hpp>, 2))
96 #  include BOOST_PP_ITERATE()
97 
98  private: // required holder implementation
99     void* holds(type_info, bool null_ptr_only);
100 
101  private: // data members
102     Pointer m_p;
103 };
104 
105 #  undef BOOST_PYTHON_UNFORWARD_LOCAL
106 
107 template <class Pointer, class Value>
pointer_holder(Pointer p)108 inline pointer_holder<Pointer,Value>::pointer_holder(Pointer p)
109 #if defined(BOOST_NO_CXX11_SMART_PTR)
110     : m_p(p)
111 #else
112     : m_p(std::move(p))
113 #endif
114 {
115 }
116 
117 template <class Pointer, class Value>
pointer_holder_back_reference(Pointer p)118 inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_reference(Pointer p)
119 #if defined(BOOST_NO_CXX11_SMART_PTR)
120     : m_p(p)
121 #else
122     : m_p(std::move(p))
123 #endif
124 {
125 }
126 
127 template <class Pointer, class Value>
holds(type_info dst_t,bool null_ptr_only)128 void* pointer_holder<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
129 {
130     typedef typename boost::python::detail::remove_const< Value >::type non_const_value;
131 
132     if (dst_t == python::type_id<Pointer>()
133         && !(null_ptr_only && get_pointer(this->m_p))
134     )
135         return &this->m_p;
136 
137     Value* p0
138 #  if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
139         = static_cast<Value*>( get_pointer(this->m_p) )
140 #  else
141         = get_pointer(this->m_p)
142 #  endif
143         ;
144     non_const_value* p = const_cast<non_const_value*>( p0 );
145 
146     if (p == 0)
147         return 0;
148 
149     if (void* wrapped = holds_wrapped(dst_t, p, p))
150         return wrapped;
151 
152     type_info src_t = python::type_id<non_const_value>();
153     return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
154 }
155 
156 template <class Pointer, class Value>
holds(type_info dst_t,bool null_ptr_only)157 void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
158 {
159     if (dst_t == python::type_id<Pointer>()
160         && !(null_ptr_only && get_pointer(this->m_p))
161     )
162         return &this->m_p;
163 
164     if (!get_pointer(this->m_p))
165         return 0;
166 
167     Value* p = get_pointer(m_p);
168 
169     if (dst_t == python::type_id<held_type>())
170         return p;
171 
172     type_info src_t = python::type_id<Value>();
173     return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
174 }
175 
176 }}} // namespace boost::python::objects
177 
178 # endif // POINTER_HOLDER_DWA20011215_HPP
179 
180 /* --------------- pointer_holder --------------- */
181 // For gcc 4.4 compatability, we must include the
182 // BOOST_PP_ITERATION_DEPTH test inside an #else clause.
183 #else // BOOST_PP_IS_ITERATING
184 #if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
185 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100)                      \
186         && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
187 #  line BOOST_PP_LINE(__LINE__, pointer_holder.hpp)
188 # endif
189 
190 # define N BOOST_PP_ITERATION()
191 
192 # if (N != 0)
193     template< BOOST_PP_ENUM_PARAMS_Z(1, N, class A) >
194 # endif
195     pointer_holder(PyObject* self BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a))
196         : m_p(new Value(
197                 BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
198             ))
199     {
200         python::detail::initialize_wrapper(self, get_pointer(this->m_p));
201     }
202 
203 # undef N
204 
205 /* --------------- pointer_holder_back_reference --------------- */
206 #elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2
207 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100)                      \
208         && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
209 #  line BOOST_PP_LINE(__LINE__, pointer_holder.hpp(pointer_holder_back_reference))
210 # endif
211 
212 # define N BOOST_PP_ITERATION()
213 
214 # if (N != 0)
215     template < BOOST_PP_ENUM_PARAMS_Z(1, N, class A) >
216 # endif
217     pointer_holder_back_reference(
218         PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a))
219         : m_p(new held_type(
220                     p BOOST_PP_COMMA_IF(N) BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
221             ))
222     {}
223 
224 # undef N
225 
226 #endif // BOOST_PP_ITERATION_DEPTH()
227 #endif
228