Line data Source code
1 : /* Cell object implementation */
2 :
3 : #include "Python.h"
4 : #include "pycore_object.h"
5 :
6 : PyObject *
7 4638440 : PyCell_New(PyObject *obj)
8 : {
9 : PyCellObject *op;
10 :
11 4638440 : op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
12 4638440 : if (op == NULL)
13 0 : return NULL;
14 4638440 : op->ob_ref = obj;
15 4638440 : Py_XINCREF(obj);
16 :
17 4638440 : _PyObject_GC_TRACK(op);
18 4638440 : return (PyObject *)op;
19 : }
20 :
21 : PyDoc_STRVAR(cell_new_doc,
22 : "cell([contents])\n"
23 : "--\n"
24 : "\n"
25 : "Create a new cell object.\n"
26 : "\n"
27 : " contents\n"
28 : " the contents of the cell. If not specified, the cell will be empty,\n"
29 : " and \n further attempts to access its cell_contents attribute will\n"
30 : " raise a ValueError.");
31 :
32 :
33 : static PyObject *
34 4 : cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
35 : {
36 4 : PyObject *return_value = NULL;
37 4 : PyObject *obj = NULL;
38 :
39 4 : if (!_PyArg_NoKeywords("cell", kwargs)) {
40 0 : goto exit;
41 : }
42 : /* min = 0: we allow the cell to be empty */
43 4 : if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) {
44 0 : goto exit;
45 : }
46 4 : return_value = PyCell_New(obj);
47 :
48 4 : exit:
49 4 : return return_value;
50 : }
51 :
52 : PyObject *
53 0 : PyCell_Get(PyObject *op)
54 : {
55 0 : if (!PyCell_Check(op)) {
56 0 : PyErr_BadInternalCall();
57 0 : return NULL;
58 : }
59 0 : PyObject *value = PyCell_GET(op);
60 0 : return Py_XNewRef(value);
61 : }
62 :
63 : int
64 119485 : PyCell_Set(PyObject *op, PyObject *value)
65 : {
66 119485 : if (!PyCell_Check(op)) {
67 0 : PyErr_BadInternalCall();
68 0 : return -1;
69 : }
70 119485 : PyObject *old_value = PyCell_GET(op);
71 119485 : Py_XINCREF(value);
72 119485 : PyCell_SET(op, value);
73 119485 : Py_XDECREF(old_value);
74 119485 : return 0;
75 : }
76 :
77 : static void
78 4632900 : cell_dealloc(PyCellObject *op)
79 : {
80 4632900 : _PyObject_GC_UNTRACK(op);
81 4632900 : Py_XDECREF(op->ob_ref);
82 4632900 : PyObject_GC_Del(op);
83 4632900 : }
84 :
85 : static PyObject *
86 5 : cell_richcompare(PyObject *a, PyObject *b, int op)
87 : {
88 : /* neither argument should be NULL, unless something's gone wrong */
89 5 : assert(a != NULL && b != NULL);
90 :
91 : /* both arguments should be instances of PyCellObject */
92 5 : if (!PyCell_Check(a) || !PyCell_Check(b)) {
93 0 : Py_RETURN_NOTIMPLEMENTED;
94 : }
95 :
96 : /* compare cells by contents; empty cells come before anything else */
97 5 : a = ((PyCellObject *)a)->ob_ref;
98 5 : b = ((PyCellObject *)b)->ob_ref;
99 5 : if (a != NULL && b != NULL)
100 2 : return PyObject_RichCompare(a, b, op);
101 :
102 3 : Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op);
103 : }
104 :
105 : static PyObject *
106 2 : cell_repr(PyCellObject *op)
107 : {
108 2 : if (op->ob_ref == NULL)
109 0 : return PyUnicode_FromFormat("<cell at %p: empty>", op);
110 :
111 2 : return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
112 2 : op, Py_TYPE(op->ob_ref)->tp_name,
113 : op->ob_ref);
114 : }
115 :
116 : static int
117 19380000 : cell_traverse(PyCellObject *op, visitproc visit, void *arg)
118 : {
119 19380000 : Py_VISIT(op->ob_ref);
120 19380000 : return 0;
121 : }
122 :
123 : static int
124 78126 : cell_clear(PyCellObject *op)
125 : {
126 78126 : Py_CLEAR(op->ob_ref);
127 78126 : return 0;
128 : }
129 :
130 : static PyObject *
131 15 : cell_get_contents(PyCellObject *op, void *closure)
132 : {
133 15 : if (op->ob_ref == NULL)
134 : {
135 3 : PyErr_SetString(PyExc_ValueError, "Cell is empty");
136 3 : return NULL;
137 : }
138 12 : Py_INCREF(op->ob_ref);
139 12 : return op->ob_ref;
140 : }
141 :
142 : static int
143 2 : cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored))
144 : {
145 2 : Py_XINCREF(obj);
146 2 : Py_XSETREF(op->ob_ref, obj);
147 2 : return 0;
148 : }
149 :
150 : static PyGetSetDef cell_getsetlist[] = {
151 : {"cell_contents", (getter)cell_get_contents,
152 : (setter)cell_set_contents, NULL},
153 : {NULL} /* sentinel */
154 : };
155 :
156 : PyTypeObject PyCell_Type = {
157 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
158 : "cell",
159 : sizeof(PyCellObject),
160 : 0,
161 : (destructor)cell_dealloc, /* tp_dealloc */
162 : 0, /* tp_vectorcall_offset */
163 : 0, /* tp_getattr */
164 : 0, /* tp_setattr */
165 : 0, /* tp_as_async */
166 : (reprfunc)cell_repr, /* tp_repr */
167 : 0, /* tp_as_number */
168 : 0, /* tp_as_sequence */
169 : 0, /* tp_as_mapping */
170 : 0, /* tp_hash */
171 : 0, /* tp_call */
172 : 0, /* tp_str */
173 : PyObject_GenericGetAttr, /* tp_getattro */
174 : 0, /* tp_setattro */
175 : 0, /* tp_as_buffer */
176 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
177 : cell_new_doc, /* tp_doc */
178 : (traverseproc)cell_traverse, /* tp_traverse */
179 : (inquiry)cell_clear, /* tp_clear */
180 : cell_richcompare, /* tp_richcompare */
181 : 0, /* tp_weaklistoffset */
182 : 0, /* tp_iter */
183 : 0, /* tp_iternext */
184 : 0, /* tp_methods */
185 : 0, /* tp_members */
186 : cell_getsetlist, /* tp_getset */
187 : 0, /* tp_base */
188 : 0, /* tp_dict */
189 : 0, /* tp_descr_get */
190 : 0, /* tp_descr_set */
191 : 0, /* tp_dictoffset */
192 : 0, /* tp_init */
193 : 0, /* tp_alloc */
194 : (newfunc)cell_new, /* tp_new */
195 : 0, /* tp_free */
196 : };
|