LCOV - code coverage report
Current view: top level - lib/talloc - pytalloc.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 76 104 73.1 %
Date: 2024-04-21 15:09:00 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Python Talloc Module
       4             :    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010-2011
       5             : 
       6             :      ** NOTE! The following LGPL license applies to the talloc
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             : 
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Lesser General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public
      21             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "lib/replace/system/python.h"
      25             : #include <talloc.h>
      26             : #include <pytalloc.h>
      27             : #include "pytalloc_private.h"
      28             : 
      29             : static PyTypeObject TallocObject_Type;
      30             : 
      31             : /* print a talloc tree report for a talloc python object */
      32           1 : static PyObject *pytalloc_report_full(PyObject *self, PyObject *args)
      33             : {
      34           1 :         PyObject *py_obj = Py_None;
      35             : 
      36           1 :         if (!PyArg_ParseTuple(args, "|O", &py_obj))
      37           0 :                 return NULL;
      38             : 
      39           1 :         if (py_obj == Py_None) {
      40           0 :                 talloc_report_full(NULL, stdout);
      41             :         } else {
      42           1 :                 talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout);
      43             :         }
      44           1 :         Py_RETURN_NONE;
      45             : }
      46             : 
      47             : /* enable null tracking */
      48          11 : static PyObject *pytalloc_enable_null_tracking(PyObject *self,
      49             :                 PyObject *Py_UNUSED(ignored))
      50             : {
      51          11 :         talloc_enable_null_tracking();
      52          11 :         Py_RETURN_NONE;
      53             : }
      54             : 
      55             : /* return the number of talloc blocks */
      56          30 : static PyObject *pytalloc_total_blocks(PyObject *self, PyObject *args)
      57             : {
      58          30 :         PyObject *py_obj = Py_None;
      59             : 
      60          30 :         if (!PyArg_ParseTuple(args, "|O", &py_obj))
      61           0 :                 return NULL;
      62             : 
      63          30 :         if (py_obj == Py_None) {
      64          25 :                 return PyLong_FromLong(talloc_total_blocks(NULL));
      65             :         }
      66             : 
      67           5 :         return PyLong_FromLong(talloc_total_blocks(pytalloc_get_mem_ctx(py_obj)));
      68             : }
      69             : 
      70             : static PyMethodDef talloc_methods[] = {
      71             :         { "report_full", (PyCFunction)pytalloc_report_full, METH_VARARGS,
      72             :                 "show a talloc tree for an object"},
      73             :         { "enable_null_tracking", (PyCFunction)pytalloc_enable_null_tracking, METH_NOARGS,
      74             :                 "enable tracking of the NULL object"},
      75             :         { "total_blocks", (PyCFunction)pytalloc_total_blocks, METH_VARARGS,
      76             :                 "return talloc block count"},
      77             :         {0}
      78             : };
      79             : 
      80             : /**
      81             :  * Default (but only slightly more useful than the default) implementation of Repr().
      82             :  */
      83           3 : static PyObject *pytalloc_default_repr(PyObject *obj)
      84             : {
      85           3 :         pytalloc_Object *talloc_obj = (pytalloc_Object *)obj;
      86           3 :         PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
      87             : 
      88           3 :         return PyUnicode_FromFormat("<%s talloc object at %p>",
      89             :                                 type->tp_name, talloc_obj->ptr);
      90             : }
      91             : 
      92             : /**
      93             :  * Simple dealloc for talloc-wrapping PyObjects
      94             :  */
      95           9 : static void pytalloc_dealloc(PyObject* self)
      96             : {
      97           9 :         pytalloc_Object *obj = (pytalloc_Object *)self;
      98           9 :         assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
      99           9 :         obj->talloc_ctx = NULL;
     100           9 :         self->ob_type->tp_free(self);
     101           9 : }
     102             : 
     103             : /**
     104             :  * Default objects do not support ordered comparisons, but talloc
     105             :  * objects do, sorting by pointers clustered by type.
     106             :  */
     107          13 : static PyObject *pytalloc_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
     108             : {
     109           0 :         void *ptr1;
     110           0 :         void *ptr2;
     111          13 :         if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
     112             :                 /* When types match, compare pointers */
     113          13 :                 ptr1 = pytalloc_get_ptr(obj1);
     114          13 :                 ptr2 = pytalloc_get_ptr(obj2);
     115           0 :         } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
     116             :                 /* Otherwise, compare types */
     117           0 :                 ptr1 = Py_TYPE(obj1);
     118           0 :                 ptr2 = Py_TYPE(obj2);
     119             :         } else {
     120           0 :                 Py_INCREF(Py_NotImplemented);
     121           0 :                 return Py_NotImplemented;
     122             :         }
     123          13 :         switch (op) {
     124           2 :                 case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
     125           2 :                 case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
     126           3 :                 case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
     127           2 :                 case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
     128           2 :                 case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
     129           2 :                 case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
     130             :         }
     131           0 :         Py_INCREF(Py_NotImplemented);
     132           0 :         return Py_NotImplemented;
     133             : }
     134             : 
     135             : static PyTypeObject TallocObject_Type = {
     136             :         .tp_name = "talloc.Object",
     137             :         .tp_doc = "Python wrapper for a talloc-maintained object.",
     138             :         .tp_basicsize = sizeof(pytalloc_Object),
     139             :         .tp_dealloc = (destructor)pytalloc_dealloc,
     140             :         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     141             :         .tp_repr = pytalloc_default_repr,
     142             :         .tp_richcompare = pytalloc_default_richcmp,
     143             : };
     144             : 
     145             : /**
     146             :  * Default (but only slightly more useful than the default) implementation of Repr().
     147             :  */
     148           4 : static PyObject *pytalloc_base_default_repr(PyObject *obj)
     149             : {
     150           4 :         pytalloc_BaseObject *talloc_obj = (pytalloc_BaseObject *)obj;
     151           4 :         PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
     152             : 
     153           4 :         return PyUnicode_FromFormat("<%s talloc based object at %p>",
     154             :                                 type->tp_name, talloc_obj->ptr);
     155             : }
     156             : 
     157             : /**
     158             :  * Simple dealloc for talloc-wrapping PyObjects
     159             :  */
     160    83813401 : static void pytalloc_base_dealloc(PyObject* self)
     161             : {
     162    83813401 :         pytalloc_BaseObject *obj = (pytalloc_BaseObject *)self;
     163    83813401 :         assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
     164    83813401 :         obj->talloc_ctx = NULL;
     165    83813401 :         self->ob_type->tp_free(self);
     166    83813401 : }
     167             : 
     168             : /**
     169             :  * Default objects do not support ordered comparisons, but talloc
     170             :  * objects do, sorting by pointers clustered by type.
     171             :  */
     172         451 : static PyObject *pytalloc_base_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
     173             : {
     174           0 :         void *ptr1;
     175           0 :         void *ptr2;
     176         451 :         if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
     177             :                 /* When types match, compare pointers */
     178         442 :                 ptr1 = pytalloc_get_ptr(obj1);
     179         442 :                 ptr2 = pytalloc_get_ptr(obj2);
     180           9 :         } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
     181             :                 /* Otherwise, compare types */
     182           0 :                 ptr1 = Py_TYPE(obj1);
     183           0 :                 ptr2 = Py_TYPE(obj2);
     184             :         } else {
     185           9 :                 Py_INCREF(Py_NotImplemented);
     186           9 :                 return Py_NotImplemented;
     187             :         }
     188         442 :         switch (op) {
     189         431 :                 case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
     190           2 :                 case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
     191           3 :                 case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
     192           2 :                 case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
     193           2 :                 case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
     194           2 :                 case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
     195             :         }
     196           0 :         Py_INCREF(Py_NotImplemented);
     197           0 :         return Py_NotImplemented;
     198             : }
     199             : 
     200             : static PyTypeObject TallocBaseObject_Type = {
     201             :         .tp_name = "talloc.BaseObject",
     202             :         .tp_doc = "Python wrapper for a talloc-maintained object.",
     203             :         .tp_basicsize = sizeof(pytalloc_BaseObject),
     204             :         .tp_dealloc = (destructor)pytalloc_base_dealloc,
     205             :         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     206             :         .tp_repr = pytalloc_base_default_repr,
     207             :         .tp_richcompare = pytalloc_base_default_richcmp,
     208             : };
     209             : 
     210             : static PyTypeObject TallocGenericObject_Type = {
     211             :         .tp_name = "talloc.GenericObject",
     212             :         .tp_doc = "Python wrapper for a talloc-maintained object.",
     213             :         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     214             :         .tp_base = &TallocBaseObject_Type,
     215             :         .tp_basicsize = sizeof(pytalloc_BaseObject),
     216             : };
     217             : 
     218             : #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
     219             : 
     220             : static struct PyModuleDef moduledef = {
     221             :     PyModuleDef_HEAD_INIT,
     222             :     .m_name = "talloc",
     223             :     .m_doc = MODULE_DOC,
     224             :     .m_size = -1,
     225             :     .m_methods = talloc_methods,
     226             : };
     227             : 
     228             : static PyObject *module_init(void);
     229       12848 : static PyObject *module_init(void)
     230             : {
     231         563 :         PyObject *m;
     232             : 
     233       12848 :         if (PyType_Ready(&TallocObject_Type) < 0)
     234           0 :                 return NULL;
     235             : 
     236       12848 :         if (PyType_Ready(&TallocBaseObject_Type) < 0)
     237           0 :                 return NULL;
     238             : 
     239       12848 :         if (PyType_Ready(&TallocGenericObject_Type) < 0)
     240           0 :                 return NULL;
     241             : 
     242       12848 :         m = PyModule_Create(&moduledef);
     243       12848 :         if (m == NULL)
     244           0 :                 return NULL;
     245             : 
     246       10717 :         Py_INCREF(&TallocObject_Type);
     247       12848 :         if (PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type)) {
     248           0 :                 goto err;
     249             :         }
     250       10717 :         Py_INCREF(&TallocBaseObject_Type);
     251       12848 :         if (PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type)) {
     252           0 :                 goto err;
     253             :         }
     254       10717 :         Py_INCREF(&TallocGenericObject_Type);
     255       12848 :         if (PyModule_AddObject(m, "GenericObject", (PyObject *)&TallocGenericObject_Type)) {
     256           0 :                 goto err;
     257             :         }
     258       12285 :         return m;
     259             : 
     260           0 : err:
     261           0 :         Py_DECREF(m);
     262           0 :         return NULL;
     263             : }
     264             : 
     265             : PyMODINIT_FUNC PyInit_talloc(void);
     266       12848 : PyMODINIT_FUNC PyInit_talloc(void)
     267             : {
     268       12848 :         return module_init();
     269             : }

Generated by: LCOV version 1.14