2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

list implementation

[SVN r14261]
This commit is contained in:
Dave Abrahams
2002-06-29 19:24:11 +00:00
parent d7273dee1c
commit f30fde3a52
23 changed files with 777 additions and 398 deletions

View File

@@ -13,6 +13,7 @@ if $(UNIX) && ( $(OS) = AIX )
dll bpl
:
src/list.cpp
src/aix_init_module.cpp
src/converter/from_python.cpp
src/converter/registry.cpp

View File

@@ -14,6 +14,7 @@
# include <boost/python/to_python_indirect.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/python/detail/convertible.hpp>
# include <boost/python/detail/string_literal.hpp>
# include <boost/python/base_type_traits.hpp>
// Bring in specializations
# include <boost/python/converter/builtin_converters.hpp>
@@ -73,6 +74,11 @@ namespace detail
template <class T>
struct select_arg_to_python
{
// Special handling for char const[N]; interpret them as char
// const* for the sake of conversion
BOOST_STATIC_CONSTANT(
bool, is_string = python::detail::is_string_literal<T const>::value);
BOOST_STATIC_CONSTANT(
bool, manager = is_object_manager<T>::value);
@@ -89,22 +95,27 @@ namespace detail
typedef typename unwrap_pointer<T>::type unwrapped_ptr;
typedef typename mpl::select_type<
manager
, object_manager_arg_to_python<T>
is_string
, arg_to_python<char const*>
, typename mpl::select_type<
ptr
, pointer_deep_arg_to_python<T>
manager
, object_manager_arg_to_python<T>
, typename mpl::select_type<
ptr_wrapper
, pointer_shallow_arg_to_python<unwrapped_ptr>
ptr
, pointer_deep_arg_to_python<T>
, typename mpl::select_type<
ref_wrapper
, reference_arg_to_python<unwrapped_referent>
, value_arg_to_python<T>
ptr_wrapper
, pointer_shallow_arg_to_python<unwrapped_ptr>
, typename mpl::select_type<
ref_wrapper
, reference_arg_to_python<unwrapped_referent>
, value_arg_to_python<T>
>::type
>::type
>::type
>::type
>::type type;
>::type
type;
};
}

View File

@@ -0,0 +1,99 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
# define PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
# include <boost/python/detail/wrap_python.hpp>
//
// arg_from_python converters for Python type wrappers, to be used as
// base classes for specializations.
//
namespace boost { namespace python { namespace converter {
template <PyTypeObject* python_type>
struct pytype_arg_from_python
{
pytype_arg_from_python(PyObject*);
bool convertible() const;
private:
PyObject* m_src;
};
// rvalue converter base
template <class Wrapper, PyTypeObject* python_type>
struct pytype_wrapper_value_arg_from_python
: pytype_arg_from_python<python_type>
{
typedef Wrapper result_type;
pytype_wrapper_value_arg_from_python(PyObject*);
Wrapper operator()(PyObject*) const;
};
// Special case for Wrapper& - must store an lvalue internally. This
// OK because the entire state of the object is actually in the Python
// object.
template <class Wrapper, PyTypeObject* python_type>
struct pytype_wrapper_ref_arg_from_python
: pytype_arg_from_python<python_type>
{
typedef Wrapper& result_type;
pytype_wrapper_ref_arg_from_python(PyObject*);
Wrapper& operator()(PyObject*) const;
private:
mutable Wrapper m_result;
};
//
// implementations
//
template <PyTypeObject* python_type>
inline pytype_arg_from_python<python_type>::pytype_arg_from_python(PyObject* x)
: m_src(x)
{
}
template <PyTypeObject* python_type>
inline bool pytype_arg_from_python<python_type>::convertible() const
{
return PyObject_IsInstance(m_src, (PyObject*)python_type);
}
template <class Wrapper, PyTypeObject* python_type>
pytype_wrapper_value_arg_from_python<Wrapper,python_type>::pytype_wrapper_value_arg_from_python(
PyObject* p)
: pytype_arg_from_python<python_type>(p)
{
}
template <class Wrapper, PyTypeObject* python_type>
Wrapper pytype_wrapper_value_arg_from_python<Wrapper,python_type>::operator()(
PyObject* x) const
{
return Wrapper(python::detail::borrowed_reference(x));
}
template <class Wrapper, PyTypeObject* python_type>
pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::pytype_wrapper_ref_arg_from_python(
PyObject* p)
: pytype_arg_from_python<python_type>(p)
, m_result(python::detail::borrowed_reference(p))
{
}
template <class Wrapper, PyTypeObject* python_type>
Wrapper& pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::operator()(
PyObject* x) const
{
return m_result;
}
}}} // namespace boost::python::converter
#endif // PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP

View File

@@ -0,0 +1,29 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef RAW_PYOBJECT_DWA2002628_HPP
# define RAW_PYOBJECT_DWA2002628_HPP
namespace boost { namespace python { namespace detail {
//
// Define some types which we can use to get around the vagaries of
// PyObject*. We will use these to initialize object instances, and
// keep them in namespace detail to make sure they stay out of the
// hands of users. That is much simpler than trying to grant
// friendship to all the appropriate parties.
//
// New references are checked for null
struct new_reference_t;
typedef new_reference_t* new_reference;
// Borrowed references are assumed to be non-null
struct borrowed_reference_t;
typedef borrowed_reference_t* borrowed_reference;
}}} // namespace boost::python::detail
#endif // RAW_PYOBJECT_DWA2002628_HPP

View File

@@ -0,0 +1,77 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef STRING_LITERAL_DWA2002629_HPP
# define STRING_LITERAL_DWA2002629_HPP
# include <cstddef>
# include <boost/type.hpp>
# include <boost/type_traits/array_traits.hpp>
# include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace detail {
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_string_literal
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
# if !defined(__MWERKS__) || __MWERKS__ > 0x2407
template <std::size_t n>
struct is_string_literal<char const[n]>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else
// CWPro7 has trouble with the array type deduction above
template <class T, std::size_t n>
struct is_string_literal<T[n]>
: is_same<T, char const>
{
};
# endif
# else
template <bool is_array = true>
struct string_literal_helper
{
typedef char (&yes_string_literal)[1];
typedef char (&no_string_literal)[2];
template <class T>
struct apply
{
typedef apply<T> self;
static T x;
static yes_string_literal check(char const*);
static no_string_literal check(char*);
static no_string_literal check(void const volatile*);
BOOST_STATIC_CONSTANT(
bool, value = sizeof(self::check(x)) == sizeof(yes_string_literal));
};
};
template <>
struct string_literal_helper<false>
{
template <class T>
struct apply
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
};
template <class T>
struct is_string_literal
: string_literal_helper<is_array<T>::value>::apply<T>
{
};
# endif
}}} // namespace boost::python::detail
#endif // STRING_LITERAL_DWA2002629_HPP

View File

@@ -0,0 +1,179 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef LIST_DWA2002627_HPP
# define LIST_DWA2002627_HPP
# include <boost/python/object.hpp>
# include <boost/python/converter/pytype_arg_from_python.hpp>
namespace boost { namespace python {
class list : public object
{
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
typedef object const& object_cref;
# else
typedef object object_cref;
# endif
public:
BOOST_PYTHON_DECL list(); // new list
explicit BOOST_PYTHON_DECL list(object_cref sequence); // new list initialized from sequence's items
template <class T>
explicit list(T const& sequence)
: object(list::call(object(sequence)))
{
}
BOOST_PYTHON_DECL void append(object_cref); // append object to end
template <class T>
void append(T const& x)
{
this->append(object(x));
}
BOOST_PYTHON_DECL long count(object_cref value) const; // return number of occurrences of value
template <class T>
long count(T const& value) const
{
return this->count(object(value));
}
BOOST_PYTHON_DECL void extend(object_cref sequence); // extend list by appending sequence elements
template <class T>
void extend(T const& x)
{
this->extend(object(x));
}
BOOST_PYTHON_DECL long index(object_cref value) const; // return index of first occurrence of value
template <class T>
long index(T const& x) const
{
return this->index(object(x));
}
BOOST_PYTHON_DECL void insert(int index, object_cref); // insert object before index
BOOST_PYTHON_DECL void insert(object const& index, object_cref);
template <class T>
void insert(int index, T const& x) // insert object before index
{
this->insert(index, object(x));
}
template <class T>
void insert(object const& index, T const& x) // insert object before index
{
this->insert(index, object(x));
}
BOOST_PYTHON_DECL object pop(); // remove and return item at index (default last)
BOOST_PYTHON_DECL object pop(long index);
BOOST_PYTHON_DECL object pop(object const& index);
BOOST_PYTHON_DECL void remove(object_cref value); // remove first occurrence of value
template <class T>
void remove(T const& value)
{
this->remove(object(value));
}
BOOST_PYTHON_DECL void reverse(); // reverse *IN PLACE*
BOOST_PYTHON_DECL void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
BOOST_PYTHON_DECL void sort(object_cref cmpfunc);
template <class T>
void sort(T const& value)
{
this->sort(object(value));
}
public: // implementation detail -- for internal use only
explicit list(detail::borrowed_reference);
explicit list(detail::new_reference);
private:
static BOOST_PYTHON_DECL detail::new_reference call(object const&);
};
//
// Converter Specializations
//
template <class T> struct arg_from_python;
template <>
struct arg_from_python<list>
: converter::pytype_wrapper_value_arg_from_python<list, &PyList_Type>
{
typedef converter::pytype_wrapper_value_arg_from_python<list, &PyList_Type> base;
typedef list result_type;
arg_from_python(PyObject* p) : base(p) {}
};
template <>
struct arg_from_python<list const&>
: arg_from_python<list>
{
arg_from_python(PyObject* p)
: arg_from_python<list>(p) {}
};
template <>
struct arg_from_python<list&>
: converter::pytype_wrapper_ref_arg_from_python<list, &PyList_Type>
{
typedef converter::pytype_wrapper_ref_arg_from_python<list, &PyList_Type> base;
typedef list result_type;
arg_from_python(PyObject* p)
: base(p) {}
};
namespace converter
{
template <class T> struct is_object_manager;
template <>
struct is_object_manager<list>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T> struct return_from_python;
template <>
struct return_from_python<list>
{
typedef list result_type;
result_type operator()(PyObject* x) const
{
return list(python::detail::new_reference(x));
}
};
}
//
// list implementation
//
inline list::list(detail::borrowed_reference p)
: object(p)
{}
inline list::list(detail::new_reference p)
: object(p)
{}
}} // namespace boost::python
#endif // LIST_DWA2002627_HPP

View File

@@ -76,7 +76,7 @@ inline module& module::setattr(const char* name, handle<> const& x)
inline module& module::add(PyTypeObject* x)
{
this->base::add(x);
this->base::add(handle<>(borrowed(x)));
return *this;
}

View File

@@ -30,14 +30,14 @@ struct attribute_policies : const_attribute_policies
template <class U>
inline object_attribute object_operators<U>::attr(char const* name)
{
object_cref x = *static_cast<U*>(this);
object_cref2 x = *static_cast<U*>(this);
return object_attribute(x, name);
}
template <class U>
inline const_object_attribute object_operators<U>::attr(char const* name) const
{
object_cref x = *static_cast<U const*>(this);
object_cref2 x = *static_cast<U const*>(this);
return const_object_attribute(x, name);
}

View File

@@ -11,6 +11,8 @@
# include <boost/python/call.hpp>
# include <boost/preprocessor/max.hpp>
# include <boost/python/slice_nil.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
# include <boost/python/refcount.hpp>
# include <boost/type.hpp>
namespace boost { namespace python {
@@ -68,35 +70,8 @@ namespace api
};
# endif
//
// object_handle -- get the handle to construct the object with,
// based on whether T is a proxy or not
//
template <bool = false>
struct object_handle
{
template <class T>
static handle<> get(T const& x)
{
return handle<>(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<T>(x).get())
)
);
}
};
template <>
struct object_handle<true>
{
template <class Policies>
static handle<> get(proxy<Policies> const& x)
{
return x.operator object().ptr();
}
};
template <bool is_proxy> struct object_initializer;
// A way to turn a conrete type T into a type dependent on U. This
// keeps conforming compilers from complaining about returning an
// incomplete T from a template member function (which must be
@@ -108,24 +83,24 @@ namespace api
};
class object;
typedef handle<> const& (object::*bool_type)() const;
typedef PyObject* (object::*bool_type)() const;
template <class U>
class object_operators
{
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
typedef object const& self_cref;
typedef object const& object_cref;
# else
typedef object self_cref;
typedef object object_cref;
# endif
// there appears to be a codegen bug here. We prevent the early
// destruction of a temporary in CWPro8 by binding a named
// object instead.
// there is a confirmed CWPro8 codegen bug here. We prevent the
// early destruction of a temporary by binding a named object
// instead.
# if __MWERKS__ != 0x3000
typedef object const& object_cref;
typedef object const& object_cref2;
# else
typedef object const object_cref;
typedef object const object_cref2;
# endif
public:
@@ -163,8 +138,8 @@ namespace api
// item access
//
const_object_item operator[](self_cref) const;
object_item operator[](self_cref);
const_object_item operator[](object_cref) const;
object_item operator[](object_cref);
template <class T>
const_object_item
@@ -190,14 +165,14 @@ namespace api
// slicing
//
const_object_slice slice(self_cref, self_cref) const;
object_slice slice(self_cref, self_cref);
const_object_slice slice(object_cref, object_cref) const;
object_slice slice(object_cref, object_cref);
const_object_slice slice(slice_nil, self_cref) const;
object_slice slice(slice_nil, self_cref);
const_object_slice slice(slice_nil, object_cref) const;
object_slice slice(slice_nil, object_cref);
const_object_slice slice(self_cref, slice_nil) const;
object_slice slice(self_cref, slice_nil);
const_object_slice slice(object_cref, slice_nil) const;
object_slice slice(object_cref, slice_nil);
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
template <class T, class V>
@@ -227,53 +202,69 @@ namespace api
, slice_bound<V>::type(end));
}
# endif
# if BOOST_MSVC == 1200
// For whatever reason, VC6 generates incorrect code unless we
// define this
object_operators& operator=(object_operators const&) { return *this; }
# endif
};
class object : public object_operators<object>
{
public:
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// copy constructor without NULL checking, for efficiency
// copy constructor without NULL checking, for efficiency. This
// confuses VC6/7 so object_initializer also handles this case.
object(object const&);
# endif
// explicit conversion from any C++ object to Python
template <class T>
explicit object(T const& x)
: m_ptr(object_handle<is_proxy<T>::value>::get(x))
: m_ptr(object_initializer<is_proxy<T>::value>::get(
x, detail::convertible<object const*>::check(&x)))
{
}
// capture this case explicitly to handle string
// literals. Otherwise, they get deduced as char[N]const& above
// and conversion fails at runtime.
explicit object(char const* x)
: m_ptr(object_handle<>::get(x))
{
}
// Throw error_already_set() if the handle is null.
explicit object(handle<> const&);
// Underlying object access
handle<> const& ptr() const;
// Underlying object access -- returns a borrowed reference
PyObject* ptr() const;
public: // implementation detail -- for internal use only
object(null_ok<detail::borrowed<PyObject> >*);
object(detail::borrowed<null_ok<PyObject> >*);
object(detail::borrowed<PyObject>*);
class new_pyobject_reference;
object(new_pyobject_reference*);
explicit object(detail::borrowed_reference);
explicit object(detail::new_reference);
private:
handle<> m_ptr;
PyObject* m_ptr;
};
//
// object_initializer -- get the handle to construct the object with,
// based on whether T is a proxy or derived from object
//
template <bool is_proxy = false>
struct object_initializer
{
static PyObject*
get(object const& x, detail::yes_convertible)
{
return python::incref(x.ptr());
}
template <class T>
static PyObject*
get(T const& x, detail::no_convertible)
{
return python::incref(converter::arg_to_python<T>(x).get());
}
};
template <>
struct object_initializer<true>
{
template <class Policies>
static PyObject*
get(proxy<Policies> const& x, detail::no_convertible)
{
return python::incref(x.operator object().ptr());
}
};
}
using api::object;
@@ -336,39 +327,32 @@ namespace converter
//
inline object::object(handle<> const& x)
: m_ptr(python::borrowed(x.get()))
: m_ptr(incref(expect_non_null(x.get())))
{}
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// copy constructor without NULL checking, for efficiency
inline object::object(object const& rhs)
: m_ptr(python::allow_null(python::borrowed(rhs.m_ptr.get())))
: m_ptr(incref(rhs.m_ptr))
{}
# endif
inline object::object(null_ok<detail::borrowed<PyObject> >* p)
: m_ptr(p)
inline object::object(detail::borrowed_reference p)
: m_ptr(incref((PyObject*)p))
{}
inline object::object(detail::borrowed<null_ok<PyObject> >* p)
: m_ptr(p)
inline object::object(detail::new_reference p)
: m_ptr(expect_non_null((PyObject*)p))
{}
inline object::object(detail::borrowed<PyObject>* p)
: m_ptr(p)
{}
inline object::object(object::new_pyobject_reference* p)
: m_ptr((PyObject*)p)
{}
inline handle<> const& object::ptr() const
inline PyObject* object::ptr() const
{
return m_ptr;
}
//
// Converter speciaization implementations
// Converter specialization implementations
//
inline arg_from_python<object>::arg_from_python(PyObject*)
{}
@@ -380,7 +364,7 @@ inline bool arg_from_python<object>::convertible() const
inline object arg_from_python<object>::operator()(PyObject* x) const
{
return object(python::borrowed(python::allow_null(x)));
return object(detail::borrowed_reference(x));
}
inline arg_from_python<object const&>::arg_from_python(PyObject*)
@@ -388,7 +372,7 @@ inline arg_from_python<object const&>::arg_from_python(PyObject*)
{}
inline arg_from_python<object&>::arg_from_python(PyObject* x)
: m_result(python::allow_null(python::borrowed(x)))
: m_result(detail::borrowed_reference(x))
{}
inline bool arg_from_python<object&>::convertible() const
@@ -406,12 +390,12 @@ namespace converter
inline object
return_from_python<object>::operator()(PyObject* x) const
{
return object((object::new_pyobject_reference*)x);
return object(python::detail::new_reference(x));
}
inline PyObject* get_managed_object(object const& x)
{
return x.ptr().get();
return x.ptr();
}
}

View File

@@ -29,17 +29,17 @@ struct item_policies : const_item_policies
//
template <class U>
inline object_item
object_operators<U>::operator[](self_cref key)
object_operators<U>::operator[](object_cref key)
{
object_cref x = *static_cast<U*>(this);
object_cref2 x = *static_cast<U*>(this);
return object_item(x, key);
}
template <class U>
inline const_object_item
object_operators<U>::operator[](self_cref key) const
object_operators<U>::operator[](object_cref key) const
{
object_cref x = *static_cast<U const*>(this);
object_cref2 x = *static_cast<U const*>(this);
return const_object_item(x, key);
}

View File

@@ -14,7 +14,7 @@ template <class U>
object object_operators<U>::operator()() const
{
object const& f = *static_cast<U const*>(this);
return call<object>(f.ptr().get());
return call<object>(f.ptr());
}
@@ -23,7 +23,7 @@ inline
object_operators<U>::operator bool_type() const
{
object const& x = *static_cast<U const*>(this);
return PyObject_IsTrue(x.ptr().get()) ? &object::ptr : 0;
return PyObject_IsTrue(x.ptr()) ? &object::ptr : 0;
}
template <class U>
@@ -31,7 +31,7 @@ inline bool
object_operators<U>::operator!() const
{
object const& x = *static_cast<U const*>(this);
return !PyObject_IsTrue(x.ptr().get());
return !PyObject_IsTrue(x.ptr());
}
# define BOOST_PYTHON_COMPARE_OP(op, opid) \
@@ -39,7 +39,7 @@ template <class L, class R> \
bool operator op(L const& l, R const& r) \
{ \
return PyObject_RichCompareBool( \
object(l).ptr().get(), object(r).ptr().get(), opid); \
object(l).ptr(), object(r).ptr(), opid); \
}
BOOST_PYTHON_COMPARE_OP(>, Py_GT)
BOOST_PYTHON_COMPARE_OP(>=, Py_GE)

View File

@@ -30,50 +30,50 @@ struct slice_policies : const_slice_policies
//
template <class U>
object_slice
object_operators<U>::slice(self_cref start, self_cref finish)
object_operators<U>::slice(object_cref start, object_cref finish)
{
object_cref x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(start.ptr(), finish.ptr()));
object_cref2 x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(borrowed(start.ptr()), borrowed(finish.ptr())));
}
template <class U>
const_object_slice
object_operators<U>::slice(self_cref start, self_cref finish) const
object_operators<U>::slice(object_cref start, object_cref finish) const
{
object_cref x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(start.ptr(), finish.ptr()));
object_cref2 x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(borrowed(start.ptr()), borrowed(finish.ptr())));
}
template <class U>
object_slice
object_operators<U>::slice(slice_nil, self_cref finish)
object_operators<U>::slice(slice_nil, object_cref finish)
{
object_cref x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(handle<>(), finish.ptr()));
object_cref2 x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr())));
}
template <class U>
const_object_slice
object_operators<U>::slice(slice_nil, self_cref finish) const
object_operators<U>::slice(slice_nil, object_cref finish) const
{
object_cref x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(handle<>(), finish.ptr()));
object_cref2 x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr())));
}
template <class U>
object_slice
object_operators<U>::slice(self_cref start, slice_nil)
object_operators<U>::slice(object_cref start, slice_nil)
{
object_cref x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(start.ptr(), handle<>()));
object_cref2 x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(borrowed(start.ptr()), allow_null((PyObject*)0)));
}
template <class U>
const_object_slice
object_operators<U>::slice(self_cref start, slice_nil) const
object_operators<U>::slice(object_cref start, slice_nil) const
{
object_cref x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(start.ptr(), handle<>()));
object_cref2 x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(borrowed(start.ptr()), allow_null((PyObject*)0)));
}
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
template <class U>

View File

@@ -11,6 +11,7 @@
# ifdef BOOST_PYTHON_V2
# include <boost/python/objects2.hpp>
# include <boost/python/list.hpp>
# else
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/detail/config.hpp>

View File

@@ -14,6 +14,8 @@
namespace boost { namespace python {
class list;
class BOOST_PYTHON_DECL objects_base
{
public:
@@ -97,67 +99,6 @@ class tuple : public tuple_base
}
};
class list;
struct BOOST_PYTHON_DECL list_proxy;
struct BOOST_PYTHON_DECL list_slice_proxy;
class BOOST_PYTHON_DECL list_base : public objects_base
{
protected:
typedef list_proxy proxy;
typedef list_slice_proxy slice_proxy;
public:
explicit list_base(handle<> p);
explicit list_base(std::size_t sz = 0);
static PyTypeObject* type_obj();
static bool accepts(handle<> p);
std::size_t size() const;
handle<> operator[](std::size_t pos) const;
proxy operator[](std::size_t pos);
handle<> get_item(std::size_t pos) const;
void set_item(std::size_t pos, const handle<>& );
// void set_item(std::size_t pos, const object& );
void insert(std::size_t index, const handle<>& item);
void push_back(const handle<>& item);
void append(const handle<>& item);
list slice(int low, int high) const;
slice_proxy slice(int low, int high);
void sort();
void reverse();
tuple as_tuple() const;
};
class list : public list_base
{
public:
explicit list(handle<> p) : list_base(p) {}
explicit list(std::size_t sz = 0) : list_base(sz) {}
template <class T>
void set_item(std::size_t pos, const T& x)
{ this->set_item(pos, make_ref(x)); }
template <class T>
void insert(std::size_t index, const T& x)
{ this->insert(index, make_ref(x)); }
template <class T>
void push_back(const T& item)
{ this->push_back(make_ref(item)); }
template <class T>
void append(const T& item)
{ this->append(make_ref(item)); }
void set_item(std::size_t pos, const handle<>& x) { list_base::set_item(pos, x); }
void insert(std::size_t index, const handle<>& item) { list_base::insert(index, item); }
void push_back(const handle<>& item) { list_base::push_back(item); }
void append(const handle<>& item) { list_base::append(item); }
};
class BOOST_PYTHON_DECL string
: public objects_base, public boost::multipliable2<string, unsigned int>
{
@@ -306,43 +247,6 @@ class dictionary : public dictionary_base
{ dictionary_base::erase(key); }
};
struct BOOST_PYTHON_DECL list_proxy
{
template <class T>
const handle<>& operator=(const T& rhs)
{ return (*this) = make_ref(rhs); }
const handle<>& operator=(const handle<>& rhs);
operator handle<>() const;
private:
friend class list_base;
list_proxy(const handle<>& list, std::size_t index);
// This is needed to work around the very strange MSVC error report that the
// return type of the built-in operator= differs from that of the ones
// defined above. Couldn't hurt to make these un-assignable anyway, though.
const handle<>& operator=(const list_proxy&); // Not actually implemented
private:
list m_list;
std::size_t m_index;
};
struct BOOST_PYTHON_DECL list_slice_proxy
{
const list& operator=(const list& rhs);
operator handle<>() const;
operator list() const;
std::size_t size() const;
handle<> operator[](std::size_t pos) const;
private:
friend class list_base;
list_slice_proxy(const handle<>& list, int low, int high);
private:
handle<> m_list;
int m_low, m_high;
};
}} // namespace boost::python
#endif // OBJECTS_DWA20020611_H

View File

@@ -73,10 +73,10 @@ inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::copy_ct
# define BOOST_PYTHON_PROXY_INPLACE(op) \
template <class Policies, class R> \
proxy<Policies> const& operator op(proxy<Policies> const& lhs, R const& other) \
proxy<Policies> const& operator op(proxy<Policies> const& lhs, R const& rhs) \
{ \
object old(lhs); \
return lhs = (old op other); \
return lhs = (old op rhs); \
}
BOOST_PYTHON_PROXY_INPLACE(+=)
BOOST_PYTHON_PROXY_INPLACE(-=)

105
src/list.cpp Normal file
View File

@@ -0,0 +1,105 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/list.hpp>
namespace boost { namespace python {
BOOST_PYTHON_DECL detail::new_reference list::call(object const& arg)
{
return (detail::new_reference)PyObject_CallFunction(
(PyObject*)&PyList_Type, "(O)",
arg.ptr());
}
BOOST_PYTHON_DECL list::list()
: object(detail::new_reference(PyList_New(0)))
{}
BOOST_PYTHON_DECL list::list(object_cref sequence)
: object(list::call(sequence))
{}
BOOST_PYTHON_DECL void list::append(object_cref x)
{
if (PyList_Append(this->ptr(), x.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL long list::count(object_cref value) const
{
object result_obj(this->attr("count")(value));
long result = PyInt_AsLong(result_obj.ptr());
if (result == -1)
throw_error_already_set();
return result;
}
BOOST_PYTHON_DECL void list::extend(object_cref sequence)
{
this->attr("extend")(sequence);
}
BOOST_PYTHON_DECL long list::index(object_cref value) const
{
object result_obj(this->attr("index")(value));
long result = PyInt_AsLong(result_obj.ptr());
if (result == -1)
throw_error_already_set();
return result;
}
BOOST_PYTHON_DECL void list::insert(int index, object_cref item)
{
if (PyList_Insert(this->ptr(), index, item.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void list::insert(object const& index, object_cref x)
{
long index_ = PyInt_AsLong(index.ptr());
if (index_ == -1 && PyErr_Occurred())
throw_error_already_set();
this->insert(index_, x);
}
BOOST_PYTHON_DECL object list::pop()
{
return this->attr("pop")();
}
BOOST_PYTHON_DECL object list::pop(long index)
{
return this->pop(object(index));
}
BOOST_PYTHON_DECL object list::pop(object const& index)
{
return this->attr("pop")(index);
}
BOOST_PYTHON_DECL void list::remove(object_cref value)
{
this->attr("remove")(value);
}
BOOST_PYTHON_DECL void list::reverse()
{
if (PyList_Reverse(this->ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void list::sort()
{
if (PyList_Sort(this->ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void list::sort(object_cref cmpfunc)
{
this->attr("sort")(cmpfunc);
}
}} // namespace boost::python

View File

@@ -5,7 +5,7 @@
// to its suitability for any purpose.
#include <boost/python/converter/registry.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/objects2.hpp>
#include <boost/python/detail/map_entry.hpp>
#include <boost/detail/binary_search.hpp>
#include <boost/python/self.hpp>
@@ -210,7 +210,7 @@ namespace objects
type_handle query(class_id id) const;
void set(class_id, type_handle class_object);
private:
typedef detail::map_entry<class_id,type_handle> entry;
typedef python::detail::map_entry<class_id,type_handle> entry;
std::vector<entry> m_impl;
};

View File

@@ -7,7 +7,7 @@
#include <boost/python/object/function.hpp>
#include <numeric>
#include <boost/python/errors.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/objects2.hpp>
#include <algorithm>
#include <cstring>

View File

@@ -5,6 +5,7 @@
// to its suitability for any purpose.
#include <boost/python/object_operators.hpp>
#include <boost/python/detail/raw_pyobject.hpp>
namespace boost { namespace python { namespace api {
@@ -12,8 +13,9 @@ namespace boost { namespace python { namespace api {
BOOST_PYTHON_DECL object operator op(object const& l, object const& r) \
{ \
return object( \
(object::new_pyobject_reference*) \
PyNumber_##name(l.ptr().get(), r.ptr().get())); \
detail::new_reference( \
PyNumber_##name(l.ptr(), r.ptr())) \
); \
}
BOOST_PYTHON_BINARY_OPERATOR(+, Add)
@@ -32,8 +34,8 @@ BOOST_PYTHON_BINARY_OPERATOR(|, Or)
BOOST_PYTHON_DECL object& operator op##=(object& l, object const& r) \
{ \
return l = object( \
(object::new_pyobject_reference*) \
PyNumber_InPlace##name(l.ptr().get(), r.ptr().get())); \
(detail::new_reference) \
PyNumber_InPlace##name(l.ptr(), r.ptr())); \
}
BOOST_PYTHON_INPLACE_OPERATOR(+, Add)

View File

@@ -12,33 +12,33 @@ namespace boost { namespace python { namespace api {
BOOST_PYTHON_DECL object getattr(object const& target, object const& key)
{
return object((object::new_pyobject_reference*)PyObject_GetAttr(target.ptr().get(), key.ptr().get()));
return object(detail::new_reference(PyObject_GetAttr(target.ptr(), key.ptr())));
}
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value)
{
if (PyObject_SetAttr(target.ptr().get(), key.ptr().get(), value.ptr().get()) == -1)
if (PyObject_SetAttr(target.ptr(), key.ptr(), value.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void delattr(object const& target, object const& key)
{
if (PyObject_DelAttr(target.ptr().get(), key.ptr().get()) == -1)
if (PyObject_DelAttr(target.ptr(), key.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL object getattr(object const& target, char const* key)
{
return object(
(object::new_pyobject_reference*)
PyObject_GetAttrString(target.ptr().get(), const_cast<char*>(key))
);
detail::new_reference(
PyObject_GetAttrString(target.ptr(), const_cast<char*>(key))
));
}
BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value)
{
if (PyObject_SetAttrString(
target.ptr().get(), const_cast<char*>(key), value.ptr().get()) == -1
target.ptr(), const_cast<char*>(key), value.ptr()) == -1
)
{
throw_error_already_set();
@@ -48,7 +48,7 @@ BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object con
BOOST_PYTHON_DECL void delattr(object const& target, char const* key)
{
if (PyObject_DelAttrString(
target.ptr().get(), const_cast<char*>(key)) == -1
target.ptr(), const_cast<char*>(key)) == -1
)
{
throw_error_already_set();
@@ -57,18 +57,19 @@ BOOST_PYTHON_DECL void delattr(object const& target, char const* key)
BOOST_PYTHON_DECL object getitem(object const& target, object const& key)
{
return object((object::new_pyobject_reference*)PyObject_GetItem(target.ptr().get(), key.ptr().get()));
return object(detail::new_reference(
PyObject_GetItem(target.ptr(), key.ptr())));
}
BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value)
{
if (PyObject_SetItem(target.ptr().get(), key.ptr().get(), value.ptr().get()) == -1)
if (PyObject_SetItem(target.ptr(), key.ptr(), value.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void delitem(object const& target, object const& key)
{
if (PyObject_DelItem(target.ptr().get(), key.ptr().get()) == -1)
if (PyObject_DelItem(target.ptr(), key.ptr()) == -1)
throw_error_already_set();
}
@@ -141,14 +142,14 @@ namespace // slicing code copied directly out of the Python implementation
BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end)
{
return object(
(object::new_pyobject_reference*)
apply_slice(target.ptr().get(), begin.get(), end.get()));
detail::new_reference(
apply_slice(target.ptr(), begin.get(), end.get())));
}
BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value)
{
if (assign_slice(
target.ptr().get(), begin.get(), end.get(), value.ptr().get()) == -1
target.ptr(), begin.get(), end.get(), value.ptr()) == -1
)
{
throw_error_already_set();
@@ -158,7 +159,7 @@ BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, han
BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end)
{
if (assign_slice(
target.ptr().get(), begin.get(), end.get(), 0) == -1
target.ptr(), begin.get(), end.get(), 0) == -1
)
{
throw_error_already_set();

View File

@@ -276,151 +276,4 @@ tuple operator+(const tuple& x, const tuple& y)
return result;
}
list_base::list_base(handle<> p)
: objects_base(p)
{
assert(accepts(p));
if (!accepts(p))
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw_error_already_set();
}
}
list_base::list_base(std::size_t sz)
: objects_base(handle<>(PyList_New(sz)))
{
}
PyTypeObject* list_base::type_obj()
{
return &PyList_Type;
}
bool list_base::accepts(handle<> p)
{
return PyList_Check(p.get());
}
std::size_t list_base::size() const
{
return PyList_Size(get());
}
handle<> list_base::operator[](std::size_t pos) const
{
return handle<>(borrowed(PyList_GetItem(get(), pos)));
}
list_proxy list_base::operator[](std::size_t pos)
{
return proxy(reference(), pos);
}
void list_base::insert(std::size_t index, const handle<>& item)
{
if (PyList_Insert(get(), index, item.get()) == -1)
throw_error_already_set();
}
void list_base::push_back(const handle<>& item)
{
if (PyList_Append(get(), item.get()) == -1)
throw_error_already_set();
}
void list_base::append(const handle<>& item)
{
this->push_back(item);
}
list list_base::slice(int low, int high) const
{
return list(handle<>(PyList_GetSlice(get(), low, high)));
}
list_slice_proxy list_base::slice(int low, int high)
{
return list_slice_proxy(reference(), low, high);
}
void list_base::sort()
{
if (PyList_Sort(get()) == -1)
throw_error_already_set();
}
void list_base::reverse()
{
if (PyList_Reverse(get()) == -1)
throw_error_already_set();
}
tuple list_base::as_tuple() const
{
return tuple(handle<>(PyList_AsTuple(get())));
}
const handle<>& list_proxy::operator=(const handle<>& rhs)
{
m_list.set_item(m_index, rhs);
return rhs;
}
list_proxy::operator handle<>() const
{
return handle<>(borrowed(PyList_GetItem(m_list.get(), m_index)));
}
handle<> list_base::get_item(std::size_t pos) const
{
return handle<>(borrowed(PyList_GetItem(this->get(), pos)));
}
void list_base::set_item(std::size_t pos, const handle<>& rhs)
{
int result = PyList_SetItem(this->get(), pos, rhs.get());
if (result == -1)
throw_error_already_set();
Py_INCREF(rhs.get());
}
list_proxy::list_proxy(const handle<>& list, std::size_t index)
: m_list(list), m_index(index)
{
}
const list& list_slice_proxy::operator=(const list& rhs)
{
if (PyList_SetSlice(m_list.get(), m_low, m_high, rhs.get()) == -1)
throw_error_already_set();
return rhs;
}
list_slice_proxy::operator handle<>() const
{
return handle<>(PyList_GetSlice(m_list.get(), m_low, m_high));
}
list_slice_proxy::operator list() const
{
return list(this->operator handle<>());
}
std::size_t list_slice_proxy::size() const
{
return this->operator list().size();
}
handle<> list_slice_proxy::operator[](std::size_t pos) const
{
return this->operator list()[pos].operator handle<>();
}
list_slice_proxy::list_slice_proxy(const handle<>& list, int low, int high)
: m_list(list), m_low(low), m_high(high)
{
}
}} // namespace boost::python

View File

@@ -62,6 +62,7 @@ bpl-test test_pointer_adoption ;
bpl-test operators ;
bpl-test callbacks ;
bpl-test object ;
bpl-test list ;
bpl-test virtual_functions ;
bpl-test back_reference ;
bpl-test implicit ;
@@ -88,6 +89,7 @@ run bases.cpp ;
run if_else.cpp ;
run pointee.cpp ;
run result.cpp ;
compile string_literal.cpp ;
compile borrowed.cpp : $(PYTHON_PROPERTIES) ;
compile object_manager.cpp : $(PYTHON_PROPERTIES) ;

131
test/list.cpp Normal file
View File

@@ -0,0 +1,131 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/list.hpp>
#include <boost/python/make_function.hpp>
#include <boost/lexical_cast.hpp>
#include "test_class.hpp"
using namespace boost::python;
object new_list()
{
return list();
}
list listify(object x)
{
return list(x);
}
object listify_string(char const* s)
{
return list(s);
}
std::string x_rep(test_class<> const& x)
{
return "X(" + boost::lexical_cast<std::string>(x.value()) + ")";
}
object apply_object_list(object f, list x)
{
return f(x);
}
void append_object(list& x, object y)
{
x.append(y);
}
void append_list(list& x, list const& y)
{
x.append(y);
}
typedef test_class<> X;
int notcmp(object const& x, object const& y)
{
return y < x ? -1 : y > x ? 1 : 0;
}
void exercise(list x, object y, object print)
{
x.append(y);
x.append(5);
x.append(X(3));
print("after append:");
print(x);
print("number of", y, "instances:", x.count(y));
print("number of 5s:", x.count(5));
x.extend("xyz");
print("after extend:");
print(x);
print("index of", y, "is:", x.index(y));
print("index of 'l' is:", x.index("l"));
x.insert(4, 666);
print("after inserting 666:");
print(x);
print("inserting with object as index:");
x.insert(x[x.index(5)], "---");
print(x);
print("popping...");
x.pop();
print(x);
x.pop(x[x.index(5)]);
print(x);
x.pop(x.index(5));
print(x);
print("removing", y);
x.remove(y);
print(x);
print("removing", 666);
x.remove(666);
print(x);
print("reversing...");
x.reverse();
print(x);
print("sorted:");
x.pop(2); // make sorting predictable
x.sort();
print(x);
print("reverse sorted:");
x.sort(handle<>(make_function(notcmp)));
print(x);
}
BOOST_PYTHON_MODULE_INIT(list_ext)
{
module("list_ext")
.def("new_list", new_list)
.def("listify", listify)
.def("listify_string", listify_string)
.def("apply_object_list", apply_object_list)
.def("append_object", append_object)
.def("append_list", append_list)
.def("exercise", exercise)
.add(class_<X>("X")
.def_init(args<int>())
.def( "__repr__", x_rep))
;
}