diff options
| author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-07-10 21:30:28 +0000 | 
|---|---|---|
| committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-07-10 21:30:28 +0000 | 
| commit | 194e43e9533b0441b4f5d680f1d0c77e20297a34 (patch) | |
| tree | 77aa1710f4f3819fd1036a8d164a9e666d4be0c2 | |
| parent | 663809ed830ac84f9c6fe94ad7c2a3cc302d0680 (diff) | |
| download | cpython-git-194e43e9533b0441b4f5d680f1d0c77e20297a34.tar.gz | |
two changes to string_join:
implementation -- use PySequence_Fast interface to iterate over elements
interface -- if instance object reports wrong length, ignore it;
   previous version raised an IndexError if reported length was too high
| -rw-r--r-- | Objects/stringobject.c | 124 | 
1 files changed, 42 insertions, 82 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 9677d4bd25..fd0a570c5f 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -744,106 +744,66 @@ string_join(PyStringObject *self, PyObject *args)  	int seqlen = 0;  	int sz = 100;  	int i, slen; -	PyObject *seq; +	PyObject *orig, *seq, *item; -	if (!PyArg_ParseTuple(args, "O:join", &seq)) +	if (!PyArg_ParseTuple(args, "O:join", &orig))  		return NULL; -	seqlen = PySequence_Length(seq); -	if (seqlen < 0 && PyErr_Occurred()) +	seq = PySequence_Fast(orig, ""); +	if (seq == NULL) { +		if (PyErr_ExceptionMatches(PyExc_TypeError)) +			PyErr_Format(PyExc_TypeError, +				     "sequence expected, %.80s found", +				     orig->ob_type->tp_name);  		return NULL; +	} +	seqlen = PySequence_Length(seq);  	if (seqlen == 1) { -		/* Optimization if there's only one item */ -		PyObject *item = PySequence_GetItem(seq, 0); -		if (item == NULL) -		    return NULL; -		if (!PyString_Check(item) &&  -		    !PyUnicode_Check(item)) { -		        PyErr_SetString(PyExc_TypeError, -			      "first argument must be sequence of strings"); -			Py_DECREF(item); -			return NULL; -		} +		item = PySequence_Fast_GET_ITEM(seq, 0); +		Py_INCREF(item);  		return item;  	} +  	if (!(res = PyString_FromStringAndSize((char*)NULL, sz)))  		return NULL;  	p = PyString_AsString(res); -	/* optimize for lists.  all others (tuples and arbitrary sequences) -	 * just use the abstract interface. -	 */ -	if (PyList_Check(seq)) { -		for (i = 0; i < seqlen; i++) { -			PyObject *item = PyList_GET_ITEM(seq, i); -			if (!PyString_Check(item)){ -				if (PyUnicode_Check(item)) { -					Py_DECREF(res); -					return PyUnicode_Join( -							 (PyObject *)self,  -							 seq); -				} -				PyErr_Format(PyExc_TypeError, -					     "sequence item %i not a string", -					     i); -				goto finally; -			} -			slen = PyString_GET_SIZE(item); -			while (reslen + slen + seplen >= sz) { -				if (_PyString_Resize(&res, sz*2)) -					goto finally; -				sz *= 2; -				p = PyString_AsString(res) + reslen; -			} -			if (i > 0) { -				memcpy(p, sep, seplen); -				p += seplen; -				reslen += seplen; +	for (i = 0; i < seqlen; i++) { +		item = PySequence_Fast_GET_ITEM(seq, i); +		if (!PyString_Check(item)){ +			if (PyUnicode_Check(item)) { +				Py_DECREF(res); +				Py_DECREF(item); +				return PyUnicode_Join((PyObject *)self,  +						      seq);  			} -			memcpy(p, PyString_AS_STRING(item), slen); -			p += slen; -			reslen += slen; +			PyErr_Format(PyExc_TypeError, +			     "sequence item %i: expected string, %.80s found", +				     i, item->ob_type->tp_name); +			Py_DECREF(item); +			Py_DECREF(seq); +			goto finally;  		} -	} -	else { -		for (i = 0; i < seqlen; i++) { -			PyObject *item = PySequence_GetItem(seq, i); -			if (!item) -				goto finally; -			if (!PyString_Check(item)){ -				if (PyUnicode_Check(item)) { -					Py_DECREF(res); -					Py_DECREF(item); -					return PyUnicode_Join( -							 (PyObject *)self,  -							 seq); -				} +		slen = PyString_GET_SIZE(item); +		while (reslen + slen + seplen >= sz) { +			if (_PyString_Resize(&res, sz*2)) {  				Py_DECREF(item); -				PyErr_Format(PyExc_TypeError, -					     "sequence item %i not a string", -					     i); +				Py_DECREF(seq);  				goto finally;  			} -			slen = PyString_GET_SIZE(item); -			while (reslen + slen + seplen >= sz) { -				if (_PyString_Resize(&res, sz*2)) { -					Py_DECREF(item); -					goto finally; -				} -				sz *= 2; -				p = PyString_AsString(res) + reslen; -			} -			if (i > 0) { -				memcpy(p, sep, seplen); -				p += seplen; -				reslen += seplen; -			} -			memcpy(p, PyString_AS_STRING(item), slen); -			Py_DECREF(item); -			p += slen; -			reslen += slen; +			sz *= 2; +			p = PyString_AsString(res) + reslen; +		} +		if (i > 0) { +			memcpy(p, sep, seplen); +			p += seplen; +			reslen += seplen;  		} +		memcpy(p, PyString_AS_STRING(item), slen); +		Py_DECREF(item); +		p += slen; +		reslen += slen;  	}  	if (_PyString_Resize(&res, reslen))  		goto finally;  | 
