2 Unix SMB/CIFS implementation.
4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010-2011
6 ** NOTE! The following LGPL license applies to the talloc
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
27 #include "pytalloc_private.h"
29 static PyTypeObject TallocObject_Type
;
31 /* print a talloc tree report for a talloc python object */
32 static PyObject
*pytalloc_report_full(PyObject
*self
, PyObject
*args
)
34 PyObject
*py_obj
= Py_None
;
36 if (!PyArg_ParseTuple(args
, "|O", &py_obj
))
39 if (py_obj
== Py_None
) {
40 talloc_report_full(NULL
, stdout
);
42 talloc_report_full(pytalloc_get_mem_ctx(py_obj
), stdout
);
47 /* enable null tracking */
48 static PyObject
*pytalloc_enable_null_tracking(PyObject
*self
,
49 PyObject
*Py_UNUSED(ignored
))
51 talloc_enable_null_tracking();
55 /* return the number of talloc blocks */
56 static PyObject
*pytalloc_total_blocks(PyObject
*self
, PyObject
*args
)
58 PyObject
*py_obj
= Py_None
;
60 if (!PyArg_ParseTuple(args
, "|O", &py_obj
))
63 if (py_obj
== Py_None
) {
64 return PyLong_FromLong(talloc_total_blocks(NULL
));
67 return PyLong_FromLong(talloc_total_blocks(pytalloc_get_mem_ctx(py_obj
)));
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"},
81 * Default (but only slightly more useful than the default) implementation of Repr().
83 static PyObject
*pytalloc_default_repr(PyObject
*obj
)
85 pytalloc_Object
*talloc_obj
= (pytalloc_Object
*)obj
;
86 PyTypeObject
*type
= (PyTypeObject
*)PyObject_Type(obj
);
88 return PyUnicode_FromFormat("<%s talloc object at %p>",
89 type
->tp_name
, talloc_obj
->ptr
);
93 * Simple dealloc for talloc-wrapping PyObjects
95 static void pytalloc_dealloc(PyObject
* self
)
97 pytalloc_Object
*obj
= (pytalloc_Object
*)self
;
98 assert(talloc_unlink(NULL
, obj
->talloc_ctx
) != -1);
99 obj
->talloc_ctx
= NULL
;
100 self
->ob_type
->tp_free(self
);
104 * Default objects do not support ordered comparisons, but talloc
105 * objects do, sorting by pointers clustered by type.
107 static PyObject
*pytalloc_default_richcmp(PyObject
*obj1
, PyObject
*obj2
, int op
)
111 if (Py_TYPE(obj1
) == Py_TYPE(obj2
)) {
112 /* When types match, compare pointers */
113 ptr1
= pytalloc_get_ptr(obj1
);
114 ptr2
= pytalloc_get_ptr(obj2
);
115 } else if (PyObject_TypeCheck(obj2
, &TallocObject_Type
)) {
116 /* Otherwise, compare types */
117 ptr1
= Py_TYPE(obj1
);
118 ptr2
= Py_TYPE(obj2
);
120 Py_INCREF(Py_NotImplemented
);
121 return Py_NotImplemented
;
124 case Py_EQ
: return PyBool_FromLong(ptr1
== ptr2
);
125 case Py_NE
: return PyBool_FromLong(ptr1
!= ptr2
);
126 case Py_LT
: return PyBool_FromLong(ptr1
< ptr2
);
127 case Py_GT
: return PyBool_FromLong(ptr1
> ptr2
);
128 case Py_LE
: return PyBool_FromLong(ptr1
<= ptr2
);
129 case Py_GE
: return PyBool_FromLong(ptr1
>= ptr2
);
131 Py_INCREF(Py_NotImplemented
);
132 return Py_NotImplemented
;
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
,
146 * Default (but only slightly more useful than the default) implementation of Repr().
148 static PyObject
*pytalloc_base_default_repr(PyObject
*obj
)
150 pytalloc_BaseObject
*talloc_obj
= (pytalloc_BaseObject
*)obj
;
151 PyTypeObject
*type
= (PyTypeObject
*)PyObject_Type(obj
);
153 return PyUnicode_FromFormat("<%s talloc based object at %p>",
154 type
->tp_name
, talloc_obj
->ptr
);
158 * Simple dealloc for talloc-wrapping PyObjects
160 static void pytalloc_base_dealloc(PyObject
* self
)
162 pytalloc_BaseObject
*obj
= (pytalloc_BaseObject
*)self
;
163 assert(talloc_unlink(NULL
, obj
->talloc_ctx
) != -1);
164 obj
->talloc_ctx
= NULL
;
165 self
->ob_type
->tp_free(self
);
169 * Default objects do not support ordered comparisons, but talloc
170 * objects do, sorting by pointers clustered by type.
172 static PyObject
*pytalloc_base_default_richcmp(PyObject
*obj1
, PyObject
*obj2
, int op
)
176 if (Py_TYPE(obj1
) == Py_TYPE(obj2
)) {
177 /* When types match, compare pointers */
178 ptr1
= pytalloc_get_ptr(obj1
);
179 ptr2
= pytalloc_get_ptr(obj2
);
180 } else if (PyObject_TypeCheck(obj2
, &TallocObject_Type
)) {
181 /* Otherwise, compare types */
182 ptr1
= Py_TYPE(obj1
);
183 ptr2
= Py_TYPE(obj2
);
185 Py_INCREF(Py_NotImplemented
);
186 return Py_NotImplemented
;
189 case Py_EQ
: return PyBool_FromLong(ptr1
== ptr2
);
190 case Py_NE
: return PyBool_FromLong(ptr1
!= ptr2
);
191 case Py_LT
: return PyBool_FromLong(ptr1
< ptr2
);
192 case Py_GT
: return PyBool_FromLong(ptr1
> ptr2
);
193 case Py_LE
: return PyBool_FromLong(ptr1
<= ptr2
);
194 case Py_GE
: return PyBool_FromLong(ptr1
>= ptr2
);
196 Py_INCREF(Py_NotImplemented
);
197 return Py_NotImplemented
;
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
,
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
),
218 #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
220 static struct PyModuleDef moduledef
= {
221 PyModuleDef_HEAD_INIT
,
225 .m_methods
= talloc_methods
,
228 static PyObject
*module_init(void);
229 static PyObject
*module_init(void)
233 if (PyType_Ready(&TallocObject_Type
) < 0)
236 if (PyType_Ready(&TallocBaseObject_Type
) < 0)
239 if (PyType_Ready(&TallocGenericObject_Type
) < 0)
242 m
= PyModule_Create(&moduledef
);
246 Py_INCREF(&TallocObject_Type
);
247 if (PyModule_AddObject(m
, "Object", (PyObject
*)&TallocObject_Type
)) {
250 Py_INCREF(&TallocBaseObject_Type
);
251 if (PyModule_AddObject(m
, "BaseObject", (PyObject
*)&TallocBaseObject_Type
)) {
254 Py_INCREF(&TallocGenericObject_Type
);
255 if (PyModule_AddObject(m
, "GenericObject", (PyObject
*)&TallocGenericObject_Type
)) {
265 PyMODINIT_FUNC
PyInit_talloc(void);
266 PyMODINIT_FUNC
PyInit_talloc(void)
268 return module_init();