Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:41

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef OBJECT_CORE_DWA2002615_HPP
0006 # define OBJECT_CORE_DWA2002615_HPP
0007 
0008 # define BOOST_PYTHON_OBJECT_HAS_IS_NONE // added 2010-03-15 by rwgk
0009 
0010 # include <boost/python/detail/prefix.hpp>
0011 
0012 # include <boost/type.hpp>
0013 
0014 # include <boost/python/call.hpp>
0015 # include <boost/python/handle_fwd.hpp>
0016 # include <boost/python/errors.hpp>
0017 # include <boost/python/refcount.hpp>
0018 # include <boost/python/detail/preprocessor.hpp>
0019 # include <boost/python/tag.hpp>
0020 # include <boost/python/def_visitor.hpp>
0021 
0022 # include <boost/python/detail/raw_pyobject.hpp>
0023 # include <boost/python/detail/dependent.hpp>
0024 
0025 # include <boost/python/object/forward.hpp>
0026 # include <boost/python/object/add_to_namespace.hpp>
0027 
0028 # include <boost/preprocessor/iterate.hpp>
0029 # include <boost/preprocessor/debug/line.hpp>
0030 
0031 # include <boost/python/detail/is_xxx.hpp>
0032 # include <boost/python/detail/string_literal.hpp>
0033 # include <boost/python/detail/def_helper_fwd.hpp>
0034 # include <boost/python/detail/type_traits.hpp>
0035 
0036 namespace boost { namespace python { 
0037 
0038 namespace detail
0039 {
0040   class kwds_proxy; 
0041   class args_proxy; 
0042 } 
0043 
0044 namespace converter
0045 {
0046   template <class T> struct arg_to_python;
0047 }
0048 
0049 // Put this in an inner namespace so that the generalized operators won't take over
0050 namespace api
0051 {
0052   
0053 // This file contains the definition of the object class and enough to
0054 // construct/copy it, but not enough to do operations like
0055 // attribute/item access or addition.
0056 
0057   template <class Policies> class proxy;
0058   
0059   struct const_attribute_policies;
0060   struct attribute_policies;
0061   struct const_objattribute_policies;
0062   struct objattribute_policies;
0063   struct const_item_policies;
0064   struct item_policies;
0065   struct const_slice_policies;
0066   struct slice_policies;
0067   class slice_nil;
0068 
0069   typedef proxy<const_attribute_policies> const_object_attribute;
0070   typedef proxy<attribute_policies> object_attribute;
0071   typedef proxy<const_objattribute_policies> const_object_objattribute;
0072   typedef proxy<objattribute_policies> object_objattribute;
0073   typedef proxy<const_item_policies> const_object_item;
0074   typedef proxy<item_policies> object_item;
0075   typedef proxy<const_slice_policies> const_object_slice;
0076   typedef proxy<slice_policies> object_slice;
0077 
0078   //
0079   // is_proxy -- proxy type detection
0080   //
0081   BOOST_PYTHON_IS_XXX_DEF(proxy, boost::python::api::proxy, 1)
0082 
0083   template <class T> struct object_initializer;
0084   
0085   class object;
0086   typedef PyObject* (object::*bool_type)() const;
0087   
0088   template <class U>
0089   class object_operators : public def_visitor<U>
0090   {
0091    protected:
0092       typedef object const& object_cref;
0093    public:
0094       // function call
0095       //
0096       object operator()() const;
0097 
0098 # define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
0099 # include BOOST_PP_ITERATE()
0100     
0101       detail::args_proxy operator* () const; 
0102       object operator()(detail::args_proxy const &args) const; 
0103       object operator()(detail::args_proxy const &args, 
0104                         detail::kwds_proxy const &kwds) const; 
0105 
0106       // truth value testing
0107       //
0108       operator bool_type() const;
0109       bool operator!() const; // needed for vc6
0110 
0111       // Attribute access
0112       //
0113       const_object_attribute attr(char const*) const;
0114       object_attribute attr(char const*);
0115       const_object_objattribute attr(object const&) const;
0116       object_objattribute attr(object const&);
0117 
0118       // Wrap 'in' operator (aka. __contains__)
0119       template <class T>
0120       object contains(T const& key) const;
0121       
0122       // item access
0123       //
0124       const_object_item operator[](object_cref) const;
0125       object_item operator[](object_cref);
0126     
0127       template <class T>
0128       const_object_item
0129       operator[](T const& key) const;
0130     
0131       template <class T>
0132       object_item
0133       operator[](T const& key);
0134 
0135       // slicing
0136       //
0137       const_object_slice slice(object_cref, object_cref) const;
0138       object_slice slice(object_cref, object_cref);
0139 
0140       const_object_slice slice(slice_nil, object_cref) const;
0141       object_slice slice(slice_nil, object_cref);
0142                              
0143       const_object_slice slice(object_cref, slice_nil) const;
0144       object_slice slice(object_cref, slice_nil);
0145 
0146       const_object_slice slice(slice_nil, slice_nil) const;
0147       object_slice slice(slice_nil, slice_nil);
0148 
0149       template <class T, class V>
0150       const_object_slice
0151       slice(T const& start, V const& end) const;
0152     
0153       template <class T, class V>
0154       object_slice
0155       slice(T const& start, V const& end);
0156       
0157    private: // def visitation for adding callable objects as class methods
0158       
0159       template <class ClassT, class DocStringT>
0160       void visit(ClassT& cl, char const* name, python::detail::def_helper<DocStringT> const& helper) const
0161       {
0162           // It's too late to specify anything other than docstrings if
0163           // the callable object is already wrapped.
0164           BOOST_STATIC_ASSERT(
0165               (detail::is_same<char const*,DocStringT>::value
0166                || detail::is_string_literal<DocStringT const>::value));
0167         
0168           objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc());
0169       }
0170 
0171       friend class python::def_visitor_access;
0172       
0173    private:
0174      // there is a confirmed CWPro8 codegen bug here. We prevent the
0175      // early destruction of a temporary by binding a named object
0176      // instead.
0177 # if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3003
0178     typedef object const& object_cref2;
0179 # else
0180     typedef object const object_cref2;
0181 # endif
0182   };
0183 
0184   
0185   // VC6 and VC7 require this base class in order to generate the
0186   // correct copy constructor for object. We can't define it there
0187   // explicitly or it will complain of ambiguity.
0188   struct object_base : object_operators<object>
0189   {
0190       // copy constructor without NULL checking, for efficiency. 
0191       inline object_base(object_base const&);
0192       inline object_base(PyObject* ptr);
0193       
0194       inline object_base& operator=(object_base const& rhs);
0195       inline ~object_base();
0196         
0197       // Underlying object access -- returns a borrowed reference
0198       inline PyObject* ptr() const;
0199 
0200       inline bool is_none() const;
0201 
0202    private:
0203       PyObject* m_ptr;
0204   };
0205 
0206   template <class T, class U>
0207   struct is_derived
0208     : boost::python::detail::is_convertible<
0209           typename detail::remove_reference<T>::type*
0210         , U const*
0211       >
0212   {};
0213 
0214   template <class T>
0215   typename objects::unforward_cref<T>::type do_unforward_cref(T const& x)
0216   {
0217       return x;
0218   }
0219 
0220   class object;
0221   
0222   template <class T>
0223   PyObject* object_base_initializer(T const& x)
0224   {
0225       typedef typename is_derived<
0226           BOOST_DEDUCED_TYPENAME objects::unforward_cref<T>::type
0227         , object
0228       >::type is_obj;
0229 
0230       return object_initializer<
0231           BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type
0232       >::get(
0233             x
0234           , is_obj()
0235       );
0236   }
0237   
0238   class object : public object_base
0239   {
0240    public:
0241       // default constructor creates a None object
0242       object();
0243       
0244       // explicit conversion from any C++ object to Python
0245       template <class T>
0246       explicit object(T const& x)
0247         : object_base(object_base_initializer(x))
0248       {
0249       }
0250 
0251       // Throw error_already_set() if the handle is null.
0252       BOOST_PYTHON_DECL explicit object(handle<> const&);
0253    private:
0254       
0255    public: // implementation detail -- for internal use only
0256       explicit object(detail::borrowed_reference);
0257       explicit object(detail::new_reference);
0258       explicit object(detail::new_non_null_reference);
0259   };
0260 
0261   // Macros for forwarding constructors in classes derived from
0262   // object. Derived classes will usually want these as an
0263   // implementation detail
0264 # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived, base)               \
0265     inline explicit derived(::boost::python::detail::borrowed_reference p)     \
0266         : base(p) {}                                                           \
0267     inline explicit derived(::boost::python::detail::new_reference p)          \
0268         : base(p) {}                                                           \
0269     inline explicit derived(::boost::python::detail::new_non_null_reference p) \
0270         : base(p) {}
0271 
0272   //
0273   // object_initializer -- get the handle to construct the object with,
0274   // based on whether T is a proxy or derived from object
0275   //
0276   template <bool is_proxy = false, bool is_object_manager = false>
0277   struct object_initializer_impl
0278   {
0279       static PyObject*
0280       get(object const& x, detail::true_)
0281       {
0282           return python::incref(x.ptr());
0283       }
0284       
0285       template <class T>
0286       static PyObject*
0287       get(T const& x, detail::false_)
0288       {
0289           return python::incref(converter::arg_to_python<T>(x).get());
0290       }
0291   };
0292       
0293   template <>
0294   struct object_initializer_impl<true, false>
0295   {
0296       template <class Policies>
0297       static PyObject* 
0298       get(proxy<Policies> const& x, detail::false_)
0299       {
0300           return python::incref(x.operator object().ptr());
0301       }
0302   };
0303 
0304   template <>
0305   struct object_initializer_impl<false, true>
0306   {
0307       template <class T, class U>
0308       static PyObject*
0309       get(T const& x, U)
0310       {
0311           return python::incref(get_managed_object(x, boost::python::tag));
0312       }
0313   };
0314 
0315   template <>
0316   struct object_initializer_impl<true, true>
0317   {}; // empty implementation should cause an error
0318 
0319   template <class T>
0320   struct object_initializer : object_initializer_impl<
0321       is_proxy<T>::value
0322     , converter::is_object_manager<T>::value
0323   >
0324   {};
0325 
0326 }
0327 using api::object;
0328 template <class T> struct extract;
0329 
0330 //
0331 // implementation
0332 //
0333 
0334 namespace detail 
0335 {
0336 
0337 class call_proxy 
0338 { 
0339 public: 
0340   call_proxy(object target) : m_target(target) {} 
0341   operator object() const { return m_target;} 
0342  
0343  private: 
0344     object m_target; 
0345 }; 
0346  
0347 class kwds_proxy : public call_proxy 
0348 { 
0349 public: 
0350   kwds_proxy(object o = object()) : call_proxy(o) {} 
0351 }; 
0352 class args_proxy : public call_proxy 
0353 { 
0354 public: 
0355   args_proxy(object o) : call_proxy(o) {} 
0356   kwds_proxy operator* () const { return kwds_proxy(*this);} 
0357 }; 
0358 } 
0359  
0360 template <typename U> 
0361 detail::args_proxy api::object_operators<U>::operator* () const 
0362 { 
0363   object_cref2 x = *static_cast<U const*>(this); 
0364   return boost::python::detail::args_proxy(x); 
0365 } 
0366  
0367 template <typename U> 
0368 object api::object_operators<U>::operator()(detail::args_proxy const &args) const 
0369 { 
0370   U const& self = *static_cast<U const*>(this); 
0371   PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag), 
0372                                    args.operator object().ptr(), 
0373                                    0); 
0374   return object(boost::python::detail::new_reference(result)); 
0375  
0376 } 
0377  
0378 template <typename U> 
0379 object api::object_operators<U>::operator()(detail::args_proxy const &args, 
0380                                             detail::kwds_proxy const &kwds) const 
0381 { 
0382   U const& self = *static_cast<U const*>(this); 
0383   PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag), 
0384                                    args.operator object().ptr(), 
0385                                    kwds.operator object().ptr()); 
0386   return object(boost::python::detail::new_reference(result)); 
0387  
0388 }  
0389 
0390 
0391 template <typename U>
0392 template <class T>
0393 object api::object_operators<U>::contains(T const& key) const
0394 {
0395     return this->attr("__contains__")(object(key));
0396 }
0397 
0398 
0399 inline object::object()
0400     : object_base(python::incref(Py_None))
0401 {}
0402 
0403 // copy constructor without NULL checking, for efficiency
0404 inline api::object_base::object_base(object_base const& rhs)
0405     : m_ptr(python::incref(rhs.m_ptr))
0406 {}
0407 
0408 inline api::object_base::object_base(PyObject* p)
0409     : m_ptr(p)
0410 {}
0411 
0412 inline api::object_base& api::object_base::operator=(api::object_base const& rhs)
0413 {
0414     Py_INCREF(rhs.m_ptr);
0415     Py_DECREF(this->m_ptr);
0416     this->m_ptr = rhs.m_ptr;
0417     return *this;
0418 }
0419 
0420 inline api::object_base::~object_base()
0421 {
0422     assert( Py_REFCNT(m_ptr) > 0 );
0423     Py_DECREF(m_ptr);
0424 }
0425 
0426 inline object::object(detail::borrowed_reference p)
0427     : object_base(python::incref((PyObject*)p))
0428 {}
0429 
0430 inline object::object(detail::new_reference p)
0431     : object_base(expect_non_null((PyObject*)p))
0432 {}
0433 
0434 inline object::object(detail::new_non_null_reference p)
0435     : object_base((PyObject*)p)
0436 {}
0437 
0438 inline PyObject* api::object_base::ptr() const
0439 {
0440     return m_ptr;
0441 }
0442 
0443 inline bool api::object_base::is_none() const
0444 {
0445     return (m_ptr == Py_None);
0446 }
0447 
0448 //
0449 // Converter specialization implementations
0450 //
0451 namespace converter
0452 {
0453   template <class T> struct object_manager_traits;
0454   
0455   template <>
0456   struct object_manager_traits<object>
0457   {
0458       BOOST_STATIC_CONSTANT(bool, is_specialized = true);
0459       static bool check(PyObject*) { return true; }
0460       
0461       static python::detail::new_non_null_reference adopt(PyObject* x)
0462       {
0463           return python::detail::new_non_null_reference(x);
0464       }
0465 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
0466       static PyTypeObject const *get_pytype() {return 0;}
0467 #endif
0468   };
0469 }
0470 
0471 inline PyObject* get_managed_object(object const& x, tag_t)
0472 {
0473     return x.ptr();
0474 }
0475 
0476 }} // namespace boost::python
0477 
0478 # include <boost/python/slice_nil.hpp>
0479 
0480 #endif // OBJECT_CORE_DWA2002615_HPP