mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 18:52:26 +00:00
Moved to new "suite" directory
[SVN r19561]
This commit is contained in:
53
include/boost/python/suite/indexing/container_utils.hpp
Normal file
53
include/boost/python/suite/indexing/container_utils.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
// (C) Copyright Joel de Guzman 2003.
|
||||
// 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 PY_CONTAINER_UTILS_JDG20038_HPP
|
||||
# define PY_CONTAINER_UTILS_JDG20038_HPP
|
||||
|
||||
# include <boost/python/object.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/extract.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace container_utils {
|
||||
|
||||
template <typename Container>
|
||||
void
|
||||
extend_container(Container& container, object l)
|
||||
{
|
||||
typedef typename Container::value_type element_t;
|
||||
|
||||
// l must be a list or some container
|
||||
|
||||
for (int i = 0; i < l.attr("__len__")(); i++)
|
||||
{
|
||||
object elem(l[i]);
|
||||
extract<element_t const&> x(elem);
|
||||
// try if elem is an exact element_t type
|
||||
if (x.check())
|
||||
{
|
||||
container.push_back(x());
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to convert elem to element_t type
|
||||
extract<element_t> x(elem);
|
||||
if (x.check())
|
||||
{
|
||||
container.push_back(x());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Incompatible Element Type");
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::container_utils
|
||||
|
||||
#endif
|
||||
317
include/boost/python/suite/indexing/indexing_suite.hpp
Normal file
317
include/boost/python/suite/indexing/indexing_suite.hpp
Normal file
@@ -0,0 +1,317 @@
|
||||
// (C) Copyright Joel de Guzman 2003.
|
||||
// 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 INDEXING_SUITE_JDG20036_HPP
|
||||
# define INDEXING_SUITE_JDG20036_HPP
|
||||
|
||||
# include <boost/python/class.hpp>
|
||||
# include <boost/python/register_ptr_to_python.hpp>
|
||||
# include <boost/python/suite/indexing/detail/indexing_suite_detail.hpp>
|
||||
# include <boost/python/suite/indexing/container_utils.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/iterator.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
# include <boost/mpl/not.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// indexing_suite class. This class is the protocol class for
|
||||
// the management of C++ containers intended to be integrated
|
||||
// to Python. The objective is make a C++ container look and
|
||||
// feel and behave exactly as we'd expect a Python container.
|
||||
// By default indexed elements are returned by proxy. This can be
|
||||
// disabled by supplying *true* in the NoProxy template parameter.
|
||||
//
|
||||
// Derived classes provide the hooks needed by the indexing_suite
|
||||
// to do its job:
|
||||
//
|
||||
// static element_type&
|
||||
// get_item(Container& container, index_type i);
|
||||
//
|
||||
// static object
|
||||
// get_slice(Container& container, index_type from, index_type to);
|
||||
//
|
||||
// static void
|
||||
// set_item(Container& container, index_type i, element_type const& v);
|
||||
//
|
||||
// static void
|
||||
// set_slice(
|
||||
// Container& container, index_type from,
|
||||
// index_type to, element_type const& v
|
||||
// );
|
||||
//
|
||||
// template <class Iter>
|
||||
// static void
|
||||
// set_slice(Container& container, index_type from,
|
||||
// index_type to, Iter first, Iter last
|
||||
// );
|
||||
//
|
||||
// static void
|
||||
// delete_item(Container& container, index_type i);
|
||||
//
|
||||
// static void
|
||||
// delete_slice(Container& container, index_type from, index_type to);
|
||||
//
|
||||
// static size_t
|
||||
// size(Container& container);
|
||||
//
|
||||
// template <class T>
|
||||
// static bool
|
||||
// contains(Container& container, T const& val);
|
||||
//
|
||||
// static index_type
|
||||
// convert_index(Container& container, PyObject* i);
|
||||
//
|
||||
// static index_type
|
||||
// adjust_index(index_type current, index_type from,
|
||||
// index_type to, size_type len
|
||||
// );
|
||||
//
|
||||
// Most of these policies are self explanatory. convert_index and
|
||||
// adjust_index, however, deserves some explanation.
|
||||
//
|
||||
// convert_index converts an Python index into a C++ index that the
|
||||
// container can handle. For instance, negative indexes in Python, by
|
||||
// convention, indexes from the right (e.g. C[-1] indexes the rightmost
|
||||
// element in C). convert_index should handle the necessary conversion
|
||||
// for the C++ container (e.g. convert -1 to C.size()-1). convert_index
|
||||
// should also be able to convert the type of the index (A dynamic Python
|
||||
// type) to the actual type that the C++ container expects.
|
||||
//
|
||||
// When a container expands or contracts, held indexes to its elements
|
||||
// must be adjusted to follow the movement of data. For instance, if
|
||||
// we erase 3 elements, starting from index 0 from a 5 element vector,
|
||||
// what used to be at index 4 will now be at index 1:
|
||||
//
|
||||
// [a][b][c][d][e] ---> [d][e]
|
||||
// ^ ^
|
||||
// 4 1
|
||||
//
|
||||
// adjust_index takes care of the adjustment. Given a current index,
|
||||
// the function should return the adjusted index when data in the
|
||||
// container at index from..to is replaced by *len* elements.
|
||||
//
|
||||
|
||||
template <
|
||||
class Container
|
||||
, class DerivedPolicies
|
||||
, bool NoProxy = false
|
||||
, bool NoSlice = false
|
||||
, class Element = typename Container::value_type
|
||||
, class Key = typename Container::value_type
|
||||
, class Index = typename Container::size_type
|
||||
>
|
||||
class indexing_suite
|
||||
: public def_arg<
|
||||
indexing_suite<
|
||||
Container
|
||||
, DerivedPolicies
|
||||
, NoProxy
|
||||
, NoSlice
|
||||
, Element
|
||||
, Key
|
||||
, Index
|
||||
> >
|
||||
{
|
||||
private:
|
||||
|
||||
typedef mpl::or_<
|
||||
mpl::bool_<NoProxy>
|
||||
, mpl::not_<is_class<Element> > >
|
||||
no_proxy;
|
||||
|
||||
typedef detail::container_element<Container, Index, DerivedPolicies>
|
||||
container_element_t;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
no_proxy
|
||||
, iterator<Container>
|
||||
, iterator<Container, return_internal_reference<> > >::type
|
||||
def_iterator;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
no_proxy
|
||||
, detail::no_proxy_helper<
|
||||
Container
|
||||
, DerivedPolicies
|
||||
, container_element_t
|
||||
, Index>
|
||||
, detail::proxy_helper<
|
||||
Container
|
||||
, DerivedPolicies
|
||||
, container_element_t
|
||||
, Index> >::type
|
||||
proxy_handler;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
mpl::bool_<NoSlice>
|
||||
, detail::slice_helper<
|
||||
Container
|
||||
, DerivedPolicies
|
||||
, proxy_handler
|
||||
, Element
|
||||
, Index>
|
||||
, detail::slice_helper<
|
||||
Container
|
||||
, DerivedPolicies
|
||||
, proxy_handler
|
||||
, Element
|
||||
, Index> >::type
|
||||
slice_handler;
|
||||
|
||||
public:
|
||||
|
||||
template <class Class>
|
||||
void visit(Class& cl) const
|
||||
{
|
||||
// Hook into the class_ generic visitation .def function
|
||||
proxy_handler::register_container_element();
|
||||
|
||||
cl
|
||||
.def("__len__", base_size)
|
||||
.def("__setitem__", &base_set_item)
|
||||
.def("__delitem__", &base_delete_item)
|
||||
.def("__getitem__", &base_get_item)
|
||||
.def("__contains__", &base_contains)
|
||||
.def("__iter__", def_iterator())
|
||||
|
||||
.def("append", &base_append)
|
||||
.def("extend", &base_extend)
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static object
|
||||
base_get_item(back_reference<Container&> container, PyObject* i)
|
||||
{
|
||||
if (PySlice_Check(i))
|
||||
return slice_handler::base_get_slice(
|
||||
container.get(), reinterpret_cast<PySliceObject*>(i));
|
||||
|
||||
return proxy_handler::base_get_item_(container, i);
|
||||
}
|
||||
|
||||
static void
|
||||
base_set_item(Container& container, PyObject* i, PyObject* v)
|
||||
{
|
||||
if (PySlice_Check(i))
|
||||
{
|
||||
slice_handler::base_set_slice(container,
|
||||
reinterpret_cast<PySliceObject*>(i), v);
|
||||
}
|
||||
else
|
||||
{
|
||||
extract<Element&> elem(v);
|
||||
// try if elem is an exact Element
|
||||
if (elem.check())
|
||||
{
|
||||
DerivedPolicies::
|
||||
set_item(container,
|
||||
DerivedPolicies::
|
||||
convert_index(container, i), elem());
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to convert elem to Element
|
||||
extract<Element> elem(v);
|
||||
if (elem.check())
|
||||
{
|
||||
DerivedPolicies::
|
||||
set_item(container,
|
||||
DerivedPolicies::
|
||||
convert_index(container, i), elem());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid assignment");
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
base_delete_item(Container& container, PyObject* i)
|
||||
{
|
||||
if (PySlice_Check(i))
|
||||
{
|
||||
slice_handler::base_delete_slice(
|
||||
container, reinterpret_cast<PySliceObject*>(i));
|
||||
return;
|
||||
}
|
||||
|
||||
Index index = DerivedPolicies::convert_index(container, i);
|
||||
proxy_handler::base_erase_indexes(container, index, index+1);
|
||||
DerivedPolicies::delete_item(container, index);
|
||||
}
|
||||
|
||||
static size_t
|
||||
base_size(Container& container)
|
||||
{
|
||||
return DerivedPolicies::size(container);
|
||||
}
|
||||
|
||||
static bool
|
||||
base_contains(Container& container, PyObject* key)
|
||||
{
|
||||
extract<Key const&> x(key);
|
||||
// try if key is an exact Key type
|
||||
if (x.check())
|
||||
{
|
||||
return DerivedPolicies::contains(container, x());
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to convert key to Key type
|
||||
extract<Key> x(key);
|
||||
if (x.check())
|
||||
return DerivedPolicies::contains(container, x());
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
base_append(Container& container, PyObject* v)
|
||||
{
|
||||
extract<Element&> elem(v);
|
||||
// try if elem is an exact Element
|
||||
if (elem.check())
|
||||
{
|
||||
DerivedPolicies::append(container, elem());
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to convert elem to Element
|
||||
extract<Element> elem(v);
|
||||
if (elem.check())
|
||||
{
|
||||
DerivedPolicies::append(container, elem());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Attempting to append an invalid type");
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
base_extend(Container& container, PyObject* v)
|
||||
{
|
||||
std::vector<Element> temp;
|
||||
handle<> l_(borrowed(v));
|
||||
object l(l_);
|
||||
container_utils::extend_container(temp, l);
|
||||
DerivedPolicies::extend(container, temp.begin(), temp.end());
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // INDEXING_SUITE_JDG20036_HPP
|
||||
175
include/boost/python/suite/indexing/vector_indexing_suite.hpp
Normal file
175
include/boost/python/suite/indexing/vector_indexing_suite.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
// (C) Copyright Joel de Guzman 2003.
|
||||
// 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 VECTOR_INDEXING_SUITE_JDG20036_HPP
|
||||
# define VECTOR_INDEXING_SUITE_JDG20036_HPP
|
||||
|
||||
# include <boost/python/suite/indexing/indexing_suite.hpp>
|
||||
# include <boost/python/iterator.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// Forward declaration
|
||||
template <class Container, bool NoProxy, class DerivedPolicies>
|
||||
class vector_indexing_suite;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Container, bool NoProxy>
|
||||
class final
|
||||
: public vector_indexing_suite<Container,
|
||||
NoProxy, final<Container, NoProxy> > {};
|
||||
}
|
||||
|
||||
// The vector_indexing_suite class is a predefined indexing_suite derived
|
||||
// class for wrapping std::vector (and std::vector like) classes. It provides
|
||||
// all the policies required by the indexing_suite (see indexing_suite).
|
||||
// Example usage:
|
||||
//
|
||||
// class X {...};
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// class_<std::vector<X> >("XVec")
|
||||
// .def(vector_indexing_suite<std::vector<X> >())
|
||||
// ;
|
||||
//
|
||||
// By default indexed elements are returned by proxy. This can be
|
||||
// disabled by supplying *true* in the NoProxy template parameter.
|
||||
//
|
||||
template <
|
||||
class Container,
|
||||
bool NoProxy = false,
|
||||
class DerivedPolicies = detail::final<Container, NoProxy> >
|
||||
class vector_indexing_suite
|
||||
: public indexing_suite<Container, DerivedPolicies, NoProxy>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename Container::value_type element_type;
|
||||
typedef typename Container::value_type key_type;
|
||||
typedef typename Container::size_type index_type;
|
||||
typedef typename Container::size_type size_type;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
|
||||
static element_type&
|
||||
get_item(Container& container, index_type i)
|
||||
{
|
||||
return container[i];
|
||||
}
|
||||
|
||||
static object
|
||||
get_slice(Container& container, index_type from, index_type to)
|
||||
{
|
||||
return object(Container(container.begin()+from, container.begin()+to));
|
||||
}
|
||||
|
||||
static void
|
||||
set_item(Container& container, index_type i, element_type const& v)
|
||||
{
|
||||
container[i] = v;
|
||||
}
|
||||
|
||||
static void
|
||||
set_slice(Container& container, index_type from,
|
||||
index_type to, element_type const& v)
|
||||
{
|
||||
container.erase(container.begin()+from, container.begin()+to);
|
||||
container.insert(container.begin()+from, v);
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
static void
|
||||
set_slice(Container& container, index_type from,
|
||||
index_type to, Iter first, Iter last)
|
||||
{
|
||||
container.erase(container.begin()+from, container.begin()+to);
|
||||
container.insert(container.begin()+from, first, last);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_item(Container& container, index_type i)
|
||||
{
|
||||
container.erase(container.begin()+i);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_slice(Container& container, index_type from, index_type to)
|
||||
{
|
||||
container.erase(container.begin()+from, container.begin()+to);
|
||||
}
|
||||
|
||||
static size_t
|
||||
size(Container& container)
|
||||
{
|
||||
return container.size();
|
||||
}
|
||||
|
||||
static bool
|
||||
contains(Container& container, key_type const& key)
|
||||
{
|
||||
return std::find(container.begin(), container.end(), key)
|
||||
!= container.end();
|
||||
}
|
||||
|
||||
static index_type
|
||||
get_min_index(Container& container)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static index_type
|
||||
get_max_index(Container& container)
|
||||
{
|
||||
return container.size();
|
||||
}
|
||||
|
||||
static index_type
|
||||
convert_index(Container& container, PyObject* i_)
|
||||
{
|
||||
extract<long> i(i_);
|
||||
if (i.check())
|
||||
{
|
||||
long index = i();
|
||||
if (index < 0)
|
||||
index += DerivedPolicies::size(container);
|
||||
if (index >= long(container.size()) || index < 0)
|
||||
{
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
throw_error_already_set();
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid index type");
|
||||
throw_error_already_set();
|
||||
return index_type();
|
||||
}
|
||||
|
||||
static index_type
|
||||
adjust_index(index_type current, index_type from,
|
||||
index_type to, size_type len)
|
||||
{
|
||||
return current - (difference_type(to) - from - len);
|
||||
}
|
||||
|
||||
static void
|
||||
append(Container& container, element_type const& v)
|
||||
{
|
||||
container.push_back(v);
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
static void
|
||||
extend(Container& container, Iter first, Iter last)
|
||||
{
|
||||
container.insert(container.end(), first, last);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // VECTOR_INDEXING_SUITE_JDG20036_HPP
|
||||
Reference in New Issue
Block a user