[857] | 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 WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
|
---|
| 6 | # define WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
|
---|
| 7 |
|
---|
| 8 | # include <boost/python/detail/prefix.hpp>
|
---|
| 9 |
|
---|
| 10 | # include <boost/python/default_call_policies.hpp>
|
---|
| 11 | # include <boost/python/object/life_support.hpp>
|
---|
| 12 | # include <algorithm>
|
---|
| 13 |
|
---|
| 14 | namespace boost { namespace python {
|
---|
| 15 |
|
---|
| 16 | namespace detail
|
---|
| 17 | {
|
---|
| 18 | template <std::size_t N>
|
---|
| 19 | struct get_prev
|
---|
| 20 | {
|
---|
| 21 | template <class ArgumentPackage>
|
---|
| 22 | static PyObject* execute(ArgumentPackage const& args, PyObject* = 0)
|
---|
| 23 | {
|
---|
| 24 | int const pre_n = static_cast<int>(N) - 1; // separate line is gcc-2.96 workaround
|
---|
| 25 | return detail::get(mpl::int_<pre_n>(), args);
|
---|
| 26 | }
|
---|
| 27 | };
|
---|
| 28 | template <>
|
---|
| 29 | struct get_prev<0>
|
---|
| 30 | {
|
---|
| 31 | template <class ArgumentPackage>
|
---|
| 32 | static PyObject* execute(ArgumentPackage const&, PyObject* zeroth)
|
---|
| 33 | {
|
---|
| 34 | return zeroth;
|
---|
| 35 | }
|
---|
| 36 | };
|
---|
| 37 | }
|
---|
| 38 | template <
|
---|
| 39 | std::size_t custodian
|
---|
| 40 | , std::size_t ward
|
---|
| 41 | , class BasePolicy_ = default_call_policies
|
---|
| 42 | >
|
---|
| 43 | struct with_custodian_and_ward : BasePolicy_
|
---|
| 44 | {
|
---|
| 45 | BOOST_STATIC_ASSERT(custodian != ward);
|
---|
| 46 | BOOST_STATIC_ASSERT(custodian > 0);
|
---|
| 47 | BOOST_STATIC_ASSERT(ward > 0);
|
---|
| 48 |
|
---|
| 49 | template <class ArgumentPackage>
|
---|
| 50 | static bool precall(ArgumentPackage const& args_)
|
---|
| 51 | {
|
---|
| 52 | unsigned arity_ = detail::arity(args_);
|
---|
| 53 | if (custodian > arity_ || ward > arity_)
|
---|
| 54 | {
|
---|
| 55 | PyErr_SetString(
|
---|
| 56 | PyExc_IndexError
|
---|
| 57 | , "boost::python::with_custodian_and_ward: argument index out of range"
|
---|
| 58 | );
|
---|
| 59 | return false;
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | PyObject* patient = detail::get_prev<ward>::execute(args_);
|
---|
| 63 | PyObject* nurse = detail::get_prev<custodian>::execute(args_);
|
---|
| 64 |
|
---|
| 65 | PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient);
|
---|
| 66 | if (life_support == 0)
|
---|
| 67 | return false;
|
---|
| 68 |
|
---|
| 69 | bool result = BasePolicy_::precall(args_);
|
---|
| 70 |
|
---|
| 71 | if (!result)
|
---|
| 72 | Py_DECREF(life_support);
|
---|
| 73 |
|
---|
| 74 | return result;
|
---|
| 75 | }
|
---|
| 76 | };
|
---|
| 77 |
|
---|
| 78 | template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
|
---|
| 79 | struct with_custodian_and_ward_postcall : BasePolicy_
|
---|
| 80 | {
|
---|
| 81 | BOOST_STATIC_ASSERT(custodian != ward);
|
---|
| 82 |
|
---|
| 83 | template <class ArgumentPackage>
|
---|
| 84 | static PyObject* postcall(ArgumentPackage const& args_, PyObject* result)
|
---|
| 85 | {
|
---|
| 86 | std::size_t arity_ = detail::arity(args_);
|
---|
| 87 | if ( custodian > arity_ || ward > arity_ )
|
---|
| 88 | {
|
---|
| 89 | PyErr_SetString(
|
---|
| 90 | PyExc_IndexError
|
---|
| 91 | , "boost::python::with_custodian_and_ward_postcall: argument index out of range"
|
---|
| 92 | );
|
---|
| 93 | return 0;
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | PyObject* patient = detail::get_prev<ward>::execute(args_, result);
|
---|
| 97 | PyObject* nurse = detail::get_prev<custodian>::execute(args_, result);
|
---|
| 98 |
|
---|
| 99 | if (nurse == 0) return 0;
|
---|
| 100 |
|
---|
| 101 | result = BasePolicy_::postcall(args_, result);
|
---|
| 102 | if (result == 0)
|
---|
| 103 | return 0;
|
---|
| 104 |
|
---|
| 105 | if (python::objects::make_nurse_and_patient(nurse, patient) == 0)
|
---|
| 106 | {
|
---|
| 107 | Py_XDECREF(result);
|
---|
| 108 | return 0;
|
---|
| 109 | }
|
---|
| 110 | return result;
|
---|
| 111 | }
|
---|
| 112 | };
|
---|
| 113 |
|
---|
| 114 |
|
---|
| 115 | }} // namespace boost::python
|
---|
| 116 |
|
---|
| 117 | #endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
|
---|