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