| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 1 | /* Cell object implementation */ | 
 | 2 |  | 
 | 3 | #include "Python.h" | 
| Eric Snow | 2ebc5ce | 2017-09-07 23:51:28 -0600 | [diff] [blame] | 4 | #include "internal/mem.h" | 
 | 5 | #include "internal/pystate.h" | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 6 |  | 
 | 7 | PyObject * | 
 | 8 | PyCell_New(PyObject *obj) | 
 | 9 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 10 |     PyCellObject *op; | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 11 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 12 |     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 Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 17 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 18 |     _PyObject_GC_TRACK(op); | 
 | 19 |     return (PyObject *)op; | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 20 | } | 
 | 21 |  | 
 | 22 | PyObject * | 
 | 23 | PyCell_Get(PyObject *op) | 
 | 24 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 25 |     if (!PyCell_Check(op)) { | 
 | 26 |         PyErr_BadInternalCall(); | 
 | 27 |         return NULL; | 
 | 28 |     } | 
 | 29 |     Py_XINCREF(((PyCellObject*)op)->ob_ref); | 
 | 30 |     return PyCell_GET(op); | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 31 | } | 
 | 32 |  | 
 | 33 | int | 
 | 34 | PyCell_Set(PyObject *op, PyObject *obj) | 
 | 35 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 36 |     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 Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 46 | } | 
 | 47 |  | 
 | 48 | static void | 
 | 49 | cell_dealloc(PyCellObject *op) | 
 | 50 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 51 |     _PyObject_GC_UNTRACK(op); | 
 | 52 |     Py_XDECREF(op->ob_ref); | 
 | 53 |     PyObject_GC_Del(op); | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 54 | } | 
 | 55 |  | 
| Mark Dickinson | 211c625 | 2009-02-01 10:28:51 +0000 | [diff] [blame] | 56 | static PyObject * | 
 | 57 | cell_richcompare(PyObject *a, PyObject *b, int op) | 
| Christian Heimes | d5e2b6f | 2008-03-19 21:50:51 +0000 | [diff] [blame] | 58 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 59 |     /* neither argument should be NULL, unless something's gone wrong */ | 
 | 60 |     assert(a != NULL && b != NULL); | 
| Mark Dickinson | 211c625 | 2009-02-01 10:28:51 +0000 | [diff] [blame] | 61 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 62 |     /* both arguments should be instances of PyCellObject */ | 
 | 63 |     if (!PyCell_Check(a) || !PyCell_Check(b)) { | 
| stratakis | e8b1965 | 2017-11-02 11:32:54 +0100 | [diff] [blame] | 64 |         Py_RETURN_NOTIMPLEMENTED; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 65 |     } | 
| Mark Dickinson | 211c625 | 2009-02-01 10:28:51 +0000 | [diff] [blame] | 66 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 67 |     /* compare cells by contents; empty cells come before anything else */ | 
 | 68 |     a = ((PyCellObject *)a)->ob_ref; | 
 | 69 |     b = ((PyCellObject *)b)->ob_ref; | 
 | 70 |     if (a != NULL && b != NULL) | 
 | 71 |         return PyObject_RichCompare(a, b, op); | 
| Mark Dickinson | 211c625 | 2009-02-01 10:28:51 +0000 | [diff] [blame] | 72 |  | 
| stratakis | e8b1965 | 2017-11-02 11:32:54 +0100 | [diff] [blame] | 73 |     Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op); | 
| Christian Heimes | d5e2b6f | 2008-03-19 21:50:51 +0000 | [diff] [blame] | 74 | } | 
 | 75 |  | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 76 | static PyObject * | 
 | 77 | cell_repr(PyCellObject *op) | 
 | 78 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 79 |     if (op->ob_ref == NULL) | 
 | 80 |         return PyUnicode_FromFormat("<cell at %p: empty>", op); | 
| Barry Warsaw | 7ce3694 | 2001-08-24 18:34:26 +0000 | [diff] [blame] | 81 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 82 |     return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>", | 
 | 83 |                                op, op->ob_ref->ob_type->tp_name, | 
 | 84 |                                op->ob_ref); | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 85 | } | 
 | 86 |  | 
 | 87 | static int | 
 | 88 | cell_traverse(PyCellObject *op, visitproc visit, void *arg) | 
 | 89 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 90 |     Py_VISIT(op->ob_ref); | 
 | 91 |     return 0; | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 92 | } | 
 | 93 |  | 
 | 94 | static int | 
 | 95 | cell_clear(PyCellObject *op) | 
 | 96 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 97 |     Py_CLEAR(op->ob_ref); | 
 | 98 |     return 0; | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 99 | } | 
 | 100 |  | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 101 | static PyObject * | 
 | 102 | cell_get_contents(PyCellObject *op, void *closure) | 
 | 103 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 104 |     if (op->ob_ref == NULL) | 
 | 105 |     { | 
 | 106 |         PyErr_SetString(PyExc_ValueError, "Cell is empty"); | 
 | 107 |         return NULL; | 
 | 108 |     } | 
 | 109 |     Py_INCREF(op->ob_ref); | 
 | 110 |     return op->ob_ref; | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 111 | } | 
 | 112 |  | 
| Victor Stinner | 0ad05c3 | 2017-09-20 06:54:13 -0700 | [diff] [blame] | 113 | static int | 
| Lisa Roach | 64505a1 | 2017-06-08 04:43:26 -0700 | [diff] [blame] | 114 | cell_set_contents(PyCellObject *op, PyObject *obj) | 
 | 115 | { | 
 | 116 |     Py_XINCREF(obj); | 
 | 117 |     Py_XSETREF(op->ob_ref, obj); | 
 | 118 |     return 0; | 
 | 119 | } | 
 | 120 |  | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 121 | static PyGetSetDef cell_getsetlist[] = { | 
| Serhiy Storchaka | 13ad3b7 | 2017-09-14 09:38:36 +0300 | [diff] [blame] | 122 |     {"cell_contents", (getter)cell_get_contents, | 
| Lisa Roach | 64505a1 | 2017-06-08 04:43:26 -0700 | [diff] [blame] | 123 |                       (setter)cell_set_contents, NULL}, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 124 |     {NULL} /* sentinel */ | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 125 | }; | 
 | 126 |  | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 127 | PyTypeObject PyCell_Type = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 128 |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
 | 129 |     "cell", | 
 | 130 |     sizeof(PyCellObject), | 
 | 131 |     0, | 
| Benjamin Peterson | 07451dd | 2016-05-12 23:12:21 -0700 | [diff] [blame] | 132 |     (destructor)cell_dealloc,                   /* tp_dealloc */ | 
 | 133 |     0,                                          /* tp_print */ | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 134 |     0,                                          /* tp_getattr */ | 
 | 135 |     0,                                          /* tp_setattr */ | 
 | 136 |     0,                                          /* tp_reserved */ | 
 | 137 |     (reprfunc)cell_repr,                        /* tp_repr */ | 
 | 138 |     0,                                          /* tp_as_number */ | 
 | 139 |     0,                                          /* tp_as_sequence */ | 
 | 140 |     0,                                          /* tp_as_mapping */ | 
 | 141 |     0,                                          /* tp_hash */ | 
 | 142 |     0,                                          /* tp_call */ | 
 | 143 |     0,                                          /* tp_str */ | 
 | 144 |     PyObject_GenericGetAttr,                    /* tp_getattro */ | 
 | 145 |     0,                                          /* tp_setattro */ | 
 | 146 |     0,                                          /* tp_as_buffer */ | 
| Benjamin Peterson | 07451dd | 2016-05-12 23:12:21 -0700 | [diff] [blame] | 147 |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */ | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 148 |     0,                                          /* tp_doc */ | 
 | 149 |     (traverseproc)cell_traverse,                /* tp_traverse */ | 
 | 150 |     (inquiry)cell_clear,                        /* tp_clear */ | 
 | 151 |     cell_richcompare,                           /* tp_richcompare */ | 
 | 152 |     0,                                          /* tp_weaklistoffset */ | 
 | 153 |     0,                                          /* tp_iter */ | 
 | 154 |     0,                                          /* tp_iternext */ | 
 | 155 |     0,                                          /* tp_methods */ | 
 | 156 |     0,                                          /* tp_members */ | 
 | 157 |     cell_getsetlist,                            /* tp_getset */ | 
| Jeremy Hylton | fbd849f | 2001-01-25 20:04:14 +0000 | [diff] [blame] | 158 | }; |