Issue #16475: Simplify the interface to r_ref_allocate and improve comments.

This commit is contained in:
Kristján Valur Jónsson 2013-03-20 11:43:57 -07:00
parent 8d0e427c39
commit e178187bf6
1 changed files with 33 additions and 26 deletions

View File

@ -743,34 +743,37 @@ r_PyLong(RFILE *p)
return NULL; return NULL;
} }
/* allocate the reflist index */ /* allocate the reflist index for a new object. Return -1 on failure */
static PyObject * static Py_ssize_t
r_ref_reserve(PyObject *o, Py_ssize_t *idx, int flag, RFILE *p) r_ref_reserve(int flag, RFILE *p)
{ {
if (flag) { /* currently only FLAG_REF is defined */ if (flag) { /* currently only FLAG_REF is defined */
*idx = PyList_Size(p->refs); Py_ssize_t idx = PyList_Size(p->refs);
if (*idx < 0) if (idx < 0)
goto err; return -1;
if (*idx >= 0x7ffffffe) { if (idx >= 0x7ffffffe) {
PyErr_SetString(PyExc_ValueError, "bad marshal data (index list too large)"); PyErr_SetString(PyExc_ValueError, "bad marshal data (index list too large)");
goto err; return -1;
} }
if (PyList_Append(p->refs, Py_None) < 0) if (PyList_Append(p->refs, Py_None) < 0)
goto err; return -1;
return idx;
} else } else
*idx = 0; return 0;
return o;
err:
Py_XDECREF(o); /* release the new object */
*idx = -1;
return NULL;
} }
/* insert actual object to the reflist */ /* insert the new object 'o' to the reflist at previously
* allocated index 'idx'.
* 'o' can be NULL, in which case nothing is done.
* if 'o' was non-NULL, and the function succeeds, 'o' is returned.
* if 'o' was non-NULL, and the function fails, 'o' is released and
* NULL returned. This simplifies error checking at the call site since
* a single test for NULL for the function result is enough.
*/
static PyObject * static PyObject *
r_ref_insert(PyObject *o, Py_ssize_t idx, int flag, RFILE *p) r_ref_insert(PyObject *o, Py_ssize_t idx, int flag, RFILE *p)
{ {
if (o && (flag & FLAG_REF)) { if (o != NULL && flag) { /* currently only FLAG_REF is defined */
if (PyList_SetItem(p->refs, idx, o) < 0) { if (PyList_SetItem(p->refs, idx, o) < 0) {
Py_DECREF(o); /* release the new object */ Py_DECREF(o); /* release the new object */
return NULL; return NULL;
@ -788,7 +791,7 @@ r_ref_insert(PyObject *o, Py_ssize_t idx, int flag, RFILE *p)
static PyObject * static PyObject *
r_ref(PyObject *o, int flag, RFILE *p) r_ref(PyObject *o, int flag, RFILE *p)
{ {
if (o && (flag & FLAG_REF)) { if (o != NULL && flag) { /* currently only FLAG_REF is defined */
if (PyList_Append(p->refs, o) < 0) { if (PyList_Append(p->refs, o) < 0) {
Py_DECREF(o); /* release the new object */ Py_DECREF(o); /* release the new object */
return NULL; return NULL;
@ -821,7 +824,8 @@ r_object(RFILE *p)
type = type & ~FLAG_REF; type = type & ~FLAG_REF;
#define R_REF(O) do{\ #define R_REF(O) do{\
O = r_ref(O, flag, p);\ if (flag) \
O = r_ref(O, flag, p);\
} while (0) } while (0)
switch (type) { switch (type) {
@ -1143,13 +1147,16 @@ r_object(RFILE *p)
break; break;
} }
v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL); v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL);
/* must use delayed registration of frozensets because they must if (type == TYPE_SET) {
* be init with a refcount of 1
*/
if (type == TYPE_SET)
R_REF(v); R_REF(v);
else } else {
v = r_ref_reserve(v, &idx, flag, p); /* must use delayed registration of frozensets because they must
* be init with a refcount of 1
*/
idx = r_ref_reserve(flag, p);
if (idx < 0)
Py_CLEAR(v); /* signal error */
}
if (v == NULL) { if (v == NULL) {
retval = NULL; retval = NULL;
break; break;
@ -1195,7 +1202,7 @@ r_object(RFILE *p)
int firstlineno; int firstlineno;
PyObject *lnotab = NULL; PyObject *lnotab = NULL;
r_ref_reserve(NULL, &idx, flag, p); idx = r_ref_reserve(flag, p);
if (idx < 0) { if (idx < 0) {
retval = NULL; retval = NULL;
break; break;