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