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) |
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)) { |
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)) { |
56 | PyErr_BadInternalCall(); |
57 | return NULL; |
58 | } |
59 | Py_XINCREF(((PyCellObject*)op)->ob_ref); |
60 | return PyCell_GET(op); |
61 | } |
62 | |
63 | int |
64 | PyCell_Set(PyObject *op, PyObject *obj) |
65 | { |
66 | PyObject* oldobj; |
67 | if (!PyCell_Check(op)) { |
68 | PyErr_BadInternalCall(); |
69 | return -1; |
70 | } |
71 | oldobj = PyCell_GET(op); |
72 | Py_XINCREF(obj); |
73 | PyCell_SET(op, obj); |
74 | Py_XDECREF(oldobj); |
75 | return 0; |
76 | } |
77 | |
78 | static void |
79 | cell_dealloc(PyCellObject *op) |
80 | { |
81 | _PyObject_GC_UNTRACK(op); |
82 | Py_XDECREF(op->ob_ref); |
83 | PyObject_GC_Del(op); |
84 | } |
85 | |
86 | static PyObject * |
87 | cell_richcompare(PyObject *a, PyObject *b, int op) |
88 | { |
89 | /* neither argument should be NULL, unless something's gone wrong */ |
90 | assert(a != NULL && b != NULL); |
91 | |
92 | /* both arguments should be instances of PyCellObject */ |
93 | if (!PyCell_Check(a) || !PyCell_Check(b)) { |
94 | Py_RETURN_NOTIMPLEMENTED; |
95 | } |
96 | |
97 | /* compare cells by contents; empty cells come before anything else */ |
98 | a = ((PyCellObject *)a)->ob_ref; |
99 | b = ((PyCellObject *)b)->ob_ref; |
100 | if (a != NULL && b != NULL) |
101 | return PyObject_RichCompare(a, b, op); |
102 | |
103 | Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op); |
104 | } |
105 | |
106 | static PyObject * |
107 | cell_repr(PyCellObject *op) |
108 | { |
109 | if (op->ob_ref == NULL) |
110 | return PyUnicode_FromFormat("<cell at %p: empty>" , op); |
111 | |
112 | return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>" , |
113 | op, Py_TYPE(op->ob_ref)->tp_name, |
114 | op->ob_ref); |
115 | } |
116 | |
117 | static int |
118 | cell_traverse(PyCellObject *op, visitproc visit, void *arg) |
119 | { |
120 | Py_VISIT(op->ob_ref); |
121 | return 0; |
122 | } |
123 | |
124 | static int |
125 | cell_clear(PyCellObject *op) |
126 | { |
127 | Py_CLEAR(op->ob_ref); |
128 | return 0; |
129 | } |
130 | |
131 | static PyObject * |
132 | cell_get_contents(PyCellObject *op, void *closure) |
133 | { |
134 | if (op->ob_ref == NULL) |
135 | { |
136 | PyErr_SetString(PyExc_ValueError, "Cell is empty" ); |
137 | return NULL; |
138 | } |
139 | Py_INCREF(op->ob_ref); |
140 | return op->ob_ref; |
141 | } |
142 | |
143 | static int |
144 | cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored)) |
145 | { |
146 | Py_XINCREF(obj); |
147 | Py_XSETREF(op->ob_ref, obj); |
148 | return 0; |
149 | } |
150 | |
151 | static PyGetSetDef cell_getsetlist[] = { |
152 | {"cell_contents" , (getter)cell_get_contents, |
153 | (setter)cell_set_contents, NULL}, |
154 | {NULL} /* sentinel */ |
155 | }; |
156 | |
157 | PyTypeObject PyCell_Type = { |
158 | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
159 | "cell" , |
160 | sizeof(PyCellObject), |
161 | 0, |
162 | (destructor)cell_dealloc, /* tp_dealloc */ |
163 | 0, /* tp_vectorcall_offset */ |
164 | 0, /* tp_getattr */ |
165 | 0, /* tp_setattr */ |
166 | 0, /* tp_as_async */ |
167 | (reprfunc)cell_repr, /* tp_repr */ |
168 | 0, /* tp_as_number */ |
169 | 0, /* tp_as_sequence */ |
170 | 0, /* tp_as_mapping */ |
171 | 0, /* tp_hash */ |
172 | 0, /* tp_call */ |
173 | 0, /* tp_str */ |
174 | PyObject_GenericGetAttr, /* tp_getattro */ |
175 | 0, /* tp_setattro */ |
176 | 0, /* tp_as_buffer */ |
177 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
178 | cell_new_doc, /* tp_doc */ |
179 | (traverseproc)cell_traverse, /* tp_traverse */ |
180 | (inquiry)cell_clear, /* tp_clear */ |
181 | cell_richcompare, /* tp_richcompare */ |
182 | 0, /* tp_weaklistoffset */ |
183 | 0, /* tp_iter */ |
184 | 0, /* tp_iternext */ |
185 | 0, /* tp_methods */ |
186 | 0, /* tp_members */ |
187 | cell_getsetlist, /* tp_getset */ |
188 | 0, /* tp_base */ |
189 | 0, /* tp_dict */ |
190 | 0, /* tp_descr_get */ |
191 | 0, /* tp_descr_set */ |
192 | 0, /* tp_dictoffset */ |
193 | 0, /* tp_init */ |
194 | 0, /* tp_alloc */ |
195 | (newfunc)cell_new, /* tp_new */ |
196 | 0, /* tp_free */ |
197 | }; |
198 | |