1 #ifndef SCITBX_BOOST_PYTHON_CONTAINER_CONVERSIONS_H
2 #define SCITBX_BOOST_PYTHON_CONTAINER_CONVERSIONS_H
4 #include <boost/python/list.hpp>
5 #include <boost/python/tuple.hpp>
6 #include <boost/python/extract.hpp>
7 #include <boost/python/to_python_converter.hpp>
9 namespace scitbx {
namespace boost_python {
namespace container_conversions {
11 template <
typename ContainerType>
14 static PyObject*
convert(ContainerType
const& a)
16 boost::python::list result;
17 typedef typename ContainerType::const_iterator const_iter;
18 for(const_iter p=a.begin();p!=a.end();p++) {
19 result.append(boost::python::object(*p));
21 return boost::python::incref(boost::python::tuple(result).ptr());
24 static const PyTypeObject*
get_pytype() {
return &PyTuple_Type; }
31 template <
typename ContainerType>
32 static bool check_size(boost::type<ContainerType>, std::size_t )
37 template <
typename ContainerType>
38 static void assert_size(boost::type<ContainerType>, std::size_t ) {}
40 template <
typename ContainerType>
41 static void reserve(ContainerType& a, std::size_t sz) {}
48 template <
typename ContainerType>
49 static bool check_size(boost::type<ContainerType>, std::size_t sz)
51 return ContainerType::size() == sz;
54 template <
typename ContainerType>
55 static void assert_size(boost::type<ContainerType>, std::size_t sz)
57 if (!
check_size(boost::type<ContainerType>(), sz)) {
58 PyErr_SetString(PyExc_RuntimeError,
59 "Insufficient elements for fixed-size array.");
60 boost::python::throw_error_already_set();
64 template <
typename ContainerType>
65 static void reserve(ContainerType& , std::size_t sz)
67 if (sz > ContainerType::size()) {
68 PyErr_SetString(PyExc_RuntimeError,
69 "Too many elements for fixed-size array.");
70 boost::python::throw_error_already_set();
74 template <
typename ContainerType,
typename ValueType>
75 static void set_value(ContainerType& a, std::size_t i, ValueType
const& v)
84 template <
typename ContainerType>
85 static void reserve(ContainerType& a, std::size_t sz)
90 template <
typename ContainerType,
typename ValueType>
100 assert(a.size() == i);
107 template <
typename ContainerType>
108 static bool check_size(boost::type<ContainerType>, std::size_t sz)
110 return ContainerType::max_size() >= sz;
116 template <
typename ContainerType,
typename ValueType>
118 set_value(ContainerType& a, std::size_t , ValueType
const& v)
126 template <
typename ContainerType,
typename ValueType>
128 set_value(ContainerType& a, std::size_t , ValueType
const& v)
134 template <
typename ContainerType,
typename ConversionPolicy>
141 boost::python::converter::registry::push_back(
144 boost::python::type_id<ContainerType>());
149 if (!( PyList_Check(obj_ptr)
150 || PyTuple_Check(obj_ptr)
151 || PyIter_Check(obj_ptr)
152 || PyRange_Check(obj_ptr)
153 || ( !PyUnicode_Check(obj_ptr)
154 && ( Py_TYPE(obj_ptr) == 0
155 || Py_TYPE(Py_TYPE(obj_ptr)) == 0
156 || Py_TYPE(Py_TYPE(obj_ptr))->tp_name == 0
158 Py_TYPE(Py_TYPE(obj_ptr))->tp_name,
159 "Boost.Python.class") != 0)
160 && PyObject_HasAttrString(obj_ptr,
"__len__")
161 && PyObject_HasAttrString(obj_ptr,
"__getitem__"))))
return 0;
162 boost::python::handle<> obj_iter(
163 boost::python::allow_null(PyObject_GetIter(obj_ptr)));
164 if (!obj_iter.get()) {
168 if (ConversionPolicy::check_convertibility_per_element()) {
169 int obj_size = PyObject_Length(obj_ptr);
174 if (!ConversionPolicy::check_size(
175 boost::type<ContainerType>(), obj_size))
return 0;
176 bool is_range = PyRange_Check(obj_ptr);
179 if (!is_range) assert(i == (std::size_t)obj_size);
188 boost::python::handle<>& obj_iter,
193 boost::python::handle<> py_elem_hdl(
194 boost::python::allow_null(PyIter_Next(obj_iter.get())));
195 if (PyErr_Occurred()) {
199 if (!py_elem_hdl.get())
break;
200 boost::python::object py_elem_obj(py_elem_hdl);
201 boost::python::extract<container_element_type>
202 elem_proxy(py_elem_obj);
203 if (!elem_proxy.check())
return false;
211 boost::python::converter::rvalue_from_python_stage1_data* data)
213 boost::python::handle<> obj_iter(PyObject_GetIter(obj_ptr));
215 (boost::python::converter::rvalue_from_python_storage<ContainerType>*)
216 data)->storage.bytes;
217 new (storage) ContainerType();
218 data->convertible = storage;
219 ContainerType& result = *((ContainerType*)storage);
222 boost::python::handle<> py_elem_hdl(
223 boost::python::allow_null(PyIter_Next(obj_iter.get())));
224 if (PyErr_Occurred()) boost::python::throw_error_already_set();
225 if (!py_elem_hdl.get())
break;
226 boost::python::object py_elem_obj(py_elem_hdl);
227 boost::python::extract<container_element_type> elem_proxy(py_elem_obj);
228 ConversionPolicy::set_value(result, i, elem_proxy());
230 ConversionPolicy::assert_size(boost::type<ContainerType>(), i);
234 template <
typename ContainerType>
238 boost::python::to_python_converter<
241 #ifdef BOOST_PYTHON_SUPPORTS_PY_SIGNATURES
248 template <
typename ContainerType,
typename ConversionPolicy>
258 template <
typename ContainerType>
268 template <
typename ContainerType>
278 template <
typename ContainerType>
288 template <
typename ContainerType>
Definition: container_conversions.h:9
Definition: container_conversions.h:28
static void assert_size(boost::type< ContainerType >, std::size_t)
Definition: container_conversions.h:38
static void reserve(ContainerType &a, std::size_t sz)
Definition: container_conversions.h:41
static bool check_convertibility_per_element()
Definition: container_conversions.h:29
static bool check_size(boost::type< ContainerType >, std::size_t)
Definition: container_conversions.h:32
Definition: container_conversions.h:106
static bool check_size(boost::type< ContainerType >, std::size_t sz)
Definition: container_conversions.h:108
Definition: container_conversions.h:45
static void assert_size(boost::type< ContainerType >, std::size_t sz)
Definition: container_conversions.h:55
static void set_value(ContainerType &a, std::size_t i, ValueType const &v)
Definition: container_conversions.h:75
static void reserve(ContainerType &, std::size_t sz)
Definition: container_conversions.h:65
static bool check_size(boost::type< ContainerType >, std::size_t sz)
Definition: container_conversions.h:49
static bool check_convertibility_per_element()
Definition: container_conversions.h:46
Definition: container_conversions.h:136
from_python_sequence()
Definition: container_conversions.h:139
static bool all_elements_convertible(boost::python::handle<> &obj_iter, bool is_range, std::size_t &i)
Definition: container_conversions.h:187
static void * convertible(PyObject *obj_ptr)
Definition: container_conversions.h:147
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)
Definition: container_conversions.h:209
ContainerType::value_type container_element_type
Definition: container_conversions.h:137
Definition: container_conversions.h:115
static void set_value(ContainerType &a, std::size_t, ValueType const &v)
Definition: container_conversions.h:118
Definition: container_conversions.h:125
static void set_value(ContainerType &a, std::size_t, ValueType const &v)
Definition: container_conversions.h:128
Definition: container_conversions.h:236
to_tuple_mapping()
Definition: container_conversions.h:237
Definition: container_conversions.h:13
static const PyTypeObject * get_pytype()
Definition: container_conversions.h:24
static PyObject * convert(ContainerType const &a)
Definition: container_conversions.h:14
Definition: container_conversions.h:270
tuple_mapping_fixed_capacity()
Definition: container_conversions.h:271
Definition: container_conversions.h:260
tuple_mapping_fixed_size()
Definition: container_conversions.h:261
Definition: container_conversions.h:290
tuple_mapping_set()
Definition: container_conversions.h:291
Definition: container_conversions.h:280
tuple_mapping_variable_capacity()
Definition: container_conversions.h:281
Definition: container_conversions.h:250
tuple_mapping()
Definition: container_conversions.h:251
Definition: container_conversions.h:83
static void reserve(ContainerType &a, std::size_t sz)
Definition: container_conversions.h:85
static void set_value(ContainerType &a, std::size_t i, ValueType const &v)
Definition: container_conversions.h:91