1 /* Cell object implementation */ 2 3 #include "Python.h" 4 5 PyObject * 6 PyCell_New(PyObject *obj) 7 { 8 PyCellObject *op; 9 10 op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type); 11 if (op == NULL) 12 return NULL; 13 op->ob_ref = obj; 14 Py_XINCREF(obj); 15 16 _PyObject_GC_TRACK(op); 17 return (PyObject *)op; 18 } 19 20 PyObject * 21 PyCell_Get(PyObject *op) 22 { 23 if (!PyCell_Check(op)) { 24 PyErr_BadInternalCall(); 25 return NULL; 26 } 27 Py_XINCREF(((PyCellObject*)op)->ob_ref); 28 return PyCell_GET(op); 29 } 30 31 int 32 PyCell_Set(PyObject *op, PyObject *obj) 33 { 34 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; 44 } 45 46 static void 47 cell_dealloc(PyCellObject *op) 48 { 49 _PyObject_GC_UNTRACK(op); 50 Py_XDECREF(op->ob_ref); 51 PyObject_GC_Del(op); 52 } 53 54 #define TEST_COND(cond) ((cond) ? Py_True : Py_False) 55 56 static PyObject * 57 cell_richcompare(PyObject *a, PyObject *b, int op) 58 { 59 int result; 60 PyObject *v; 61 62 /* neither argument should be NULL, unless something's gone wrong */ 63 assert(a != NULL && b != NULL); 64 65 /* 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 } 71 72 /* 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); 77 78 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; 104 } 105 106 static PyObject * 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, op->ob_ref->ob_type->tp_name, 114 op->ob_ref); 115 } 116 117 static int 118 cell_traverse(PyCellObject *op, visitproc visit, void *arg) 119 { 120 Py_VISIT(op->ob_ref); 121 return 0; 122 } 123 124 static int 125 cell_clear(PyCellObject *op) 126 { 127 Py_CLEAR(op->ob_ref); 128 return 0; 129 } 130 131 static PyObject * 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 PyGetSetDef cell_getsetlist[] = { 144 {"cell_contents", (getter)cell_get_contents, NULL}, 145 {NULL} /* sentinel */ 146 }; 147 148 PyTypeObject PyCell_Type = { 149 PyVarObject_HEAD_INIT(&PyType_Type, 0) 150 "cell", 151 sizeof(PyCellObject), 152 0, 153 (destructor)cell_dealloc, /* tp_dealloc */ 154 0, /* tp_print */ 155 0, /* tp_getattr */ 156 0, /* tp_setattr */ 157 0, /* tp_reserved */ 158 (reprfunc)cell_repr, /* tp_repr */ 159 0, /* tp_as_number */ 160 0, /* tp_as_sequence */ 161 0, /* tp_as_mapping */ 162 0, /* tp_hash */ 163 0, /* tp_call */ 164 0, /* tp_str */ 165 PyObject_GenericGetAttr, /* tp_getattro */ 166 0, /* tp_setattro */ 167 0, /* tp_as_buffer */ 168 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 169 0, /* tp_doc */ 170 (traverseproc)cell_traverse, /* tp_traverse */ 171 (inquiry)cell_clear, /* tp_clear */ 172 cell_richcompare, /* tp_richcompare */ 173 0, /* tp_weaklistoffset */ 174 0, /* tp_iter */ 175 0, /* tp_iternext */ 176 0, /* tp_methods */ 177 0, /* tp_members */ 178 cell_getsetlist, /* tp_getset */ 179 }; 180