diff options
author | Andrew M. Kuchling <amk@amk.ca> | 2000-06-18 18:43:14 (GMT) |
---|---|---|
committer | Andrew M. Kuchling <amk@amk.ca> | 2000-06-18 18:43:14 (GMT) |
commit | 74042d6e5d44cc9d332c28414a1e04eadd204248 (patch) | |
tree | 888efb4a5da65b5fed5d282d019af6fb29fefe0b | |
parent | b75c485f0bc6394f616d4a0bc746e613fd7b1021 (diff) | |
download | cpython-74042d6e5d44cc9d332c28414a1e04eadd204248.zip cpython-74042d6e5d44cc9d332c28414a1e04eadd204248.tar.gz cpython-74042d6e5d44cc9d332c28414a1e04eadd204248.tar.bz2 |
Patch from /F:
this patch introduces PySequence_Fast and PySequence_Fast_GET_ITEM,
and modifies the list.extend method to accept any kind of sequence.
-rw-r--r-- | Include/abstract.h | 21 | ||||
-rw-r--r-- | Objects/abstract.c | 20 | ||||
-rw-r--r-- | Objects/listobject.c | 37 |
3 files changed, 56 insertions, 22 deletions
diff --git a/Include/abstract.h b/Include/abstract.h index 12d799d..70c0e7c 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -731,7 +731,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ /* Return the ith element of o, or NULL on failure. This is the equivalent of the Python expression: o[i]. - */ DL_IMPORT(PyObject *) PySequence_GetSlice Py_PROTO((PyObject *o, int i1, int i2)); @@ -783,6 +782,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ This is equivalent to the Python expression: tuple(o) */ + DL_IMPORT(PyObject *) PySequence_List Py_PROTO((PyObject *o)); /* @@ -790,6 +790,25 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ This is equivalent to the Python expression: list(o) */ + DL_IMPORT(PyObject *) PySequence_Fast Py_PROTO((PyObject *o, const char* m)); + + /* + Returns the sequence, o, as a tuple, unless it's already a + tuple or list. Use PySequence_Fast_GET_ITEM to access the + members of this list. + + Returns NULL on failure. If the object is not a sequence, + raises a TypeError exception with m as the message text. + */ + +#define PySequence_Fast_GET_ITEM(o, i)\ + (PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i)) + + /* + Return the ith element of o, assuming that o was returned by + PySequence_Fast, and that i is within bounds. + */ + DL_IMPORT(int) PySequence_Count Py_PROTO((PyObject *o, PyObject *value)); /* diff --git a/Objects/abstract.c b/Objects/abstract.c index 410b80b..79af2f8 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1207,6 +1207,26 @@ PySequence_List(v) return type_error("list() argument must be a sequence"); } +PyObject * +PySequence_Fast(v, m) + PyObject *v; + const char* m; +{ + if (v == NULL) + return null_error(); + + if (PyList_Check(v) || PyTuple_Check(v)) { + Py_INCREF(v); + return v; + } + + v = PySequence_Tuple(v); + if (v == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) + return type_error(m); + + return v; +} + int PySequence_Count(s, o) PyObject *s; diff --git a/Objects/listobject.c b/Objects/listobject.c index 3bb5aec..163ba2a 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -627,16 +627,14 @@ listextend(self, args) if (!PyArg_ParseTuple(args, "O:extend", &b)) return NULL; - if (!PyList_Check(b)) { - PyErr_SetString(PyExc_TypeError, - "list.extend() argument must be a list"); + b = PySequence_Fast(b, "list.extend() argument must be a sequence"); + if (!b) return NULL; - } - if (PyList_GET_SIZE(b) == 0) { + + if (PyObject_Length(b) == 0) /* short circuit when b is empty */ - Py_INCREF(Py_None); - return Py_None; - } + goto ok; + if (self == (PyListObject*)b) { /* as in list_ass_slice() we must special case the * situation: a.extend(a) @@ -644,6 +642,7 @@ listextend(self, args) * XXX: I think this way ought to be faster than using * list_slice() the way list_ass_slice() does. */ + Py_DECREF(b); b = PyList_New(selflen); if (!b) return NULL; @@ -653,33 +652,29 @@ listextend(self, args) PyList_SET_ITEM(b, i, o); } } - else - /* we want b to have the same refcount semantics for the - * Py_XDECREF() in the finally clause regardless of which - * branch in the above conditional we took. - */ - Py_INCREF(b); - blen = PyList_GET_SIZE(b); + blen = PyObject_Length(b); + /* resize a using idiom */ items = self->ob_item; NRESIZE(items, PyObject*, selflen + blen); - if (items == NULL ) { + if (items == NULL) { PyErr_NoMemory(); - goto finally; + goto failed; } self->ob_item = items; - /* populate the end self with b's items */ + /* populate the end of self with b's items */ for (i = 0; i < blen; i++) { - PyObject *o = PyList_GET_ITEM(b, i); + PyObject *o = PySequence_Fast_GET_ITEM(b, i); Py_INCREF(o); PyList_SET_ITEM(self, self->ob_size++, o); } + ok: res = Py_None; Py_INCREF(res); - finally: - Py_XDECREF(b); + failed: + Py_DECREF(b); return res; } |