diff options
Diffstat (limited to '')
-rw-r--r-- | pytalloc.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/pytalloc.c b/pytalloc.c new file mode 100644 index 0000000..f6f0681 --- /dev/null +++ b/pytalloc.c @@ -0,0 +1,269 @@ +/* + Unix SMB/CIFS implementation. + Python Talloc Module + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010-2011 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "lib/replace/system/python.h" +#include <talloc.h> +#include <pytalloc.h> +#include "pytalloc_private.h" + +static PyTypeObject TallocObject_Type; + +/* print a talloc tree report for a talloc python object */ +static PyObject *pytalloc_report_full(PyObject *self, PyObject *args) +{ + PyObject *py_obj = Py_None; + + if (!PyArg_ParseTuple(args, "|O", &py_obj)) + return NULL; + + if (py_obj == Py_None) { + talloc_report_full(NULL, stdout); + } else { + talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout); + } + Py_RETURN_NONE; +} + +/* enable null tracking */ +static PyObject *pytalloc_enable_null_tracking(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + talloc_enable_null_tracking(); + Py_RETURN_NONE; +} + +/* return the number of talloc blocks */ +static PyObject *pytalloc_total_blocks(PyObject *self, PyObject *args) +{ + PyObject *py_obj = Py_None; + + if (!PyArg_ParseTuple(args, "|O", &py_obj)) + return NULL; + + if (py_obj == Py_None) { + return PyLong_FromLong(talloc_total_blocks(NULL)); + } + + return PyLong_FromLong(talloc_total_blocks(pytalloc_get_mem_ctx(py_obj))); +} + +static PyMethodDef talloc_methods[] = { + { "report_full", (PyCFunction)pytalloc_report_full, METH_VARARGS, + "show a talloc tree for an object"}, + { "enable_null_tracking", (PyCFunction)pytalloc_enable_null_tracking, METH_NOARGS, + "enable tracking of the NULL object"}, + { "total_blocks", (PyCFunction)pytalloc_total_blocks, METH_VARARGS, + "return talloc block count"}, + {0} +}; + +/** + * Default (but only slightly more useful than the default) implementation of Repr(). + */ +static PyObject *pytalloc_default_repr(PyObject *obj) +{ + pytalloc_Object *talloc_obj = (pytalloc_Object *)obj; + PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj); + + return PyUnicode_FromFormat("<%s talloc object at %p>", + type->tp_name, talloc_obj->ptr); +} + +/** + * Simple dealloc for talloc-wrapping PyObjects + */ +static void pytalloc_dealloc(PyObject* self) +{ + pytalloc_Object *obj = (pytalloc_Object *)self; + assert(talloc_unlink(NULL, obj->talloc_ctx) != -1); + obj->talloc_ctx = NULL; + self->ob_type->tp_free(self); +} + +/** + * Default objects do not support ordered comparisons, but talloc + * objects do, sorting by pointers clustered by type. + */ +static PyObject *pytalloc_default_richcmp(PyObject *obj1, PyObject *obj2, int op) +{ + void *ptr1; + void *ptr2; + if (Py_TYPE(obj1) == Py_TYPE(obj2)) { + /* When types match, compare pointers */ + ptr1 = pytalloc_get_ptr(obj1); + ptr2 = pytalloc_get_ptr(obj2); + } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) { + /* Otherwise, compare types */ + ptr1 = Py_TYPE(obj1); + ptr2 = Py_TYPE(obj2); + } else { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + switch (op) { + case Py_EQ: return PyBool_FromLong(ptr1 == ptr2); + case Py_NE: return PyBool_FromLong(ptr1 != ptr2); + case Py_LT: return PyBool_FromLong(ptr1 < ptr2); + case Py_GT: return PyBool_FromLong(ptr1 > ptr2); + case Py_LE: return PyBool_FromLong(ptr1 <= ptr2); + case Py_GE: return PyBool_FromLong(ptr1 >= ptr2); + } + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; +} + +static PyTypeObject TallocObject_Type = { + .tp_name = "talloc.Object", + .tp_doc = "Python wrapper for a talloc-maintained object.", + .tp_basicsize = sizeof(pytalloc_Object), + .tp_dealloc = (destructor)pytalloc_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_repr = pytalloc_default_repr, + .tp_richcompare = pytalloc_default_richcmp, +}; + +/** + * Default (but only slightly more useful than the default) implementation of Repr(). + */ +static PyObject *pytalloc_base_default_repr(PyObject *obj) +{ + pytalloc_BaseObject *talloc_obj = (pytalloc_BaseObject *)obj; + PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj); + + return PyUnicode_FromFormat("<%s talloc based object at %p>", + type->tp_name, talloc_obj->ptr); +} + +/** + * Simple dealloc for talloc-wrapping PyObjects + */ +static void pytalloc_base_dealloc(PyObject* self) +{ + pytalloc_BaseObject *obj = (pytalloc_BaseObject *)self; + assert(talloc_unlink(NULL, obj->talloc_ctx) != -1); + obj->talloc_ctx = NULL; + self->ob_type->tp_free(self); +} + +/** + * Default objects do not support ordered comparisons, but talloc + * objects do, sorting by pointers clustered by type. + */ +static PyObject *pytalloc_base_default_richcmp(PyObject *obj1, PyObject *obj2, int op) +{ + void *ptr1; + void *ptr2; + if (Py_TYPE(obj1) == Py_TYPE(obj2)) { + /* When types match, compare pointers */ + ptr1 = pytalloc_get_ptr(obj1); + ptr2 = pytalloc_get_ptr(obj2); + } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) { + /* Otherwise, compare types */ + ptr1 = Py_TYPE(obj1); + ptr2 = Py_TYPE(obj2); + } else { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + switch (op) { + case Py_EQ: return PyBool_FromLong(ptr1 == ptr2); + case Py_NE: return PyBool_FromLong(ptr1 != ptr2); + case Py_LT: return PyBool_FromLong(ptr1 < ptr2); + case Py_GT: return PyBool_FromLong(ptr1 > ptr2); + case Py_LE: return PyBool_FromLong(ptr1 <= ptr2); + case Py_GE: return PyBool_FromLong(ptr1 >= ptr2); + } + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; +} + +static PyTypeObject TallocBaseObject_Type = { + .tp_name = "talloc.BaseObject", + .tp_doc = "Python wrapper for a talloc-maintained object.", + .tp_basicsize = sizeof(pytalloc_BaseObject), + .tp_dealloc = (destructor)pytalloc_base_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_repr = pytalloc_base_default_repr, + .tp_richcompare = pytalloc_base_default_richcmp, +}; + +static PyTypeObject TallocGenericObject_Type = { + .tp_name = "talloc.GenericObject", + .tp_doc = "Python wrapper for a talloc-maintained object.", + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_base = &TallocBaseObject_Type, + .tp_basicsize = sizeof(pytalloc_BaseObject), +}; + +#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "talloc", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = talloc_methods, +}; + +static PyObject *module_init(void); +static PyObject *module_init(void) +{ + PyObject *m; + + if (PyType_Ready(&TallocObject_Type) < 0) + return NULL; + + if (PyType_Ready(&TallocBaseObject_Type) < 0) + return NULL; + + if (PyType_Ready(&TallocGenericObject_Type) < 0) + return NULL; + + m = PyModule_Create(&moduledef); + if (m == NULL) + return NULL; + + Py_INCREF(&TallocObject_Type); + if (PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type)) { + goto err; + } + Py_INCREF(&TallocBaseObject_Type); + if (PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type)) { + goto err; + } + Py_INCREF(&TallocGenericObject_Type); + if (PyModule_AddObject(m, "GenericObject", (PyObject *)&TallocGenericObject_Type)) { + goto err; + } + return m; + +err: + Py_DECREF(m); + return NULL; +} + +PyMODINIT_FUNC PyInit_talloc(void); +PyMODINIT_FUNC PyInit_talloc(void) +{ + return module_init(); +} |