• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Cell object implementation */
2 
3 #include "Python.h"
4 
5 PyObject *
PyCell_New(PyObject * obj)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 *
PyCell_Get(PyObject * op)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
PyCell_Set(PyObject * op,PyObject * obj)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
cell_dealloc(PyCellObject * op)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
cell_compare(PyCellObject * a,PyCellObject * b)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 *
cell_repr(PyCellObject * op)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
cell_traverse(PyCellObject * op,visitproc visit,void * arg)84 cell_traverse(PyCellObject *op, visitproc visit, void *arg)
85 {
86     Py_VISIT(op->ob_ref);
87     return 0;
88 }
89 
90 static int
cell_clear(PyCellObject * op)91 cell_clear(PyCellObject *op)
92 {
93     Py_CLEAR(op->ob_ref);
94     return 0;
95 }
96 
97 static PyObject *
cell_get_contents(PyCellObject * op,void * closure)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