os/ossrv/ossrv_pub/boost_apis/boost/python/handle.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 HANDLE_DWA200269_HPP
     6 # define HANDLE_DWA200269_HPP
     7 
     8 # include <boost/python/detail/prefix.hpp>
     9 
    10 # include <boost/python/cast.hpp>
    11 # include <boost/python/errors.hpp>
    12 # include <boost/python/borrowed.hpp>
    13 # include <boost/python/handle_fwd.hpp>
    14 # include <boost/python/refcount.hpp>
    15 # include <boost/python/tag.hpp>
    16 # include <boost/python/detail/raw_pyobject.hpp>
    17 
    18 namespace boost { namespace python { 
    19 
    20 template <class T> struct null_ok;
    21 
    22 template <class T>
    23 inline null_ok<T>* allow_null(T* p)
    24 {
    25     return (null_ok<T>*)p;
    26 }
    27 
    28 namespace detail
    29 {
    30   template <class T>
    31   inline T* manage_ptr(detail::borrowed<null_ok<T> >* p, int)
    32   {
    33       return python::xincref((T*)p);
    34   }
    35   
    36   template <class T>
    37   inline T* manage_ptr(null_ok<detail::borrowed<T> >* p, int)
    38   {
    39       return python::xincref((T*)p);
    40   }
    41   
    42   template <class T>
    43   inline T* manage_ptr(detail::borrowed<T>* p, long)
    44   {
    45       return python::incref(expect_non_null((T*)p));
    46   }
    47   
    48   template <class T>
    49   inline T* manage_ptr(null_ok<T>* p, long)
    50   {
    51       return (T*)p;
    52   }
    53   
    54   template <class T>
    55   inline T* manage_ptr(T* p, ...)
    56   {
    57       return expect_non_null(p);
    58   }
    59 }
    60 
    61 template <class T>
    62 class handle
    63 {
    64     typedef T* (handle::* bool_type )() const;
    65 
    66  public: // types
    67     typedef T element_type;
    68     
    69  public: // member functions
    70     handle();
    71     ~handle();
    72 
    73     template <class Y>
    74     explicit handle(Y* p)
    75         : m_p(
    76             python::upcast<T>(
    77                 detail::manage_ptr(p, 0)
    78                 )
    79             )
    80     {
    81     }
    82 
    83     handle& operator=(handle const& r)
    84     {
    85         python::xdecref(m_p);
    86         m_p = python::xincref(r.m_p);
    87         return *this;
    88     }
    89 
    90 #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
    91 
    92     template<typename Y>
    93     handle& operator=(handle<Y> const & r) // never throws
    94     {
    95         python::xdecref(m_p);
    96         m_p = python::xincref(python::upcast<T>(r.get()));
    97         return *this;
    98     }
    99 
   100 #endif
   101 
   102     template <typename Y>
   103     handle(handle<Y> const& r)
   104         : m_p(python::xincref(python::upcast<T>(r.get())))
   105     {
   106     }
   107     
   108     handle(handle const& r)
   109         : m_p(python::xincref(r.m_p))
   110     {
   111     }
   112     
   113     T* operator-> () const;
   114     T& operator* () const;
   115     T* get() const;
   116     T* release();
   117     void reset();
   118     
   119     operator bool_type() const // never throws
   120     {
   121         return m_p ? &handle<T>::get : 0;
   122     }
   123     bool operator! () const; // never throws
   124 
   125  public: // implementation details -- do not touch
   126     // Defining this in the class body suppresses a VC7 link failure
   127     inline handle(detail::borrowed_reference x)
   128         : m_p(
   129             python::incref(
   130                 downcast<T>((PyObject*)x)
   131                 ))
   132     {
   133     }
   134     
   135  private: // data members
   136     T* m_p;
   137 };
   138 
   139 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
   140 } // namespace python
   141 #endif
   142 
   143 template<class T> inline T * get_pointer(python::handle<T> const & p)
   144 {
   145     return p.get();
   146 }
   147 
   148 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
   149 namespace python {
   150 #else
   151 
   152 // We don't want get_pointer above to hide the others
   153 using boost::get_pointer;
   154 
   155 #endif
   156 
   157 typedef handle<PyTypeObject> type_handle;
   158 
   159 //
   160 // Compile-time introspection
   161 //
   162 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   163 template<typename T>
   164 class is_handle
   165 {
   166  public:
   167     BOOST_STATIC_CONSTANT(bool, value = false); 
   168 };
   169 
   170 template<typename T>
   171 class is_handle<handle<T> >
   172 {
   173  public:
   174     BOOST_STATIC_CONSTANT(bool, value = true);
   175 };
   176 # else
   177 namespace detail
   178 {
   179   typedef char (&yes_handle_t)[1];
   180   typedef char (&no_handle_t)[2];
   181       
   182   no_handle_t is_handle_test(...);
   183 
   184   template<typename T>
   185   yes_handle_t is_handle_test(boost::type< handle<T> >);
   186 }
   187 
   188 template<typename T>
   189 class is_handle
   190 {
   191  public:
   192     BOOST_STATIC_CONSTANT(
   193         bool, value = (
   194             sizeof(detail::is_handle_test(boost::type<T>()))
   195             == sizeof(detail::yes_handle_t)));
   196 };
   197 # endif
   198 
   199 //
   200 // implementations
   201 //
   202 template <class T>
   203 inline handle<T>::handle()
   204     : m_p(0)
   205 {
   206 }
   207 
   208 template <class T>
   209 inline handle<T>::~handle()
   210 {
   211     python::xdecref(m_p);
   212 }
   213 
   214 template <class T>
   215 inline T* handle<T>::operator->() const
   216 {
   217     return m_p;
   218 }
   219 
   220 template <class T>
   221 inline T& handle<T>::operator*() const
   222 {
   223     return *m_p;
   224 }
   225 
   226 template <class T>
   227 inline T* handle<T>::get() const
   228 {
   229     return m_p;
   230 }
   231     
   232 template <class T>
   233 inline bool handle<T>::operator!() const
   234 {
   235     return m_p == 0;
   236 }
   237 
   238 template <class T>
   239 inline T* handle<T>::release()
   240 {
   241     T* result = m_p;
   242     m_p = 0;
   243     return result;
   244 }
   245 
   246 template <class T>
   247 inline void handle<T>::reset()
   248 {
   249     python::xdecref(m_p);
   250     m_p = 0;
   251 }
   252 
   253 // Because get_managed_object must return a non-null PyObject*, we
   254 // return Py_None if the handle is null.
   255 template <class T>
   256 inline PyObject* get_managed_object(handle<T> const& h, tag_t)
   257 {
   258     return h.get() ? python::upcast<PyObject>(h.get()) : Py_None;
   259 }
   260 
   261 }} // namespace boost::python
   262 
   263 
   264 #endif // HANDLE_DWA200269_HPP