]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Objects/structseq.c
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Objects / structseq.c
CommitLineData
4710c53d 1/* Implementation helper: a struct that looks like a tuple. See timemodule\r
2 and posixmodule for example uses. */\r
3\r
4#include "Python.h"\r
5#include "structmember.h"\r
6#include "structseq.h"\r
7\r
8static char visible_length_key[] = "n_sequence_fields";\r
9static char real_length_key[] = "n_fields";\r
10static char unnamed_fields_key[] = "n_unnamed_fields";\r
11\r
12/* Fields with this name have only a field index, not a field name.\r
13 They are only allowed for indices < n_visible_fields. */\r
14char *PyStructSequence_UnnamedField = "unnamed field";\r
15\r
16#define VISIBLE_SIZE(op) Py_SIZE(op)\r
17#define VISIBLE_SIZE_TP(tp) PyInt_AsLong( \\r
18 PyDict_GetItemString((tp)->tp_dict, visible_length_key))\r
19\r
20#define REAL_SIZE_TP(tp) PyInt_AsLong( \\r
21 PyDict_GetItemString((tp)->tp_dict, real_length_key))\r
22#define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))\r
23\r
24#define UNNAMED_FIELDS_TP(tp) PyInt_AsLong( \\r
25 PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))\r
26#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))\r
27\r
28\r
29PyObject *\r
30PyStructSequence_New(PyTypeObject *type)\r
31{\r
32 PyStructSequence *obj;\r
33\r
34 obj = PyObject_New(PyStructSequence, type);\r
35 if (obj == NULL)\r
36 return NULL;\r
37 Py_SIZE(obj) = VISIBLE_SIZE_TP(type);\r
38\r
39 return (PyObject*) obj;\r
40}\r
41\r
42static void\r
43structseq_dealloc(PyStructSequence *obj)\r
44{\r
45 Py_ssize_t i, size;\r
46\r
47 size = REAL_SIZE(obj);\r
48 for (i = 0; i < size; ++i) {\r
49 Py_XDECREF(obj->ob_item[i]);\r
50 }\r
51 PyObject_Del(obj);\r
52}\r
53\r
54static Py_ssize_t\r
55structseq_length(PyStructSequence *obj)\r
56{\r
57 return VISIBLE_SIZE(obj);\r
58}\r
59\r
60static PyObject*\r
61structseq_item(PyStructSequence *obj, Py_ssize_t i)\r
62{\r
63 if (i < 0 || i >= VISIBLE_SIZE(obj)) {\r
64 PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
65 return NULL;\r
66 }\r
67 Py_INCREF(obj->ob_item[i]);\r
68 return obj->ob_item[i];\r
69}\r
70\r
71static PyObject*\r
72structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)\r
73{\r
74 PyTupleObject *np;\r
75 Py_ssize_t i;\r
76\r
77 if (low < 0)\r
78 low = 0;\r
79 if (high > VISIBLE_SIZE(obj))\r
80 high = VISIBLE_SIZE(obj);\r
81 if (high < low)\r
82 high = low;\r
83 np = (PyTupleObject *)PyTuple_New(high-low);\r
84 if (np == NULL)\r
85 return NULL;\r
86 for(i = low; i < high; ++i) {\r
87 PyObject *v = obj->ob_item[i];\r
88 Py_INCREF(v);\r
89 PyTuple_SET_ITEM(np, i-low, v);\r
90 }\r
91 return (PyObject *) np;\r
92}\r
93\r
94static PyObject *\r
95structseq_subscript(PyStructSequence *self, PyObject *item)\r
96{\r
97 if (PyIndex_Check(item)) {\r
98 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
99 if (i == -1 && PyErr_Occurred())\r
100 return NULL;\r
101\r
102 if (i < 0)\r
103 i += VISIBLE_SIZE(self);\r
104\r
105 if (i < 0 || i >= VISIBLE_SIZE(self)) {\r
106 PyErr_SetString(PyExc_IndexError,\r
107 "tuple index out of range");\r
108 return NULL;\r
109 }\r
110 Py_INCREF(self->ob_item[i]);\r
111 return self->ob_item[i];\r
112 }\r
113 else if (PySlice_Check(item)) {\r
114 Py_ssize_t start, stop, step, slicelen, cur, i;\r
115 PyObject *result;\r
116\r
117 if (PySlice_GetIndicesEx((PySliceObject *)item,\r
118 VISIBLE_SIZE(self), &start, &stop,\r
119 &step, &slicelen) < 0) {\r
120 return NULL;\r
121 }\r
122 if (slicelen <= 0)\r
123 return PyTuple_New(0);\r
124 result = PyTuple_New(slicelen);\r
125 if (result == NULL)\r
126 return NULL;\r
127 for (cur = start, i = 0; i < slicelen;\r
128 cur += step, i++) {\r
129 PyObject *v = self->ob_item[cur];\r
130 Py_INCREF(v);\r
131 PyTuple_SET_ITEM(result, i, v);\r
132 }\r
133 return result;\r
134 }\r
135 else {\r
136 PyErr_SetString(PyExc_TypeError,\r
137 "structseq index must be integer");\r
138 return NULL;\r
139 }\r
140}\r
141\r
142static PyObject *\r
143structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
144{\r
145 PyObject *arg = NULL;\r
146 PyObject *dict = NULL;\r
147 PyObject *ob;\r
148 PyStructSequence *res = NULL;\r
149 Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;\r
150 static char *kwlist[] = {"sequence", "dict", 0};\r
151\r
152 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",\r
153 kwlist, &arg, &dict))\r
154 return NULL;\r
155\r
156 arg = PySequence_Fast(arg, "constructor requires a sequence");\r
157\r
158 if (!arg) {\r
159 return NULL;\r
160 }\r
161\r
162 if (dict && !PyDict_Check(dict)) {\r
163 PyErr_Format(PyExc_TypeError,\r
164 "%.500s() takes a dict as second arg, if any",\r
165 type->tp_name);\r
166 Py_DECREF(arg);\r
167 return NULL;\r
168 }\r
169\r
170 len = PySequence_Fast_GET_SIZE(arg);\r
171 min_len = VISIBLE_SIZE_TP(type);\r
172 max_len = REAL_SIZE_TP(type);\r
173 n_unnamed_fields = UNNAMED_FIELDS_TP(type);\r
174\r
175 if (min_len != max_len) {\r
176 if (len < min_len) {\r
177 PyErr_Format(PyExc_TypeError,\r
178 "%.500s() takes an at least %zd-sequence (%zd-sequence given)",\r
179 type->tp_name, min_len, len);\r
180 Py_DECREF(arg);\r
181 return NULL;\r
182 }\r
183\r
184 if (len > max_len) {\r
185 PyErr_Format(PyExc_TypeError,\r
186 "%.500s() takes an at most %zd-sequence (%zd-sequence given)",\r
187 type->tp_name, max_len, len);\r
188 Py_DECREF(arg);\r
189 return NULL;\r
190 }\r
191 }\r
192 else {\r
193 if (len != min_len) {\r
194 PyErr_Format(PyExc_TypeError,\r
195 "%.500s() takes a %zd-sequence (%zd-sequence given)",\r
196 type->tp_name, min_len, len);\r
197 Py_DECREF(arg);\r
198 return NULL;\r
199 }\r
200 }\r
201\r
202 res = (PyStructSequence*) PyStructSequence_New(type);\r
203 if (res == NULL) {\r
204 return NULL;\r
205 }\r
206 for (i = 0; i < len; ++i) {\r
207 PyObject *v = PySequence_Fast_GET_ITEM(arg, i);\r
208 Py_INCREF(v);\r
209 res->ob_item[i] = v;\r
210 }\r
211 for (; i < max_len; ++i) {\r
212 if (dict && (ob = PyDict_GetItemString(\r
213 dict, type->tp_members[i-n_unnamed_fields].name))) {\r
214 }\r
215 else {\r
216 ob = Py_None;\r
217 }\r
218 Py_INCREF(ob);\r
219 res->ob_item[i] = ob;\r
220 }\r
221\r
222 Py_DECREF(arg);\r
223 return (PyObject*) res;\r
224}\r
225\r
226static PyObject *\r
227make_tuple(PyStructSequence *obj)\r
228{\r
229 return structseq_slice(obj, 0, VISIBLE_SIZE(obj));\r
230}\r
231\r
232static PyObject *\r
233structseq_repr(PyStructSequence *obj)\r
234{\r
235 /* buffer and type size were chosen well considered. */\r
236#define REPR_BUFFER_SIZE 512\r
237#define TYPE_MAXSIZE 100\r
238\r
239 PyObject *tup;\r
240 PyTypeObject *typ = Py_TYPE(obj);\r
241 int i, removelast = 0;\r
242 Py_ssize_t len;\r
243 char buf[REPR_BUFFER_SIZE];\r
244 char *endofbuf, *pbuf = buf;\r
245\r
246 /* pointer to end of writeable buffer; safes space for "...)\0" */\r
247 endofbuf= &buf[REPR_BUFFER_SIZE-5];\r
248\r
249 if ((tup = make_tuple(obj)) == NULL) {\r
250 return NULL;\r
251 }\r
252\r
253 /* "typename(", limited to TYPE_MAXSIZE */\r
254 len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :\r
255 strlen(typ->tp_name);\r
256 strncpy(pbuf, typ->tp_name, len);\r
257 pbuf += len;\r
258 *pbuf++ = '(';\r
259\r
260 for (i=0; i < VISIBLE_SIZE(obj); i++) {\r
261 PyObject *val, *repr;\r
262 char *cname, *crepr;\r
263\r
264 cname = typ->tp_members[i].name;\r
265\r
266 val = PyTuple_GetItem(tup, i);\r
267 if (cname == NULL || val == NULL) {\r
268 return NULL;\r
269 }\r
270 repr = PyObject_Repr(val);\r
271 if (repr == NULL) {\r
272 Py_DECREF(tup);\r
273 return NULL;\r
274 }\r
275 crepr = PyString_AsString(repr);\r
276 if (crepr == NULL) {\r
277 Py_DECREF(tup);\r
278 Py_DECREF(repr);\r
279 return NULL;\r
280 }\r
281\r
282 /* + 3: keep space for "=" and ", " */\r
283 len = strlen(cname) + strlen(crepr) + 3;\r
284 if ((pbuf+len) <= endofbuf) {\r
285 strcpy(pbuf, cname);\r
286 pbuf += strlen(cname);\r
287 *pbuf++ = '=';\r
288 strcpy(pbuf, crepr);\r
289 pbuf += strlen(crepr);\r
290 *pbuf++ = ',';\r
291 *pbuf++ = ' ';\r
292 removelast = 1;\r
293 Py_DECREF(repr);\r
294 }\r
295 else {\r
296 strcpy(pbuf, "...");\r
297 pbuf += 3;\r
298 removelast = 0;\r
299 Py_DECREF(repr);\r
300 break;\r
301 }\r
302 }\r
303 Py_DECREF(tup);\r
304 if (removelast) {\r
305 /* overwrite last ", " */\r
306 pbuf-=2;\r
307 }\r
308 *pbuf++ = ')';\r
309 *pbuf = '\0';\r
310\r
311 return PyString_FromString(buf);\r
312}\r
313\r
314static PyObject *\r
315structseq_concat(PyStructSequence *obj, PyObject *b)\r
316{\r
317 PyObject *tup, *result;\r
318 tup = make_tuple(obj);\r
319 result = PySequence_Concat(tup, b);\r
320 Py_DECREF(tup);\r
321 return result;\r
322}\r
323\r
324static PyObject *\r
325structseq_repeat(PyStructSequence *obj, Py_ssize_t n)\r
326{\r
327 PyObject *tup, *result;\r
328 tup = make_tuple(obj);\r
329 result = PySequence_Repeat(tup, n);\r
330 Py_DECREF(tup);\r
331 return result;\r
332}\r
333\r
334static int\r
335structseq_contains(PyStructSequence *obj, PyObject *o)\r
336{\r
337 PyObject *tup;\r
338 int result;\r
339 tup = make_tuple(obj);\r
340 if (!tup)\r
341 return -1;\r
342 result = PySequence_Contains(tup, o);\r
343 Py_DECREF(tup);\r
344 return result;\r
345}\r
346\r
347static long\r
348structseq_hash(PyObject *obj)\r
349{\r
350 PyObject *tup;\r
351 long result;\r
352 tup = make_tuple((PyStructSequence*) obj);\r
353 if (!tup)\r
354 return -1;\r
355 result = PyObject_Hash(tup);\r
356 Py_DECREF(tup);\r
357 return result;\r
358}\r
359\r
360static PyObject *\r
361structseq_richcompare(PyObject *obj, PyObject *o2, int op)\r
362{\r
363 PyObject *tup, *result;\r
364 tup = make_tuple((PyStructSequence*) obj);\r
365 result = PyObject_RichCompare(tup, o2, op);\r
366 Py_DECREF(tup);\r
367 return result;\r
368}\r
369\r
370static PyObject *\r
371structseq_reduce(PyStructSequence* self)\r
372{\r
373 PyObject* tup;\r
374 PyObject* dict;\r
375 PyObject* result;\r
376 Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;\r
377 int i;\r
378\r
379 n_fields = REAL_SIZE(self);\r
380 n_visible_fields = VISIBLE_SIZE(self);\r
381 n_unnamed_fields = UNNAMED_FIELDS(self);\r
382 tup = PyTuple_New(n_visible_fields);\r
383 if (!tup) {\r
384 return NULL;\r
385 }\r
386\r
387 dict = PyDict_New();\r
388 if (!dict) {\r
389 Py_DECREF(tup);\r
390 return NULL;\r
391 }\r
392\r
393 for (i = 0; i < n_visible_fields; i++) {\r
394 Py_INCREF(self->ob_item[i]);\r
395 PyTuple_SET_ITEM(tup, i, self->ob_item[i]);\r
396 }\r
397\r
398 for (; i < n_fields; i++) {\r
399 char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;\r
400 PyDict_SetItemString(dict, n,\r
401 self->ob_item[i]);\r
402 }\r
403\r
404 result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);\r
405\r
406 Py_DECREF(tup);\r
407 Py_DECREF(dict);\r
408\r
409 return result;\r
410}\r
411\r
412static PySequenceMethods structseq_as_sequence = {\r
413 (lenfunc)structseq_length,\r
414 (binaryfunc)structseq_concat, /* sq_concat */\r
415 (ssizeargfunc)structseq_repeat, /* sq_repeat */\r
416 (ssizeargfunc)structseq_item, /* sq_item */\r
417 (ssizessizeargfunc)structseq_slice, /* sq_slice */\r
418 0, /* sq_ass_item */\r
419 0, /* sq_ass_slice */\r
420 (objobjproc)structseq_contains, /* sq_contains */\r
421};\r
422\r
423static PyMappingMethods structseq_as_mapping = {\r
424 (lenfunc)structseq_length,\r
425 (binaryfunc)structseq_subscript,\r
426};\r
427\r
428static PyMethodDef structseq_methods[] = {\r
429 {"__reduce__", (PyCFunction)structseq_reduce,\r
430 METH_NOARGS, NULL},\r
431 {NULL, NULL}\r
432};\r
433\r
434static PyTypeObject _struct_sequence_template = {\r
435 PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
436 NULL, /* tp_name */\r
437 0, /* tp_basicsize */\r
438 0, /* tp_itemsize */\r
439 (destructor)structseq_dealloc, /* tp_dealloc */\r
440 0, /* tp_print */\r
441 0, /* tp_getattr */\r
442 0, /* tp_setattr */\r
443 0, /* tp_compare */\r
444 (reprfunc)structseq_repr, /* tp_repr */\r
445 0, /* tp_as_number */\r
446 &structseq_as_sequence, /* tp_as_sequence */\r
447 &structseq_as_mapping, /* tp_as_mapping */\r
448 structseq_hash, /* tp_hash */\r
449 0, /* tp_call */\r
450 0, /* tp_str */\r
451 0, /* tp_getattro */\r
452 0, /* tp_setattro */\r
453 0, /* tp_as_buffer */\r
454 Py_TPFLAGS_DEFAULT, /* tp_flags */\r
455 NULL, /* tp_doc */\r
456 0, /* tp_traverse */\r
457 0, /* tp_clear */\r
458 structseq_richcompare, /* tp_richcompare */\r
459 0, /* tp_weaklistoffset */\r
460 0, /* tp_iter */\r
461 0, /* tp_iternext */\r
462 structseq_methods, /* tp_methods */\r
463 NULL, /* tp_members */\r
464 0, /* tp_getset */\r
465 0, /* tp_base */\r
466 0, /* tp_dict */\r
467 0, /* tp_descr_get */\r
468 0, /* tp_descr_set */\r
469 0, /* tp_dictoffset */\r
470 0, /* tp_init */\r
471 0, /* tp_alloc */\r
472 structseq_new, /* tp_new */\r
473};\r
474\r
475void\r
476PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)\r
477{\r
478 PyObject *dict;\r
479 PyMemberDef* members;\r
480 int n_members, n_unnamed_members, i, k;\r
481\r
482#ifdef Py_TRACE_REFS\r
483 /* if the type object was chained, unchain it first\r
484 before overwriting its storage */\r
485 if (type->_ob_next) {\r
486 _Py_ForgetReference((PyObject*)type);\r
487 }\r
488#endif\r
489\r
490 n_unnamed_members = 0;\r
491 for (i = 0; desc->fields[i].name != NULL; ++i)\r
492 if (desc->fields[i].name == PyStructSequence_UnnamedField)\r
493 n_unnamed_members++;\r
494 n_members = i;\r
495\r
496 memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));\r
497 type->tp_name = desc->name;\r
498 type->tp_doc = desc->doc;\r
499 type->tp_basicsize = sizeof(PyStructSequence)+\r
500 sizeof(PyObject*)*(n_members-1);\r
501 type->tp_itemsize = 0;\r
502\r
503 members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);\r
504 if (members == NULL)\r
505 return;\r
506\r
507 for (i = k = 0; i < n_members; ++i) {\r
508 if (desc->fields[i].name == PyStructSequence_UnnamedField)\r
509 continue;\r
510 members[k].name = desc->fields[i].name;\r
511 members[k].type = T_OBJECT;\r
512 members[k].offset = offsetof(PyStructSequence, ob_item)\r
513 + i * sizeof(PyObject*);\r
514 members[k].flags = READONLY;\r
515 members[k].doc = desc->fields[i].doc;\r
516 k++;\r
517 }\r
518 members[k].name = NULL;\r
519\r
520 type->tp_members = members;\r
521\r
522 if (PyType_Ready(type) < 0)\r
523 return;\r
524 Py_INCREF(type);\r
525\r
526 dict = type->tp_dict;\r
527#define SET_DICT_FROM_INT(key, value) \\r
528 do { \\r
529 PyObject *v = PyInt_FromLong((long) value); \\r
530 if (v != NULL) { \\r
531 PyDict_SetItemString(dict, key, v); \\r
532 Py_DECREF(v); \\r
533 } \\r
534 } while (0)\r
535\r
536 SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);\r
537 SET_DICT_FROM_INT(real_length_key, n_members);\r
538 SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);\r
539}\r