blob: 8f16f07d7b30299aed7faa8c19c90b74a0c5d43f [file] [log] [blame]
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +00001/* Cell object implementation */
2
3#include "Python.h"
Eric Snow2ebc5ce2017-09-07 23:51:28 -06004#include "internal/mem.h"
5#include "internal/pystate.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
22PyObject *
23PyCell_Get(PyObject *op)
24{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000025 if (!PyCell_Check(op)) {
26 PyErr_BadInternalCall();
27 return NULL;
28 }
29 Py_XINCREF(((PyCellObject*)op)->ob_ref);
30 return PyCell_GET(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000031}
32
33int
34PyCell_Set(PyObject *op, PyObject *obj)
35{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000036 PyObject* oldobj;
37 if (!PyCell_Check(op)) {
38 PyErr_BadInternalCall();
39 return -1;
40 }
41 oldobj = PyCell_GET(op);
42 Py_XINCREF(obj);
43 PyCell_SET(op, obj);
44 Py_XDECREF(oldobj);
45 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000046}
47
48static void
49cell_dealloc(PyCellObject *op)
50{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 _PyObject_GC_UNTRACK(op);
52 Py_XDECREF(op->ob_ref);
53 PyObject_GC_Del(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000054}
55
Mark Dickinson211c6252009-02-01 10:28:51 +000056#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
57
58static PyObject *
59cell_richcompare(PyObject *a, PyObject *b, int op)
Christian Heimesd5e2b6f2008-03-19 21:50:51 +000060{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 int result;
62 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +000063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 /* neither argument should be NULL, unless something's gone wrong */
65 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +000066
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 /* both arguments should be instances of PyCellObject */
68 if (!PyCell_Check(a) || !PyCell_Check(b)) {
69 v = Py_NotImplemented;
70 Py_INCREF(v);
71 return v;
72 }
Mark Dickinson211c6252009-02-01 10:28:51 +000073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 /* compare cells by contents; empty cells come before anything else */
75 a = ((PyCellObject *)a)->ob_ref;
76 b = ((PyCellObject *)b)->ob_ref;
77 if (a != NULL && b != NULL)
78 return PyObject_RichCompare(a, b, op);
Mark Dickinson211c6252009-02-01 10:28:51 +000079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 result = (b == NULL) - (a == NULL);
81 switch (op) {
82 case Py_EQ:
83 v = TEST_COND(result == 0);
84 break;
85 case Py_NE:
86 v = TEST_COND(result != 0);
87 break;
88 case Py_LE:
89 v = TEST_COND(result <= 0);
90 break;
91 case Py_GE:
92 v = TEST_COND(result >= 0);
93 break;
94 case Py_LT:
95 v = TEST_COND(result < 0);
96 break;
97 case Py_GT:
98 v = TEST_COND(result > 0);
99 break;
100 default:
101 PyErr_BadArgument();
102 return NULL;
103 }
104 Py_INCREF(v);
105 return v;
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
Lisa Roach64505a12017-06-08 04:43:26 -0700145int
146cell_set_contents(PyCellObject *op, PyObject *obj)
147{
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 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 0, /* 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 */
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000190};