1 /* Cell object implementation */ 2 3 #include "Python.h" 4 #include "pycore_object.h" 5 6 PyObject * PyCell_New(PyObject * obj)7 PyCell_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 21 PyDoc_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 33 static PyObject * cell_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)34 cell_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 48 exit: 49 return return_value; 50 } 51 52 PyObject * PyCell_Get(PyObject * op)53 PyCell_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 63 int PyCell_Set(PyObject * op,PyObject * obj)64 PyCell_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 78 static void cell_dealloc(PyCellObject * op)79 cell_dealloc(PyCellObject *op) 80 { 81 _PyObject_GC_UNTRACK(op); 82 Py_XDECREF(op->ob_ref); 83 PyObject_GC_Del(op); 84 } 85 86 static PyObject * cell_richcompare(PyObject * a,PyObject * b,int op)87 cell_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 106 static PyObject * cell_repr(PyCellObject * op)107 cell_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 117 static int cell_traverse(PyCellObject * op,visitproc visit,void * arg)118 cell_traverse(PyCellObject *op, visitproc visit, void *arg) 119 { 120 Py_VISIT(op->ob_ref); 121 return 0; 122 } 123 124 static int cell_clear(PyCellObject * op)125 cell_clear(PyCellObject *op) 126 { 127 Py_CLEAR(op->ob_ref); 128 return 0; 129 } 130 131 static PyObject * cell_get_contents(PyCellObject * op,void * closure)132 cell_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 143 static int cell_set_contents(PyCellObject * op,PyObject * obj,void * Py_UNUSED (ignored))144 cell_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 151 static PyGetSetDef cell_getsetlist[] = { 152 {"cell_contents", (getter)cell_get_contents, 153 (setter)cell_set_contents, NULL}, 154 {NULL} /* sentinel */ 155 }; 156 157 PyTypeObject 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