make struct sequences subclass tuple; kill lots of code

This fixes #8413.
This commit is contained in:
Benjamin Peterson 2010-07-07 20:54:01 +00:00
parent a9800a8d5b
commit ccabcd4bd4
3 changed files with 23 additions and 215 deletions

View File

@ -26,17 +26,12 @@ PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type,
PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type); PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
typedef struct { typedef PyTupleObject PyStructSequence;
PyObject_VAR_HEAD
PyObject *ob_item[1];
} PyStructSequence;
/* Macro, *only* to be used to fill in brand new objects */ /* Macro, *only* to be used to fill in brand new objects */
#define PyStructSequence_SET_ITEM(op, i, v) \ #define PyStructSequence_SET_ITEM(op, i, v) PyTuple_SET_ITEM(op, i, v)
(((PyStructSequence *)(op))->ob_item[i] = v)
#define PyStructSequence_GET_ITEM(op, i) \ #define PyStructSequence_GET_ITEM(op, i) PyTuple_GET_ITEM(op, i)
(((PyStructSequence *)(op))->ob_item[i])
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -12,6 +12,8 @@ What's New in Python 3.2 Alpha 1?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #8413: structsequence now subclasses tuple.
- Issue #8271: during the decoding of an invalid UTF-8 byte sequence, only the - Issue #8271: during the decoding of an invalid UTF-8 byte sequence, only the
start byte and the continuation byte(s) are now considered invalid, instead start byte and the continuation byte(s) are now considered invalid, instead
of the number of bytes specified by the start byte. of the number of bytes specified by the start byte.

View File

@ -30,113 +30,15 @@ PyObject *
PyStructSequence_New(PyTypeObject *type) PyStructSequence_New(PyTypeObject *type)
{ {
PyStructSequence *obj; PyStructSequence *obj;
Py_ssize_t size = REAL_SIZE_TP(type), i;
obj = PyObject_New(PyStructSequence, type); obj = PyObject_GC_NewVar(PyStructSequence, type, size);
if (obj == NULL) if (obj == NULL)
return NULL; return NULL;
Py_SIZE(obj) = VISIBLE_SIZE_TP(type); for (i = 0; i < size; i++)
obj->ob_item[i] = NULL;
return (PyObject*) obj; return (PyObject*)obj;
}
static void
structseq_dealloc(PyStructSequence *obj)
{
Py_ssize_t i, size;
size = REAL_SIZE(obj);
for (i = 0; i < size; ++i) {
Py_XDECREF(obj->ob_item[i]);
}
PyObject_Del(obj);
}
static Py_ssize_t
structseq_length(PyStructSequence *obj)
{
return VISIBLE_SIZE(obj);
}
static PyObject*
structseq_item(PyStructSequence *obj, Py_ssize_t i)
{
if (i < 0 || i >= VISIBLE_SIZE(obj)) {
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
return NULL;
}
Py_INCREF(obj->ob_item[i]);
return obj->ob_item[i];
}
static PyObject*
structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
{
PyTupleObject *np;
Py_ssize_t i;
if (low < 0)
low = 0;
if (high > VISIBLE_SIZE(obj))
high = VISIBLE_SIZE(obj);
if (high < low)
high = low;
np = (PyTupleObject *)PyTuple_New(high-low);
if (np == NULL)
return NULL;
for(i = low; i < high; ++i) {
PyObject *v = obj->ob_item[i];
Py_INCREF(v);
PyTuple_SET_ITEM(np, i-low, v);
}
return (PyObject *) np;
}
static PyObject *
structseq_subscript(PyStructSequence *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += VISIBLE_SIZE(self);
if (i < 0 || i >= VISIBLE_SIZE(self)) {
PyErr_SetString(PyExc_IndexError,
"tuple index out of range");
return NULL;
}
Py_INCREF(self->ob_item[i]);
return self->ob_item[i];
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen, cur, i;
PyObject *result;
if (PySlice_GetIndicesEx((PySliceObject *)item,
VISIBLE_SIZE(self), &start, &stop,
&step, &slicelen) < 0) {
return NULL;
}
if (slicelen <= 0)
return PyTuple_New(0);
result = PyTuple_New(slicelen);
if (result == NULL)
return NULL;
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
PyObject *v = self->ob_item[cur];
Py_INCREF(v);
PyTuple_SET_ITEM(result, i, v);
}
return result;
}
else {
PyErr_SetString(PyExc_TypeError,
"structseq index must be integer");
return NULL;
}
} }
static PyObject * static PyObject *
@ -223,11 +125,6 @@ structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject*) res; return (PyObject*) res;
} }
static PyObject *
make_tuple(PyStructSequence *obj)
{
return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
}
static PyObject * static PyObject *
structseq_repr(PyStructSequence *obj) structseq_repr(PyStructSequence *obj)
@ -236,7 +133,6 @@ structseq_repr(PyStructSequence *obj)
#define REPR_BUFFER_SIZE 512 #define REPR_BUFFER_SIZE 512
#define TYPE_MAXSIZE 100 #define TYPE_MAXSIZE 100
PyObject *tup;
PyTypeObject *typ = Py_TYPE(obj); PyTypeObject *typ = Py_TYPE(obj);
int i, removelast = 0; int i, removelast = 0;
Py_ssize_t len; Py_ssize_t len;
@ -246,10 +142,6 @@ structseq_repr(PyStructSequence *obj)
/* pointer to end of writeable buffer; safes space for "...)\0" */ /* pointer to end of writeable buffer; safes space for "...)\0" */
endofbuf= &buf[REPR_BUFFER_SIZE-5]; endofbuf= &buf[REPR_BUFFER_SIZE-5];
if ((tup = make_tuple(obj)) == NULL) {
return NULL;
}
/* "typename(", limited to TYPE_MAXSIZE */ /* "typename(", limited to TYPE_MAXSIZE */
len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE : len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
strlen(typ->tp_name); strlen(typ->tp_name);
@ -262,19 +154,14 @@ structseq_repr(PyStructSequence *obj)
char *cname, *crepr; char *cname, *crepr;
cname = typ->tp_members[i].name; cname = typ->tp_members[i].name;
if (cname == NULL)
val = PyTuple_GetItem(tup, i);
if (cname == NULL || val == NULL) {
return NULL; return NULL;
} val = PyStructSequence_GET_ITEM(obj, i);
repr = PyObject_Repr(val); repr = PyObject_Repr(val);
if (repr == NULL) { if (repr == NULL)
Py_DECREF(tup);
return NULL; return NULL;
}
crepr = _PyUnicode_AsString(repr); crepr = _PyUnicode_AsString(repr);
if (crepr == NULL) { if (crepr == NULL) {
Py_DECREF(tup);
Py_DECREF(repr); Py_DECREF(repr);
return NULL; return NULL;
} }
@ -300,7 +187,6 @@ structseq_repr(PyStructSequence *obj)
break; break;
} }
} }
Py_DECREF(tup);
if (removelast) { if (removelast) {
/* overwrite last ", " */ /* overwrite last ", " */
pbuf-=2; pbuf-=2;
@ -311,62 +197,6 @@ structseq_repr(PyStructSequence *obj)
return PyUnicode_FromString(buf); return PyUnicode_FromString(buf);
} }
static PyObject *
structseq_concat(PyStructSequence *obj, PyObject *b)
{
PyObject *tup, *result;
tup = make_tuple(obj);
result = PySequence_Concat(tup, b);
Py_DECREF(tup);
return result;
}
static PyObject *
structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
{
PyObject *tup, *result;
tup = make_tuple(obj);
result = PySequence_Repeat(tup, n);
Py_DECREF(tup);
return result;
}
static int
structseq_contains(PyStructSequence *obj, PyObject *o)
{
PyObject *tup;
int result;
tup = make_tuple(obj);
if (!tup)
return -1;
result = PySequence_Contains(tup, o);
Py_DECREF(tup);
return result;
}
static long
structseq_hash(PyObject *obj)
{
PyObject *tup;
long result;
tup = make_tuple((PyStructSequence*) obj);
if (!tup)
return -1;
result = PyObject_Hash(tup);
Py_DECREF(tup);
return result;
}
static PyObject *
structseq_richcompare(PyObject *obj, PyObject *o2, int op)
{
PyObject *tup, *result;
tup = make_tuple((PyStructSequence*) obj);
result = PyObject_RichCompare(tup, o2, op);
Py_DECREF(tup);
return result;
}
static PyObject * static PyObject *
structseq_reduce(PyStructSequence* self) structseq_reduce(PyStructSequence* self)
{ {
@ -409,53 +239,36 @@ structseq_reduce(PyStructSequence* self)
return result; return result;
} }
static PySequenceMethods structseq_as_sequence = {
(lenfunc)structseq_length,
(binaryfunc)structseq_concat, /* sq_concat */
(ssizeargfunc)structseq_repeat, /* sq_repeat */
(ssizeargfunc)structseq_item, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)structseq_contains, /* sq_contains */
};
static PyMappingMethods structseq_as_mapping = {
(lenfunc)structseq_length,
(binaryfunc)structseq_subscript,
};
static PyMethodDef structseq_methods[] = { static PyMethodDef structseq_methods[] = {
{"__reduce__", (PyCFunction)structseq_reduce, {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL},
METH_NOARGS, NULL},
{NULL, NULL} {NULL, NULL}
}; };
static PyTypeObject _struct_sequence_template = { static PyTypeObject _struct_sequence_template = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
NULL, /* tp_name */ NULL, /* tp_name */
0, /* tp_basicsize */ sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */
0, /* tp_itemsize */ sizeof(PyObject *), /* tp_itemsize */
(destructor)structseq_dealloc, /* tp_dealloc */ 0, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_reserved */ 0, /* tp_reserved */
(reprfunc)structseq_repr, /* tp_repr */ (reprfunc)structseq_repr, /* tp_repr */
0, /* tp_as_number */ 0, /* tp_as_number */
&structseq_as_sequence, /* tp_as_sequence */ 0, /* tp_as_sequence */
&structseq_as_mapping, /* tp_as_mapping */ 0, /* tp_as_mapping */
structseq_hash, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ 0, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_flags */
NULL, /* tp_doc */ NULL, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
structseq_richcompare, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
@ -494,11 +307,9 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
n_members = i; n_members = i;
memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject)); memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
type->tp_base = &PyTuple_Type;
type->tp_name = desc->name; type->tp_name = desc->name;
type->tp_doc = desc->doc; type->tp_doc = desc->doc;
type->tp_basicsize = sizeof(PyStructSequence)+
sizeof(PyObject*)*(n_members-1);
type->tp_itemsize = 0;
members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1); members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
if (members == NULL) if (members == NULL)