33
44#include "Python.h"
55
6+ static void
7+ dup_buffer (Py_buffer * dest , Py_buffer * src )
8+ {
9+ * dest = * src ;
10+ if (src -> shape == & (src -> len ))
11+ dest -> shape = & (dest -> len );
12+ if (src -> strides == & (src -> itemsize ))
13+ dest -> strides = & (dest -> itemsize );
14+ }
15+
616static int
717memory_getbuf (PyMemoryViewObject * self , Py_buffer * view , int flags )
818{
9- if ( view != NULL ) {
10- if ( self -> view . obj )
11- Py_INCREF (self -> view .obj );
12- * view = self -> view ;
13- }
14- if (self -> view .obj == NULL )
15- return 0 ;
16- return self -> view . obj -> ob_type -> tp_as_buffer -> bf_getbuffer (
17- self -> view . obj , NULL , PyBUF_FULL ) ;
19+ int res = 0 ;
20+ /* XXX for whatever reason fixing the flags seems necessary */
21+ if (self -> view .readonly )
22+ flags &= ~ PyBUF_WRITABLE ;
23+ if ( self -> view . obj != NULL )
24+ res = PyObject_GetBuffer (self -> view .obj , view , flags );
25+ if ( view )
26+ dup_buffer ( view , & self -> view );
27+ return res ;
1828}
1929
2030static void
2131memory_releasebuf (PyMemoryViewObject * self , Py_buffer * view )
2232{
23- PyBuffer_Release (& self -> view );
33+ PyBuffer_Release (view );
2434}
2535
2636PyDoc_STRVAR (memory_doc ,
@@ -33,18 +43,15 @@ PyMemoryView_FromBuffer(Py_buffer *info)
3343{
3444 PyMemoryViewObject * mview ;
3545
36- mview = (PyMemoryViewObject * )PyObject_New (PyMemoryViewObject ,
37- & PyMemoryView_Type );
38- if (mview == NULL ) return NULL ;
46+ mview = (PyMemoryViewObject * )
47+ PyObject_GC_New (PyMemoryViewObject , & PyMemoryView_Type );
48+ if (mview == NULL )
49+ return NULL ;
3950 mview -> base = NULL ;
40- /* XXX there should be an API to duplicate a buffer object */
41- mview -> view = * info ;
42- if (info -> shape == & (info -> len ))
43- mview -> view .shape = & (mview -> view .len );
44- if (info -> strides == & (info -> itemsize ))
45- mview -> view .strides = & (mview -> view .itemsize );
51+ dup_buffer (& mview -> view , info );
4652 /* NOTE: mview->view.obj should already have been incref'ed as
4753 part of PyBuffer_FillInfo(). */
54+ _PyObject_GC_TRACK (mview );
4855 return (PyObject * )mview ;
4956}
5057
@@ -60,9 +67,10 @@ PyMemoryView_FromObject(PyObject *base)
6067 return NULL ;
6168 }
6269
63- mview = (PyMemoryViewObject * )PyObject_New (PyMemoryViewObject ,
64- & PyMemoryView_Type );
65- if (mview == NULL ) return NULL ;
70+ mview = (PyMemoryViewObject * )
71+ PyObject_GC_New (PyMemoryViewObject , & PyMemoryView_Type );
72+ if (mview == NULL )
73+ return NULL ;
6674
6775 mview -> base = NULL ;
6876 if (PyObject_GetBuffer (base , & (mview -> view ), PyBUF_FULL_RO ) < 0 ) {
@@ -72,6 +80,7 @@ PyMemoryView_FromObject(PyObject *base)
7280
7381 mview -> base = base ;
7482 Py_INCREF (base );
83+ _PyObject_GC_TRACK (mview );
7584 return (PyObject * )mview ;
7685}
7786
@@ -233,8 +242,9 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
233242 return NULL ;
234243 }
235244
236- mem = PyObject_New (PyMemoryViewObject , & PyMemoryView_Type );
237- if (mem == NULL ) return NULL ;
245+ mem = PyObject_GC_New (PyMemoryViewObject , & PyMemoryView_Type );
246+ if (mem == NULL )
247+ return NULL ;
238248
239249 view = & mem -> view ;
240250 flags = PyBUF_FULL_RO ;
@@ -245,27 +255,28 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
245255 }
246256
247257 if (PyObject_GetBuffer (obj , view , flags ) != 0 ) {
248- PyObject_DEL (mem );
258+ Py_DECREF (mem );
249259 return NULL ;
250260 }
251261
252262 if (PyBuffer_IsContiguous (view , fort )) {
253263 /* no copy needed */
254264 Py_INCREF (obj );
255265 mem -> base = obj ;
266+ _PyObject_GC_TRACK (mem );
256267 return (PyObject * )mem ;
257268 }
258269 /* otherwise a copy is needed */
259270 if (buffertype == PyBUF_WRITE ) {
260- PyObject_DEL (mem );
271+ Py_DECREF (mem );
261272 PyErr_SetString (PyExc_BufferError ,
262273 "writable contiguous buffer requested "
263274 "for a non-contiguousobject." );
264275 return NULL ;
265276 }
266277 bytes = PyBytes_FromStringAndSize (NULL , view -> len );
267278 if (bytes == NULL ) {
268- PyBuffer_Release ( view );
279+ Py_DECREF ( mem );
269280 return NULL ;
270281 }
271282 dest = PyBytes_AS_STRING (bytes );
@@ -280,7 +291,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
280291 else {
281292 if (_indirect_copy_nd (dest , view , fort ) < 0 ) {
282293 Py_DECREF (bytes );
283- PyBuffer_Release ( view );
294+ Py_DECREF ( mem );
284295 return NULL ;
285296 }
286297 }
@@ -290,15 +301,16 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
290301 mem -> base = PyTuple_Pack (2 , obj , bytes );
291302 Py_DECREF (bytes );
292303 if (mem -> base == NULL ) {
293- PyBuffer_Release ( view );
304+ Py_DECREF ( mem );
294305 return NULL ;
295306 }
296307 }
297308 else {
298- PyBuffer_Release (view );
309+ PyBuffer_Release (view ); /* XXX ? */
299310 /* steal the reference */
300311 mem -> base = bytes ;
301312 }
313+ _PyObject_GC_TRACK (mem );
302314 return (PyObject * )mem ;
303315}
304316
@@ -444,6 +456,7 @@ static PyMethodDef memory_methods[] = {
444456static void
445457memory_dealloc (PyMemoryViewObject * self )
446458{
459+ _PyObject_GC_UNTRACK (self );
447460 if (self -> view .obj != NULL ) {
448461 if (self -> base && PyTuple_Check (self -> base )) {
449462 /* Special case when first element is generic object
@@ -468,7 +481,7 @@ memory_dealloc(PyMemoryViewObject *self)
468481 }
469482 Py_CLEAR (self -> base );
470483 }
471- PyObject_DEL (self );
484+ PyObject_GC_Del (self );
472485}
473486
474487static PyObject *
@@ -749,6 +762,25 @@ memory_richcompare(PyObject *v, PyObject *w, int op)
749762}
750763
751764
765+ static int
766+ memory_traverse (PyMemoryViewObject * self , visitproc visit , void * arg )
767+ {
768+ if (self -> base != NULL )
769+ Py_VISIT (self -> base );
770+ if (self -> view .obj != NULL )
771+ Py_VISIT (self -> view .obj );
772+ return 0 ;
773+ }
774+
775+ static int
776+ memory_clear (PyMemoryViewObject * self )
777+ {
778+ Py_CLEAR (self -> base );
779+ PyBuffer_Release (& self -> view );
780+ return 0 ;
781+ }
782+
783+
752784/* As mapping */
753785static PyMappingMethods memory_as_mapping = {
754786 (lenfunc )memory_length , /*mp_length*/
@@ -785,10 +817,10 @@ PyTypeObject PyMemoryView_Type = {
785817 PyObject_GenericGetAttr , /* tp_getattro */
786818 0 , /* tp_setattro */
787819 & memory_as_buffer , /* tp_as_buffer */
788- Py_TPFLAGS_DEFAULT , /* tp_flags */
820+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC , /* tp_flags */
789821 memory_doc , /* tp_doc */
790- 0 , /* tp_traverse */
791- 0 , /* tp_clear */
822+ ( traverseproc ) memory_traverse , /* tp_traverse */
823+ ( inquiry ) memory_clear , /* tp_clear */
792824 memory_richcompare , /* tp_richcompare */
793825 0 , /* tp_weaklistoffset */
794826 0 , /* tp_iter */
0 commit comments