Branch data Line data Source code
1 : : /* Cell object implementation */
2 : :
3 : : #include "Python.h"
4 : : #include "pycore_object.h"
5 : :
6 : : PyObject *
7 : 4526566 : PyCell_New(PyObject *obj)
8 : : {
9 : : PyCellObject *op;
10 : :
11 : 4526566 : op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
12 [ - + ]: 4526566 : if (op == NULL)
13 : 0 : return NULL;
14 : 4526566 : op->ob_ref = obj;
15 : 4526566 : Py_XINCREF(obj);
16 : :
17 : 4526566 : _PyObject_GC_TRACK(op);
18 : 4526566 : 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 : 118472 : PyCell_Set(PyObject *op, PyObject *value)
65 : : {
66 [ - + ]: 118472 : if (!PyCell_Check(op)) {
67 : 0 : PyErr_BadInternalCall();
68 : 0 : return -1;
69 : : }
70 : 118472 : PyObject *old_value = PyCell_GET(op);
71 : 118472 : Py_XINCREF(value);
72 : 118472 : PyCell_SET(op, value);
73 : 118472 : Py_XDECREF(old_value);
74 : 118472 : return 0;
75 : : }
76 : :
77 : : static void
78 : 4520377 : cell_dealloc(PyCellObject *op)
79 : : {
80 : 4520377 : _PyObject_GC_UNTRACK(op);
81 : 4520377 : Py_XDECREF(op->ob_ref);
82 : 4520377 : PyObject_GC_Del(op);
83 : 4520377 : }
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 : : 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 : 18693163 : cell_traverse(PyCellObject *op, visitproc visit, void *arg)
118 : : {
119 [ + + + + ]: 18693163 : Py_VISIT(op->ob_ref);
120 : 18693162 : return 0;
121 : : }
122 : :
123 : : static int
124 : 77612 : cell_clear(PyCellObject *op)
125 : : {
126 [ + + ]: 77612 : Py_CLEAR(op->ob_ref);
127 : 77612 : 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 : : };
|