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