30
30
PyStructSequence_New(PyTypeObject *type)
32
PyStructSequence *obj;
34
obj = PyObject_New(PyStructSequence, type);
37
Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
39
return (PyObject*) obj;
32
PyStructSequence *obj;
34
obj = PyObject_New(PyStructSequence, type);
37
Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
39
return (PyObject*) obj;
43
43
structseq_dealloc(PyStructSequence *obj)
47
size = REAL_SIZE(obj);
48
for (i = 0; i < size; ++i) {
49
Py_XDECREF(obj->ob_item[i]);
47
size = REAL_SIZE(obj);
48
for (i = 0; i < size; ++i) {
49
Py_XDECREF(obj->ob_item[i]);
55
55
structseq_length(PyStructSequence *obj)
57
return VISIBLE_SIZE(obj);
57
return VISIBLE_SIZE(obj);
61
61
structseq_item(PyStructSequence *obj, Py_ssize_t i)
63
if (i < 0 || i >= VISIBLE_SIZE(obj)) {
64
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
67
Py_INCREF(obj->ob_item[i]);
68
return obj->ob_item[i];
63
if (i < 0 || i >= VISIBLE_SIZE(obj)) {
64
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
67
Py_INCREF(obj->ob_item[i]);
68
return obj->ob_item[i];
72
72
structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
79
if (high > VISIBLE_SIZE(obj))
80
high = VISIBLE_SIZE(obj);
83
np = (PyTupleObject *)PyTuple_New(high-low);
86
for(i = low; i < high; ++i) {
87
PyObject *v = obj->ob_item[i];
89
PyTuple_SET_ITEM(np, i-low, v);
91
return (PyObject *) np;
79
if (high > VISIBLE_SIZE(obj))
80
high = VISIBLE_SIZE(obj);
83
np = (PyTupleObject *)PyTuple_New(high-low);
86
for(i = low; i < high; ++i) {
87
PyObject *v = obj->ob_item[i];
89
PyTuple_SET_ITEM(np, i-low, v);
91
return (PyObject *) np;
95
95
structseq_subscript(PyStructSequence *self, PyObject *item)
97
if (PyIndex_Check(item)) {
98
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
99
if (i == -1 && PyErr_Occurred())
103
i += VISIBLE_SIZE(self);
105
if (i < 0 || i >= VISIBLE_SIZE(self)) {
106
PyErr_SetString(PyExc_IndexError,
107
"tuple index out of range");
110
Py_INCREF(self->ob_item[i]);
111
return self->ob_item[i];
113
else if (PySlice_Check(item)) {
114
Py_ssize_t start, stop, step, slicelen, cur, i;
117
if (PySlice_GetIndicesEx((PySliceObject *)item,
118
VISIBLE_SIZE(self), &start, &stop,
119
&step, &slicelen) < 0) {
123
return PyTuple_New(0);
124
result = PyTuple_New(slicelen);
127
for (cur = start, i = 0; i < slicelen;
129
PyObject *v = self->ob_item[cur];
131
PyTuple_SET_ITEM(result, i, v);
136
PyErr_SetString(PyExc_TypeError,
137
"structseq index must be integer");
97
if (PyIndex_Check(item)) {
98
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
99
if (i == -1 && PyErr_Occurred())
103
i += VISIBLE_SIZE(self);
105
if (i < 0 || i >= VISIBLE_SIZE(self)) {
106
PyErr_SetString(PyExc_IndexError,
107
"tuple index out of range");
110
Py_INCREF(self->ob_item[i]);
111
return self->ob_item[i];
113
else if (PySlice_Check(item)) {
114
Py_ssize_t start, stop, step, slicelen, cur, i;
117
if (PySlice_GetIndicesEx((PySliceObject *)item,
118
VISIBLE_SIZE(self), &start, &stop,
119
&step, &slicelen) < 0) {
123
return PyTuple_New(0);
124
result = PyTuple_New(slicelen);
127
for (cur = start, i = 0; i < slicelen;
129
PyObject *v = self->ob_item[cur];
131
PyTuple_SET_ITEM(result, i, v);
136
PyErr_SetString(PyExc_TypeError,
137
"structseq index must be integer");
142
142
static PyObject *
143
143
structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
145
PyObject *arg = NULL;
146
PyObject *dict = NULL;
148
PyStructSequence *res = NULL;
149
Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
150
static char *kwlist[] = {"sequence", "dict", 0};
152
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",
153
kwlist, &arg, &dict))
156
arg = PySequence_Fast(arg, "constructor requires a sequence");
162
if (dict && !PyDict_Check(dict)) {
163
PyErr_Format(PyExc_TypeError,
164
"%.500s() takes a dict as second arg, if any",
170
len = PySequence_Fast_GET_SIZE(arg);
171
min_len = VISIBLE_SIZE_TP(type);
172
max_len = REAL_SIZE_TP(type);
173
n_unnamed_fields = UNNAMED_FIELDS_TP(type);
175
if (min_len != max_len) {
177
PyErr_Format(PyExc_TypeError,
178
"%.500s() takes an at least %zd-sequence (%zd-sequence given)",
179
type->tp_name, min_len, len);
185
PyErr_Format(PyExc_TypeError,
186
"%.500s() takes an at most %zd-sequence (%zd-sequence given)",
187
type->tp_name, max_len, len);
193
if (len != min_len) {
194
PyErr_Format(PyExc_TypeError,
195
"%.500s() takes a %zd-sequence (%zd-sequence given)",
196
type->tp_name, min_len, len);
202
res = (PyStructSequence*) PyStructSequence_New(type);
206
for (i = 0; i < len; ++i) {
207
PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
211
for (; i < max_len; ++i) {
212
if (dict && (ob = PyDict_GetItemString(
213
dict, type->tp_members[i-n_unnamed_fields].name))) {
219
res->ob_item[i] = ob;
223
return (PyObject*) res;
145
PyObject *arg = NULL;
146
PyObject *dict = NULL;
148
PyStructSequence *res = NULL;
149
Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
150
static char *kwlist[] = {"sequence", "dict", 0};
152
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",
153
kwlist, &arg, &dict))
156
arg = PySequence_Fast(arg, "constructor requires a sequence");
162
if (dict && !PyDict_Check(dict)) {
163
PyErr_Format(PyExc_TypeError,
164
"%.500s() takes a dict as second arg, if any",
170
len = PySequence_Fast_GET_SIZE(arg);
171
min_len = VISIBLE_SIZE_TP(type);
172
max_len = REAL_SIZE_TP(type);
173
n_unnamed_fields = UNNAMED_FIELDS_TP(type);
175
if (min_len != max_len) {
177
PyErr_Format(PyExc_TypeError,
178
"%.500s() takes an at least %zd-sequence (%zd-sequence given)",
179
type->tp_name, min_len, len);
185
PyErr_Format(PyExc_TypeError,
186
"%.500s() takes an at most %zd-sequence (%zd-sequence given)",
187
type->tp_name, max_len, len);
193
if (len != min_len) {
194
PyErr_Format(PyExc_TypeError,
195
"%.500s() takes a %zd-sequence (%zd-sequence given)",
196
type->tp_name, min_len, len);
202
res = (PyStructSequence*) PyStructSequence_New(type);
206
for (i = 0; i < len; ++i) {
207
PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
211
for (; i < max_len; ++i) {
212
if (dict && (ob = PyDict_GetItemString(
213
dict, type->tp_members[i-n_unnamed_fields].name))) {
219
res->ob_item[i] = ob;
223
return (PyObject*) res;
226
226
static PyObject *
227
227
make_tuple(PyStructSequence *obj)
229
return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
229
return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
232
232
static PyObject *
233
233
structseq_repr(PyStructSequence *obj)
235
/* buffer and type size were chosen well considered. */
235
/* buffer and type size were chosen well considered. */
236
236
#define REPR_BUFFER_SIZE 512
237
237
#define TYPE_MAXSIZE 100
240
PyTypeObject *typ = Py_TYPE(obj);
241
int i, removelast = 0;
243
char buf[REPR_BUFFER_SIZE];
244
char *endofbuf, *pbuf = buf;
246
/* pointer to end of writeable buffer; safes space for "...)\0" */
247
endofbuf= &buf[REPR_BUFFER_SIZE-5];
249
if ((tup = make_tuple(obj)) == NULL) {
253
/* "typename(", limited to TYPE_MAXSIZE */
254
len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
255
strlen(typ->tp_name);
256
strncpy(pbuf, typ->tp_name, len);
260
for (i=0; i < VISIBLE_SIZE(obj); i++) {
261
PyObject *val, *repr;
264
cname = typ->tp_members[i].name;
266
val = PyTuple_GetItem(tup, i);
267
if (cname == NULL || val == NULL) {
270
repr = PyObject_Repr(val);
275
crepr = _PyUnicode_AsString(repr);
282
/* + 3: keep space for "=" and ", " */
283
len = strlen(cname) + strlen(crepr) + 3;
284
if ((pbuf+len) <= endofbuf) {
286
pbuf += strlen(cname);
289
pbuf += strlen(crepr);
305
/* overwrite last ", " */
311
return PyUnicode_FromString(buf);
240
PyTypeObject *typ = Py_TYPE(obj);
241
int i, removelast = 0;
243
char buf[REPR_BUFFER_SIZE];
244
char *endofbuf, *pbuf = buf;
246
/* pointer to end of writeable buffer; safes space for "...)\0" */
247
endofbuf= &buf[REPR_BUFFER_SIZE-5];
249
if ((tup = make_tuple(obj)) == NULL) {
253
/* "typename(", limited to TYPE_MAXSIZE */
254
len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
255
strlen(typ->tp_name);
256
strncpy(pbuf, typ->tp_name, len);
260
for (i=0; i < VISIBLE_SIZE(obj); i++) {
261
PyObject *val, *repr;
264
cname = typ->tp_members[i].name;
266
val = PyTuple_GetItem(tup, i);
267
if (cname == NULL || val == NULL) {
270
repr = PyObject_Repr(val);
275
crepr = _PyUnicode_AsString(repr);
282
/* + 3: keep space for "=" and ", " */
283
len = strlen(cname) + strlen(crepr) + 3;
284
if ((pbuf+len) <= endofbuf) {
286
pbuf += strlen(cname);
289
pbuf += strlen(crepr);
305
/* overwrite last ", " */
311
return PyUnicode_FromString(buf);
314
314
static PyObject *
315
315
structseq_concat(PyStructSequence *obj, PyObject *b)
317
PyObject *tup, *result;
318
tup = make_tuple(obj);
319
result = PySequence_Concat(tup, b);
317
PyObject *tup, *result;
318
tup = make_tuple(obj);
319
result = PySequence_Concat(tup, b);
324
324
static PyObject *
325
325
structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
327
PyObject *tup, *result;
328
tup = make_tuple(obj);
329
result = PySequence_Repeat(tup, n);
327
PyObject *tup, *result;
328
tup = make_tuple(obj);
329
result = PySequence_Repeat(tup, n);
335
335
structseq_contains(PyStructSequence *obj, PyObject *o)
339
tup = make_tuple(obj);
342
result = PySequence_Contains(tup, o);
339
tup = make_tuple(obj);
342
result = PySequence_Contains(tup, o);
348
348
structseq_hash(PyObject *obj)
352
tup = make_tuple((PyStructSequence*) obj);
355
result = PyObject_Hash(tup);
352
tup = make_tuple((PyStructSequence*) obj);
355
result = PyObject_Hash(tup);
360
360
static PyObject *
361
361
structseq_richcompare(PyObject *obj, PyObject *o2, int op)
363
PyObject *tup, *result;
364
tup = make_tuple((PyStructSequence*) obj);
365
result = PyObject_RichCompare(tup, o2, op);
363
PyObject *tup, *result;
364
tup = make_tuple((PyStructSequence*) obj);
365
result = PyObject_RichCompare(tup, o2, op);
370
370
static PyObject *
371
371
structseq_reduce(PyStructSequence* self)
376
Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
379
n_fields = REAL_SIZE(self);
380
n_visible_fields = VISIBLE_SIZE(self);
381
n_unnamed_fields = UNNAMED_FIELDS(self);
382
tup = PyTuple_New(n_visible_fields);
393
for (i = 0; i < n_visible_fields; i++) {
394
Py_INCREF(self->ob_item[i]);
395
PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
398
for (; i < n_fields; i++) {
399
char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
400
PyDict_SetItemString(dict, n,
404
result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
376
Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
379
n_fields = REAL_SIZE(self);
380
n_visible_fields = VISIBLE_SIZE(self);
381
n_unnamed_fields = UNNAMED_FIELDS(self);
382
tup = PyTuple_New(n_visible_fields);
393
for (i = 0; i < n_visible_fields; i++) {
394
Py_INCREF(self->ob_item[i]);
395
PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
398
for (; i < n_fields; i++) {
399
char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
400
PyDict_SetItemString(dict, n,
404
result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
412
412
static PySequenceMethods structseq_as_sequence = {
413
(lenfunc)structseq_length,
414
(binaryfunc)structseq_concat, /* sq_concat */
415
(ssizeargfunc)structseq_repeat, /* sq_repeat */
416
(ssizeargfunc)structseq_item, /* sq_item */
419
0, /* sq_ass_slice */
420
(objobjproc)structseq_contains, /* sq_contains */
413
(lenfunc)structseq_length,
414
(binaryfunc)structseq_concat, /* sq_concat */
415
(ssizeargfunc)structseq_repeat, /* sq_repeat */
416
(ssizeargfunc)structseq_item, /* sq_item */
419
0, /* sq_ass_slice */
420
(objobjproc)structseq_contains, /* sq_contains */
423
423
static PyMappingMethods structseq_as_mapping = {
424
(lenfunc)structseq_length,
425
(binaryfunc)structseq_subscript,
424
(lenfunc)structseq_length,
425
(binaryfunc)structseq_subscript,
428
428
static PyMethodDef structseq_methods[] = {
429
{"__reduce__", (PyCFunction)structseq_reduce,
429
{"__reduce__", (PyCFunction)structseq_reduce,
434
434
static PyTypeObject _struct_sequence_template = {
435
PyVarObject_HEAD_INIT(&PyType_Type, 0)
437
0, /* tp_basicsize */
439
(destructor)structseq_dealloc, /* tp_dealloc */
444
(reprfunc)structseq_repr, /* tp_repr */
445
0, /* tp_as_number */
446
&structseq_as_sequence, /* tp_as_sequence */
447
&structseq_as_mapping, /* tp_as_mapping */
448
structseq_hash, /* tp_hash */
453
0, /* tp_as_buffer */
454
Py_TPFLAGS_DEFAULT, /* tp_flags */
458
structseq_richcompare, /* tp_richcompare */
459
0, /* tp_weaklistoffset */
462
structseq_methods, /* tp_methods */
463
NULL, /* tp_members */
467
0, /* tp_descr_get */
468
0, /* tp_descr_set */
469
0, /* tp_dictoffset */
472
structseq_new, /* tp_new */
435
PyVarObject_HEAD_INIT(&PyType_Type, 0)
437
0, /* tp_basicsize */
439
(destructor)structseq_dealloc, /* tp_dealloc */
444
(reprfunc)structseq_repr, /* tp_repr */
445
0, /* tp_as_number */
446
&structseq_as_sequence, /* tp_as_sequence */
447
&structseq_as_mapping, /* tp_as_mapping */
448
structseq_hash, /* tp_hash */
453
0, /* tp_as_buffer */
454
Py_TPFLAGS_DEFAULT, /* tp_flags */
458
structseq_richcompare, /* tp_richcompare */
459
0, /* tp_weaklistoffset */
462
structseq_methods, /* tp_methods */
463
NULL, /* tp_members */
467
0, /* tp_descr_get */
468
0, /* tp_descr_set */
469
0, /* tp_dictoffset */
472
structseq_new, /* tp_new */
476
476
PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
479
PyMemberDef* members;
480
int n_members, n_unnamed_members, i, k;
479
PyMemberDef* members;
480
int n_members, n_unnamed_members, i, k;
482
482
#ifdef Py_TRACE_REFS
483
/* if the type object was chained, unchain it first
484
before overwriting its storage */
485
if (type->ob_base.ob_base._ob_next) {
486
_Py_ForgetReference((PyObject*)type);
483
/* if the type object was chained, unchain it first
484
before overwriting its storage */
485
if (type->ob_base.ob_base._ob_next) {
486
_Py_ForgetReference((PyObject*)type);
490
n_unnamed_members = 0;
491
for (i = 0; desc->fields[i].name != NULL; ++i)
492
if (desc->fields[i].name == PyStructSequence_UnnamedField)
496
memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
497
type->tp_name = desc->name;
498
type->tp_doc = desc->doc;
499
type->tp_basicsize = sizeof(PyStructSequence)+
500
sizeof(PyObject*)*(n_members-1);
501
type->tp_itemsize = 0;
503
members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
507
for (i = k = 0; i < n_members; ++i) {
508
if (desc->fields[i].name == PyStructSequence_UnnamedField)
510
members[k].name = desc->fields[i].name;
511
members[k].type = T_OBJECT;
512
members[k].offset = offsetof(PyStructSequence, ob_item)
513
+ i * sizeof(PyObject*);
514
members[k].flags = READONLY;
515
members[k].doc = desc->fields[i].doc;
518
members[k].name = NULL;
520
type->tp_members = members;
522
if (PyType_Ready(type) < 0)
526
dict = type->tp_dict;
527
#define SET_DICT_FROM_INT(key, value) \
529
PyObject *v = PyLong_FromLong((long) value); \
531
PyDict_SetItemString(dict, key, v); \
536
SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
537
SET_DICT_FROM_INT(real_length_key, n_members);
538
SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);
490
n_unnamed_members = 0;
491
for (i = 0; desc->fields[i].name != NULL; ++i)
492
if (desc->fields[i].name == PyStructSequence_UnnamedField)
496
memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
497
type->tp_name = desc->name;
498
type->tp_doc = desc->doc;
499
type->tp_basicsize = sizeof(PyStructSequence)+
500
sizeof(PyObject*)*(n_members-1);
501
type->tp_itemsize = 0;
503
members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
507
for (i = k = 0; i < n_members; ++i) {
508
if (desc->fields[i].name == PyStructSequence_UnnamedField)
510
members[k].name = desc->fields[i].name;
511
members[k].type = T_OBJECT;
512
members[k].offset = offsetof(PyStructSequence, ob_item)
513
+ i * sizeof(PyObject*);
514
members[k].flags = READONLY;
515
members[k].doc = desc->fields[i].doc;
518
members[k].name = NULL;
520
type->tp_members = members;
522
if (PyType_Ready(type) < 0)
526
dict = type->tp_dict;
527
#define SET_DICT_FROM_INT(key, value) \
529
PyObject *v = PyLong_FromLong((long) value); \
531
PyDict_SetItemString(dict, key, v); \
536
SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
537
SET_DICT_FROM_INT(real_length_key, n_members);
538
SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);