blob: 6af93b0030815ec682da00d705fad58ae070faab [file] [log] [blame]
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +00001/* Cell object implementation */
2
3#include "Python.h"
4
5PyObject *
6PyCell_New(PyObject *obj)
7{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00008 PyCellObject *op;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +00009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000010 op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
11 if (op == NULL)
12 return NULL;
13 op->ob_ref = obj;
14 Py_XINCREF(obj);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000016 _PyObject_GC_TRACK(op);
17 return (PyObject *)op;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000018}
19
20PyObject *
21PyCell_Get(PyObject *op)
22{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023 if (!PyCell_Check(op)) {
24 PyErr_BadInternalCall();
25 return NULL;
26 }
27 Py_XINCREF(((PyCellObject*)op)->ob_ref);
28 return PyCell_GET(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000029}
30
31int
32PyCell_Set(PyObject *op, PyObject *obj)
33{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000034 PyObject* oldobj;
35 if (!PyCell_Check(op)) {
36 PyErr_BadInternalCall();
37 return -1;
38 }
39 oldobj = PyCell_GET(op);
40 Py_XINCREF(obj);
41 PyCell_SET(op, obj);
42 Py_XDECREF(oldobj);
43 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000044}
45
46static void
47cell_dealloc(PyCellObject *op)
48{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 _PyObject_GC_UNTRACK(op);
50 Py_XDECREF(op->ob_ref);
51 PyObject_GC_Del(op);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +000052}
53
Mark Dickinson211c6252009-02-01 10:28:51 +000054#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
55
56static PyObject *
57cell_richcompare(PyObject *a, PyObject *b, int op)
Christian Heimesd5e2b6f2008-03-19 21:50:51 +000058{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000059 int result;
60 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +000061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 /* neither argument should be NULL, unless something's gone wrong */
63 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 /* both arguments should be instances of PyCellObject */
66 if (!PyCell_Check(a) || !PyCell_Check(b)) {
67 v = Py_NotImplemented;
68 Py_INCREF(v);
69 return v;
70 }
Mark Dickinson211c6252009-02-01 10:28:51 +000071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 /* compare cells by contents; empty cells come before anything else */
73 a = ((PyCellObject *)a)->ob_ref;
74 b = ((PyCellObject *)b)->ob_ref;
75 if (a != NULL && b != NULL)
76 return PyObject_RichCompare(a, b, op);
Mark Dickinson211c6252009-02-01 10:28:51 +000077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 result = (b == NULL) - (a == NULL);
79 switch (op) {
80 case Py_EQ:
81 v = TEST_COND(result == 0);
82 break;
83 case Py_NE:
84 v = TEST_COND(result != 0);
85 break;
86 case Py_LE:
87 v = TEST_COND(result <= 0);
88 break;
89 case Py_GE:
90 v = TEST_COND(result >= 0);
91 break;
92 case Py_LT:
93 v = TEST_COND(result < 0);
94 break;
95 case Py_GT:
96 v = TEST_COND(result > 0);
97 break;
98 default:
99 PyErr_BadArgument();
100 return NULL;
101 }
102 Py_INCREF(v);
103 return v;
Christian Heimesd5e2b6f2008-03-19 21:50:51 +0000104}
105
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000106static PyObject *
107cell_repr(PyCellObject *op)
108{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 if (op->ob_ref == NULL)
110 return PyUnicode_FromFormat("<cell at %p: empty>", op);
Barry Warsaw7ce36942001-08-24 18:34:26 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
113 op, op->ob_ref->ob_type->tp_name,
114 op->ob_ref);
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000115}
116
117static int
118cell_traverse(PyCellObject *op, visitproc visit, void *arg)
119{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000120 Py_VISIT(op->ob_ref);
121 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000122}
123
124static int
125cell_clear(PyCellObject *op)
126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 Py_CLEAR(op->ob_ref);
128 return 0;
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000129}
130
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000131static PyObject *
132cell_get_contents(PyCellObject *op, void *closure)
133{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 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;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000141}
142
Lisa Roach64505a12017-06-08 04:43:26 -0700143int
144cell_set_contents(PyCellObject *op, PyObject *obj)
145{
146 Py_XINCREF(obj);
147 Py_XSETREF(op->ob_ref, obj);
148 return 0;
149}
150
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000151static PyGetSetDef cell_getsetlist[] = {
Lisa Roach64505a12017-06-08 04:43:26 -0700152 {"cell_contents", (getter)cell_get_contents,
153 (setter)cell_set_contents, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000154 {NULL} /* sentinel */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000155};
156
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000157PyTypeObject PyCell_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000158 PyVarObject_HEAD_INIT(&PyType_Type, 0)
159 "cell",
160 sizeof(PyCellObject),
161 0,
Benjamin Peterson07451dd2016-05-12 23:12:21 -0700162 (destructor)cell_dealloc, /* tp_dealloc */
163 0, /* tp_print */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 0, /* tp_getattr */
165 0, /* tp_setattr */
166 0, /* tp_reserved */
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 */
Benjamin Peterson07451dd2016-05-12 23:12:21 -0700177 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000178 0, /* 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 */
Jeremy Hyltonfbd849f2001-01-25 20:04:14 +0000188};