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