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