blob: 4e359f889fdc81ce24b3f5a2816ef7f5146ee9f3 [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"
6#include "pycore_pystate.h"
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +00007
8PyObject *
9PyCell_New(PyObject *obj)
10{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000011 PyCellObject *op;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013 op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
14 if (op == NULL)
15 return NULL;
16 op->ob_ref = obj;
17 Py_XINCREF(obj);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000019 _PyObject_GC_TRACK(op);
20 return (PyObject *)op;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000021}
22
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +010023PyDoc_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
35static PyObject *
36cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
37{
38 PyObject *return_value = NULL;
39 PyObject *obj = NULL;
40
41 if (!_PyArg_NoKeywords("cell", kwargs)) {
42 goto exit;
43 }
44 /* min = 0: we allow the cell to be empty */
45 if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) {
46 goto exit;
47 }
48 return_value = PyCell_New(obj);
49
50exit:
51 return return_value;
52}
53
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000054PyObject *
55PyCell_Get(PyObject *op)
56{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 if (!PyCell_Check(op)) {
58 PyErr_BadInternalCall();
59 return NULL;
60 }
61 Py_XINCREF(((PyCellObject*)op)->ob_ref);
62 return PyCell_GET(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000063}
64
65int
66PyCell_Set(PyObject *op, PyObject *obj)
67{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 PyObject* oldobj;
69 if (!PyCell_Check(op)) {
70 PyErr_BadInternalCall();
71 return -1;
72 }
73 oldobj = PyCell_GET(op);
74 Py_XINCREF(obj);
75 PyCell_SET(op, obj);
76 Py_XDECREF(oldobj);
77 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000078}
79
80static void
81cell_dealloc(PyCellObject *op)
82{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 _PyObject_GC_UNTRACK(op);
84 Py_XDECREF(op->ob_ref);
85 PyObject_GC_Del(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000086}
87
Mark Dickinson211c6252009-02-01 10:28:51 +000088static PyObject *
89cell_richcompare(PyObject *a, PyObject *b, int op)
Christian Heimesd5e2b6f2008-03-19 21:50:51 +000090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 /* neither argument should be NULL, unless something's gone wrong */
92 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +000093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 /* both arguments should be instances of PyCellObject */
95 if (!PyCell_Check(a) || !PyCell_Check(b)) {
stratakise8b19652017-11-02 11:32:54 +010096 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 }
Mark Dickinson211c6252009-02-01 10:28:51 +000098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 /* compare cells by contents; empty cells come before anything else */
100 a = ((PyCellObject *)a)->ob_ref;
101 b = ((PyCellObject *)b)->ob_ref;
102 if (a != NULL && b != NULL)
103 return PyObject_RichCompare(a, b, op);
Mark Dickinson211c6252009-02-01 10:28:51 +0000104
stratakise8b19652017-11-02 11:32:54 +0100105 Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op);
Christian Heimesd5e2b6f2008-03-19 21:50:51 +0000106}
107
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000108static PyObject *
109cell_repr(PyCellObject *op)
110{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000111 if (op->ob_ref == NULL)
112 return PyUnicode_FromFormat("<cell at %p: empty>", op);
Barry Warsaw7ce36942001-08-24 18:34:26 +0000113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
115 op, op->ob_ref->ob_type->tp_name,
116 op->ob_ref);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000117}
118
119static int
120cell_traverse(PyCellObject *op, visitproc visit, void *arg)
121{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 Py_VISIT(op->ob_ref);
123 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000124}
125
126static int
127cell_clear(PyCellObject *op)
128{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 Py_CLEAR(op->ob_ref);
130 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000131}
132
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000133static PyObject *
134cell_get_contents(PyCellObject *op, void *closure)
135{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 if (op->ob_ref == NULL)
137 {
138 PyErr_SetString(PyExc_ValueError, "Cell is empty");
139 return NULL;
140 }
141 Py_INCREF(op->ob_ref);
142 return op->ob_ref;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000143}
144
Victor Stinner0ad05c32017-09-20 06:54:13 -0700145static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200146cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored))
Lisa Roach64505a12017-06-08 04:43:26 -0700147{
148 Py_XINCREF(obj);
149 Py_XSETREF(op->ob_ref, obj);
150 return 0;
151}
152
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000153static PyGetSetDef cell_getsetlist[] = {
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300154 {"cell_contents", (getter)cell_get_contents,
Lisa Roach64505a12017-06-08 04:43:26 -0700155 (setter)cell_set_contents, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000156 {NULL} /* sentinel */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000157};
158
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000159PyTypeObject PyCell_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000160 PyVarObject_HEAD_INIT(&PyType_Type, 0)
161 "cell",
162 sizeof(PyCellObject),
163 0,
Benjamin Peterson07451dd2016-05-12 23:12:21 -0700164 (destructor)cell_dealloc, /* tp_dealloc */
165 0, /* tp_print */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 0, /* tp_getattr */
167 0, /* tp_setattr */
168 0, /* tp_reserved */
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 */
Benjamin Peterson07451dd2016-05-12 23:12:21 -0700179 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +0100180 cell_new_doc, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 (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 */
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +0100190 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 */
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000199};