1/* Cell object implementation */ 2 3#include "Python.h" 4#include "pycore_object.h" 5 6PyObject * 7PyCell_New(PyObject *obj) 8{ 9 PyCellObject *op; 10 11 op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type); 12 if (op == NULL) 13 return NULL; 14 op->ob_ref = obj; 15 Py_XINCREF(obj); 16 17 _PyObject_GC_TRACK(op); 18 return (PyObject *)op; 19} 20 21PyDoc_STRVAR(cell_new_doc, 22"cell([contents])\n" 23"--\n" 24"\n" 25"Create a new cell object.\n" 26"\n" 27" contents\n" 28" the contents of the cell. If not specified, the cell will be empty,\n" 29" and \n further attempts to access its cell_contents attribute will\n" 30" raise a ValueError."); 31 32 33static PyObject * 34cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 35{ 36 PyObject *return_value = NULL; 37 PyObject *obj = NULL; 38 39 if (!_PyArg_NoKeywords("cell", kwargs)) { 40 goto exit; 41 } 42 /* min = 0: we allow the cell to be empty */ 43 if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) { 44 goto exit; 45 } 46 return_value = PyCell_New(obj); 47 48exit: 49 return return_value; 50} 51 52PyObject * 53PyCell_Get(PyObject *op) 54{ 55 if (!PyCell_Check(op)) { 56 PyErr_BadInternalCall(); 57 return NULL; 58 } 59 Py_XINCREF(((PyCellObject*)op)->ob_ref); 60 return PyCell_GET(op); 61} 62 63int 64PyCell_Set(PyObject *op, PyObject *obj) 65{ 66 PyObject* oldobj; 67 if (!PyCell_Check(op)) { 68 PyErr_BadInternalCall(); 69 return -1; 70 } 71 oldobj = PyCell_GET(op); 72 Py_XINCREF(obj); 73 PyCell_SET(op, obj); 74 Py_XDECREF(oldobj); 75 return 0; 76} 77 78static void 79cell_dealloc(PyCellObject *op) 80{ 81 _PyObject_GC_UNTRACK(op); 82 Py_XDECREF(op->ob_ref); 83 PyObject_GC_Del(op); 84} 85 86static PyObject * 87cell_richcompare(PyObject *a, PyObject *b, int op) 88{ 89 /* neither argument should be NULL, unless something's gone wrong */ 90 assert(a != NULL && b != NULL); 91 92 /* both arguments should be instances of PyCellObject */ 93 if (!PyCell_Check(a) || !PyCell_Check(b)) { 94 Py_RETURN_NOTIMPLEMENTED; 95 } 96 97 /* compare cells by contents; empty cells come before anything else */ 98 a = ((PyCellObject *)a)->ob_ref; 99 b = ((PyCellObject *)b)->ob_ref; 100 if (a != NULL && b != NULL) 101 return PyObject_RichCompare(a, b, op); 102 103 Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op); 104} 105 106static PyObject * 107cell_repr(PyCellObject *op) 108{ 109 if (op->ob_ref == NULL) 110 return PyUnicode_FromFormat("<cell at %p: empty>", op); 111 112 return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>", 113 op, Py_TYPE(op->ob_ref)->tp_name, 114 op->ob_ref); 115} 116 117static int 118cell_traverse(PyCellObject *op, visitproc visit, void *arg) 119{ 120 Py_VISIT(op->ob_ref); 121 return 0; 122} 123 124static int 125cell_clear(PyCellObject *op) 126{ 127 Py_CLEAR(op->ob_ref); 128 return 0; 129} 130 131static PyObject * 132cell_get_contents(PyCellObject *op, void *closure) 133{ 134 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; 141} 142 143static int 144cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored)) 145{ 146 Py_XINCREF(obj); 147 Py_XSETREF(op->ob_ref, obj); 148 return 0; 149} 150 151static PyGetSetDef cell_getsetlist[] = { 152 {"cell_contents", (getter)cell_get_contents, 153 (setter)cell_set_contents, NULL}, 154 {NULL} /* sentinel */ 155}; 156 157PyTypeObject PyCell_Type = { 158 PyVarObject_HEAD_INIT(&PyType_Type, 0) 159 "cell", 160 sizeof(PyCellObject), 161 0, 162 (destructor)cell_dealloc, /* tp_dealloc */ 163 0, /* tp_vectorcall_offset */ 164 0, /* tp_getattr */ 165 0, /* tp_setattr */ 166 0, /* tp_as_async */ 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 */ 177 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 178 cell_new_doc, /* 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 */ 188 0, /* tp_base */ 189 0, /* tp_dict */ 190 0, /* tp_descr_get */ 191 0, /* tp_descr_set */ 192 0, /* tp_dictoffset */ 193 0, /* tp_init */ 194 0, /* tp_alloc */ 195 (newfunc)cell_new, /* tp_new */ 196 0, /* tp_free */ 197}; 198