From fbd849f201a4a8c17745a72eb9f0ee3bae34d330 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Thu, 25 Jan 2001 20:04:14 +0000 Subject: [PATCH] PEP 227 implementation A cell contains a reference to a single PyObject. It could be implemented as a mutable, one-element sequence, but the separate type has less overhead. --- Include/Python.h | 1 + Include/cellobject.h | 28 +++++++++++ Makefile.pre.in | 1 + Objects/cellobject.c | 115 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 Include/cellobject.h create mode 100644 Objects/cellobject.c diff --git a/Include/Python.h b/Include/Python.h index 308655250de..b771c8cf702 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -81,6 +81,7 @@ #include "cobject.h" #include "traceback.h" #include "sliceobject.h" +#include "cellobject.h" #include "codecs.h" #include "pyerrors.h" diff --git a/Include/cellobject.h b/Include/cellobject.h new file mode 100644 index 00000000000..cc4a159e859 --- /dev/null +++ b/Include/cellobject.h @@ -0,0 +1,28 @@ +/* Cell object interface */ + +#ifndef Py_CELLOBJECT_H +#define Py_CELLOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + PyObject_VAR_HEAD + PyObject *ob_ref; +} PyCellObject; + +extern DL_IMPORT(PyTypeObject) PyCell_Type; + +#define PyCell_Check(op) ((op)->ob_type == &PyCell_Type) + +extern DL_IMPORT(PyObject *) PyCell_New(PyObject *); +extern DL_IMPORT(PyObject *) PyCell_Get(PyObject *); +extern DL_IMPORT(int) PyCell_Set(PyObject *, PyObject *); + +#define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref) +#define PyCell_SET(op, v) (((PyCellObject *)(op))->ob_ref = v) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_TUPLEOBJECT_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index cd5436ff7bf..ce54e444bf6 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -236,6 +236,7 @@ PYTHON_OBJS= \ OBJECT_OBJS= \ Objects/abstract.o \ Objects/bufferobject.o \ + Objects/cellobject.o \ Objects/classobject.o \ Objects/cobject.o \ Objects/complexobject.o \ diff --git a/Objects/cellobject.c b/Objects/cellobject.c new file mode 100644 index 00000000000..d9ecfd76f00 --- /dev/null +++ b/Objects/cellobject.c @@ -0,0 +1,115 @@ +/* Cell object implementation */ + +#include "Python.h" + +PyObject * +PyCell_New(PyObject *obj) +{ + PyCellObject *op; + + op = (PyCellObject *)PyObject_New(PyCellObject, &PyCell_Type); + op->ob_ref = obj; + Py_XINCREF(obj); + + PyObject_GC_Init(op); + return (PyObject *)op; +} + +PyObject * +PyCell_Get(PyObject *op) +{ + if (!PyCell_Check(op)) { + PyErr_BadInternalCall(); + return NULL; + } + Py_XINCREF(((PyCellObject*)op)->ob_ref); + return PyCell_GET(op); +} + +int +PyCell_Set(PyObject *op, PyObject *obj) +{ + if (!PyCell_Check(op)) { + PyErr_BadInternalCall(); + return -1; + } + Py_XDECREF(((PyCellObject*)op)->ob_ref); + Py_XINCREF(obj); + PyCell_SET(op, obj); + return 0; +} + +static void +cell_dealloc(PyCellObject *op) +{ + PyObject_GC_Fini(op); + Py_XDECREF(op->ob_ref); + PyObject_Del(op); +} + +static int +cell_compare(PyCellObject *a, PyCellObject *b) +{ + if (a->ob_ref == NULL) { + if (b->ob_ref == NULL) + return 0; + return -1; + } else if (b->ob_ref == NULL) + return 1; + return PyObject_Compare(a->ob_ref, b->ob_ref); +} + +static PyObject * +cell_repr(PyCellObject *op) +{ + char buf[256]; + + if (op->ob_ref == NULL) + sprintf(buf, "", op); + else + sprintf(buf, "", + op, op->ob_ref->ob_type->tp_name, op->ob_ref); + return PyString_FromString(buf); +} + +static int +cell_traverse(PyCellObject *op, visitproc visit, void *arg) +{ + if (op->ob_ref) + return visit(op->ob_ref, arg); + return 0; +} + +static int +cell_clear(PyCellObject *op) +{ + op->ob_ref = NULL; + return 0; +} + +PyTypeObject PyCell_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "cell", + sizeof(PyCellObject) + PyGC_HEAD_SIZE, + 0, + (destructor)cell_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + (cmpfunc)cell_compare, /* tp_compare */ + (reprfunc)cell_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)cell_traverse, /* tp_traverse */ + (inquiry)cell_clear, /* tp_clear */ +};