History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Objects/structseq.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Objects/structseq.c+407−0
@@ -0,0 +1,407 @@
1+/* 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"
6+#include "structseq.h"
7+
8+static char visible_length_key[] = "n_sequence_fields";
9+static char real_length_key[] = "n_fields";
10+static char unnamed_fields_key[] = "n_unnamed_fields";
11+
12+/* Fields with this name have only a field index, not a field name.
13+ They are only allowed for indices < n_visible_fields. */
14+char *PyStructSequence_UnnamedField = "unnamed field";
15+
16+#define VISIBLE_SIZE(op) ((op)->ob_size)
17+#define VISIBLE_SIZE_TP(tp) PyInt_AsLong( \
18+ PyDict_GetItemString((tp)->tp_dict, visible_length_key))
19+
20+#define REAL_SIZE_TP(tp) PyInt_AsLong( \
21+ PyDict_GetItemString((tp)->tp_dict, real_length_key))
22+#define REAL_SIZE(op) REAL_SIZE_TP((op)->ob_type)
23+
24+#define UNNAMED_FIELDS_TP(tp) PyInt_AsLong( \
25+ PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))
26+#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP((op)->ob_type)
27+
28+
29+PyObject *
30+PyStructSequence_New(PyTypeObject *type)
31+{
32+ PyStructSequence *obj;
33+
34+ obj = PyObject_New(PyStructSequence, type);
35+ obj->ob_size = VISIBLE_SIZE_TP(type);
36+
37+ return (PyObject*) obj;
38+}
39+
40+static void
41+structseq_dealloc(PyStructSequence *obj)
42+{
43+ Py_ssize_t i, size;
44+
45+ size = REAL_SIZE(obj);
46+ for (i = 0; i < size; ++i) {
47+ Py_XDECREF(obj->ob_item[i]);
48+ }
49+ PyObject_Del(obj);
50+}
51+
52+static Py_ssize_t
53+structseq_length(PyStructSequence *obj)
54+{
55+ return VISIBLE_SIZE(obj);
56+}
57+
58+static PyObject*
59+structseq_item(PyStructSequence *obj, Py_ssize_t i)
60+{
61+ if (i < 0 || i >= VISIBLE_SIZE(obj)) {
62+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");
63+ return NULL;
64+ }
65+ Py_INCREF(obj->ob_item[i]);
66+ return obj->ob_item[i];
67+}
68+
69+static PyObject*
70+structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
71+{
72+ PyTupleObject *np;
73+ Py_ssize_t i;
74+
75+ if (low < 0)
76+ low = 0;
77+ if (high > VISIBLE_SIZE(obj))
78+ high = VISIBLE_SIZE(obj);
79+ if (high < low)
80+ high = low;
81+ np = (PyTupleObject *)PyTuple_New(high-low);
82+ if (np == NULL)
83+ return NULL;
84+ for(i = low; i < high; ++i) {
85+ PyObject *v = obj->ob_item[i];
86+ Py_INCREF(v);
87+ PyTuple_SET_ITEM(np, i-low, v);
88+ }
89+ return (PyObject *) np;
90+}
91+
92+static PyObject *
93+structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
94+{
95+ PyObject *arg = NULL;
96+ PyObject *dict = NULL;
97+ PyObject *ob;
98+ PyStructSequence *res = NULL;
99+ Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
100+ static char *kwlist[] = {"sequence", "dict", 0};
101+
102+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",
103+ kwlist, &arg, &dict))
104+ return NULL;
105+
106+ arg = PySequence_Fast(arg, "constructor requires a sequence");
107+
108+ if (!arg) {
109+ return NULL;
110+ }
111+
112+ if (dict && !PyDict_Check(dict)) {
113+ PyErr_Format(PyExc_TypeError,
114+ "%.500s() takes a dict as second arg, if any",
115+ type->tp_name);
116+ Py_DECREF(arg);
117+ return NULL;
118+ }
119+
120+ len = PySequence_Fast_GET_SIZE(arg);
121+ min_len = VISIBLE_SIZE_TP(type);
122+ max_len = REAL_SIZE_TP(type);
123+ n_unnamed_fields = UNNAMED_FIELDS_TP(type);
124+
125+ if (min_len != max_len) {
126+ if (len < min_len) {
127+ PyErr_Format(PyExc_TypeError,
128+ "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
129+ type->tp_name, min_len, len);
130+ Py_DECREF(arg);
131+ return NULL;
132+ }
133+
134+ if (len > max_len) {
135+ PyErr_Format(PyExc_TypeError,
136+ "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
137+ type->tp_name, max_len, len);
138+ Py_DECREF(arg);
139+ return NULL;
140+ }
141+ }
142+ else {
143+ if (len != min_len) {
144+ PyErr_Format(PyExc_TypeError,
145+ "%.500s() takes a %zd-sequence (%zd-sequence given)",
146+ type->tp_name, min_len, len);
147+ Py_DECREF(arg);
148+ return NULL;
149+ }
150+ }
151+
152+ res = (PyStructSequence*) PyStructSequence_New(type);
153+ if (res == NULL) {
154+ return NULL;
155+ }
156+ for (i = 0; i < len; ++i) {
157+ PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
158+ Py_INCREF(v);
159+ res->ob_item[i] = v;
160+ }
161+ for (; i < max_len; ++i) {
162+ if (dict && (ob = PyDict_GetItemString(
163+ dict, type->tp_members[i-n_unnamed_fields].name))) {
164+ }
165+ else {
166+ ob = Py_None;
167+ }
168+ Py_INCREF(ob);
169+ res->ob_item[i] = ob;
170+ }
171+
172+ Py_DECREF(arg);
173+ return (PyObject*) res;
174+}
175+
176+static PyObject *
177+make_tuple(PyStructSequence *obj)
178+{
179+ return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
180+}
181+
182+static PyObject *
183+structseq_repr(PyStructSequence *obj)
184+{
185+ PyObject *tup, *str;
186+ tup = make_tuple(obj);
187+ str = PyObject_Repr(tup);
188+ Py_DECREF(tup);
189+ return str;
190+}
191+
192+static PyObject *
193+structseq_concat(PyStructSequence *obj, PyObject *b)
194+{
195+ PyObject *tup, *result;
196+ tup = make_tuple(obj);
197+ result = PySequence_Concat(tup, b);
198+ Py_DECREF(tup);
199+ return result;
200+}
201+
202+static PyObject *
203+structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
204+{
205+ PyObject *tup, *result;
206+ tup = make_tuple(obj);
207+ result = PySequence_Repeat(tup, n);
208+ Py_DECREF(tup);
209+ return result;
210+}
211+
212+static int
213+structseq_contains(PyStructSequence *obj, PyObject *o)
214+{
215+ PyObject *tup;
216+ int result;
217+ tup = make_tuple(obj);
218+ if (!tup)
219+ return -1;
220+ result = PySequence_Contains(tup, o);
221+ Py_DECREF(tup);
222+ return result;
223+}
224+
225+static long
226+structseq_hash(PyObject *obj)
227+{
228+ PyObject *tup;
229+ long result;
230+ tup = make_tuple((PyStructSequence*) obj);
231+ if (!tup)
232+ return -1;
233+ result = PyObject_Hash(tup);
234+ Py_DECREF(tup);
235+ return result;
236+}
237+
238+static PyObject *
239+structseq_richcompare(PyObject *obj, PyObject *o2, int op)
240+{
241+ PyObject *tup, *result;
242+ tup = make_tuple((PyStructSequence*) obj);
243+ result = PyObject_RichCompare(tup, o2, op);
244+ Py_DECREF(tup);
245+ return result;
246+}
247+
248+static PyObject *
249+structseq_reduce(PyStructSequence* self)
250+{
251+ PyObject* tup;
252+ PyObject* dict;
253+ PyObject* result;
254+ Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
255+ int i;
256+
257+ n_fields = REAL_SIZE(self);
258+ n_visible_fields = VISIBLE_SIZE(self);
259+ n_unnamed_fields = UNNAMED_FIELDS(self);
260+ tup = PyTuple_New(n_visible_fields);
261+ if (!tup) {
262+ return NULL;
263+ }
264+
265+ dict = PyDict_New();
266+ if (!dict) {
267+ Py_DECREF(tup);
268+ return NULL;
269+ }
270+
271+ for (i = 0; i < n_visible_fields; i++) {
272+ Py_INCREF(self->ob_item[i]);
273+ PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
274+ }
275+
276+ for (; i < n_fields; i++) {
277+ char *n = self->ob_type->tp_members[i-n_unnamed_fields].name;
278+ PyDict_SetItemString(dict, n,
279+ self->ob_item[i]);
280+ }
281+
282+ result = Py_BuildValue("(O(OO))", self->ob_type, tup, dict);
283+
284+ Py_DECREF(tup);
285+ Py_DECREF(dict);
286+
287+ return result;
288+}
289+
290+static PySequenceMethods structseq_as_sequence = {
291+ (lenfunc)structseq_length,
292+ (binaryfunc)structseq_concat, /* sq_concat */
293+ (ssizeargfunc)structseq_repeat, /* sq_repeat */
294+ (ssizeargfunc)structseq_item, /* sq_item */
295+ (ssizessizeargfunc)structseq_slice, /* sq_slice */
296+ 0, /* sq_ass_item */
297+ 0, /* sq_ass_slice */
298+ (objobjproc)structseq_contains, /* sq_contains */
299+};
300+
301+static PyMethodDef structseq_methods[] = {
302+ {"__reduce__", (PyCFunction)structseq_reduce,
303+ METH_NOARGS, NULL},
304+ {NULL, NULL}
305+};
306+
307+static PyTypeObject _struct_sequence_template = {
308+ PyObject_HEAD_INIT(&PyType_Type)
309+ 0, /* ob_size */
310+ NULL, /* tp_name */
311+ 0, /* tp_basicsize */
312+ 0, /* tp_itemsize */
313+ (destructor)structseq_dealloc, /* tp_dealloc */
314+ 0, /* tp_print */
315+ 0, /* tp_getattr */
316+ 0, /* tp_setattr */
317+ 0, /* tp_compare */
318+ (reprfunc)structseq_repr, /* tp_repr */
319+ 0, /* tp_as_number */
320+ &structseq_as_sequence, /* tp_as_sequence */
321+ 0, /* tp_as_mapping */
322+ structseq_hash, /* tp_hash */
323+ 0, /* tp_call */
324+ 0, /* tp_str */
325+ 0, /* tp_getattro */
326+ 0, /* tp_setattro */
327+ 0, /* tp_as_buffer */
328+ Py_TPFLAGS_DEFAULT, /* tp_flags */
329+ NULL, /* tp_doc */
330+ 0, /* tp_traverse */
331+ 0, /* tp_clear */
332+ structseq_richcompare, /* tp_richcompare */
333+ 0, /* tp_weaklistoffset */
334+ 0, /* tp_iter */
335+ 0, /* tp_iternext */
336+ structseq_methods, /* tp_methods */
337+ NULL, /* tp_members */
338+ 0, /* tp_getset */
339+ 0, /* tp_base */
340+ 0, /* tp_dict */
341+ 0, /* tp_descr_get */
342+ 0, /* tp_descr_set */
343+ 0, /* tp_dictoffset */
344+ 0, /* tp_init */
345+ 0, /* tp_alloc */
346+ structseq_new, /* tp_new */
347+};
348+
349+void
350+PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
351+{
352+ PyObject *dict;
353+ PyMemberDef* members;
354+ int n_members, n_unnamed_members, i, k;
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_next) {
360+ _Py_ForgetReference((PyObject*)type);
361+ }
362+#endif
363+
364+ n_unnamed_members = 0;
365+ for (i = 0; desc->fields[i].name != NULL; ++i)
366+ if (desc->fields[i].name == PyStructSequence_UnnamedField)
367+ n_unnamed_members++;
368+ n_members = i;
369+
370+ memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
371+ type->tp_name = desc->name;
372+ type->tp_doc = desc->doc;
373+ type->tp_basicsize = sizeof(PyStructSequence)+
374+ sizeof(PyObject*)*(n_members-1);
375+ type->tp_itemsize = 0;
376+
377+ members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
378+ if (members == NULL)
379+ return;
380+
381+ for (i = k = 0; i < n_members; ++i) {
382+ if (desc->fields[i].name == PyStructSequence_UnnamedField)
383+ continue;
384+ members[k].name = desc->fields[i].name;
385+ members[k].type = T_OBJECT;
386+ members[k].offset = offsetof(PyStructSequence, ob_item)
387+ + i * sizeof(PyObject*);
388+ members[k].flags = READONLY;
389+ members[k].doc = desc->fields[i].doc;
390+ k++;
391+ }
392+ members[k].name = NULL;
393+
394+ type->tp_members = members;
395+
396+ if (PyType_Ready(type) < 0)
397+ return;
398+ Py_INCREF(type);
399+
400+ dict = type->tp_dict;
401+ PyDict_SetItemString(dict, visible_length_key,
402+ PyInt_FromLong((long) desc->n_in_sequence));
403+ PyDict_SetItemString(dict, real_length_key,
404+ PyInt_FromLong((long) n_members));
405+ PyDict_SetItemString(dict, unnamed_fields_key,
406+ PyInt_FromLong((long) n_unnamed_members));
407+}