Home | History | Annotate | Download | only in Objects
      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