@@ -3160,6 +3160,112 @@ static PyMethodDef memory_methods[] = {
3160
3160
{NULL , NULL }
3161
3161
};
3162
3162
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
+ };
3163
3269
3164
3270
PyTypeObject PyMemoryView_Type = {
3165
3271
PyVarObject_HEAD_INIT (& PyType_Type , 0 )
@@ -3187,7 +3293,7 @@ PyTypeObject PyMemoryView_Type = {
3187
3293
(inquiry )memory_clear , /* tp_clear */
3188
3294
memory_richcompare , /* tp_richcompare */
3189
3295
offsetof(PyMemoryViewObject , weakreflist ),/* tp_weaklistoffset */
3190
- 0 , /* tp_iter */
3296
+ memory_iter , /* tp_iter */
3191
3297
0 , /* tp_iternext */
3192
3298
memory_methods , /* tp_methods */
3193
3299
0 , /* tp_members */
0 commit comments