Skip to content

Commit b0ac5d7

Browse files
author
dxflores
authored
bpo-41732: add iterator to memoryview (GH-22119)
1 parent 207c321 commit b0ac5d7

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added an :term:`iterator` to :class:`memoryview`.

Objects/memoryobject.c

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3160,6 +3160,112 @@ static PyMethodDef memory_methods[] = {
31603160
{NULL, NULL}
31613161
};
31623162

3163+
/**************************************************************************/
3164+
/* Memoryview Iterator */
3165+
/**************************************************************************/
3166+
3167+
static PyTypeObject PyMemoryIter_Type;
3168+
3169+
typedef struct {
3170+
PyObject_HEAD
3171+
Py_ssize_t it_index;
3172+
PyMemoryViewObject *it_seq; // Set to NULL when iterator is exhausted
3173+
Py_ssize_t it_length;
3174+
const char *it_fmt;
3175+
} memoryiterobject;
3176+
3177+
static void
3178+
memoryiter_dealloc(memoryiterobject *it)
3179+
{
3180+
_PyObject_GC_UNTRACK(it);
3181+
Py_XDECREF(it->it_seq);
3182+
PyObject_GC_Del(it);
3183+
}
3184+
3185+
static int
3186+
memoryiter_traverse(memoryiterobject *it, visitproc visit, void *arg)
3187+
{
3188+
Py_VISIT(it->it_seq);
3189+
return 0;
3190+
}
3191+
3192+
static PyObject *
3193+
memoryiter_next(memoryiterobject *it)
3194+
{
3195+
PyMemoryViewObject *seq;
3196+
seq = it->it_seq;
3197+
if (seq == NULL) {
3198+
return NULL;
3199+
}
3200+
3201+
if (it->it_index < it->it_length) {
3202+
CHECK_RELEASED(seq);
3203+
Py_buffer *view = &(seq->view);
3204+
char *ptr = (char *)seq->view.buf;
3205+
3206+
ptr += view->strides[0] * it->it_index++;
3207+
ptr = ADJUST_PTR(ptr, view->suboffsets, 0);
3208+
if (ptr == NULL) {
3209+
return NULL;
3210+
}
3211+
return unpack_single(ptr, it->it_fmt);
3212+
}
3213+
3214+
it->it_seq = NULL;
3215+
Py_DECREF(seq);
3216+
return NULL;
3217+
}
3218+
3219+
static PyObject *
3220+
memory_iter(PyObject *seq)
3221+
{
3222+
if (!PyMemoryView_Check(seq)) {
3223+
PyErr_BadInternalCall();
3224+
return NULL;
3225+
}
3226+
PyMemoryViewObject *obj = (PyMemoryViewObject *)seq;
3227+
int ndims = obj->view.ndim;
3228+
if (ndims == 0) {
3229+
PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
3230+
return NULL;
3231+
}
3232+
if (ndims != 1) {
3233+
PyErr_SetString(PyExc_NotImplementedError,
3234+
"multi-dimensional sub-views are not implemented");
3235+
return NULL;
3236+
}
3237+
3238+
const char *fmt = adjust_fmt(&obj->view);
3239+
if (fmt == NULL) {
3240+
return NULL;
3241+
}
3242+
3243+
memoryiterobject *it;
3244+
it = PyObject_GC_New(memoryiterobject, &PyMemoryIter_Type);
3245+
if (it == NULL) {
3246+
return NULL;
3247+
}
3248+
it->it_fmt = fmt;
3249+
it->it_length = memory_length(obj);
3250+
it->it_index = 0;
3251+
Py_INCREF(seq);
3252+
it->it_seq = obj;
3253+
_PyObject_GC_TRACK(it);
3254+
return (PyObject *)it;
3255+
}
3256+
3257+
static PyTypeObject PyMemoryIter_Type = {
3258+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
3259+
.tp_name = "memory_iterator",
3260+
.tp_basicsize = sizeof(memoryiterobject),
3261+
// methods
3262+
.tp_dealloc = (destructor)memoryiter_dealloc,
3263+
.tp_getattro = PyObject_GenericGetAttr,
3264+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
3265+
.tp_traverse = (traverseproc)memoryiter_traverse,
3266+
.tp_iter = PyObject_SelfIter,
3267+
.tp_iternext = (iternextfunc)memoryiter_next,
3268+
};
31633269

31643270
PyTypeObject PyMemoryView_Type = {
31653271
PyVarObject_HEAD_INIT(&PyType_Type, 0)
@@ -3187,7 +3293,7 @@ PyTypeObject PyMemoryView_Type = {
31873293
(inquiry)memory_clear, /* tp_clear */
31883294
memory_richcompare, /* tp_richcompare */
31893295
offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
3190-
0, /* tp_iter */
3296+
memory_iter, /* tp_iter */
31913297
0, /* tp_iternext */
31923298
memory_methods, /* tp_methods */
31933299
0, /* tp_members */

0 commit comments

Comments
 (0)