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 static int 55 cell_compare(PyCellObject *a, PyCellObject *b) 56 { 57 /* Py3K warning for comparisons */ 58 if (PyErr_WarnPy3k("cell comparisons not supported in 3.x", 59 1) < 0) { 60 return -2; 61 } 62 63 if (a->ob_ref == NULL) { 64 if (b->ob_ref == NULL) 65 return 0; 66 return -1; 67 } else if (b->ob_ref == NULL) 68 return 1; 69 return PyObject_Compare(a->ob_ref, b->ob_ref); 70 } 71 72 static PyObject * 73 cell_repr(PyCellObject *op) 74 { 75 if (op->ob_ref == NULL) 76 return PyString_FromFormat("<cell at %p: empty>", op); 77 78 return PyString_FromFormat("<cell at %p: %.80s object at %p>", 79 op, op->ob_ref->ob_type->tp_name, 80 op->ob_ref); 81 } 82 83 static int 84 cell_traverse(PyCellObject *op, visitproc visit, void *arg) 85 { 86 Py_VISIT(op->ob_ref); 87 return 0; 88 } 89 90 static int 91 cell_clear(PyCellObject *op) 92 { 93 Py_CLEAR(op->ob_ref); 94 return 0; 95 } 96 97 static PyObject * 98 cell_get_contents(PyCellObject *op, void *closure) 99 { 100 if (op->ob_ref == NULL) 101 { 102 PyErr_SetString(PyExc_ValueError, "Cell is empty"); 103 return NULL; 104 } 105 Py_INCREF(op->ob_ref); 106 return op->ob_ref; 107 } 108 109 static PyGetSetDef cell_getsetlist[] = { 110 {"cell_contents", (getter)cell_get_contents, NULL}, 111 {NULL} /* sentinel */ 112 }; 113 114 PyTypeObject PyCell_Type = { 115 PyVarObject_HEAD_INIT(&PyType_Type, 0) 116 "cell", 117 sizeof(PyCellObject), 118 0, 119 (destructor)cell_dealloc, /* tp_dealloc */ 120 0, /* tp_print */ 121 0, /* tp_getattr */ 122 0, /* tp_setattr */ 123 (cmpfunc)cell_compare, /* tp_compare */ 124 (reprfunc)cell_repr, /* tp_repr */ 125 0, /* tp_as_number */ 126 0, /* tp_as_sequence */ 127 0, /* tp_as_mapping */ 128 0, /* tp_hash */ 129 0, /* tp_call */ 130 0, /* tp_str */ 131 PyObject_GenericGetAttr, /* tp_getattro */ 132 0, /* tp_setattro */ 133 0, /* tp_as_buffer */ 134 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 135 0, /* tp_doc */ 136 (traverseproc)cell_traverse, /* tp_traverse */ 137 (inquiry)cell_clear, /* tp_clear */ 138 0, /* tp_richcompare */ 139 0, /* tp_weaklistoffset */ 140 0, /* tp_iter */ 141 0, /* tp_iternext */ 142 0, /* tp_methods */ 143 0, /* tp_members */ 144 cell_getsetlist, /* tp_getset */ 145 }; 146