Chris@16
|
1 // Copyright David Abrahams 2002.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
3 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5 #ifndef WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
|
Chris@16
|
6 # define WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
|
Chris@16
|
7
|
Chris@16
|
8 # include <boost/python/detail/prefix.hpp>
|
Chris@16
|
9
|
Chris@16
|
10 # include <boost/python/default_call_policies.hpp>
|
Chris@16
|
11 # include <boost/python/object/life_support.hpp>
|
Chris@16
|
12 # include <algorithm>
|
Chris@16
|
13
|
Chris@16
|
14 namespace boost { namespace python {
|
Chris@16
|
15
|
Chris@16
|
16 namespace detail
|
Chris@16
|
17 {
|
Chris@16
|
18 template <std::size_t N>
|
Chris@16
|
19 struct get_prev
|
Chris@16
|
20 {
|
Chris@16
|
21 template <class ArgumentPackage>
|
Chris@16
|
22 static PyObject* execute(ArgumentPackage const& args, PyObject* = 0)
|
Chris@16
|
23 {
|
Chris@16
|
24 int const pre_n = static_cast<int>(N) - 1; // separate line is gcc-2.96 workaround
|
Chris@16
|
25 return detail::get(mpl::int_<pre_n>(), args);
|
Chris@16
|
26 }
|
Chris@16
|
27 };
|
Chris@16
|
28 template <>
|
Chris@16
|
29 struct get_prev<0>
|
Chris@16
|
30 {
|
Chris@16
|
31 template <class ArgumentPackage>
|
Chris@16
|
32 static PyObject* execute(ArgumentPackage const&, PyObject* zeroth)
|
Chris@16
|
33 {
|
Chris@16
|
34 return zeroth;
|
Chris@16
|
35 }
|
Chris@16
|
36 };
|
Chris@16
|
37 }
|
Chris@16
|
38 template <
|
Chris@16
|
39 std::size_t custodian
|
Chris@16
|
40 , std::size_t ward
|
Chris@16
|
41 , class BasePolicy_ = default_call_policies
|
Chris@16
|
42 >
|
Chris@16
|
43 struct with_custodian_and_ward : BasePolicy_
|
Chris@16
|
44 {
|
Chris@16
|
45 BOOST_STATIC_ASSERT(custodian != ward);
|
Chris@16
|
46 BOOST_STATIC_ASSERT(custodian > 0);
|
Chris@16
|
47 BOOST_STATIC_ASSERT(ward > 0);
|
Chris@16
|
48
|
Chris@16
|
49 template <class ArgumentPackage>
|
Chris@16
|
50 static bool precall(ArgumentPackage const& args_)
|
Chris@16
|
51 {
|
Chris@16
|
52 unsigned arity_ = detail::arity(args_);
|
Chris@16
|
53 if (custodian > arity_ || ward > arity_)
|
Chris@16
|
54 {
|
Chris@16
|
55 PyErr_SetString(
|
Chris@16
|
56 PyExc_IndexError
|
Chris@16
|
57 , "boost::python::with_custodian_and_ward: argument index out of range"
|
Chris@16
|
58 );
|
Chris@16
|
59 return false;
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 PyObject* patient = detail::get_prev<ward>::execute(args_);
|
Chris@16
|
63 PyObject* nurse = detail::get_prev<custodian>::execute(args_);
|
Chris@16
|
64
|
Chris@16
|
65 PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient);
|
Chris@16
|
66 if (life_support == 0)
|
Chris@16
|
67 return false;
|
Chris@16
|
68
|
Chris@16
|
69 bool result = BasePolicy_::precall(args_);
|
Chris@16
|
70
|
Chris@16
|
71 if (!result) {
|
Chris@16
|
72 Py_DECREF(life_support);
|
Chris@16
|
73 }
|
Chris@16
|
74
|
Chris@16
|
75 return result;
|
Chris@16
|
76 }
|
Chris@16
|
77 };
|
Chris@16
|
78
|
Chris@16
|
79 template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
|
Chris@16
|
80 struct with_custodian_and_ward_postcall : BasePolicy_
|
Chris@16
|
81 {
|
Chris@16
|
82 BOOST_STATIC_ASSERT(custodian != ward);
|
Chris@16
|
83
|
Chris@16
|
84 template <class ArgumentPackage>
|
Chris@16
|
85 static PyObject* postcall(ArgumentPackage const& args_, PyObject* result)
|
Chris@16
|
86 {
|
Chris@16
|
87 std::size_t arity_ = detail::arity(args_);
|
Chris@16
|
88 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
Chris@16
|
89 if ( custodian > arity_ || ward > arity_ )
|
Chris@16
|
90 #else
|
Chris@16
|
91 // check if either custodian or ward exceeds the arity
|
Chris@16
|
92 // (this weird formulation avoids "always false" warnings
|
Chris@16
|
93 // for arity_ = 0)
|
Chris@16
|
94 if ( (std::max)(custodian, ward) > arity_ )
|
Chris@16
|
95 #endif
|
Chris@16
|
96 {
|
Chris@16
|
97 PyErr_SetString(
|
Chris@16
|
98 PyExc_IndexError
|
Chris@16
|
99 , "boost::python::with_custodian_and_ward_postcall: argument index out of range"
|
Chris@16
|
100 );
|
Chris@16
|
101 return 0;
|
Chris@16
|
102 }
|
Chris@16
|
103
|
Chris@16
|
104 PyObject* patient = detail::get_prev<ward>::execute(args_, result);
|
Chris@16
|
105 PyObject* nurse = detail::get_prev<custodian>::execute(args_, result);
|
Chris@16
|
106
|
Chris@16
|
107 if (nurse == 0) return 0;
|
Chris@16
|
108
|
Chris@16
|
109 result = BasePolicy_::postcall(args_, result);
|
Chris@16
|
110 if (result == 0)
|
Chris@16
|
111 return 0;
|
Chris@16
|
112
|
Chris@16
|
113 if (python::objects::make_nurse_and_patient(nurse, patient) == 0)
|
Chris@16
|
114 {
|
Chris@16
|
115 Py_XDECREF(result);
|
Chris@16
|
116 return 0;
|
Chris@16
|
117 }
|
Chris@16
|
118 return result;
|
Chris@16
|
119 }
|
Chris@16
|
120 };
|
Chris@16
|
121
|
Chris@16
|
122
|
Chris@16
|
123 }} // namespace boost::python
|
Chris@16
|
124
|
Chris@16
|
125 #endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
|