@@ -13,6 +13,18 @@ dup_buffer(Py_buffer *dest, Py_buffer *src)
1313 dest -> strides = & (dest -> itemsize );
1414}
1515
16+ /* XXX The buffer API should mandate that the shape array be non-NULL, but
17+ it would complicate some code since the (de)allocation semantics of shape
18+ are not specified. */
19+ static Py_ssize_t
20+ get_shape0 (Py_buffer * buf )
21+ {
22+ if (buf -> shape != NULL )
23+ return buf -> shape [0 ];
24+ assert (buf -> ndim == 1 && buf -> itemsize > 0 );
25+ return buf -> len / buf -> itemsize ;
26+ }
27+
1628static int
1729memory_getbuf (PyMemoryViewObject * self , Py_buffer * view , int flags )
1830{
@@ -523,99 +535,99 @@ memory_length(PyMemoryViewObject *self)
523535static PyObject *
524536memory_subscript (PyMemoryViewObject * self , PyObject * key )
525537{
526- Py_buffer * view ;
527- view = & (self -> view );
528-
529- if (view -> ndim == 0 ) {
530- if (key == Py_Ellipsis ||
538+ Py_buffer * view ;
539+ view = & (self -> view );
540+
541+ if (view -> ndim == 0 ) {
542+ if (key == Py_Ellipsis ||
531543 (PyTuple_Check (key ) && PyTuple_GET_SIZE (key )== 0 )) {
532- Py_INCREF (self );
533- return (PyObject * )self ;
534- }
535- else {
536- PyErr_SetString (PyExc_IndexError ,
544+ Py_INCREF (self );
545+ return (PyObject * )self ;
546+ }
547+ else {
548+ PyErr_SetString (PyExc_IndexError ,
537549 "invalid indexing of 0-dim memory" );
538- return NULL ;
539- }
540- }
541- if (PyIndex_Check (key )) {
542- Py_ssize_t result ;
543- result = PyNumber_AsSsize_t (key , NULL );
544- if (result == -1 && PyErr_Occurred ())
545- return NULL ;
546- if (view -> ndim == 1 ) {
547- /* Return a bytes object */
548- char * ptr ;
549- ptr = (char * )view -> buf ;
550- if (result < 0 ) {
551- result += view -> shape [ 0 ] ;
552- }
553- if ((result < 0 ) || (result >= view -> shape [ 0 ] )) {
554- PyErr_SetString (PyExc_IndexError ,
555- "index out of bounds" );
556- return NULL ;
557- }
558- if (view -> strides == NULL )
559- ptr += view -> itemsize * result ;
560- else
561- ptr += view -> strides [0 ] * result ;
562- if (view -> suboffsets != NULL &&
550+ return NULL ;
551+ }
552+ }
553+ if (PyIndex_Check (key )) {
554+ Py_ssize_t result ;
555+ result = PyNumber_AsSsize_t (key , NULL );
556+ if (result == -1 && PyErr_Occurred ())
557+ return NULL ;
558+ if (view -> ndim == 1 ) {
559+ /* Return a bytes object */
560+ char * ptr ;
561+ ptr = (char * )view -> buf ;
562+ if (result < 0 ) {
563+ result += get_shape0 ( view ) ;
564+ }
565+ if ((result < 0 ) || (result >= get_shape0 ( view ) )) {
566+ PyErr_SetString (PyExc_IndexError ,
567+ "index out of bounds" );
568+ return NULL ;
569+ }
570+ if (view -> strides == NULL )
571+ ptr += view -> itemsize * result ;
572+ else
573+ ptr += view -> strides [0 ] * result ;
574+ if (view -> suboffsets != NULL &&
563575 view -> suboffsets [0 ] >= 0 )
564576 {
565- ptr = * ((char * * )ptr ) + view -> suboffsets [0 ];
566- }
567- return PyBytes_FromStringAndSize (ptr , view -> itemsize );
568- }
569- else {
570- /* Return a new memory-view object */
571- Py_buffer newview ;
572- memset (& newview , 0 , sizeof (newview ));
573- /* XXX: This needs to be fixed so it
577+ ptr = * ((char * * )ptr ) + view -> suboffsets [0 ];
578+ }
579+ return PyBytes_FromStringAndSize (ptr , view -> itemsize );
580+ }
581+ else {
582+ /* Return a new memory-view object */
583+ Py_buffer newview ;
584+ memset (& newview , 0 , sizeof (newview ));
585+ /* XXX: This needs to be fixed so it
574586 actually returns a sub-view
575- */
576- return PyMemoryView_FromBuffer (& newview );
577- }
578- }
579- else if (PySlice_Check (key )) {
580- Py_ssize_t start , stop , step , slicelength ;
581-
582- if (PySlice_GetIndicesEx ((PySliceObject * )key , view -> len ,
583- & start , & stop , & step , & slicelength ) < 0 ) {
584- return NULL ;
585- }
586-
587- if (step == 1 && view -> ndim == 1 ) {
588- Py_buffer newview ;
589- void * newbuf = (char * ) view -> buf
590- + start * view -> itemsize ;
591- int newflags = view -> readonly
592- ? PyBUF_CONTIG_RO : PyBUF_CONTIG ;
593-
594- /* XXX There should be an API to create a subbuffer */
595- if (view -> obj != NULL ) {
596- if (PyObject_GetBuffer (view -> obj ,
597- & newview , newflags ) == -1 )
598- return NULL ;
599- }
600- else {
601- newview = * view ;
602- }
603- newview .buf = newbuf ;
604- newview .len = slicelength ;
605- newview .format = view -> format ;
606- if (view -> shape == & (view -> len ))
607- newview .shape = & (newview .len );
608- if (view -> strides == & (view -> itemsize ))
609- newview .strides = & (newview .itemsize );
610- return PyMemoryView_FromBuffer (& newview );
611- }
612- PyErr_SetNone (PyExc_NotImplementedError );
613- return NULL ;
614- }
615- PyErr_Format (PyExc_TypeError ,
616- "cannot index memory using \"%.200s\"" ,
617- key -> ob_type -> tp_name );
618- return NULL ;
587+ */
588+ return PyMemoryView_FromBuffer (& newview );
589+ }
590+ }
591+ else if (PySlice_Check (key )) {
592+ Py_ssize_t start , stop , step , slicelength ;
593+
594+ if (PySlice_GetIndicesEx ((PySliceObject * )key , get_shape0 ( view ) ,
595+ & start , & stop , & step , & slicelength ) < 0 ) {
596+ return NULL ;
597+ }
598+
599+ if (step == 1 && view -> ndim == 1 ) {
600+ Py_buffer newview ;
601+ void * newbuf = (char * ) view -> buf
602+ + start * view -> itemsize ;
603+ int newflags = view -> readonly
604+ ? PyBUF_CONTIG_RO : PyBUF_CONTIG ;
605+
606+ /* XXX There should be an API to create a subbuffer */
607+ if (view -> obj != NULL ) {
608+ if (PyObject_GetBuffer (view -> obj ,
609+ & newview , newflags ) == -1 )
610+ return NULL ;
611+ }
612+ else {
613+ newview = * view ;
614+ }
615+ newview .buf = newbuf ;
616+ newview .len = slicelength ;
617+ newview .format = view -> format ;
618+ if (view -> shape == & (view -> len ))
619+ newview .shape = & (newview .len );
620+ if (view -> strides == & (view -> itemsize ))
621+ newview .strides = & (newview .itemsize );
622+ return PyMemoryView_FromBuffer (& newview );
623+ }
624+ PyErr_SetNone (PyExc_NotImplementedError );
625+ return NULL ;
626+ }
627+ PyErr_Format (PyExc_TypeError ,
628+ "cannot index memory using \"%.200s\"" ,
629+ key -> ob_type -> tp_name );
630+ return NULL ;
619631}
620632
621633
@@ -642,9 +654,9 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
642654 if (start == -1 && PyErr_Occurred ())
643655 return -1 ;
644656 if (start < 0 ) {
645- start += view -> shape [ 0 ] ;
657+ start += get_shape0 ( view ) ;
646658 }
647- if ((start < 0 ) || (start >= view -> shape [ 0 ] )) {
659+ if ((start < 0 ) || (start >= get_shape0 ( view ) )) {
648660 PyErr_SetString (PyExc_IndexError ,
649661 "index out of bounds" );
650662 return -1 ;
@@ -654,7 +666,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
654666 else if (PySlice_Check (key )) {
655667 Py_ssize_t stop , step ;
656668
657- if (PySlice_GetIndicesEx ((PySliceObject * )key , view -> len ,
669+ if (PySlice_GetIndicesEx ((PySliceObject * )key , get_shape0 ( view ) ,
658670 & start , & stop , & step , & len ) < 0 ) {
659671 return -1 ;
660672 }
@@ -681,15 +693,15 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
681693 view -> obj -> ob_type -> tp_name , srcview .obj -> ob_type -> tp_name );
682694 goto _error ;
683695 }
684- if (srcview .len != len ) {
696+ bytelen = len * view -> itemsize ;
697+ if (bytelen != srcview .len ) {
685698 PyErr_SetString (PyExc_ValueError ,
686699 "cannot modify size of memoryview object" );
687700 goto _error ;
688701 }
689702 /* Do the actual copy */
690703 destbuf = (char * ) view -> buf + start * view -> itemsize ;
691704 srcbuf = (char * ) srcview .buf ;
692- bytelen = len * view -> itemsize ;
693705 if (destbuf + bytelen < srcbuf || srcbuf + bytelen < destbuf )
694706 /* No overlapping */
695707 memcpy (destbuf , srcbuf , bytelen );
0 commit comments