[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;
  }