Chris@16: // Copyright David Abrahams 2002. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef HANDLE_DWA200269_HPP Chris@16: # define HANDLE_DWA200269_HPP Chris@16: Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: namespace boost { namespace python { Chris@16: Chris@16: template struct null_ok; Chris@16: Chris@16: template Chris@16: inline null_ok* allow_null(T* p) Chris@16: { Chris@16: return (null_ok*)p; Chris@16: } Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: inline T* manage_ptr(detail::borrowed >* p, int) Chris@16: { Chris@16: return python::xincref((T*)p); Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* manage_ptr(null_ok >* p, int) Chris@16: { Chris@16: return python::xincref((T*)p); Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* manage_ptr(detail::borrowed* p, long) Chris@16: { Chris@16: return python::incref(expect_non_null((T*)p)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* manage_ptr(null_ok* p, long) Chris@16: { Chris@16: return (T*)p; Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* manage_ptr(T* p, ...) Chris@16: { Chris@16: return expect_non_null(p); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: class handle Chris@16: { Chris@16: typedef T* (handle::* bool_type )() const; Chris@16: Chris@16: public: // types Chris@16: typedef T element_type; Chris@16: Chris@16: public: // member functions Chris@16: handle(); Chris@16: ~handle(); Chris@16: Chris@16: template Chris@16: explicit handle(Y* p) Chris@16: : m_p( Chris@16: python::upcast( Chris@16: detail::manage_ptr(p, 0) Chris@16: ) Chris@16: ) Chris@16: { Chris@16: } Chris@16: Chris@16: handle& operator=(handle const& r) Chris@16: { Chris@16: python::xdecref(m_p); Chris@16: m_p = python::xincref(r.m_p); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) Chris@16: Chris@16: template Chris@16: handle& operator=(handle const & r) // never throws Chris@16: { Chris@16: python::xdecref(m_p); Chris@16: m_p = python::xincref(python::upcast(r.get())); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: template Chris@16: handle(handle const& r) Chris@16: : m_p(python::xincref(python::upcast(r.get()))) Chris@16: { Chris@16: } Chris@16: Chris@16: handle(handle const& r) Chris@16: : m_p(python::xincref(r.m_p)) Chris@16: { Chris@16: } Chris@16: Chris@16: T* operator-> () const; Chris@16: T& operator* () const; Chris@16: T* get() const; Chris@16: T* release(); Chris@16: void reset(); Chris@16: Chris@16: operator bool_type() const // never throws Chris@16: { Chris@16: return m_p ? &handle::get : 0; Chris@16: } Chris@16: bool operator! () const; // never throws Chris@16: Chris@16: public: // implementation details -- do not touch Chris@16: // Defining this in the class body suppresses a VC7 link failure Chris@16: inline handle(detail::borrowed_reference x) Chris@16: : m_p( Chris@16: python::incref( Chris@16: downcast((PyObject*)x) Chris@16: )) Chris@16: { Chris@16: } Chris@16: Chris@16: private: // data members Chris@16: T* m_p; Chris@16: }; Chris@16: Chris@16: #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP Chris@16: } // namespace python Chris@16: #endif Chris@16: Chris@16: template inline T * get_pointer(python::handle const & p) Chris@16: { Chris@16: return p.get(); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP Chris@16: namespace python { Chris@16: #else Chris@16: Chris@16: // We don't want get_pointer above to hide the others Chris@16: using boost::get_pointer; Chris@16: Chris@16: #endif Chris@16: Chris@16: typedef handle type_handle; Chris@16: Chris@16: // Chris@16: // Compile-time introspection Chris@16: // Chris@16: # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Chris@16: template Chris@16: class is_handle Chris@16: { Chris@16: public: Chris@16: BOOST_STATIC_CONSTANT(bool, value = false); Chris@16: }; Chris@16: Chris@16: template Chris@16: class is_handle > Chris@16: { Chris@16: public: Chris@16: BOOST_STATIC_CONSTANT(bool, value = true); Chris@16: }; Chris@16: # else Chris@16: namespace detail Chris@16: { Chris@16: typedef char (&yes_handle_t)[1]; Chris@16: typedef char (&no_handle_t)[2]; Chris@16: Chris@16: no_handle_t is_handle_test(...); Chris@16: Chris@16: template Chris@16: yes_handle_t is_handle_test(boost::type< handle >); Chris@16: } Chris@16: Chris@16: template Chris@16: class is_handle Chris@16: { Chris@16: public: Chris@16: BOOST_STATIC_CONSTANT( Chris@16: bool, value = ( Chris@16: sizeof(detail::is_handle_test(boost::type())) Chris@16: == sizeof(detail::yes_handle_t))); Chris@16: }; Chris@16: # endif Chris@16: Chris@16: // Chris@16: // implementations Chris@16: // Chris@16: template Chris@16: inline handle::handle() Chris@16: : m_p(0) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: inline handle::~handle() Chris@16: { Chris@16: python::xdecref(m_p); Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* handle::operator->() const Chris@16: { Chris@16: return m_p; Chris@16: } Chris@16: Chris@16: template Chris@16: inline T& handle::operator*() const Chris@16: { Chris@16: return *m_p; Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* handle::get() const Chris@16: { Chris@16: return m_p; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool handle::operator!() const Chris@16: { Chris@16: return m_p == 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline T* handle::release() Chris@16: { Chris@16: T* result = m_p; Chris@16: m_p = 0; Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void handle::reset() Chris@16: { Chris@16: python::xdecref(m_p); Chris@16: m_p = 0; Chris@16: } Chris@16: Chris@16: // Because get_managed_object must return a non-null PyObject*, we Chris@16: // return Py_None if the handle is null. Chris@16: template Chris@16: inline PyObject* get_managed_object(handle const& h, tag_t) Chris@16: { Chris@16: return h.get() ? python::upcast(h.get()) : Py_None; Chris@16: } Chris@16: Chris@16: }} // namespace boost::python Chris@16: Chris@16: Chris@16: #endif // HANDLE_DWA200269_HPP