LCOV - code coverage report
Current view: top level - Objects - capsule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 97 123 78.9 %
Date: 2022-07-07 18:19:46 Functions: 14 15 93.3 %

          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      566839 : _is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
      18             : {
      19      566839 :     if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
      20           0 :         PyErr_SetString(PyExc_ValueError, invalid_capsule);
      21           0 :         return 0;
      22             :     }
      23      566839 :     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      567522 : name_matches(const char *name1, const char *name2) {
      33             :     /* if either is NULL, */
      34      567522 :     if (!name1 || !name2) {
      35             :         /* they're only the same if they're both NULL. */
      36           0 :         return name1 == name2;
      37             :     }
      38      567522 :     return !strcmp(name1, name2);
      39             : }
      40             : 
      41             : 
      42             : 
      43             : PyObject *
      44      352488 : PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
      45             : {
      46             :     PyCapsule *capsule;
      47             : 
      48      352488 :     if (!pointer) {
      49           0 :         PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
      50           0 :         return NULL;
      51             :     }
      52             : 
      53      352488 :     capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
      54      352488 :     if (capsule == NULL) {
      55           0 :         return NULL;
      56             :     }
      57             : 
      58      352488 :     capsule->pointer = pointer;
      59      352488 :     capsule->name = name;
      60      352488 :     capsule->context = NULL;
      61      352488 :     capsule->destructor = destructor;
      62             : 
      63      352488 :     return (PyObject *)capsule;
      64             : }
      65             : 
      66             : 
      67             : int
      68         698 : PyCapsule_IsValid(PyObject *o, const char *name)
      69             : {
      70         698 :     PyCapsule *capsule = (PyCapsule *)o;
      71             : 
      72         698 :     return (capsule != NULL &&
      73         698 :             PyCapsule_CheckExact(capsule) &&
      74        2094 :             capsule->pointer != NULL &&
      75         698 :             name_matches(capsule->name, name));
      76             : }
      77             : 
      78             : 
      79             : void *
      80      566824 : PyCapsule_GetPointer(PyObject *o, const char *name)
      81             : {
      82      566824 :     PyCapsule *capsule = (PyCapsule *)o;
      83             : 
      84      566824 :     if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
      85           0 :         return NULL;
      86             :     }
      87             : 
      88      566824 :     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      566820 :     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         475 : PyCapsule_Import(const char *name, int no_block)
     196             : {
     197         475 :     PyObject *object = NULL;
     198         475 :     void *return_value = NULL;
     199             :     char *trace;
     200         475 :     size_t name_length = (strlen(name) + 1) * sizeof(char);
     201         475 :     char *name_dup = (char *)PyMem_Malloc(name_length);
     202             : 
     203         475 :     if (!name_dup) {
     204           0 :         return PyErr_NoMemory();
     205             :     }
     206             : 
     207         475 :     memcpy(name_dup, name, name_length);
     208             : 
     209         475 :     trace = name_dup;
     210        1423 :     while (trace) {
     211         949 :         char *dot = strchr(trace, '.');
     212         949 :         if (dot) {
     213         475 :             *dot++ = '\0';
     214             :         }
     215             : 
     216         949 :         if (object == NULL) {
     217         475 :             object = PyImport_ImportModule(trace);
     218         475 :             if (!object) {
     219           1 :                 PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
     220             :             }
     221             :         } else {
     222         474 :             PyObject *object2 = PyObject_GetAttrString(object, trace);
     223         474 :             Py_DECREF(object);
     224         474 :             object = object2;
     225             :         }
     226         949 :         if (!object) {
     227           1 :             goto EXIT;
     228             :         }
     229             : 
     230         948 :         trace = dot;
     231             :     }
     232             : 
     233             :     /* compare attribute name to module.name by hand */
     234         474 :     if (PyCapsule_IsValid(object, name)) {
     235         474 :         PyCapsule *capsule = (PyCapsule *)object;
     236         474 :         return_value = capsule->pointer;
     237             :     } else {
     238           0 :         PyErr_Format(PyExc_AttributeError,
     239             :             "PyCapsule_Import \"%s\" is not valid",
     240             :             name);
     241             :     }
     242             : 
     243         475 : EXIT:
     244         475 :     Py_XDECREF(object);
     245         475 :     if (name_dup) {
     246         475 :         PyMem_Free(name_dup);
     247             :     }
     248         475 :     return return_value;
     249             : }
     250             : 
     251             : 
     252             : static void
     253      352461 : capsule_dealloc(PyObject *o)
     254             : {
     255      352461 :     PyCapsule *capsule = (PyCapsule *)o;
     256      352461 :     if (capsule->destructor) {
     257        1050 :         capsule->destructor(o);
     258             :     }
     259      352461 :     PyObject_Free(o);
     260      352461 : }
     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             : 

Generated by: LCOV version 1.14