WHATSNEW: document ldaps/tls related option changes
[samba.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 /* print a talloc tree report for a talloc python object */
28 static PyObject *pytalloc_report_full(PyObject *self, PyObject *args)
29 {
30         PyObject *py_obj = Py_None;
31
32         if (!PyArg_ParseTuple(args, "|O", &py_obj))
33                 return NULL;
34
35         if (py_obj == Py_None) {
36                 talloc_report_full(NULL, stdout);
37         } else {
38                 talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout);
39         }
40         return Py_None;
41 }
42
43 /* enable null tracking */
44 static PyObject *pytalloc_enable_null_tracking(PyObject *self,
45                 PyObject *Py_UNUSED(ignored))
46 {
47         talloc_enable_null_tracking();
48         return Py_None;
49 }
50
51 /* return the number of talloc blocks */
52 static PyObject *pytalloc_total_blocks(PyObject *self, PyObject *args)
53 {
54         PyObject *py_obj = Py_None;
55
56         if (!PyArg_ParseTuple(args, "|O", &py_obj))
57                 return NULL;
58
59         if (py_obj == Py_None) {
60                 return PyLong_FromLong(talloc_total_blocks(NULL));
61         }
62
63         return PyLong_FromLong(talloc_total_blocks(pytalloc_get_mem_ctx(py_obj)));
64 }
65
66 static PyMethodDef talloc_methods[] = {
67         { "report_full", (PyCFunction)pytalloc_report_full, METH_VARARGS,
68                 "show a talloc tree for an object"},
69         { "enable_null_tracking", (PyCFunction)pytalloc_enable_null_tracking, METH_NOARGS,
70                 "enable tracking of the NULL object"},
71         { "total_blocks", (PyCFunction)pytalloc_total_blocks, METH_VARARGS,
72                 "return talloc block count"},
73         {0}
74 };
75
76 /**
77  * Default (but only slightly more useful than the default) implementation of Repr().
78  */
79 static PyObject *pytalloc_default_repr(PyObject *obj)
80 {
81         pytalloc_Object *talloc_obj = (pytalloc_Object *)obj;
82         PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
83
84         return PyUnicode_FromFormat("<%s talloc object at %p>",
85                                 type->tp_name, talloc_obj->ptr);
86 }
87
88 /**
89  * Simple dealloc for talloc-wrapping PyObjects
90  */
91 static void pytalloc_dealloc(PyObject* self)
92 {
93         pytalloc_Object *obj = (pytalloc_Object *)self;
94         assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
95         obj->talloc_ctx = NULL;
96         self->ob_type->tp_free(self);
97 }
98
99 /**
100  * Default (but only slightly more useful than the default) implementation of cmp.
101  */
102 #if PY_MAJOR_VERSION >= 3
103 static PyObject *pytalloc_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
104 {
105         void *ptr1;
106         void *ptr2;
107         if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
108                 /* When types match, compare pointers */
109                 ptr1 = pytalloc_get_ptr(obj1);
110                 ptr2 = pytalloc_get_ptr(obj2);
111         } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
112                 /* Otherwise, compare types */
113                 ptr1 = Py_TYPE(obj1);
114                 ptr2 = Py_TYPE(obj2);
115         } else {
116                 Py_INCREF(Py_NotImplemented);
117                 return Py_NotImplemented;
118         }
119         switch (op) {
120                 case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
121                 case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
122                 case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
123                 case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
124                 case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
125                 case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
126         }
127         Py_INCREF(Py_NotImplemented);
128         return Py_NotImplemented;
129 }
130 #else
131 static int pytalloc_default_cmp(PyObject *_obj1, PyObject *_obj2)
132 {
133         pytalloc_Object *obj1 = (pytalloc_Object *)_obj1,
134                                          *obj2 = (pytalloc_Object *)_obj2;
135         if (obj1->ob_type != obj2->ob_type)
136                 return ((char *)obj1->ob_type - (char *)obj2->ob_type);
137
138         return ((char *)pytalloc_get_ptr(obj1) - (char *)pytalloc_get_ptr(obj2));
139 }
140 #endif
141
142 static PyTypeObject TallocObject_Type = {
143         .tp_name = "talloc.Object",
144         .tp_doc = "Python wrapper for a talloc-maintained object.",
145         .tp_basicsize = sizeof(pytalloc_Object),
146         .tp_dealloc = (destructor)pytalloc_dealloc,
147         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
148         .tp_repr = pytalloc_default_repr,
149 #if PY_MAJOR_VERSION >= 3
150         .tp_richcompare = pytalloc_default_richcmp,
151 #else
152         .tp_compare = pytalloc_default_cmp,
153 #endif
154 };
155
156 /**
157  * Default (but only slightly more useful than the default) implementation of Repr().
158  */
159 static PyObject *pytalloc_base_default_repr(PyObject *obj)
160 {
161         pytalloc_BaseObject *talloc_obj = (pytalloc_BaseObject *)obj;
162         PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
163
164         return PyUnicode_FromFormat("<%s talloc based object at %p>",
165                                 type->tp_name, talloc_obj->ptr);
166 }
167
168 /**
169  * Simple dealloc for talloc-wrapping PyObjects
170  */
171 static void pytalloc_base_dealloc(PyObject* self)
172 {
173         pytalloc_BaseObject *obj = (pytalloc_BaseObject *)self;
174         assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
175         obj->talloc_ctx = NULL;
176         self->ob_type->tp_free(self);
177 }
178
179 /**
180  * Default (but only slightly more useful than the default) implementation of cmp.
181  */
182 #if PY_MAJOR_VERSION >= 3
183 static PyObject *pytalloc_base_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
184 {
185         void *ptr1;
186         void *ptr2;
187         if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
188                 /* When types match, compare pointers */
189                 ptr1 = pytalloc_get_ptr(obj1);
190                 ptr2 = pytalloc_get_ptr(obj2);
191         } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
192                 /* Otherwise, compare types */
193                 ptr1 = Py_TYPE(obj1);
194                 ptr2 = Py_TYPE(obj2);
195         } else {
196                 Py_INCREF(Py_NotImplemented);
197                 return Py_NotImplemented;
198         }
199         switch (op) {
200                 case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
201                 case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
202                 case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
203                 case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
204                 case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
205                 case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
206         }
207         Py_INCREF(Py_NotImplemented);
208         return Py_NotImplemented;
209 }
210 #else
211 static int pytalloc_base_default_cmp(PyObject *_obj1, PyObject *_obj2)
212 {
213         pytalloc_BaseObject *obj1 = (pytalloc_BaseObject *)_obj1,
214                                          *obj2 = (pytalloc_BaseObject *)_obj2;
215         if (obj1->ob_type != obj2->ob_type)
216                 return ((char *)obj1->ob_type - (char *)obj2->ob_type);
217
218         return ((char *)pytalloc_get_ptr(obj1) - (char *)pytalloc_get_ptr(obj2));
219 }
220 #endif
221
222 static PyTypeObject TallocBaseObject_Type = {
223         .tp_name = "talloc.BaseObject",
224         .tp_doc = "Python wrapper for a talloc-maintained object.",
225         .tp_basicsize = sizeof(pytalloc_BaseObject),
226         .tp_dealloc = (destructor)pytalloc_base_dealloc,
227         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
228         .tp_repr = pytalloc_base_default_repr,
229 #if PY_MAJOR_VERSION >= 3
230         .tp_richcompare = pytalloc_base_default_richcmp,
231 #else
232         .tp_compare = pytalloc_base_default_cmp,
233 #endif
234 };
235
236 static PyTypeObject TallocGenericObject_Type = {
237         .tp_name = "talloc.GenericObject",
238         .tp_doc = "Python wrapper for a talloc-maintained object.",
239         .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
240         .tp_base = &TallocBaseObject_Type,
241         .tp_basicsize = sizeof(pytalloc_BaseObject),
242 };
243
244 #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
245
246 #if PY_MAJOR_VERSION >= 3
247 static struct PyModuleDef moduledef = {
248     PyModuleDef_HEAD_INIT,
249     .m_name = "talloc",
250     .m_doc = MODULE_DOC,
251     .m_size = -1,
252     .m_methods = talloc_methods,
253 };
254 #endif
255
256 static PyObject *module_init(void);
257 static PyObject *module_init(void)
258 {
259         PyObject *m;
260
261         if (PyType_Ready(&TallocObject_Type) < 0)
262                 return NULL;
263
264         if (PyType_Ready(&TallocBaseObject_Type) < 0)
265                 return NULL;
266
267         if (PyType_Ready(&TallocGenericObject_Type) < 0)
268                 return NULL;
269
270 #if PY_MAJOR_VERSION >= 3
271         m = PyModule_Create(&moduledef);
272 #else
273         m = Py_InitModule3("talloc", talloc_methods, MODULE_DOC);
274 #endif
275         if (m == NULL)
276                 return NULL;
277
278         Py_INCREF(&TallocObject_Type);
279         if (PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type)) {
280                 goto err;
281         }
282         Py_INCREF(&TallocBaseObject_Type);
283         if (PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type)) {
284                 goto err;
285         }
286         Py_INCREF(&TallocGenericObject_Type);
287         if (PyModule_AddObject(m, "GenericObject", (PyObject *)&TallocGenericObject_Type)) {
288                 goto err;
289         }
290         return m;
291
292 err:
293         Py_DECREF(m);
294         return NULL;
295 }
296
297 #if PY_MAJOR_VERSION >= 3
298 PyMODINIT_FUNC PyInit_talloc(void);
299 PyMODINIT_FUNC PyInit_talloc(void)
300 {
301         return module_init();
302 }
303 #else
304 void inittalloc(void);
305 void inittalloc(void)
306 {
307         module_init();
308 }
309 #endif