/home/mdboom/Work/builds/cpython/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 | |
6 | PyObject * |
7 | PyCell_New(PyObject *obj) |
8 | { |
9 | PyCellObject *op; |
10 | |
11 | op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type); |
12 | if (op == NULL) Branch (12:9): [True: 0, False: 3.29M]
|
13 | return NULL; |
14 | op->ob_ref = obj; |
15 | Py_XINCREF(obj); |
16 | |
17 | _PyObject_GC_TRACK(op); |
18 | 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 | cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) |
35 | { |
36 | PyObject *return_value = NULL; |
37 | PyObject *obj = NULL; |
38 | |
39 | if (!_PyArg_NoKeywords("cell", kwargs)) { |
40 | goto exit; |
41 | } |
42 | /* min = 0: we allow the cell to be empty */ |
43 | if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) { Branch (43:9): [True: 0, False: 4]
|
44 | goto exit; |
45 | } |
46 | return_value = PyCell_New(obj); |
47 | |
48 | exit: |
49 | return return_value; |
50 | } |
51 | |
52 | PyObject * |
53 | PyCell_Get(PyObject *op) |
54 | { |
55 | if (!PyCell_Check(op)) { Branch (55:9): [True: 0, False: 0]
|
56 | PyErr_BadInternalCall(); |
57 | return NULL; |
58 | } |
59 | PyObject *value = PyCell_GET(op); |
60 | return Py_XNewRef(value); |
61 | } |
62 | |
63 | int |
64 | PyCell_Set(PyObject *op, PyObject *value) |
65 | { |
66 | if (!PyCell_Check(op)) { Branch (66:9): [True: 0, False: 3.16k]
|
67 | PyErr_BadInternalCall(); |
68 | return -1; |
69 | } |
70 | PyObject *old_value = PyCell_GET(op); |
71 | Py_XINCREF(value); |
72 | PyCell_SET(op, value); |
73 | Py_XDECREF(old_value); |
74 | return 0; |
75 | } |
76 | |
77 | static void |
78 | cell_dealloc(PyCellObject *op) |
79 | { |
80 | _PyObject_GC_UNTRACK(op); |
81 | Py_XDECREF(op->ob_ref); |
82 | PyObject_GC_Del(op); |
83 | } |
84 | |
85 | static PyObject * |
86 | 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 | if (!PyCell_Check(a) || !PyCell_Check(b)) { Branch (92:9): [True: 0, False: 5]
Branch (92:29): [True: 0, False: 5]
|
93 | Py_RETURN_NOTIMPLEMENTED; |
94 | } |
95 | |
96 | /* compare cells by contents; empty cells come before anything else */ |
97 | a = ((PyCellObject *)a)->ob_ref; |
98 | b = ((PyCellObject *)b)->ob_ref; |
99 | if (a != NULL && b != NULL3 ) Branch (99:9): [True: 3, False: 2]
Branch (99:22): [True: 2, False: 1]
|
100 | return PyObject_RichCompare(a, b, op); |
101 | |
102 | Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op); |
103 | } |
104 | |
105 | static PyObject * |
106 | cell_repr(PyCellObject *op) |
107 | { |
108 | if (op->ob_ref == NULL) Branch (108:9): [True: 0, False: 2]
|
109 | return PyUnicode_FromFormat("<cell at %p: empty>", op); |
110 | |
111 | return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>", |
112 | op, Py_TYPE(op->ob_ref)->tp_name, |
113 | op->ob_ref); |
114 | } |
115 | |
116 | static int |
117 | cell_traverse(PyCellObject *op, visitproc visit, void *arg) |
118 | { |
119 | Py_VISIT(op->ob_ref); |
120 | return 0; |
121 | } |
122 | |
123 | static int |
124 | cell_clear(PyCellObject *op) |
125 | { |
126 | Py_CLEAR(op->ob_ref); |
127 | return 0; |
128 | } |
129 | |
130 | static PyObject * |
131 | cell_get_contents(PyCellObject *op, void *closure) |
132 | { |
133 | if (op->ob_ref == NULL) Branch (133:9): [True: 3, False: 12]
|
134 | { |
135 | PyErr_SetString(PyExc_ValueError, "Cell is empty"); |
136 | return NULL; |
137 | } |
138 | Py_INCREF(op->ob_ref); |
139 | return op->ob_ref; |
140 | } |
141 | |
142 | static int |
143 | cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored)) |
144 | { |
145 | Py_XINCREF(obj); |
146 | Py_XSETREF(op->ob_ref, obj); |
147 | 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 | }; |