summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2023-04-03 22:09:39 +0100
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2023-04-26 18:18:11 +0100
commit6098b26f3ece2096e14695fd02b040bd0658d2ac (patch)
tree0a84b3ed7a77802ef1ebd821293abfd6763be9e9 /Lib
parentb72703acdf42ce0939737ed73ca4830c1e1b6b2d (diff)
downloadswig-6098b26f3ece2096e14695fd02b040bd0658d2ac.tar.gz
Iterator Protocol support for std::array wrappers
Introduce swig::IteratorProtocol class and assign which can be partially specialized by different container types, such as std::array.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/python/pycontainer.swg46
-rw-r--r--Lib/python/std_array.i48
2 files changed, 61 insertions, 33 deletions
diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg
index a1affa86b..65223b615 100644
--- a/Lib/python/pycontainer.swg
+++ b/Lib/python/pycontainer.swg
@@ -1014,7 +1014,8 @@ namespace swig {
}
template <class Seq, class T = typename Seq::value_type >
- static int assign_iterator_protocol(PyObject *obj, Seq **seq) {
+ struct IteratorProtocol {
+ static int assign(PyObject *obj, Seq **seq) {
int ret = SWIG_ERROR;
PyObject *iter = PyObject_GetIter(obj);
if (iter) {
@@ -1046,12 +1047,21 @@ namespace swig {
return ret;
}
+ };
template <class Seq, class T = typename Seq::value_type >
struct traits_asptr_stdseq {
typedef Seq sequence;
typedef T value_type;
+ static bool is_iterable(PyObject *obj) {
+ PyObject *iter = PyObject_GetIter(obj);
+ bool is_iter = iter != 0;
+ Py_XDECREF(iter);
+ PyErr_Clear();
+ return is_iter;
+ }
+
static int asptr(PyObject *obj, sequence **seq) {
int ret = SWIG_ERROR;
if (obj == Py_None || SWIG_Python_GetSwigThis(obj)) {
@@ -1061,6 +1071,8 @@ namespace swig {
if (seq) *seq = p;
return SWIG_OLDOBJ;
}
+ } else if (is_iterable(obj)) {
+ ret = IteratorProtocol<Seq, T>::assign(obj, seq);
} else if (PySequence_Check(obj)) {
try {
SwigPySequence_Cont<value_type> swigpyseq(obj);
@@ -1080,38 +1092,6 @@ namespace swig {
}
return SWIG_ERROR;
}
- } else {
-#if 0
- PyObject *iter = PyObject_GetIter(obj);
- if (iter) {
- PyObject *item = PyIter_Next(iter);
- ret = SWIG_OK;
- if (seq)
- *seq = new sequence();
- while (item) {
- try {
- if (seq) {
- (*seq)->insert((*seq)->end(), swig::as<value_type>(item));
- } else {
- if (!swig::check<value_type>(item))
- ret = SWIG_ERROR;
- }
- } catch (std::exception& e) {
- if (seq) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, e.what());
- }
- }
- ret = SWIG_ERROR;
- }
- Py_DECREF(item);
- item = (ret == SWIG_OK) ? PyIter_Next(iter) : 0;
- }
- Py_DECREF(iter);
- }
-#else
- ret = swig::assign_iterator_protocol<Seq, T>(obj, seq);
-#endif
}
return ret;
}
diff --git a/Lib/python/std_array.i b/Lib/python/std_array.i
index a3de3125b..9cca563c0 100644
--- a/Lib/python/std_array.i
+++ b/Lib/python/std_array.i
@@ -30,6 +30,54 @@
}
template <class T, size_t N>
+ struct IteratorProtocol<std::array<T, N>, T> {
+ static int assign(PyObject *obj, std::array<T, N> **seq) {
+ int ret = SWIG_ERROR;
+ PyObject *iter = PyObject_GetIter(obj);
+ if (iter) {
+ PyObject *item = PyIter_Next(iter);
+ size_t count = 0;
+ typename std::array<T, N>::iterator array_iter = nullptr;
+ ret = SWIG_OK;
+ if (seq) {
+ *seq = new std::array<T, N>();
+ array_iter = (*seq)->begin();
+ }
+ while (item && (count < N)) {
+ try {
+ if (seq) {
+ *array_iter++ = swig::as<T>(item);
+ } else {
+ if (!swig::check<T>(item))
+ ret = SWIG_ERROR;
+ }
+ } catch (std::exception& e) {
+ if (seq) {
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, e.what());
+ }
+ }
+ ret = SWIG_ERROR;
+ }
+ ++count;
+ Py_DECREF(item);
+ item = (ret == SWIG_OK) ? PyIter_Next(iter) : 0;
+ }
+ if ((ret == SWIG_OK) && (count != N || item)) {
+ PyErr_SetString(PyExc_TypeError, "std::array size does not match source container size");
+ ret = SWIG_ERROR;
+ }
+ Py_XDECREF(item);
+ Py_DECREF(iter);
+ if (seq && (ret == SWIG_ERROR))
+ delete *seq;
+ }
+
+ return ret;
+ }
+ };
+
+ template <class T, size_t N>
inline void
erase(std::array<T, N>* SWIGUNUSEDPARM(seq), const typename std::array<T, N>::iterator& SWIGUNUSEDPARM(position)) {
throw std::invalid_argument("std::array object does not support item deletion");