Branch data Line data Source code
1 : : /* Wrap void * pointers to be passed between C modules */
2 : :
3 : : #include "Python.h"
4 : :
5 : : /* Internal structure of PyCapsule */
6 : : typedef struct {
7 : : PyObject_HEAD
8 : : void *pointer;
9 : : const char *name;
10 : : void *context;
11 : : PyCapsule_Destructor destructor;
12 : : } PyCapsule;
13 : :
14 : :
15 : :
16 : : static int
17 : 12709 : _is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
18 : : {
19 [ + - + - : 12709 : if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
- + ]
20 : 0 : PyErr_SetString(PyExc_ValueError, invalid_capsule);
21 : 0 : return 0;
22 : : }
23 : 12709 : return 1;
24 : : }
25 : :
26 : : #define is_legal_capsule(capsule, name) \
27 : : (_is_legal_capsule(capsule, \
28 : : name " called with invalid PyCapsule object"))
29 : :
30 : :
31 : : static int
32 : 12714 : name_matches(const char *name1, const char *name2) {
33 : : /* if either is NULL, */
34 [ + - - + ]: 12714 : if (!name1 || !name2) {
35 : : /* they're only the same if they're both NULL. */
36 : 0 : return name1 == name2;
37 : : }
38 : 12714 : return !strcmp(name1, name2);
39 : : }
40 : :
41 : :
42 : :
43 : : PyObject *
44 : 7751 : PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
45 : : {
46 : : PyCapsule *capsule;
47 : :
48 [ - + ]: 7751 : if (!pointer) {
49 : 0 : PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
50 : 0 : return NULL;
51 : : }
52 : :
53 : 7751 : capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
54 [ - + ]: 7751 : if (capsule == NULL) {
55 : 0 : return NULL;
56 : : }
57 : :
58 : 7751 : capsule->pointer = pointer;
59 : 7751 : capsule->name = name;
60 : 7751 : capsule->context = NULL;
61 : 7751 : capsule->destructor = destructor;
62 : :
63 : 7751 : return (PyObject *)capsule;
64 : : }
65 : :
66 : :
67 : : int
68 : 5 : PyCapsule_IsValid(PyObject *o, const char *name)
69 : : {
70 : 5 : PyCapsule *capsule = (PyCapsule *)o;
71 : :
72 [ + - ]: 5 : return (capsule != NULL &&
73 : 5 : PyCapsule_CheckExact(capsule) &&
74 [ + - + - : 15 : capsule->pointer != NULL &&
+ - ]
75 : 5 : name_matches(capsule->name, name));
76 : : }
77 : :
78 : :
79 : : void *
80 : 12709 : PyCapsule_GetPointer(PyObject *o, const char *name)
81 : : {
82 : 12709 : PyCapsule *capsule = (PyCapsule *)o;
83 : :
84 [ - + ]: 12709 : if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
85 : 0 : return NULL;
86 : : }
87 : :
88 [ - + ]: 12709 : if (!name_matches(name, capsule->name)) {
89 : 0 : PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
90 : 0 : return NULL;
91 : : }
92 : :
93 : 12709 : return capsule->pointer;
94 : : }
95 : :
96 : :
97 : : const char *
98 : 0 : PyCapsule_GetName(PyObject *o)
99 : : {
100 : 0 : PyCapsule *capsule = (PyCapsule *)o;
101 : :
102 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
103 : 0 : return NULL;
104 : : }
105 : 0 : return capsule->name;
106 : : }
107 : :
108 : :
109 : : PyCapsule_Destructor
110 : 0 : PyCapsule_GetDestructor(PyObject *o)
111 : : {
112 : 0 : PyCapsule *capsule = (PyCapsule *)o;
113 : :
114 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
115 : 0 : return NULL;
116 : : }
117 : 0 : return capsule->destructor;
118 : : }
119 : :
120 : :
121 : : void *
122 : 0 : PyCapsule_GetContext(PyObject *o)
123 : : {
124 : 0 : PyCapsule *capsule = (PyCapsule *)o;
125 : :
126 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
127 : 0 : return NULL;
128 : : }
129 : 0 : return capsule->context;
130 : : }
131 : :
132 : :
133 : : int
134 : 0 : PyCapsule_SetPointer(PyObject *o, void *pointer)
135 : : {
136 : 0 : PyCapsule *capsule = (PyCapsule *)o;
137 : :
138 [ # # ]: 0 : if (!pointer) {
139 : 0 : PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
140 : 0 : return -1;
141 : : }
142 : :
143 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
144 : 0 : return -1;
145 : : }
146 : :
147 : 0 : capsule->pointer = pointer;
148 : 0 : return 0;
149 : : }
150 : :
151 : :
152 : : int
153 : 0 : PyCapsule_SetName(PyObject *o, const char *name)
154 : : {
155 : 0 : PyCapsule *capsule = (PyCapsule *)o;
156 : :
157 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
158 : 0 : return -1;
159 : : }
160 : :
161 : 0 : capsule->name = name;
162 : 0 : return 0;
163 : : }
164 : :
165 : :
166 : : int
167 : 0 : PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
168 : : {
169 : 0 : PyCapsule *capsule = (PyCapsule *)o;
170 : :
171 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
172 : 0 : return -1;
173 : : }
174 : :
175 : 0 : capsule->destructor = destructor;
176 : 0 : return 0;
177 : : }
178 : :
179 : :
180 : : int
181 : 0 : PyCapsule_SetContext(PyObject *o, void *context)
182 : : {
183 : 0 : PyCapsule *capsule = (PyCapsule *)o;
184 : :
185 [ # # ]: 0 : if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
186 : 0 : return -1;
187 : : }
188 : :
189 : 0 : capsule->context = context;
190 : 0 : return 0;
191 : : }
192 : :
193 : :
194 : : void *
195 : 5 : PyCapsule_Import(const char *name, int no_block)
196 : : {
197 : 5 : PyObject *object = NULL;
198 : 5 : void *return_value = NULL;
199 : : char *trace;
200 : 5 : size_t name_length = (strlen(name) + 1) * sizeof(char);
201 : 5 : char *name_dup = (char *)PyMem_Malloc(name_length);
202 : :
203 [ - + ]: 5 : if (!name_dup) {
204 : 0 : return PyErr_NoMemory();
205 : : }
206 : :
207 : 5 : memcpy(name_dup, name, name_length);
208 : :
209 : 5 : trace = name_dup;
210 [ + + ]: 15 : while (trace) {
211 : 10 : char *dot = strchr(trace, '.');
212 [ + + ]: 10 : if (dot) {
213 : 5 : *dot++ = '\0';
214 : : }
215 : :
216 [ + + ]: 10 : if (object == NULL) {
217 : 5 : object = PyImport_ImportModule(trace);
218 [ - + ]: 5 : if (!object) {
219 : 0 : PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
220 : : }
221 : : } else {
222 : 5 : PyObject *object2 = PyObject_GetAttrString(object, trace);
223 : 5 : Py_SETREF(object, object2);
224 : : }
225 [ - + ]: 10 : if (!object) {
226 : 0 : goto EXIT;
227 : : }
228 : :
229 : 10 : trace = dot;
230 : : }
231 : :
232 : : /* compare attribute name to module.name by hand */
233 [ + - ]: 5 : if (PyCapsule_IsValid(object, name)) {
234 : 5 : PyCapsule *capsule = (PyCapsule *)object;
235 : 5 : return_value = capsule->pointer;
236 : : } else {
237 : 0 : PyErr_Format(PyExc_AttributeError,
238 : : "PyCapsule_Import \"%s\" is not valid",
239 : : name);
240 : : }
241 : :
242 : 5 : EXIT:
243 : 5 : Py_XDECREF(object);
244 [ + - ]: 5 : if (name_dup) {
245 : 5 : PyMem_Free(name_dup);
246 : : }
247 : 5 : return return_value;
248 : : }
249 : :
250 : :
251 : : static void
252 : 7751 : capsule_dealloc(PyObject *o)
253 : : {
254 : 7751 : PyCapsule *capsule = (PyCapsule *)o;
255 [ + + ]: 7751 : if (capsule->destructor) {
256 : 6 : capsule->destructor(o);
257 : : }
258 : 7751 : PyObject_Free(o);
259 : 7751 : }
260 : :
261 : :
262 : : static PyObject *
263 : 0 : capsule_repr(PyObject *o)
264 : : {
265 : 0 : PyCapsule *capsule = (PyCapsule *)o;
266 : : const char *name;
267 : : const char *quote;
268 : :
269 [ # # ]: 0 : if (capsule->name) {
270 : 0 : quote = "\"";
271 : 0 : name = capsule->name;
272 : : } else {
273 : 0 : quote = "";
274 : 0 : name = "NULL";
275 : : }
276 : :
277 : 0 : return PyUnicode_FromFormat("<capsule object %s%s%s at %p>",
278 : : quote, name, quote, capsule);
279 : : }
280 : :
281 : :
282 : :
283 : : PyDoc_STRVAR(PyCapsule_Type__doc__,
284 : : "Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
285 : : object. They're a way of passing data through the Python interpreter\n\
286 : : without creating your own custom type.\n\
287 : : \n\
288 : : Capsules are used for communication between extension modules.\n\
289 : : They provide a way for an extension module to export a C interface\n\
290 : : to other extension modules, so that extension modules can use the\n\
291 : : Python import mechanism to link to one another.\n\
292 : : ");
293 : :
294 : : PyTypeObject PyCapsule_Type = {
295 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
296 : : "PyCapsule", /*tp_name*/
297 : : sizeof(PyCapsule), /*tp_basicsize*/
298 : : 0, /*tp_itemsize*/
299 : : /* methods */
300 : : capsule_dealloc, /*tp_dealloc*/
301 : : 0, /*tp_vectorcall_offset*/
302 : : 0, /*tp_getattr*/
303 : : 0, /*tp_setattr*/
304 : : 0, /*tp_as_async*/
305 : : capsule_repr, /*tp_repr*/
306 : : 0, /*tp_as_number*/
307 : : 0, /*tp_as_sequence*/
308 : : 0, /*tp_as_mapping*/
309 : : 0, /*tp_hash*/
310 : : 0, /*tp_call*/
311 : : 0, /*tp_str*/
312 : : 0, /*tp_getattro*/
313 : : 0, /*tp_setattro*/
314 : : 0, /*tp_as_buffer*/
315 : : 0, /*tp_flags*/
316 : : PyCapsule_Type__doc__ /*tp_doc*/
317 : : };
318 : :
319 : :
|