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