@@ -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
31643270PyTypeObject 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