1 /* Cell object implementation */ 2 3 #include "Python.h" 4 #include "internal/mem.h" 5 #include "internal/pystate.h" 6 7 PyObject * 8 PyCell_New(PyObject *obj) 9 { 10 PyCellObject *op; 11 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); 17 18 _PyObject_GC_TRACK(op); 19 return (PyObject *)op; 20 } 21 22 PyObject * 23 PyCell_Get(PyObject *op) 24 { 25 if (!PyCell_Check(op)) { 26 PyErr_BadInternalCall(); 27 return NULL; 28 } 29 Py_XINCREF(((PyCellObject*)op)->ob_ref); 30 return PyCell_GET(op); 31 } 32 33 int 34 PyCell_Set(PyObject *op, PyObject *obj) 35 { 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; 46 } 47 48 static void 49 cell_dealloc(PyCellObject *op) 50 { 51 _PyObject_GC_UNTRACK(op); 52 Py_XDECREF(op->ob_ref); 53 PyObject_GC_Del(op); 54 } 55 56 static PyObject * 57 cell_richcompare(PyObject *a, PyObject *b, int op) 58 { 59 /* neither argument should be NULL, unless something's gone wrong */ 60 assert(a != NULL && b != NULL); 61 62 /* both arguments should be instances of PyCellObject */ 63 if (!PyCell_Check(a) || !PyCell_Check(b)) { 64 Py_RETURN_NOTIMPLEMENTED; 65 } 66 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); 72 73 Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op); 74 } 75 76 static PyObject * 77 cell_repr(PyCellObject *op) 78 { 79 if (op->ob_ref == NULL) 80 return PyUnicode_FromFormat("<cell at %p: empty>", op); 81 82 return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>", 83 op, op->ob_ref->ob_type->tp_name, 84 op->ob_ref); 85 } 86 87 static int 88 cell_traverse(PyCellObject *op, visitproc visit, void *arg) 89 { 90 Py_VISIT(op->ob_ref); 91 return 0; 92 } 93 94 static int 95 cell_clear(PyCellObject *op) 96 { 97 Py_CLEAR(op->ob_ref); 98 return 0; 99 } 100 101 static PyObject * 102 cell_get_contents(PyCellObject *op, void *closure) 103 { 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; 111 } 112 113 static int 114 cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored)) 115 { 116 Py_XINCREF(obj); 117 Py_XSETREF(op->ob_ref, obj); 118 return 0; 119 } 120 121 static PyGetSetDef cell_getsetlist[] = { 122 {"cell_contents", (getter)cell_get_contents, 123 (setter)cell_set_contents, NULL}, 124 {NULL} /* sentinel */ 125 }; 126 127 PyTypeObject PyCell_Type = { 128 PyVarObject_HEAD_INIT(&PyType_Type, 0) 129 "cell", 130 sizeof(PyCellObject), 131 0, 132 (destructor)cell_dealloc, /* tp_dealloc */ 133 0, /* tp_print */ 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 */ 147 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 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 */ 158 }; 159