[Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.199,2.200
Tim Peters
tim_one@users.sourceforge.net
Wed, 02 May 2001 00:39:40 -0700
Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv11690/python/dist/src/Python
Modified Files:
bltinmodule.c
Log Message:
Generalize filter(f, seq) to work with iterators. This also generalizes
filter() to no longer insist that len(seq) be defined.
NEEDS DOC CHANGES.
Index: bltinmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v
retrieving revision 2.199
retrieving revision 2.200
diff -C2 -r2.199 -r2.200
*** bltinmodule.c 2001/04/28 08:20:22 2.199
--- bltinmodule.c 2001/05/02 07:39:38 2.200
***************
*** 163,169 ****
builtin_filter(PyObject *self, PyObject *args)
{
! PyObject *func, *seq, *result;
! PySequenceMethods *sqf;
! int len;
register int i, j;
--- 163,168 ----
builtin_filter(PyObject *self, PyObject *args)
{
! PyObject *func, *seq, *result, *it;
! int len; /* guess for result list size */
register int i, j;
***************
*** 171,213 ****
return NULL;
! if (PyString_Check(seq)) {
! PyObject *r = filterstring(func, seq);
! return r;
! }
!
! if (PyTuple_Check(seq)) {
! PyObject *r = filtertuple(func, seq);
! return r;
! }
! sqf = seq->ob_type->tp_as_sequence;
! if (sqf == NULL || sqf->sq_length == NULL || sqf->sq_item == NULL) {
! PyErr_SetString(PyExc_TypeError,
! "filter() arg 2 must be a sequence");
! goto Fail_2;
}
!
! if ((len = (*sqf->sq_length)(seq)) < 0)
! goto Fail_2;
if (PyList_Check(seq) && seq->ob_refcnt == 1) {
Py_INCREF(seq);
result = seq;
}
else {
! if ((result = PyList_New(len)) == NULL)
! goto Fail_2;
}
for (i = j = 0; ; ++i) {
PyObject *item, *good;
int ok;
! if ((item = (*sqf->sq_item)(seq, i)) == NULL) {
! if (PyErr_ExceptionMatches(PyExc_IndexError)) {
! PyErr_Clear();
! break;
}
! goto Fail_1;
}
--- 170,225 ----
return NULL;
! /* Strings and tuples return a result of the same type. */
! if (PyString_Check(seq))
! return filterstring(func, seq);
! if (PyTuple_Check(seq))
! return filtertuple(func, seq);
!
! /* Get iterator. */
! it = PyObject_GetIter(seq);
! if (it == NULL)
! return NULL;
! /* Guess a result list size. */
! len = -1; /* unknown */
! if (PySequence_Check(seq) &&
! seq->ob_type->tp_as_sequence->sq_length) {
! len = PySequence_Size(seq);
! if (len < 0)
! PyErr_Clear();
}
! if (len < 0)
! len = 8; /* arbitrary */
+ /* Get a result list. */
if (PyList_Check(seq) && seq->ob_refcnt == 1) {
+ /* Eww - can modify the list in-place. */
Py_INCREF(seq);
result = seq;
}
else {
! result = PyList_New(len);
! if (result == NULL)
! goto Fail_it;
}
+ /* Build the result list. */
for (i = j = 0; ; ++i) {
PyObject *item, *good;
int ok;
! item = PyIter_Next(it);
! if (item == NULL) {
! /* We're out of here in any case, but if this is a
! * StopIteration exception it's expected, but if
! * any other kind of exception it's an error.
! */
! if (PyErr_Occurred()) {
! if (PyErr_ExceptionMatches(PyExc_StopIteration))
! PyErr_Clear();
! else
! goto Fail_result_it;
}
! break;
}
***************
*** 218,228 ****
else {
PyObject *arg = Py_BuildValue("(O)", item);
! if (arg == NULL)
! goto Fail_1;
good = PyEval_CallObject(func, arg);
Py_DECREF(arg);
if (good == NULL) {
Py_DECREF(item);
! goto Fail_1;
}
}
--- 230,242 ----
else {
PyObject *arg = Py_BuildValue("(O)", item);
! if (arg == NULL) {
! Py_DECREF(item);
! goto Fail_result_it;
! }
good = PyEval_CallObject(func, arg);
Py_DECREF(arg);
if (good == NULL) {
Py_DECREF(item);
! goto Fail_result_it;
}
}
***************
*** 230,258 ****
Py_DECREF(good);
if (ok) {
! if (j < len) {
! if (PyList_SetItem(result, j++, item) < 0)
! goto Fail_1;
! }
else {
int status = PyList_Append(result, item);
- j++;
Py_DECREF(item);
if (status < 0)
! goto Fail_1;
}
! } else {
! Py_DECREF(item);
}
}
if (j < len && PyList_SetSlice(result, j, len, NULL) < 0)
! goto Fail_1;
return result;
! Fail_1:
Py_DECREF(result);
! Fail_2:
return NULL;
}
--- 244,272 ----
Py_DECREF(good);
if (ok) {
! if (j < len)
! PyList_SET_ITEM(result, j, item);
else {
int status = PyList_Append(result, item);
Py_DECREF(item);
if (status < 0)
! goto Fail_result_it;
}
! ++j;
}
+ else
+ Py_DECREF(item);
}
+ /* Cut back result list if len is too big. */
if (j < len && PyList_SetSlice(result, j, len, NULL) < 0)
! goto Fail_result_it;
return result;
! Fail_result_it:
Py_DECREF(result);
! Fail_it:
! Py_DECREF(it);
return NULL;
}