32
32
*/
33
33
34
34
#include "Python.h"
35
+ #include "pycore_set.h" // struct _PySetIterObject
35
36
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
36
37
#include <stddef.h> // offsetof()
37
38
38
39
/* Object used as dummy key to fill deleted entries */
39
40
static PyObject _dummy_struct ;
40
-
41
41
#define dummy (&_dummy_struct)
42
42
43
43
@@ -730,16 +730,8 @@ frozenset_hash(PyObject *self)
730
730
731
731
/***** Set iterator type ***********************************************/
732
732
733
- typedef struct {
734
- PyObject_HEAD
735
- PySetObject * si_set ; /* Set to NULL when iterator is exhausted */
736
- Py_ssize_t si_used ;
737
- Py_ssize_t si_pos ;
738
- Py_ssize_t len ;
739
- } setiterobject ;
740
-
741
733
static void
742
- setiter_dealloc (setiterobject * si )
734
+ setiter_dealloc (_PySetIterObject * si )
743
735
{
744
736
/* bpo-31095: UnTrack is needed before calling any callbacks */
745
737
_PyObject_GC_UNTRACK (si );
@@ -748,30 +740,30 @@ setiter_dealloc(setiterobject *si)
748
740
}
749
741
750
742
static int
751
- setiter_traverse (setiterobject * si , visitproc visit , void * arg )
743
+ setiter_traverse (_PySetIterObject * si , visitproc visit , void * arg )
752
744
{
753
745
Py_VISIT (si -> si_set );
754
746
return 0 ;
755
747
}
756
748
757
749
static PyObject *
758
- setiter_len (setiterobject * si , PyObject * Py_UNUSED (ignored ))
750
+ setiter_len (_PySetIterObject * si , PyObject * Py_UNUSED (ignored ))
759
751
{
760
752
Py_ssize_t len = 0 ;
761
753
if (si -> si_set != NULL && si -> si_used == si -> si_set -> used )
762
754
len = si -> len ;
763
755
return PyLong_FromSsize_t (len );
764
756
}
765
757
766
- PyDoc_STRVAR ( length_hint_doc , "Private method returning an estimate of len(list(it))." );
758
+ static PyObject * setiter_iternext ( _PySetIterObject * si );
767
759
768
- static PyObject * setiter_iternext ( setiterobject * si );
760
+ PyDoc_STRVAR ( length_hint_doc , "Private method returning an estimate of len(list(it))." );
769
761
770
762
static PyObject *
771
- setiter_reduce (setiterobject * si , PyObject * Py_UNUSED (ignored ))
763
+ setiter_reduce (_PySetIterObject * si , PyObject * Py_UNUSED (ignored ))
772
764
{
773
765
/* copy the iterator state */
774
- setiterobject tmp = * si ;
766
+ _PySetIterObject tmp = * si ;
775
767
Py_XINCREF (tmp .si_set );
776
768
777
769
/* iterate the temporary into a list */
@@ -791,48 +783,60 @@ static PyMethodDef setiter_methods[] = {
791
783
{NULL , NULL } /* sentinel */
792
784
};
793
785
794
- static PyObject * setiter_iternext ( setiterobject * si )
786
+ int _PySetIter_GetNext ( _PySetIterObject * si , PyObject * * stack )
795
787
{
796
- PyObject * key ;
788
+ assert ( Py_IS_TYPE (( PyObject * ) si , & PySetIter_Type )) ;
797
789
Py_ssize_t i , mask ;
798
790
setentry * entry ;
799
791
PySetObject * so = si -> si_set ;
800
792
801
- if (so == NULL )
802
- return NULL ;
793
+ if (so == NULL ) {
794
+ return 0 ;
795
+ }
803
796
assert (PyAnySet_Check (so ));
804
797
805
798
if (si -> si_used != so -> used ) {
806
799
PyErr_SetString (PyExc_RuntimeError ,
807
800
"Set changed size during iteration" );
808
801
si -> si_used = -1 ; /* Make this state sticky */
809
- return NULL ;
802
+ return -1 ;
810
803
}
811
804
812
805
i = si -> si_pos ;
813
806
assert (i >=0 );
814
807
entry = so -> table ;
815
808
mask = so -> mask ;
816
- while (i <= mask && (entry [i ].key == NULL || entry [i ].key == dummy ))
809
+ while (i <= mask && (entry [i ].key == NULL || entry [i ].key == dummy )) {
817
810
i ++ ;
811
+ }
818
812
si -> si_pos = i + 1 ;
819
- if (i > mask )
813
+ if (i > mask ) {
820
814
goto fail ;
815
+ }
821
816
si -> len -- ;
822
- key = entry [i ].key ;
823
- Py_INCREF (key );
824
- return key ;
825
-
817
+ stack [0 ] = entry [i ].key ;
818
+ Py_INCREF (stack [0 ]);
819
+ return 1 ;
826
820
fail :
827
821
si -> si_set = NULL ;
828
822
Py_DECREF (so );
829
- return NULL ;
823
+ return 0 ;
824
+ }
825
+
826
+ static PyObject * setiter_iternext (_PySetIterObject * si ) {
827
+ PyObject * key = NULL ;
828
+ PyObject * stack [1 ];
829
+ int err = _PySetIter_GetNext (si , stack );
830
+ if (err <= 0 ) {
831
+ return NULL ;
832
+ }
833
+ return stack [0 ];
830
834
}
831
835
832
836
PyTypeObject PySetIter_Type = {
833
837
PyVarObject_HEAD_INIT (& PyType_Type , 0 )
834
838
"set_iterator" , /* tp_name */
835
- sizeof (setiterobject ), /* tp_basicsize */
839
+ sizeof (_PySetIterObject ), /* tp_basicsize */
836
840
0 , /* tp_itemsize */
837
841
/* methods */
838
842
(destructor )setiter_dealloc , /* tp_dealloc */
@@ -865,7 +869,7 @@ PyTypeObject PySetIter_Type = {
865
869
static PyObject *
866
870
set_iter (PySetObject * so )
867
871
{
868
- setiterobject * si = PyObject_GC_New (setiterobject , & PySetIter_Type );
872
+ _PySetIterObject * si = PyObject_GC_New (_PySetIterObject , & PySetIter_Type );
869
873
if (si == NULL )
870
874
return NULL ;
871
875
Py_INCREF (so );
0 commit comments