Eliminate a big block of duplicate code in PySequence_List() by
exposing _PyList_Extend().
This commit is contained in:
parent
97bc618229
commit
8ca92ae54c
|
@ -41,6 +41,7 @@ PyAPI_FUNC(int) PyList_SetSlice(PyObject *, int, int, PyObject *);
|
||||||
PyAPI_FUNC(int) PyList_Sort(PyObject *);
|
PyAPI_FUNC(int) PyList_Sort(PyObject *);
|
||||||
PyAPI_FUNC(int) PyList_Reverse(PyObject *);
|
PyAPI_FUNC(int) PyList_Reverse(PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *);
|
PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *);
|
||||||
|
PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *);
|
||||||
|
|
||||||
/* Macro, trading safety for speed */
|
/* Macro, trading safety for speed */
|
||||||
#define PyList_GET_ITEM(op, i) (((PyListObject *)(op))->ob_item[i])
|
#define PyList_GET_ITEM(op, i) (((PyListObject *)(op))->ob_item[i])
|
||||||
|
|
|
@ -1427,69 +1427,21 @@ Fail:
|
||||||
PyObject *
|
PyObject *
|
||||||
PySequence_List(PyObject *v)
|
PySequence_List(PyObject *v)
|
||||||
{
|
{
|
||||||
PyObject *it; /* iter(v) */
|
|
||||||
PyObject *result; /* result list */
|
PyObject *result; /* result list */
|
||||||
int n; /* guess for result list size */
|
PyObject *rv; /* return value from PyList_Extend */
|
||||||
int i;
|
|
||||||
|
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return null_error();
|
return null_error();
|
||||||
|
|
||||||
/* Special-case list(a_list), for speed. */
|
result = PyList_New(0);
|
||||||
if (PyList_Check(v))
|
if (result == NULL)
|
||||||
return PyList_GetSlice(v, 0, PyList_GET_SIZE(v));
|
|
||||||
|
|
||||||
/* Get iterator. There may be some low-level efficiency to be gained
|
|
||||||
* by caching the tp_iternext slot instead of using PyIter_Next()
|
|
||||||
* later, but premature optimization is the root etc.
|
|
||||||
*/
|
|
||||||
it = PyObject_GetIter(v);
|
|
||||||
if (it == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Guess a result list size. */
|
rv = _PyList_Extend((PyListObject *)result, v);
|
||||||
n = PyObject_Size(v);
|
if (rv == NULL) {
|
||||||
if (n < 0) {
|
Py_DECREF(result);
|
||||||
PyErr_Clear();
|
|
||||||
n = 8; /* arbitrary */
|
|
||||||
}
|
|
||||||
result = PyList_New(n);
|
|
||||||
if (result == NULL) {
|
|
||||||
Py_DECREF(it);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run iterator to exhaustion. */
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
PyObject *item = PyIter_Next(it);
|
|
||||||
if (item == NULL) {
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
Py_DECREF(result);
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i < n)
|
|
||||||
PyList_SET_ITEM(result, i, item); /* steals ref */
|
|
||||||
else {
|
|
||||||
int status = PyList_Append(result, item);
|
|
||||||
Py_DECREF(item); /* append creates a new ref */
|
|
||||||
if (status < 0) {
|
|
||||||
Py_DECREF(result);
|
|
||||||
result = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cut back result list if initial guess was too large. */
|
|
||||||
if (i < n && result != NULL) {
|
|
||||||
if (PyList_SetSlice(result, i, n, (PyObject *)NULL) != 0) {
|
|
||||||
Py_DECREF(result);
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_DECREF(it);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -776,6 +776,12 @@ listextend(PyListObject *self, PyObject *b)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyList_Extend(PyListObject *self, PyObject *b)
|
||||||
|
{
|
||||||
|
return listextend(self, b);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
list_inplace_concat(PyListObject *self, PyObject *other)
|
list_inplace_concat(PyListObject *self, PyObject *other)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue