Kaydet (Commit) ccabcd4b authored tarafından Benjamin Peterson's avatar Benjamin Peterson

make struct sequences subclass tuple; kill lots of code

This fixes #8413.
üst a9800a8d
...@@ -26,17 +26,12 @@ PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type, ...@@ -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
......
...@@ -12,6 +12,8 @@ What's New in Python 3.2 Alpha 1? ...@@ -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.
......
...@@ -30,113 +30,15 @@ PyObject * ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment