@@ -456,7 +456,7 @@ static PyObject *_buffer_info_cache = NULL;
456
456
457
457
/* Fill in the info structure */
458
458
static _buffer_info_t *
459
- _buffer_info_new (PyObject * obj , npy_bool f_contiguous )
459
+ _buffer_info_new (PyObject * obj , int flags )
460
460
{
461
461
/*
462
462
* Note that the buffer info is cached as PyLongObjects making them appear
@@ -514,6 +514,7 @@ _buffer_info_new(PyObject *obj, npy_bool f_contiguous)
514
514
* (This is unnecessary, but has no effect in the case where
515
515
* NPY_RELAXED_STRIDES CHECKING is disabled.)
516
516
*/
517
+ int f_contiguous = (flags & PyBUF_F_CONTIGUOUS ) == PyBUF_F_CONTIGUOUS ;
517
518
if (PyArray_IS_C_CONTIGUOUS (arr ) && !(
518
519
f_contiguous && PyArray_IS_F_CONTIGUOUS (arr ))) {
519
520
Py_ssize_t sd = PyArray_ITEMSIZE (arr );
@@ -547,16 +548,20 @@ _buffer_info_new(PyObject *obj, npy_bool f_contiguous)
547
548
}
548
549
549
550
/* Fill in format */
550
- err = _buffer_format_string (descr , & fmt , obj , NULL , NULL );
551
- Py_DECREF (descr );
552
- if (err != 0 ) {
553
- goto fail ;
551
+ if ((flags & PyBUF_FORMAT ) == PyBUF_FORMAT ) {
552
+ err = _buffer_format_string (descr , & fmt , obj , NULL , NULL );
553
+ Py_DECREF (descr );
554
+ if (err != 0 ) {
555
+ goto fail ;
556
+ }
557
+ if (_append_char (& fmt , '\0' ) < 0 ) {
558
+ goto fail ;
559
+ }
560
+ info -> format = fmt .s ;
554
561
}
555
- if ( _append_char ( & fmt , '\0' ) < 0 ) {
556
- goto fail ;
562
+ else {
563
+ info -> format = NULL ;
557
564
}
558
- info -> format = fmt .s ;
559
-
560
565
return info ;
561
566
562
567
fail :
@@ -572,9 +577,10 @@ _buffer_info_cmp(_buffer_info_t *a, _buffer_info_t *b)
572
577
Py_ssize_t c ;
573
578
int k ;
574
579
575
- c = strcmp (a -> format , b -> format );
576
- if (c != 0 ) return c ;
577
-
580
+ if (a -> format != NULL && b -> format != NULL ) {
581
+ c = strcmp (a -> format , b -> format );
582
+ if (c != 0 ) return c ;
583
+ }
578
584
c = a -> ndim - b -> ndim ;
579
585
if (c != 0 ) return c ;
580
586
@@ -599,7 +605,7 @@ _buffer_info_free(_buffer_info_t *info)
599
605
600
606
/* Get buffer info from the global dictionary */
601
607
static _buffer_info_t *
602
- _buffer_get_info (PyObject * obj , npy_bool f_contiguous )
608
+ _buffer_get_info (PyObject * obj , int flags )
603
609
{
604
610
PyObject * key = NULL , * item_list = NULL , * item = NULL ;
605
611
_buffer_info_t * info = NULL , * old_info = NULL ;
@@ -612,7 +618,7 @@ _buffer_get_info(PyObject *obj, npy_bool f_contiguous)
612
618
}
613
619
614
620
/* Compute information */
615
- info = _buffer_info_new (obj , f_contiguous );
621
+ info = _buffer_info_new (obj , flags );
616
622
if (info == NULL ) {
617
623
return NULL ;
618
624
}
@@ -630,11 +636,9 @@ _buffer_get_info(PyObject *obj, npy_bool f_contiguous)
630
636
if (item_list_length > 0 ) {
631
637
item = PyList_GetItem (item_list , item_list_length - 1 );
632
638
old_info = (_buffer_info_t * )PyLong_AsVoidPtr (item );
633
- if (_buffer_info_cmp (info , old_info ) == 0 ) {
634
- _buffer_info_free (info );
635
- info = old_info ;
636
- }
637
- else {
639
+ if (_buffer_info_cmp (info , old_info ) != 0 ) {
640
+ old_info = NULL ; /* Can't use this one, but possibly next */
641
+
638
642
if (item_list_length > 1 && info -> ndim > 1 ) {
639
643
/*
640
644
* Some arrays are C- and F-contiguous and if they have more
@@ -648,12 +652,26 @@ _buffer_get_info(PyObject *obj, npy_bool f_contiguous)
648
652
*/
649
653
item = PyList_GetItem (item_list , item_list_length - 2 );
650
654
old_info = (_buffer_info_t * )PyLong_AsVoidPtr (item );
651
- if (_buffer_info_cmp (info , old_info ) == 0 ) {
652
- _buffer_info_free (info );
653
- info = old_info ;
655
+ if (_buffer_info_cmp (info , old_info ) != 0 ) {
656
+ old_info = NULL ;
654
657
}
655
658
}
656
659
}
660
+
661
+ if (old_info != NULL ) {
662
+ /*
663
+ * The two info->format are considered equal if one of them
664
+ * has no format set (meaning the format is arbitrary and can
665
+ * be modified). If the new info has a format, but we reuse
666
+ * the old one, this transfers the ownership to the old one.
667
+ */
668
+ if (old_info -> format == NULL ) {
669
+ old_info -> format = info -> format ;
670
+ info -> format = NULL ;
671
+ }
672
+ _buffer_info_free (info );
673
+ info = old_info ;
674
+ }
657
675
}
658
676
}
659
677
else {
@@ -760,7 +778,7 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
760
778
}
761
779
762
780
/* Fill in information */
763
- info = _buffer_get_info (obj , ( flags & PyBUF_F_CONTIGUOUS ) == PyBUF_F_CONTIGUOUS );
781
+ info = _buffer_get_info (obj , flags );
764
782
if (info == NULL ) {
765
783
goto fail ;
766
784
}
@@ -825,7 +843,7 @@ void_getbuffer(PyObject *self, Py_buffer *view, int flags)
825
843
}
826
844
827
845
/* Fill in information */
828
- info = _buffer_get_info (self , 0 );
846
+ info = _buffer_get_info (self , flags );
829
847
if (info == NULL ) {
830
848
goto fail ;
831
849
}
0 commit comments