[Python-checkins] CVS: python/dist/src/Objects abstract.c,2.73,2.74 classobject.c,2.145,2.146 typeobject.c,2.57,2.58
Tim Peters
tim_one@users.sourceforge.net
Fri, 07 Sep 2001 21:00:14 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv1044/python/Objects
Modified Files:
abstract.c classobject.c typeobject.c
Log Message:
Generalize operator.indexOf (PySequence_Index) to work with any
iterable object. I'm not sure how that got overlooked before!
Got rid of the internal _PySequence_IterContains, introduced a new
internal _PySequence_IterSearch, and rewrote all the iteration-based
"count of", "index of", and "is the object in it or not?" routines to
just call the new function. I suppose it's slower this way, but the
code duplication was getting depressing.
Index: abstract.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v
retrieving revision 2.73
retrieving revision 2.74
diff -C2 -d -r2.73 -r2.74
*** abstract.c 2001/09/07 20:20:11 2.73
--- abstract.c 2001/09/08 04:00:12 2.74
***************
*** 1373,1395 ****
}
! /* Return # of times o appears in s. */
int
! PySequence_Count(PyObject *s, PyObject *o)
{
! int n; /* running count of o hits */
! PyObject *it; /* iter(s) */
! if (s == NULL || o == NULL) {
null_error();
return -1;
}
! it = PyObject_GetIter(s);
if (it == NULL) {
! type_error(".count() requires iterable argument");
return -1;
}
! n = 0;
for (;;) {
int cmp;
--- 1373,1401 ----
}
! /* Iterate over seq. Result depends on the operation:
! PY_ITERSEARCH_COUNT: -1 if error, else # of times obj appears in seq.
! PY_ITERSEARCH_INDEX: 0-based index of first occurence of obj in seq;
! set ValueError and return -1 if none found; also return -1 on error.
! Py_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on error.
! */
int
! _PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
{
! int n;
! int wrapped; /* for PY_ITERSEARCH_INDEX, true iff n wrapped around */
! PyObject *it; /* iter(seq) */
! if (seq == NULL || obj == NULL) {
null_error();
return -1;
}
! it = PyObject_GetIter(seq);
if (it == NULL) {
! type_error("iterable argument required");
return -1;
}
! n = wrapped = 0;
for (;;) {
int cmp;
***************
*** 1400,1458 ****
break;
}
! cmp = PyObject_RichCompareBool(o, item, Py_EQ);
Py_DECREF(item);
if (cmp < 0)
goto Fail;
if (cmp > 0) {
! if (n == INT_MAX) {
! PyErr_SetString(PyExc_OverflowError,
"count exceeds C int size");
! goto Fail;
}
! n++;
}
}
- Py_DECREF(it);
- return n;
Fail:
Py_DECREF(it);
! return -1;
}
! /* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
! * Always uses the iteration protocol, and only Py_EQ comparison.
! */
int
! _PySequence_IterContains(PyObject *seq, PyObject *ob)
{
! int result;
! PyObject *it = PyObject_GetIter(seq);
! if (it == NULL) {
! PyErr_SetString(PyExc_TypeError,
! "'in' or 'not in' needs iterable right argument");
! return -1;
! }
!
! for (;;) {
! int cmp;
! PyObject *item = PyIter_Next(it);
! if (item == NULL) {
! result = PyErr_Occurred() ? -1 : 0;
! break;
! }
! cmp = PyObject_RichCompareBool(ob, item, Py_EQ);
! Py_DECREF(item);
! if (cmp == 0)
! continue;
! result = cmp > 0 ? 1 : -1;
! break;
! }
! Py_DECREF(it);
! return result;
}
/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
! * Use sq_contains if possible, else defer to _PySequence_IterContains().
*/
int
--- 1406,1473 ----
break;
}
!
! cmp = PyObject_RichCompareBool(obj, item, Py_EQ);
Py_DECREF(item);
if (cmp < 0)
goto Fail;
if (cmp > 0) {
! switch (operation) {
! case PY_ITERSEARCH_COUNT:
! ++n;
! if (n <= 0) {
! PyErr_SetString(PyExc_OverflowError,
"count exceeds C int size");
! goto Fail;
! }
! break;
!
! case PY_ITERSEARCH_INDEX:
! if (wrapped) {
! PyErr_SetString(PyExc_OverflowError,
! "index exceeds C int size");
! goto Fail;
! }
! goto Done;
!
! case PY_ITERSEARCH_CONTAINS:
! n = 1;
! goto Done;
!
! default:
! assert(!"unknown operation");
}
! }
!
! if (operation == PY_ITERSEARCH_INDEX) {
! ++n;
! if (n <= 0)
! wrapped = 1;
}
}
+ if (operation != PY_ITERSEARCH_INDEX)
+ goto Done;
+
+ PyErr_SetString(PyExc_ValueError,
+ "sequence.index(x): x not in sequence");
+ /* fall into failure code */
Fail:
+ n = -1;
+ /* fall through */
+ Done:
Py_DECREF(it);
! return n;
!
}
! /* Return # of times o appears in s. */
int
! PySequence_Count(PyObject *s, PyObject *o)
{
! return _PySequence_IterSearch(s, o, PY_ITERSEARCH_COUNT);
}
/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
! * Use sq_contains if possible, else defer to _PySequence_IterSearch().
*/
int
***************
*** 1464,1468 ****
return (*sqm->sq_contains)(seq, ob);
}
! return _PySequence_IterContains(seq, ob);
}
--- 1479,1483 ----
return (*sqm->sq_contains)(seq, ob);
}
! return _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);
}
***************
*** 1478,1507 ****
PySequence_Index(PyObject *s, PyObject *o)
{
! int l, i, cmp, err;
! PyObject *item;
!
! if (s == NULL || o == NULL) {
! null_error();
! return -1;
! }
!
! l = PySequence_Size(s);
! if (l < 0)
! return -1;
!
! for (i = 0; i < l; i++) {
! item = PySequence_GetItem(s, i);
! if (item == NULL)
! return -1;
! err = PyObject_Cmp(item, o, &cmp);
! Py_DECREF(item);
! if (err < 0)
! return err;
! if (cmp == 0)
! return i;
! }
!
! PyErr_SetString(PyExc_ValueError, "sequence.index(x): x not in list");
! return -1;
}
--- 1493,1497 ----
PySequence_Index(PyObject *s, PyObject *o)
{
! return _PySequence_IterSearch(s, o, PY_ITERSEARCH_INDEX);
}
Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.145
retrieving revision 2.146
diff -C2 -d -r2.145 -r2.146
*** classobject.c 2001/09/07 21:08:32 2.145
--- classobject.c 2001/09/08 04:00:12 2.146
***************
*** 1225,1229 ****
*/
PyErr_Clear();
! return _PySequence_IterContains((PyObject *)inst, member);
}
else
--- 1225,1230 ----
*/
PyErr_Clear();
! return _PySequence_IterSearch((PyObject *)inst, member,
! PY_ITERSEARCH_CONTAINS);
}
else
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.57
retrieving revision 2.58
diff -C2 -d -r2.57 -r2.58
*** typeobject.c 2001/09/07 18:52:13 2.57
--- typeobject.c 2001/09/08 04:00:12 2.58
***************
*** 2560,2564 ****
else {
PyErr_Clear();
! return _PySequence_IterContains(self, value);
}
}
--- 2560,2565 ----
else {
PyErr_Clear();
! return _PySequence_IterSearch(self, value,
! PY_ITERSEARCH_CONTAINS);
}
}