Issue #25558: Refactoring OrderedDict iteration.

This commit is contained in:
Serhiy Storchaka 2015-11-06 10:39:51 +02:00
parent 98da9d0e0d
commit 9c967611e3
1 changed files with 35 additions and 44 deletions

View File

@ -1829,7 +1829,7 @@ done:
static PyObject * static PyObject *
odictiter_iternext(odictiterobject *di) odictiter_iternext(odictiterobject *di)
{ {
PyObject *value; PyObject *result, *value;
PyObject *key = odictiter_nextkey(di); /* new reference */ PyObject *key = odictiter_nextkey(di); /* new reference */
if (key == NULL) if (key == NULL)
@ -1840,53 +1840,44 @@ odictiter_iternext(odictiterobject *di)
return key; return key;
} }
/* Handle the items case. */ value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
if (di->kind & _odict_ITER_KEYS) { if (value == NULL) {
PyObject *result = di->di_result; if (!PyErr_Occurred())
PyErr_SetObject(PyExc_KeyError, key);
value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ Py_DECREF(key);
if (value == NULL) { goto done;
if (!PyErr_Occurred()) }
PyErr_SetObject(PyExc_KeyError, key); Py_INCREF(value);
Py_DECREF(key);
goto done; /* Handle the values case. */
} if (!(di->kind & _odict_ITER_KEYS)) {
Py_INCREF(value);
if (result->ob_refcnt == 1) {
/* not in use so we can reuse it
* (the common case during iteration) */
Py_INCREF(result);
Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
}
else {
result = PyTuple_New(2);
if (result == NULL) {
Py_DECREF(key);
Py_DECREF(value);
goto done;
}
}
PyTuple_SET_ITEM(result, 0, key); /* steals reference */
PyTuple_SET_ITEM(result, 1, value); /* steals reference */
return result;
}
/* Handle the values case. */
else {
value = PyODict_GetItem((PyObject *)di->di_odict, key);
Py_DECREF(key); Py_DECREF(key);
if (value == NULL) {
if (!PyErr_Occurred())
PyErr_SetObject(PyExc_KeyError, key);
goto done;
}
Py_INCREF(value);
return value; return value;
} }
/* Handle the items case. */
result = di->di_result;
if (Py_REFCNT(result) == 1) {
/* not in use so we can reuse it
* (the common case during iteration) */
Py_INCREF(result);
Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
}
else {
result = PyTuple_New(2);
if (result == NULL) {
Py_DECREF(key);
Py_DECREF(value);
goto done;
}
}
PyTuple_SET_ITEM(result, 0, key); /* steals reference */
PyTuple_SET_ITEM(result, 1, value); /* steals reference */
return result;
done: done:
Py_CLEAR(di->di_current); Py_CLEAR(di->di_current);
Py_CLEAR(di->di_odict); Py_CLEAR(di->di_odict);