Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/python/with_custodian_and_ward.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 3.6 KB
Line 
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
14namespace boost { namespace python { 
15
16namespace 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}
38template <
39    std::size_t custodian
40  , std::size_t ward
41  , class BasePolicy_ = default_call_policies
42>
43struct 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
78template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
79struct 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 BOOST_WORKAROUND(BOOST_MSVC, < 1300)
88        if ( custodian > arity_ || ward > arity_ )
89#else
90        // check if either custodian or ward exceeds the arity
91        // (this weird formulation avoids "always false" warnings
92        // for arity_ = 0)
93        if ( (std::max)(custodian, ward) > arity_ )
94#endif
95        {
96            PyErr_SetString(
97                PyExc_IndexError
98              , "boost::python::with_custodian_and_ward_postcall: argument index out of range"
99            );
100            return 0;
101        }
102       
103        PyObject* patient = detail::get_prev<ward>::execute(args_, result);
104        PyObject* nurse = detail::get_prev<custodian>::execute(args_, result);
105
106        if (nurse == 0) return 0;
107   
108        result = BasePolicy_::postcall(args_, result);
109        if (result == 0)
110            return 0;
111           
112        if (python::objects::make_nurse_and_patient(nurse, patient) == 0)
113        {
114            Py_XDECREF(result);
115            return 0;
116        }
117        return result;
118    }
119};
120
121
122}} // namespace boost::python
123
124#endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
Note: See TracBrowser for help on using the repository browser.