blob: cf94155f18f833d27b81aae0cef98d4e4eb55f02 [file] [log] [blame]
Guido van Rossume82f75a2001-10-18 20:47:51 +00001/* Implementation helper: a struct that looks like a tuple. See timemodule
2 and posixmodule for example uses. */
3
4#include "Python.h"
5#include "structmember.h"
Guido van Rossume82f75a2001-10-18 20:47:51 +00006
Serhiy Storchaka2d06e842015-12-25 19:53:18 +02007static const char visible_length_key[] = "n_sequence_fields";
8static const char real_length_key[] = "n_fields";
9static const char unnamed_fields_key[] = "n_unnamed_fields";
Guido van Rossume82f75a2001-10-18 20:47:51 +000010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000011/* Fields with this name have only a field index, not a field name.
Martin v. Löwisf607bda2002-10-16 18:27:39 +000012 They are only allowed for indices < n_visible_fields. */
13char *PyStructSequence_UnnamedField = "unnamed field";
Victor Stinner26f91992013-07-17 01:22:45 +020014_Py_IDENTIFIER(n_sequence_fields);
15_Py_IDENTIFIER(n_fields);
16_Py_IDENTIFIER(n_unnamed_fields);
Martin v. Löwisf607bda2002-10-16 18:27:39 +000017
Christian Heimes90aa7642007-12-19 02:45:37 +000018#define VISIBLE_SIZE(op) Py_SIZE(op)
Serhiy Storchaka56f6e762015-09-06 21:25:30 +030019#define VISIBLE_SIZE_TP(tp) PyLong_AsSsize_t( \
Victor Stinner26f91992013-07-17 01:22:45 +020020 _PyDict_GetItemId((tp)->tp_dict, &PyId_n_sequence_fields))
Guido van Rossume82f75a2001-10-18 20:47:51 +000021
Serhiy Storchaka56f6e762015-09-06 21:25:30 +030022#define REAL_SIZE_TP(tp) PyLong_AsSsize_t( \
Victor Stinner26f91992013-07-17 01:22:45 +020023 _PyDict_GetItemId((tp)->tp_dict, &PyId_n_fields))
Christian Heimes90aa7642007-12-19 02:45:37 +000024#define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
Guido van Rossume82f75a2001-10-18 20:47:51 +000025
Serhiy Storchaka56f6e762015-09-06 21:25:30 +030026#define UNNAMED_FIELDS_TP(tp) PyLong_AsSsize_t( \
Victor Stinner26f91992013-07-17 01:22:45 +020027 _PyDict_GetItemId((tp)->tp_dict, &PyId_n_unnamed_fields))
Christian Heimes90aa7642007-12-19 02:45:37 +000028#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
Martin v. Löwisceaa77c2002-10-16 19:10:03 +000029
Guido van Rossume82f75a2001-10-18 20:47:51 +000030
31PyObject *
32PyStructSequence_New(PyTypeObject *type)
33{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000034 PyStructSequence *obj;
Benjamin Petersonccabcd42010-07-07 20:54:01 +000035 Py_ssize_t size = REAL_SIZE_TP(type), i;
Christian Heimesd32ed6f2008-01-14 18:49:24 +000036
Benjamin Petersonccabcd42010-07-07 20:54:01 +000037 obj = PyObject_GC_NewVar(PyStructSequence, type, size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 if (obj == NULL)
39 return NULL;
Benjamin Petersond02441e2010-07-08 22:33:03 +000040 /* Hack the size of the variable object, so invisible fields don't appear
41 to Python code. */
42 Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
Benjamin Petersonccabcd42010-07-07 20:54:01 +000043 for (i = 0; i < size; i++)
44 obj->ob_item[i] = NULL;
Guido van Rossume82f75a2001-10-18 20:47:51 +000045
Benjamin Petersonccabcd42010-07-07 20:54:01 +000046 return (PyObject*)obj;
Thomas Woutersed03b412007-08-28 21:37:11 +000047}
48
Martin v. Löwis4d0d4712010-12-03 20:14:31 +000049void
50PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v)
51{
52 PyStructSequence_SET_ITEM(op, i, v);
53}
54
55PyObject*
56PyStructSequence_GetItem(PyObject* op, Py_ssize_t i)
57{
58 return PyStructSequence_GET_ITEM(op, i);
59}
60
Benjamin Petersond02441e2010-07-08 22:33:03 +000061static void
62structseq_dealloc(PyStructSequence *obj)
63{
64 Py_ssize_t i, size;
Victor Stinner26f91992013-07-17 01:22:45 +020065
Benjamin Petersond02441e2010-07-08 22:33:03 +000066 size = REAL_SIZE(obj);
67 for (i = 0; i < size; ++i) {
68 Py_XDECREF(obj->ob_item[i]);
69 }
70 PyObject_GC_Del(obj);
71}
72
Serhiy Storchaka18b250f2017-03-19 08:51:07 +020073/*[clinic input]
74class structseq "PyStructSequence *" "NULL"
75[clinic start generated code]*/
76/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d781c6922c77752]*/
77
78#include "clinic/structseq.c.h"
79
80/*[clinic input]
81@classmethod
82structseq.__new__ as structseq_new
83 sequence as arg: object
84 dict: object = NULL
85[clinic start generated code]*/
86
Thomas Woutersed03b412007-08-28 21:37:11 +000087static PyObject *
Serhiy Storchaka18b250f2017-03-19 08:51:07 +020088structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict)
89/*[clinic end generated code: output=baa082e788b171da input=9b44810243907377]*/
Guido van Rossume82f75a2001-10-18 20:47:51 +000090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 PyObject *ob;
92 PyStructSequence *res = NULL;
93 Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
Guido van Rossume82f75a2001-10-18 20:47:51 +000094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 arg = PySequence_Fast(arg, "constructor requires a sequence");
Michael W. Hudsonce358e32002-03-06 17:07:49 +000096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 if (!arg) {
98 return NULL;
99 }
Guido van Rossume82f75a2001-10-18 20:47:51 +0000100
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000101 if (dict && !PyDict_Check(dict)) {
102 PyErr_Format(PyExc_TypeError,
103 "%.500s() takes a dict as second arg, if any",
104 type->tp_name);
105 Py_DECREF(arg);
106 return NULL;
107 }
Guido van Rossume82f75a2001-10-18 20:47:51 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 len = PySequence_Fast_GET_SIZE(arg);
110 min_len = VISIBLE_SIZE_TP(type);
111 max_len = REAL_SIZE_TP(type);
112 n_unnamed_fields = UNNAMED_FIELDS_TP(type);
Michael W. Hudsonce358e32002-03-06 17:07:49 +0000113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 if (min_len != max_len) {
115 if (len < min_len) {
116 PyErr_Format(PyExc_TypeError,
Antoine Pitrou4b3c7842012-02-15 02:52:58 +0100117 "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
118 type->tp_name, min_len, len);
119 Py_DECREF(arg);
120 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 }
Michael W. Hudsonce358e32002-03-06 17:07:49 +0000122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 if (len > max_len) {
124 PyErr_Format(PyExc_TypeError,
Antoine Pitrou4b3c7842012-02-15 02:52:58 +0100125 "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
126 type->tp_name, max_len, len);
127 Py_DECREF(arg);
128 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 }
130 }
131 else {
132 if (len != min_len) {
133 PyErr_Format(PyExc_TypeError,
Antoine Pitrou4b3c7842012-02-15 02:52:58 +0100134 "%.500s() takes a %zd-sequence (%zd-sequence given)",
135 type->tp_name, min_len, len);
136 Py_DECREF(arg);
137 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 }
139 }
Michael W. Hudsonce358e32002-03-06 17:07:49 +0000140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 res = (PyStructSequence*) PyStructSequence_New(type);
142 if (res == NULL) {
Antoine Pitrou37784ba2012-02-15 02:51:43 +0100143 Py_DECREF(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000144 return NULL;
145 }
146 for (i = 0; i < len; ++i) {
147 PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
148 Py_INCREF(v);
149 res->ob_item[i] = v;
150 }
151 for (; i < max_len; ++i) {
152 if (dict && (ob = PyDict_GetItemString(
153 dict, type->tp_members[i-n_unnamed_fields].name))) {
154 }
155 else {
156 ob = Py_None;
157 }
158 Py_INCREF(ob);
159 res->ob_item[i] = ob;
160 }
161
162 Py_DECREF(arg);
163 return (PyObject*) res;
Guido van Rossume82f75a2001-10-18 20:47:51 +0000164}
165
Guido van Rossume82f75a2001-10-18 20:47:51 +0000166
167static PyObject *
168structseq_repr(PyStructSequence *obj)
169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 /* buffer and type size were chosen well considered. */
Christian Heimesd32ed6f2008-01-14 18:49:24 +0000171#define REPR_BUFFER_SIZE 512
172#define TYPE_MAXSIZE 100
173
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000174 PyTypeObject *typ = Py_TYPE(obj);
Serhiy Storchaka56f6e762015-09-06 21:25:30 +0300175 Py_ssize_t i;
176 int removelast = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 Py_ssize_t len;
178 char buf[REPR_BUFFER_SIZE];
179 char *endofbuf, *pbuf = buf;
Christian Heimesd32ed6f2008-01-14 18:49:24 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 /* pointer to end of writeable buffer; safes space for "...)\0" */
182 endofbuf= &buf[REPR_BUFFER_SIZE-5];
Christian Heimesd32ed6f2008-01-14 18:49:24 +0000183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 /* "typename(", limited to TYPE_MAXSIZE */
Victor Stinner98905202018-12-01 02:46:40 +0100185 len = strlen(typ->tp_name);
186 len = Py_MIN(len, TYPE_MAXSIZE);
187 memcpy(pbuf, typ->tp_name, len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 pbuf += len;
189 *pbuf++ = '(';
Christian Heimesd32ed6f2008-01-14 18:49:24 +0000190
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 for (i=0; i < VISIBLE_SIZE(obj); i++) {
192 PyObject *val, *repr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200193 const char *cname, *crepr;
Christian Heimesd32ed6f2008-01-14 18:49:24 +0000194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 cname = typ->tp_members[i].name;
Benjamin Petersond02441e2010-07-08 22:33:03 +0000196 if (cname == NULL) {
197 PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %d name is NULL"
198 " for type %.500s", i, typ->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 return NULL;
Benjamin Petersond02441e2010-07-08 22:33:03 +0000200 }
Benjamin Petersonccabcd42010-07-07 20:54:01 +0000201 val = PyStructSequence_GET_ITEM(obj, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 repr = PyObject_Repr(val);
Benjamin Petersonccabcd42010-07-07 20:54:01 +0000203 if (repr == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 return NULL;
Serhiy Storchaka06515832016-11-20 09:13:07 +0200205 crepr = PyUnicode_AsUTF8(repr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000206 if (crepr == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 Py_DECREF(repr);
208 return NULL;
209 }
210
211 /* + 3: keep space for "=" and ", " */
212 len = strlen(cname) + strlen(crepr) + 3;
213 if ((pbuf+len) <= endofbuf) {
214 strcpy(pbuf, cname);
215 pbuf += strlen(cname);
216 *pbuf++ = '=';
217 strcpy(pbuf, crepr);
218 pbuf += strlen(crepr);
219 *pbuf++ = ',';
220 *pbuf++ = ' ';
221 removelast = 1;
222 Py_DECREF(repr);
223 }
224 else {
225 strcpy(pbuf, "...");
226 pbuf += 3;
227 removelast = 0;
228 Py_DECREF(repr);
229 break;
230 }
231 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 if (removelast) {
233 /* overwrite last ", " */
234 pbuf-=2;
235 }
236 *pbuf++ = ')';
237 *pbuf = '\0';
238
239 return PyUnicode_FromString(buf);
Guido van Rossume82f75a2001-10-18 20:47:51 +0000240}
241
242static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530243structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000244{
Victor Stinner9a146ee2013-07-17 13:41:39 +0200245 PyObject* tup = NULL;
246 PyObject* dict = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 PyObject* result;
Serhiy Storchaka56f6e762015-09-06 21:25:30 +0300248 Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields, i;
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 n_fields = REAL_SIZE(self);
251 n_visible_fields = VISIBLE_SIZE(self);
252 n_unnamed_fields = UNNAMED_FIELDS(self);
253 tup = PyTuple_New(n_visible_fields);
Victor Stinner9a146ee2013-07-17 13:41:39 +0200254 if (!tup)
255 goto error;
Michael W. Hudsonce358e32002-03-06 17:07:49 +0000256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 dict = PyDict_New();
Victor Stinner9a146ee2013-07-17 13:41:39 +0200258 if (!dict)
259 goto error;
Michael W. Hudsonce358e32002-03-06 17:07:49 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261 for (i = 0; i < n_visible_fields; i++) {
262 Py_INCREF(self->ob_item[i]);
263 PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
264 }
Michael W. Hudson70ffddf2002-03-07 15:13:40 +0000265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 for (; i < n_fields; i++) {
Serhiy Storchaka007d7ff2016-11-22 07:58:08 +0200267 const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
Victor Stinner9a146ee2013-07-17 13:41:39 +0200268 if (PyDict_SetItemString(dict, n, self->ob_item[i]) < 0)
269 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 }
Michael W. Hudson70ffddf2002-03-07 15:13:40 +0000271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
273
274 Py_DECREF(tup);
275 Py_DECREF(dict);
276
277 return result;
Victor Stinner9a146ee2013-07-17 13:41:39 +0200278
279error:
280 Py_XDECREF(tup);
281 Py_XDECREF(dict);
282 return NULL;
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000283}
284
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000285static PyMethodDef structseq_methods[] = {
Benjamin Petersonccabcd42010-07-07 20:54:01 +0000286 {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 {NULL, NULL}
Michael W. Hudson7bb466a2002-03-05 13:27:58 +0000288};
289
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800290static Py_ssize_t
291count_members(PyStructSequence_Desc *desc, Py_ssize_t *n_unnamed_members) {
292 Py_ssize_t i;
Guido van Rossume82f75a2001-10-18 20:47:51 +0000293
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800294 *n_unnamed_members = 0;
295 for (i = 0; desc->fields[i].name != NULL; ++i) {
296 if (desc->fields[i].name == PyStructSequence_UnnamedField) {
297 (*n_unnamed_members)++;
298 }
299 }
300 return i;
301}
302
303static int
304initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict,
305 Py_ssize_t n_members, Py_ssize_t n_unnamed_members) {
Victor Stinner1c8f0592013-07-22 22:24:54 +0200306 PyObject *v;
Guido van Rossume82f75a2001-10-18 20:47:51 +0000307
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800308#define SET_DICT_FROM_SIZE(key, value) \
309 do { \
310 v = PyLong_FromSsize_t(value); \
311 if (v == NULL) { \
312 return -1; \
313 } \
314 if (PyDict_SetItemString(dict, key, v) < 0) { \
315 Py_DECREF(v); \
316 return -1; \
317 } \
318 Py_DECREF(v); \
319 } while (0)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000320
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800321 SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
322 SET_DICT_FROM_SIZE(real_length_key, n_members);
323 SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
324 return 0;
325}
Guido van Rossume82f75a2001-10-18 20:47:51 +0000326
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800327static void
328initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members,
329 Py_ssize_t n_members) {
330 Py_ssize_t i, k;
Guido van Rossume82f75a2001-10-18 20:47:51 +0000331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 for (i = k = 0; i < n_members; ++i) {
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800333 if (desc->fields[i].name == PyStructSequence_UnnamedField) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 continue;
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800335 }
336
337 /* The names and docstrings in these MemberDefs are statically */
338 /* allocated so it is expected that they'll outlive the MemberDef */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 members[k].name = desc->fields[i].name;
340 members[k].type = T_OBJECT;
341 members[k].offset = offsetof(PyStructSequence, ob_item)
342 + i * sizeof(PyObject*);
343 members[k].flags = READONLY;
344 members[k].doc = desc->fields[i].doc;
345 k++;
346 }
347 members[k].name = NULL;
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800348}
Guido van Rossume82f75a2001-10-18 20:47:51 +0000349
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800350int
351PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
352{
353 PyMemberDef *members;
354 Py_ssize_t n_members, n_unnamed_members;
355
356#ifdef Py_TRACE_REFS
357 /* if the type object was chained, unchain it first
358 before overwriting its storage */
359 if (type->ob_base.ob_base._ob_next) {
360 _Py_ForgetReference((PyObject *)type);
361 }
362#endif
363
364 /* PyTypeObject has already been initialized */
365 if (Py_REFCNT(type) != 0) {
366 PyErr_BadInternalCall();
367 return -1;
368 }
369
370 type->tp_name = desc->name;
371 type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
372 type->tp_itemsize = sizeof(PyObject *);
373 type->tp_dealloc = (destructor)structseq_dealloc;
374 type->tp_repr = (reprfunc)structseq_repr;
375 type->tp_doc = desc->doc;
376 type->tp_base = &PyTuple_Type;
377 type->tp_methods = structseq_methods;
378 type->tp_new = structseq_new;
379 type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC;
380
381 n_members = count_members(desc, &n_unnamed_members);
382 members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1);
383 if (members == NULL) {
384 PyErr_NoMemory();
385 return -1;
386 }
387 initialize_members(desc, members, n_members);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 type->tp_members = members;
Guido van Rossume82f75a2001-10-18 20:47:51 +0000389
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800390 if (PyType_Ready(type) < 0) {
391 PyMem_FREE(members);
Victor Stinner1c8f0592013-07-22 22:24:54 +0200392 return -1;
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800393 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 Py_INCREF(type);
Neal Norwitz2f99b242008-08-24 05:48:10 +0000395
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800396 if (initialize_structseq_dict(
397 desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
398 PyMem_FREE(members);
399 Py_DECREF(type);
400 return -1;
401 }
Victor Stinner1c8f0592013-07-22 22:24:54 +0200402
403 return 0;
404}
405
406void
407PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
408{
409 (void)PyStructSequence_InitType2(type, desc);
Guido van Rossume82f75a2001-10-18 20:47:51 +0000410}
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000411
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800412PyTypeObject *
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000413PyStructSequence_NewType(PyStructSequence_Desc *desc)
414{
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800415 PyMemberDef *members;
416 PyObject *bases;
417 PyTypeObject *type;
418 PyType_Slot slots[7];
419 PyType_Spec spec;
420 Py_ssize_t n_members, n_unnamed_members;
Victor Stinner26f91992013-07-17 01:22:45 +0200421
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800422 /* Initialize MemberDefs */
423 n_members = count_members(desc, &n_unnamed_members);
424 members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1);
425 if (members == NULL) {
426 PyErr_NoMemory();
Victor Stinner1c8f0592013-07-22 22:24:54 +0200427 return NULL;
Stefan Krah6b962862012-08-19 11:20:41 +0200428 }
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800429 initialize_members(desc, members, n_members);
430
431 /* Initialize Slots */
432 slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc};
433 slots[1] = (PyType_Slot){Py_tp_repr, (reprfunc)structseq_repr};
434 slots[2] = (PyType_Slot){Py_tp_doc, (void *)desc->doc};
435 slots[3] = (PyType_Slot){Py_tp_methods, structseq_methods};
436 slots[4] = (PyType_Slot){Py_tp_new, structseq_new};
437 slots[5] = (PyType_Slot){Py_tp_members, members};
438 slots[6] = (PyType_Slot){0, 0};
439
440 /* Initialize Spec */
441 /* The name in this PyType_Spec is statically allocated so it is */
442 /* expected that it'll outlive the PyType_Spec */
443 spec.name = desc->name;
444 spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
445 spec.itemsize = sizeof(PyObject *);
446 spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC;
447 spec.slots = slots;
448
449 bases = PyTuple_Pack(1, &PyTuple_Type);
Pablo Galindobfb855b2018-11-15 02:03:57 +0000450 if (bases == NULL) {
451 PyMem_FREE(members);
452 return NULL;
453 }
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800454 type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, bases);
455 Py_DECREF(bases);
456 PyMem_FREE(members);
457 if (type == NULL) {
458 return NULL;
459 }
460
461 if (initialize_structseq_dict(
462 desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
Pablo Galindobfb855b2018-11-15 02:03:57 +0000463 Py_DECREF(type);
Eddie Elizondo474eedf2018-11-13 04:09:31 -0800464 return NULL;
465 }
466
467 return type;
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000468}
Victor Stinner26f91992013-07-17 01:22:45 +0200469
470int _PyStructSequence_Init(void)
471{
472 if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL
473 || _PyUnicode_FromId(&PyId_n_fields) == NULL
474 || _PyUnicode_FromId(&PyId_n_unnamed_fields) == NULL)
475 return -1;
476
477 return 0;
478}