LCOV - code coverage report
Current view: top level - Objects - capsule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 30 124 24.2 %
Date: 2017-04-19 Functions: 6 15 40.0 %

          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        1064 : _is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
      18             : {
      19        1064 :     if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
      20           0 :         PyErr_SetString(PyExc_ValueError, invalid_capsule);
      21           0 :         return 0;
      22             :     }
      23        1064 :     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         980 : name_matches(const char *name1, const char *name2) {
      33             :     /* if either is NULL, */
      34         980 :     if (!name1 || !name2) {
      35             :         /* they're only the same if they're both NULL. */
      36           0 :         return name1 == name2;
      37             :     }
      38         980 :     return !strcmp(name1, name2);
      39             : }
      40             : 
      41             : 
      42             : 
      43             : PyObject *
      44        1067 : PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
      45             : {
      46             :     PyCapsule *capsule;
      47             : 
      48        1067 :     if (!pointer) {
      49           0 :         PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
      50           0 :         return NULL;
      51             :     }
      52             : 
      53        1067 :     capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
      54        1067 :     if (capsule == NULL) {
      55           0 :         return NULL;
      56             :     }
      57             : 
      58        1067 :     capsule->pointer = pointer;
      59        1067 :     capsule->name = name;
      60        1067 :     capsule->context = NULL;
      61        1067 :     capsule->destructor = destructor;
      62             : 
      63        1067 :     return (PyObject *)capsule;
      64             : }
      65             : 
      66             : 
      67             : int
      68           0 : PyCapsule_IsValid(PyObject *o, const char *name)
      69             : {
      70           0 :     PyCapsule *capsule = (PyCapsule *)o;
      71             : 
      72           0 :     return (capsule != NULL &&
      73           0 :             PyCapsule_CheckExact(capsule) &&
      74           0 :             capsule->pointer != NULL &&
      75           0 :             name_matches(capsule->name, name));
      76             : }
      77             : 
      78             : 
      79             : void *
      80         980 : PyCapsule_GetPointer(PyObject *o, const char *name)
      81             : {
      82         980 :     PyCapsule *capsule = (PyCapsule *)o;
      83             : 
      84         980 :     if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
      85           0 :         return NULL;
      86             :     }
      87             : 
      88         980 :     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         980 :     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          84 : PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
     168             : {
     169          84 :     PyCapsule *capsule = (PyCapsule *)o;
     170             : 
     171          84 :     if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
     172           0 :         return -1;
     173             :     }
     174             : 
     175          84 :     capsule->destructor = destructor;
     176          84 :     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           0 : PyCapsule_Import(const char *name, int no_block)
     196             : {
     197           0 :     PyObject *object = NULL;
     198           0 :     void *return_value = NULL;
     199             :     char *trace;
     200           0 :     size_t name_length = (strlen(name) + 1) * sizeof(char);
     201           0 :     char *name_dup = (char *)PyMem_MALLOC(name_length);
     202             : 
     203           0 :     if (!name_dup) {
     204           0 :         return NULL;
     205             :     }
     206             : 
     207           0 :     memcpy(name_dup, name, name_length);
     208             : 
     209           0 :     trace = name_dup;
     210           0 :     while (trace) {
     211           0 :         char *dot = strchr(trace, '.');
     212           0 :         if (dot) {
     213           0 :             *dot++ = '\0';
     214             :         }
     215             : 
     216           0 :         if (object == NULL) {
     217           0 :             if (no_block) {
     218           0 :                 object = PyImport_ImportModuleNoBlock(trace);
     219             :             } else {
     220           0 :                 object = PyImport_ImportModule(trace);
     221           0 :                 if (!object) {
     222           0 :                     PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
     223             :                 }
     224             :             }
     225             :         } else {
     226           0 :             PyObject *object2 = PyObject_GetAttrString(object, trace);
     227           0 :             Py_DECREF(object);
     228           0 :             object = object2;
     229             :         }
     230           0 :         if (!object) {
     231           0 :             goto EXIT;
     232             :         }
     233             : 
     234           0 :         trace = dot;
     235             :     }
     236             : 
     237             :     /* compare attribute name to module.name by hand */
     238           0 :     if (PyCapsule_IsValid(object, name)) {
     239           0 :         PyCapsule *capsule = (PyCapsule *)object;
     240           0 :         return_value = capsule->pointer;
     241             :     } else {
     242           0 :         PyErr_Format(PyExc_AttributeError,
     243             :             "PyCapsule_Import \"%s\" is not valid",
     244             :             name);
     245             :     }
     246             : 
     247             : EXIT:
     248           0 :     Py_XDECREF(object);
     249           0 :     if (name_dup) {
     250           0 :         PyMem_FREE(name_dup);
     251             :     }
     252           0 :     return return_value;
     253             : }
     254             : 
     255             : 
     256             : static void
     257        1067 : capsule_dealloc(PyObject *o)
     258             : {
     259        1067 :     PyCapsule *capsule = (PyCapsule *)o;
     260        1067 :     if (capsule->destructor) {
     261           0 :         capsule->destructor(o);
     262             :     }
     263        1067 :     PyObject_DEL(o);
     264        1067 : }
     265             : 
     266             : 
     267             : static PyObject *
     268           0 : capsule_repr(PyObject *o)
     269             : {
     270           0 :     PyCapsule *capsule = (PyCapsule *)o;
     271             :     const char *name;
     272             :     const char *quote;
     273             : 
     274           0 :     if (capsule->name) {
     275           0 :         quote = "\"";
     276           0 :         name = capsule->name;
     277             :     } else {
     278           0 :         quote = "";
     279           0 :         name = "NULL";
     280             :     }
     281             : 
     282           0 :     return PyString_FromFormat("<capsule object %s%s%s at %p>",
     283             :         quote, name, quote, capsule);
     284             : }
     285             : 
     286             : 
     287             : 
     288             : PyDoc_STRVAR(PyCapsule_Type__doc__,
     289             : "Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
     290             : object.  They're a way of passing data through the Python interpreter\n\
     291             : without creating your own custom type.\n\
     292             : \n\
     293             : Capsules are used for communication between extension modules.\n\
     294             : They provide a way for an extension module to export a C interface\n\
     295             : to other extension modules, so that extension modules can use the\n\
     296             : Python import mechanism to link to one another.\n\
     297             : ");
     298             : 
     299             : PyTypeObject PyCapsule_Type = {
     300             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     301             :     "PyCapsule",              /*tp_name*/
     302             :     sizeof(PyCapsule),          /*tp_basicsize*/
     303             :     0,                          /*tp_itemsize*/
     304             :     /* methods */
     305             :     capsule_dealloc, /*tp_dealloc*/
     306             :     0,                          /*tp_print*/
     307             :     0,                          /*tp_getattr*/
     308             :     0,                          /*tp_setattr*/
     309             :     0,                          /*tp_reserved*/
     310             :     capsule_repr, /*tp_repr*/
     311             :     0,                          /*tp_as_number*/
     312             :     0,                          /*tp_as_sequence*/
     313             :     0,                          /*tp_as_mapping*/
     314             :     0,                          /*tp_hash*/
     315             :     0,                          /*tp_call*/
     316             :     0,                          /*tp_str*/
     317             :     0,                          /*tp_getattro*/
     318             :     0,                          /*tp_setattro*/
     319             :     0,                          /*tp_as_buffer*/
     320             :     0,                          /*tp_flags*/
     321             :     PyCapsule_Type__doc__       /*tp_doc*/
     322             : };
     323             : 
     324             : 

Generated by: LCOV version 1.10