Line data Source code
1 : /* Cell object implementation */
2 :
3 : #include "Python.h"
4 :
5 : PyObject *
6 387 : PyCell_New(PyObject *obj)
7 : {
8 : PyCellObject *op;
9 :
10 387 : op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
11 387 : if (op == NULL)
12 0 : return NULL;
13 387 : op->ob_ref = obj;
14 387 : Py_XINCREF(obj);
15 :
16 387 : _PyObject_GC_TRACK(op);
17 387 : return (PyObject *)op;
18 : }
19 :
20 : PyObject *
21 3938 : PyCell_Get(PyObject *op)
22 : {
23 3938 : if (!PyCell_Check(op)) {
24 0 : PyErr_BadInternalCall();
25 0 : return NULL;
26 : }
27 3938 : Py_XINCREF(((PyCellObject*)op)->ob_ref);
28 3938 : return PyCell_GET(op);
29 : }
30 :
31 : int
32 382 : PyCell_Set(PyObject *op, PyObject *obj)
33 : {
34 : PyObject* oldobj;
35 382 : if (!PyCell_Check(op)) {
36 0 : PyErr_BadInternalCall();
37 0 : return -1;
38 : }
39 382 : oldobj = PyCell_GET(op);
40 382 : Py_XINCREF(obj);
41 382 : PyCell_SET(op, obj);
42 382 : Py_XDECREF(oldobj);
43 382 : return 0;
44 : }
45 :
46 : static void
47 316 : cell_dealloc(PyCellObject *op)
48 : {
49 316 : _PyObject_GC_UNTRACK(op);
50 316 : Py_XDECREF(op->ob_ref);
51 316 : PyObject_GC_Del(op);
52 316 : }
53 :
54 : #define TEST_COND(cond) ((cond) ? Py_True : Py_False)
55 :
56 : static PyObject *
57 0 : cell_richcompare(PyObject *a, PyObject *b, int op)
58 : {
59 : int result;
60 : PyObject *v;
61 :
62 : /* neither argument should be NULL, unless something's gone wrong */
63 : assert(a != NULL && b != NULL);
64 :
65 : /* both arguments should be instances of PyCellObject */
66 0 : if (!PyCell_Check(a) || !PyCell_Check(b)) {
67 0 : v = Py_NotImplemented;
68 0 : Py_INCREF(v);
69 0 : return v;
70 : }
71 :
72 : /* compare cells by contents; empty cells come before anything else */
73 0 : a = ((PyCellObject *)a)->ob_ref;
74 0 : b = ((PyCellObject *)b)->ob_ref;
75 0 : if (a != NULL && b != NULL)
76 0 : return PyObject_RichCompare(a, b, op);
77 :
78 0 : result = (b == NULL) - (a == NULL);
79 0 : switch (op) {
80 : case Py_EQ:
81 0 : v = TEST_COND(result == 0);
82 0 : break;
83 : case Py_NE:
84 0 : v = TEST_COND(result != 0);
85 0 : break;
86 : case Py_LE:
87 0 : v = TEST_COND(result <= 0);
88 0 : break;
89 : case Py_GE:
90 0 : v = TEST_COND(result >= 0);
91 0 : break;
92 : case Py_LT:
93 0 : v = TEST_COND(result < 0);
94 0 : break;
95 : case Py_GT:
96 0 : v = TEST_COND(result > 0);
97 0 : break;
98 : default:
99 0 : PyErr_BadArgument();
100 0 : return NULL;
101 : }
102 0 : Py_INCREF(v);
103 0 : return v;
104 : }
105 :
106 : static PyObject *
107 0 : cell_repr(PyCellObject *op)
108 : {
109 0 : if (op->ob_ref == NULL)
110 0 : return PyUnicode_FromFormat("<cell at %p: empty>", op);
111 :
112 0 : return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
113 0 : op, op->ob_ref->ob_type->tp_name,
114 : op->ob_ref);
115 : }
116 :
117 : static int
118 252 : cell_traverse(PyCellObject *op, visitproc visit, void *arg)
119 : {
120 252 : Py_VISIT(op->ob_ref);
121 252 : return 0;
122 : }
123 :
124 : static int
125 0 : cell_clear(PyCellObject *op)
126 : {
127 0 : Py_CLEAR(op->ob_ref);
128 0 : return 0;
129 : }
130 :
131 : static PyObject *
132 0 : cell_get_contents(PyCellObject *op, void *closure)
133 : {
134 0 : if (op->ob_ref == NULL)
135 : {
136 0 : PyErr_SetString(PyExc_ValueError, "Cell is empty");
137 0 : return NULL;
138 : }
139 0 : Py_INCREF(op->ob_ref);
140 0 : return op->ob_ref;
141 : }
142 :
143 : static PyGetSetDef cell_getsetlist[] = {
144 : {"cell_contents", (getter)cell_get_contents, NULL},
145 : {NULL} /* sentinel */
146 : };
147 :
148 : PyTypeObject PyCell_Type = {
149 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
150 : "cell",
151 : sizeof(PyCellObject),
152 : 0,
153 : (destructor)cell_dealloc, /* tp_dealloc */
154 : 0, /* tp_print */
155 : 0, /* tp_getattr */
156 : 0, /* tp_setattr */
157 : 0, /* tp_reserved */
158 : (reprfunc)cell_repr, /* tp_repr */
159 : 0, /* tp_as_number */
160 : 0, /* tp_as_sequence */
161 : 0, /* tp_as_mapping */
162 : 0, /* tp_hash */
163 : 0, /* tp_call */
164 : 0, /* tp_str */
165 : PyObject_GenericGetAttr, /* tp_getattro */
166 : 0, /* tp_setattro */
167 : 0, /* tp_as_buffer */
168 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
169 : 0, /* tp_doc */
170 : (traverseproc)cell_traverse, /* tp_traverse */
171 : (inquiry)cell_clear, /* tp_clear */
172 : cell_richcompare, /* tp_richcompare */
173 : 0, /* tp_weaklistoffset */
174 : 0, /* tp_iter */
175 : 0, /* tp_iternext */
176 : 0, /* tp_methods */
177 : 0, /* tp_members */
178 : cell_getsetlist, /* tp_getset */
179 : };
|