blob: 6efae626bf5b7d2b363e5584d1c36aec335cedb1 [file] [log] [blame]
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +00001/* Cell object implementation */
2
3#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01004#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pymem.h"
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +00006
7PyObject *
8PyCell_New(PyObject *obj)
9{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000010 PyCellObject *op;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000012 op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
13 if (op == NULL)
14 return NULL;
15 op->ob_ref = obj;
16 Py_XINCREF(obj);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000018 _PyObject_GC_TRACK(op);
19 return (PyObject *)op;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000020}
21
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +010022PyDoc_STRVAR(cell_new_doc,
23"cell([contents])\n"
24"--\n"
25"\n"
26"Create a new cell object.\n"
27"\n"
28" contents\n"
29" the contents of the cell. If not specified, the cell will be empty,\n"
30" and \n further attempts to access its cell_contents attribute will\n"
31" raise a ValueError.");
32
33
34static PyObject *
35cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
36{
37 PyObject *return_value = NULL;
38 PyObject *obj = NULL;
39
40 if (!_PyArg_NoKeywords("cell", kwargs)) {
41 goto exit;
42 }
43 /* min = 0: we allow the cell to be empty */
44 if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) {
45 goto exit;
46 }
47 return_value = PyCell_New(obj);
48
49exit:
50 return return_value;
51}
52
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000053PyObject *
54PyCell_Get(PyObject *op)
55{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000056 if (!PyCell_Check(op)) {
57 PyErr_BadInternalCall();
58 return NULL;
59 }
60 Py_XINCREF(((PyCellObject*)op)->ob_ref);
61 return PyCell_GET(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000062}
63
64int
65PyCell_Set(PyObject *op, PyObject *obj)
66{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 PyObject* oldobj;
68 if (!PyCell_Check(op)) {
69 PyErr_BadInternalCall();
70 return -1;
71 }
72 oldobj = PyCell_GET(op);
73 Py_XINCREF(obj);
74 PyCell_SET(op, obj);
75 Py_XDECREF(oldobj);
76 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000077}
78
79static void
80cell_dealloc(PyCellObject *op)
81{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 _PyObject_GC_UNTRACK(op);
83 Py_XDECREF(op->ob_ref);
84 PyObject_GC_Del(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000085}
86
Mark Dickinson211c6252009-02-01 10:28:51 +000087static PyObject *
88cell_richcompare(PyObject *a, PyObject *b, int op)
Christian Heimesd5e2b6f2008-03-19 21:50:51 +000089{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000090 /* neither argument should be NULL, unless something's gone wrong */
91 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +000092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 /* both arguments should be instances of PyCellObject */
94 if (!PyCell_Check(a) || !PyCell_Check(b)) {
stratakise8b19652017-11-02 11:32:54 +010095 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 }
Mark Dickinson211c6252009-02-01 10:28:51 +000097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 /* compare cells by contents; empty cells come before anything else */
99 a = ((PyCellObject *)a)->ob_ref;
100 b = ((PyCellObject *)b)->ob_ref;
101 if (a != NULL && b != NULL)
102 return PyObject_RichCompare(a, b, op);
Mark Dickinson211c6252009-02-01 10:28:51 +0000103
stratakise8b19652017-11-02 11:32:54 +0100104 Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op);
Christian Heimesd5e2b6f2008-03-19 21:50:51 +0000105}
106
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000107static PyObject *
108cell_repr(PyCellObject *op)
109{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 if (op->ob_ref == NULL)
111 return PyUnicode_FromFormat("<cell at %p: empty>", op);
Barry Warsaw7ce36942001-08-24 18:34:26 +0000112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000113 return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
Victor Stinner58ac7002020-02-07 03:04:21 +0100114 op, Py_TYPE(op->ob_ref)->tp_name,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000115 op->ob_ref);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000116}
117
118static int
119cell_traverse(PyCellObject *op, visitproc visit, void *arg)
120{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 Py_VISIT(op->ob_ref);
122 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000123}
124
125static int
126cell_clear(PyCellObject *op)
127{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000128 Py_CLEAR(op->ob_ref);
129 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000130}
131
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000132static PyObject *
133cell_get_contents(PyCellObject *op, void *closure)
134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 if (op->ob_ref == NULL)
136 {
137 PyErr_SetString(PyExc_ValueError, "Cell is empty");
138 return NULL;
139 }
140 Py_INCREF(op->ob_ref);
141 return op->ob_ref;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000142}
143
Victor Stinner0ad05c32017-09-20 06:54:13 -0700144static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200145cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored))
Lisa Roach64505a12017-06-08 04:43:26 -0700146{
147 Py_XINCREF(obj);
148 Py_XSETREF(op->ob_ref, obj);
149 return 0;
150}
151
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000152static PyGetSetDef cell_getsetlist[] = {
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300153 {"cell_contents", (getter)cell_get_contents,
Lisa Roach64505a12017-06-08 04:43:26 -0700154 (setter)cell_set_contents, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 {NULL} /* sentinel */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156};
157
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000158PyTypeObject PyCell_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000159 PyVarObject_HEAD_INIT(&PyType_Type, 0)
160 "cell",
161 sizeof(PyCellObject),
162 0,
Benjamin Peterson07451dd2016-05-12 23:12:21 -0700163 (destructor)cell_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200164 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000165 0, /* tp_getattr */
166 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200167 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 (reprfunc)cell_repr, /* tp_repr */
169 0, /* tp_as_number */
170 0, /* tp_as_sequence */
171 0, /* tp_as_mapping */
172 0, /* tp_hash */
173 0, /* tp_call */
174 0, /* tp_str */
175 PyObject_GenericGetAttr, /* tp_getattro */
176 0, /* tp_setattro */
177 0, /* tp_as_buffer */
Benjamin Peterson07451dd2016-05-12 23:12:21 -0700178 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +0100179 cell_new_doc, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 (traverseproc)cell_traverse, /* tp_traverse */
181 (inquiry)cell_clear, /* tp_clear */
182 cell_richcompare, /* tp_richcompare */
183 0, /* tp_weaklistoffset */
184 0, /* tp_iter */
185 0, /* tp_iternext */
186 0, /* tp_methods */
187 0, /* tp_members */
188 cell_getsetlist, /* tp_getset */
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +0100189 0, /* tp_base */
190 0, /* tp_dict */
191 0, /* tp_descr_get */
192 0, /* tp_descr_set */
193 0, /* tp_dictoffset */
194 0, /* tp_init */
195 0, /* tp_alloc */
196 (newfunc)cell_new, /* tp_new */
197 0, /* tp_free */
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000198};