1/* Cell object implementation */ 2 3#include "Python.h" 4 5PyObject * 6PyCell_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 20PyObject * 21PyCell_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 31int 32PyCell_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 46static void 47cell_dealloc(PyCellObject *op) 48{ 49 _PyObject_GC_UNTRACK(op); 50 Py_XDECREF(op->ob_ref); 51 PyObject_GC_Del(op); 52} 53 54static int 55cell_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 72static PyObject * 73cell_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 83static int 84cell_traverse(PyCellObject *op, visitproc visit, void *arg) 85{ 86 Py_VISIT(op->ob_ref); 87 return 0; 88} 89 90static int 91cell_clear(PyCellObject *op) 92{ 93 Py_CLEAR(op->ob_ref); 94 return 0; 95} 96 97static PyObject * 98cell_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 109static PyGetSetDef cell_getsetlist[] = { 110 {"cell_contents", (getter)cell_get_contents, NULL}, 111 {NULL} /* sentinel */ 112}; 113 114PyTypeObject 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