LCOV - code coverage report
Current view: | top level - Modules/_ctypes - _ctypes.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 336 | 2203 | 15.3 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 23 | 120 | 19.2 %
|  |  | Branches: | 180 | 1384 | 13.0 %

               Branch data     Line data    Source code
           1                 :            : /*
           2                 :            :   ToDo:
           3                 :            :
           4                 :            :   Get rid of the checker (and also the converters) field in PyCFuncPtrObject and
           5                 :            :   StgDictObject, and replace them by slot functions in StgDictObject.
           6                 :            :
           7                 :            :   think about a buffer-like object (memory? bytes?)
           8                 :            :
           9                 :            :   Should POINTER(c_char) and POINTER(c_wchar) have a .value property?
          10                 :            :   What about c_char and c_wchar arrays then?
          11                 :            :
          12                 :            :   Add from_mmap, from_file, from_string metaclass methods.
          13                 :            :
          14                 :            :   Maybe we can get away with from_file (calls read) and with a from_buffer
          15                 :            :   method?
          16                 :            :
          17                 :            :   And what about the to_mmap, to_file, to_str(?) methods?  They would clobber
          18                 :            :   the namespace, probably. So, functions instead? And we already have memmove...
          19                 :            : */
          20                 :            :
          21                 :            : /*
          22                 :            :
          23                 :            : Name                    methods, members, getsets
          24                 :            : ==============================================================================
          25                 :            :
          26                 :            : PyCStructType_Type              __new__(), from_address(), __mul__(), from_param()
          27                 :            : UnionType_Type                  __new__(), from_address(), __mul__(), from_param()
          28                 :            : PyCPointerType_Type             __new__(), from_address(), __mul__(), from_param(), set_type()
          29                 :            : PyCArrayType_Type               __new__(), from_address(), __mul__(), from_param()
          30                 :            : PyCSimpleType_Type              __new__(), from_address(), __mul__(), from_param()
          31                 :            :
          32                 :            : PyCData_Type
          33                 :            :   Struct_Type                   __new__(), __init__()
          34                 :            :   PyCPointer_Type               __new__(), __init__(), _as_parameter_, contents
          35                 :            :   PyCArray_Type                 __new__(), __init__(), _as_parameter_, __get/setitem__(), __len__()
          36                 :            :   Simple_Type                   __new__(), __init__(), _as_parameter_
          37                 :            :
          38                 :            : PyCField_Type
          39                 :            : PyCStgDict_Type
          40                 :            :
          41                 :            : ==============================================================================
          42                 :            :
          43                 :            : class methods
          44                 :            : -------------
          45                 :            :
          46                 :            : It has some similarity to the byref() construct compared to pointer()
          47                 :            : from_address(addr)
          48                 :            :     - construct an instance from a given memory block (sharing this memory block)
          49                 :            :
          50                 :            : from_param(obj)
          51                 :            :     - typecheck and convert a Python object into a C function call parameter
          52                 :            :       The result may be an instance of the type, or an integer or tuple
          53                 :            :       (typecode, value[, obj])
          54                 :            :
          55                 :            : instance methods/properties
          56                 :            : ---------------------------
          57                 :            :
          58                 :            : _as_parameter_
          59                 :            :     - convert self into a C function call parameter
          60                 :            :       This is either an integer, or a 3-tuple (typecode, value, obj)
          61                 :            :
          62                 :            : functions
          63                 :            : ---------
          64                 :            :
          65                 :            : sizeof(cdata)
          66                 :            :     - return the number of bytes the buffer contains
          67                 :            :
          68                 :            : sizeof(ctype)
          69                 :            :     - return the number of bytes the buffer of an instance would contain
          70                 :            :
          71                 :            : byref(cdata)
          72                 :            :
          73                 :            : addressof(cdata)
          74                 :            :
          75                 :            : pointer(cdata)
          76                 :            :
          77                 :            : POINTER(ctype)
          78                 :            :
          79                 :            : bytes(cdata)
          80                 :            :     - return the buffer contents as a sequence of bytes (which is currently a string)
          81                 :            :
          82                 :            : */
          83                 :            :
          84                 :            : /*
          85                 :            :  * PyCStgDict_Type
          86                 :            :  * PyCStructType_Type
          87                 :            :  * UnionType_Type
          88                 :            :  * PyCPointerType_Type
          89                 :            :  * PyCArrayType_Type
          90                 :            :  * PyCSimpleType_Type
          91                 :            :  *
          92                 :            :  * PyCData_Type
          93                 :            :  * Struct_Type
          94                 :            :  * Union_Type
          95                 :            :  * PyCArray_Type
          96                 :            :  * Simple_Type
          97                 :            :  * PyCPointer_Type
          98                 :            :  * PyCField_Type
          99                 :            :  *
         100                 :            :  */
         101                 :            : #ifndef Py_BUILD_CORE_BUILTIN
         102                 :            : #  define Py_BUILD_CORE_MODULE 1
         103                 :            : #endif
         104                 :            : #define PY_SSIZE_T_CLEAN
         105                 :            :
         106                 :            : #include "Python.h"
         107                 :            : // windows.h must be included before pycore internal headers
         108                 :            : #ifdef MS_WIN32
         109                 :            : #  include <windows.h>
         110                 :            : #endif
         111                 :            :
         112                 :            : #include "pycore_call.h"          // _PyObject_CallNoArgs()
         113                 :            : #include "pycore_ceval.h"         // _Py_EnterRecursiveCall()
         114                 :            : #include "structmember.h"         // PyMemberDef
         115                 :            :
         116                 :            : #include <ffi.h>
         117                 :            : #ifdef MS_WIN32
         118                 :            : #include <malloc.h>
         119                 :            : #ifndef IS_INTRESOURCE
         120                 :            : #define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0)
         121                 :            : #endif
         122                 :            : #else
         123                 :            : #include <dlfcn.h>
         124                 :            : #endif
         125                 :            : #include "ctypes.h"
         126                 :            :
         127                 :            : #include "pycore_long.h"          // _PyLong_GetZero()
         128                 :            :
         129                 :            : PyObject *PyExc_ArgError = NULL;
         130                 :            :
         131                 :            : /* This dict maps ctypes types to POINTER types */
         132                 :            : PyObject *_ctypes_ptrtype_cache = NULL;
         133                 :            :
         134                 :            : static PyTypeObject Simple_Type;
         135                 :            :
         136                 :            : /* a callable object used for unpickling:
         137                 :            :    strong reference to _ctypes._unpickle() function */
         138                 :            : static PyObject *_unpickle;
         139                 :            :
         140                 :            : #ifdef MS_WIN32
         141                 :            : PyObject *ComError;  // Borrowed reference to: &PyComError_Type
         142                 :            : #endif
         143                 :            :
         144                 :            :
         145                 :            : /****************************************************************/
         146                 :            :
         147                 :            : typedef struct {
         148                 :            :     PyObject_HEAD
         149                 :            :     PyObject *key;
         150                 :            :     PyObject *dict;
         151                 :            : } DictRemoverObject;
         152                 :            :
         153                 :            : static void
         154                 :          0 : _DictRemover_dealloc(PyObject *myself)
         155                 :            : {
         156                 :          0 :     DictRemoverObject *self = (DictRemoverObject *)myself;
         157                 :          0 :     Py_XDECREF(self->key);
         158                 :          0 :     Py_XDECREF(self->dict);
         159                 :          0 :     Py_TYPE(self)->tp_free(myself);
         160                 :          0 : }
         161                 :            :
         162                 :            : static PyObject *
         163                 :          0 : _DictRemover_call(PyObject *myself, PyObject *args, PyObject *kw)
         164                 :            : {
         165                 :          0 :     DictRemoverObject *self = (DictRemoverObject *)myself;
         166   [ #  #  #  # ]:          0 :     if (self->key && self->dict) {
         167         [ #  # ]:          0 :         if (-1 == PyDict_DelItem(self->dict, self->key)) {
         168                 :          0 :             _PyErr_WriteUnraisableMsg("on calling _ctypes.DictRemover", NULL);
         169                 :            :         }
         170         [ #  # ]:          0 :         Py_CLEAR(self->key);
         171         [ #  # ]:          0 :         Py_CLEAR(self->dict);
         172                 :            :     }
         173                 :          0 :     Py_RETURN_NONE;
         174                 :            : }
         175                 :            :
         176                 :            : static PyTypeObject DictRemover_Type = {
         177                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         178                 :            :     "_ctypes.DictRemover",                      /* tp_name */
         179                 :            :     sizeof(DictRemoverObject),                  /* tp_basicsize */
         180                 :            :     0,                                          /* tp_itemsize */
         181                 :            :     _DictRemover_dealloc,                       /* tp_dealloc */
         182                 :            :     0,                                          /* tp_vectorcall_offset */
         183                 :            :     0,                                          /* tp_getattr */
         184                 :            :     0,                                          /* tp_setattr */
         185                 :            :     0,                                          /* tp_as_async */
         186                 :            :     0,                                          /* tp_repr */
         187                 :            :     0,                                          /* tp_as_number */
         188                 :            :     0,                                          /* tp_as_sequence */
         189                 :            :     0,                                          /* tp_as_mapping */
         190                 :            :     0,                                          /* tp_hash */
         191                 :            :     _DictRemover_call,                          /* tp_call */
         192                 :            :     0,                                          /* tp_str */
         193                 :            :     0,                                          /* tp_getattro */
         194                 :            :     0,                                          /* tp_setattro */
         195                 :            :     0,                                          /* tp_as_buffer */
         196                 :            : /* XXX should participate in GC? */
         197                 :            :     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
         198                 :            :     PyDoc_STR("deletes a key from a dictionary"), /* tp_doc */
         199                 :            :     0,                                          /* tp_traverse */
         200                 :            :     0,                                          /* tp_clear */
         201                 :            :     0,                                          /* tp_richcompare */
         202                 :            :     0,                                          /* tp_weaklistoffset */
         203                 :            :     0,                                          /* tp_iter */
         204                 :            :     0,                                          /* tp_iternext */
         205                 :            :     0,                                          /* tp_methods */
         206                 :            :     0,                                          /* tp_members */
         207                 :            :     0,                                          /* tp_getset */
         208                 :            :     0,                                          /* tp_base */
         209                 :            :     0,                                          /* tp_dict */
         210                 :            :     0,                                          /* tp_descr_get */
         211                 :            :     0,                                          /* tp_descr_set */
         212                 :            :     0,                                          /* tp_dictoffset */
         213                 :            :     0,                                          /* tp_init */
         214                 :            :     0,                                          /* tp_alloc */
         215                 :            :     0,                                          /* tp_new */
         216                 :            :     0,                                          /* tp_free */
         217                 :            : };
         218                 :            :
         219                 :            : int
         220                 :          0 : PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item)
         221                 :            : {
         222                 :            :     PyObject *obj;
         223                 :            :     DictRemoverObject *remover;
         224                 :            :     PyObject *proxy;
         225                 :            :     int result;
         226                 :            :
         227                 :          0 :     obj = _PyObject_CallNoArgs((PyObject *)&DictRemover_Type);
         228         [ #  # ]:          0 :     if (obj == NULL)
         229                 :          0 :         return -1;
         230                 :            :
         231                 :          0 :     remover = (DictRemoverObject *)obj;
         232                 :            :     assert(remover->key == NULL);
         233                 :            :     assert(remover->dict == NULL);
         234                 :          0 :     remover->key = Py_NewRef(key);
         235                 :          0 :     remover->dict = Py_NewRef(dict);
         236                 :            :
         237                 :          0 :     proxy = PyWeakref_NewProxy(item, obj);
         238                 :          0 :     Py_DECREF(obj);
         239         [ #  # ]:          0 :     if (proxy == NULL)
         240                 :          0 :         return -1;
         241                 :            :
         242                 :          0 :     result = PyDict_SetItem(dict, key, proxy);
         243                 :          0 :     Py_DECREF(proxy);
         244                 :          0 :     return result;
         245                 :            : }
         246                 :            :
         247                 :            : PyObject *
         248                 :          0 : PyDict_GetItemProxy(PyObject *dict, PyObject *key)
         249                 :            : {
         250                 :            :     PyObject *result;
         251                 :          0 :     PyObject *item = PyDict_GetItemWithError(dict, key);
         252                 :            :
         253         [ #  # ]:          0 :     if (item == NULL)
         254                 :          0 :         return NULL;
         255   [ #  #  #  # ]:          0 :     if (!PyWeakref_CheckProxy(item))
         256                 :          0 :         return item;
         257                 :          0 :     result = PyWeakref_GET_OBJECT(item);
         258         [ #  # ]:          0 :     if (result == Py_None)
         259                 :          0 :         return NULL;
         260                 :          0 :     return result;
         261                 :            : }
         262                 :            :
         263                 :            : /******************************************************************/
         264                 :            :
         265                 :            : /*
         266                 :            :   Allocate a memory block for a pep3118 format string, filled with
         267                 :            :   a suitable PEP 3118 type code corresponding to the given ctypes
         268                 :            :   type. Returns NULL on failure, with the error indicator set.
         269                 :            :
         270                 :            :   This produces type codes in the standard size mode (cf. struct module),
         271                 :            :   since the endianness may need to be swapped to a non-native one
         272                 :            :   later on.
         273                 :            :  */
         274                 :            : static char *
         275                 :         18 : _ctypes_alloc_format_string_for_type(char code, int big_endian)
         276                 :            : {
         277                 :            :     char *result;
         278                 :         18 :     char pep_code = '\0';
         279                 :            :
         280   [ +  +  +  +  :         18 :     switch (code) {
                       +  + ]
         281                 :            : #if SIZEOF_INT == 2
         282                 :            :     case 'i': pep_code = 'h'; break;
         283                 :            :     case 'I': pep_code = 'H'; break;
         284                 :            : #elif SIZEOF_INT == 4
         285                 :          1 :     case 'i': pep_code = 'i'; break;
         286                 :          1 :     case 'I': pep_code = 'I'; break;
         287                 :            : #elif SIZEOF_INT == 8
         288                 :            :     case 'i': pep_code = 'q'; break;
         289                 :            :     case 'I': pep_code = 'Q'; break;
         290                 :            : #else
         291                 :            : # error SIZEOF_INT has an unexpected value
         292                 :            : #endif /* SIZEOF_INT */
         293                 :            : #if SIZEOF_LONG == 4
         294                 :            :     case 'l': pep_code = 'l'; break;
         295                 :            :     case 'L': pep_code = 'L'; break;
         296                 :            : #elif SIZEOF_LONG == 8
         297                 :          1 :     case 'l': pep_code = 'q'; break;
         298                 :          1 :     case 'L': pep_code = 'Q'; break;
         299                 :            : #else
         300                 :            : # error SIZEOF_LONG has an unexpected value
         301                 :            : #endif /* SIZEOF_LONG */
         302                 :            : #if SIZEOF__BOOL == 1
         303                 :          1 :     case '?': pep_code = '?'; break;
         304                 :            : #elif SIZEOF__BOOL == 2
         305                 :            :     case '?': pep_code = 'H'; break;
         306                 :            : #elif SIZEOF__BOOL == 4
         307                 :            :     case '?': pep_code = 'L'; break;
         308                 :            : #elif SIZEOF__BOOL == 8
         309                 :            :     case '?': pep_code = 'Q'; break;
         310                 :            : #else
         311                 :            : # error SIZEOF__BOOL has an unexpected value
         312                 :            : #endif /* SIZEOF__BOOL */
         313                 :         13 :     default:
         314                 :            :         /* The standard-size code is the same as the ctypes one */
         315                 :         13 :         pep_code = code;
         316                 :         13 :         break;
         317                 :            :     }
         318                 :            :
         319                 :         18 :     result = PyMem_Malloc(3);
         320         [ -  + ]:         18 :     if (result == NULL) {
         321                 :          0 :         PyErr_NoMemory();
         322                 :          0 :         return NULL;
         323                 :            :     }
         324                 :            :
         325         [ -  + ]:         18 :     result[0] = big_endian ? '>' : '<';
         326                 :         18 :     result[1] = pep_code;
         327                 :         18 :     result[2] = '\0';
         328                 :         18 :     return result;
         329                 :            : }
         330                 :            :
         331                 :            : /*
         332                 :            :   Allocate a memory block for a pep3118 format string, copy prefix (if
         333                 :            :   non-null) and suffix into it.  Returns NULL on failure, with the error
         334                 :            :   indicator set.  If called with a suffix of NULL the error indicator must
         335                 :            :   already be set.
         336                 :            :  */
         337                 :            : char *
         338                 :         20 : _ctypes_alloc_format_string(const char *prefix, const char *suffix)
         339                 :            : {
         340                 :            :     size_t len;
         341                 :            :     char *result;
         342                 :            :
         343         [ -  + ]:         20 :     if (suffix == NULL) {
         344                 :            :         assert(PyErr_Occurred());
         345                 :          0 :         return NULL;
         346                 :            :     }
         347                 :         20 :     len = strlen(suffix);
         348         [ +  + ]:         20 :     if (prefix)
         349                 :         12 :         len += strlen(prefix);
         350                 :         20 :     result = PyMem_Malloc(len + 1);
         351         [ -  + ]:         20 :     if (result == NULL) {
         352                 :          0 :         PyErr_NoMemory();
         353                 :          0 :         return NULL;
         354                 :            :     }
         355         [ +  + ]:         20 :     if (prefix)
         356                 :         12 :         strcpy(result, prefix);
         357                 :            :     else
         358                 :          8 :         result[0] = '\0';
         359                 :         20 :     strcat(result, suffix);
         360                 :         20 :     return result;
         361                 :            : }
         362                 :            :
         363                 :            : /*
         364                 :            :   Allocate a memory block for a pep3118 format string, adding
         365                 :            :   the given prefix (if non-null), an additional shape prefix, and a suffix.
         366                 :            :   Returns NULL on failure, with the error indicator set.  If called with
         367                 :            :   a suffix of NULL the error indicator must already be set.
         368                 :            :  */
         369                 :            : char *
         370                 :          0 : _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape,
         371                 :            :                                        const char *prefix, const char *suffix)
         372                 :            : {
         373                 :            :     char *new_prefix;
         374                 :            :     char *result;
         375                 :            :     char buf[32];
         376                 :            :     Py_ssize_t prefix_len;
         377                 :            :     int k;
         378                 :            :
         379                 :          0 :     prefix_len = 32 * ndim + 3;
         380         [ #  # ]:          0 :     if (prefix)
         381                 :          0 :         prefix_len += strlen(prefix);
         382                 :          0 :     new_prefix = PyMem_Malloc(prefix_len);
         383         [ #  # ]:          0 :     if (new_prefix == NULL) {
         384                 :          0 :         PyErr_NoMemory();
         385                 :          0 :         return NULL;
         386                 :            :     }
         387                 :          0 :     new_prefix[0] = '\0';
         388         [ #  # ]:          0 :     if (prefix)
         389                 :          0 :         strcpy(new_prefix, prefix);
         390         [ #  # ]:          0 :     if (ndim > 0) {
         391                 :            :         /* Add the prefix "(shape[0],shape[1],...,shape[ndim-1])" */
         392                 :          0 :         strcat(new_prefix, "(");
         393         [ #  # ]:          0 :         for (k = 0; k < ndim; ++k) {
         394         [ #  # ]:          0 :             if (k < ndim-1) {
         395                 :          0 :                 sprintf(buf, "%zd,", shape[k]);
         396                 :            :             } else {
         397                 :          0 :                 sprintf(buf, "%zd)", shape[k]);
         398                 :            :             }
         399                 :          0 :             strcat(new_prefix, buf);
         400                 :            :         }
         401                 :            :     }
         402                 :          0 :     result = _ctypes_alloc_format_string(new_prefix, suffix);
         403                 :          0 :     PyMem_Free(new_prefix);
         404                 :          0 :     return result;
         405                 :            : }
         406                 :            :
         407                 :            : /* StructParamObject and StructParam_Type are used in _ctypes_callproc()
         408                 :            :    for argument.keep to call PyMem_Free(ptr) on Py_DECREF(argument).
         409                 :            :
         410                 :            :    StructUnionType_paramfunc() creates such object when a ctypes Structure is
         411                 :            :    passed by copy to a C function. */
         412                 :            : typedef struct {
         413                 :            :     PyObject_HEAD
         414                 :            :     void *ptr;
         415                 :            :     PyObject *keep;  // If set, a reference to the original CDataObject.
         416                 :            : } StructParamObject;
         417                 :            :
         418                 :            :
         419                 :            : static void
         420                 :          0 : StructParam_dealloc(PyObject *myself)
         421                 :            : {
         422                 :          0 :     StructParamObject *self = (StructParamObject *)myself;
         423                 :          0 :     Py_XDECREF(self->keep);
         424                 :          0 :     PyMem_Free(self->ptr);
         425                 :          0 :     Py_TYPE(self)->tp_free(myself);
         426                 :          0 : }
         427                 :            :
         428                 :            :
         429                 :            : static PyTypeObject StructParam_Type = {
         430                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         431                 :            :     .tp_name = "_ctypes.StructParam_Type",
         432                 :            :     .tp_basicsize = sizeof(StructParamObject),
         433                 :            :     .tp_dealloc = StructParam_dealloc,
         434                 :            :     .tp_flags = Py_TPFLAGS_DEFAULT,
         435                 :            : };
         436                 :            :
         437                 :            :
         438                 :            : /*
         439                 :            :   PyCStructType_Type - a meta type/class.  Creating a new class using this one as
         440                 :            :   __metaclass__ will call the constructor StructUnionType_new.  It replaces the
         441                 :            :   tp_dict member with a new instance of StgDict, and initializes the C
         442                 :            :   accessible fields somehow.
         443                 :            : */
         444                 :            :
         445                 :            : static PyCArgObject *
         446                 :          0 : StructUnionType_paramfunc(CDataObject *self)
         447                 :            : {
         448                 :            :     PyCArgObject *parg;
         449                 :            :     PyObject *obj;
         450                 :            :     StgDictObject *stgdict;
         451                 :            :     void *ptr;
         452                 :            :
         453         [ #  # ]:          0 :     if ((size_t)self->b_size > sizeof(void*)) {
         454                 :          0 :         ptr = PyMem_Malloc(self->b_size);
         455         [ #  # ]:          0 :         if (ptr == NULL) {
         456                 :          0 :             return NULL;
         457                 :            :         }
         458                 :          0 :         memcpy(ptr, self->b_ptr, self->b_size);
         459                 :            :
         460                 :            :         /* Create a Python object which calls PyMem_Free(ptr) in
         461                 :            :            its deallocator. The object will be destroyed
         462                 :            :            at _ctypes_callproc() cleanup. */
         463                 :          0 :         obj = (&StructParam_Type)->tp_alloc(&StructParam_Type, 0);
         464         [ #  # ]:          0 :         if (obj == NULL) {
         465                 :          0 :             PyMem_Free(ptr);
         466                 :          0 :             return NULL;
         467                 :            :         }
         468                 :            :
         469                 :          0 :         StructParamObject *struct_param = (StructParamObject *)obj;
         470                 :          0 :         struct_param->ptr = ptr;
         471                 :          0 :         struct_param->keep = Py_NewRef(self);
         472                 :            :     } else {
         473                 :          0 :         ptr = self->b_ptr;
         474                 :          0 :         obj = Py_NewRef(self);
         475                 :            :     }
         476                 :            :
         477                 :          0 :     parg = PyCArgObject_new();
         478         [ #  # ]:          0 :     if (parg == NULL) {
         479                 :          0 :         Py_DECREF(obj);
         480                 :          0 :         return NULL;
         481                 :            :     }
         482                 :            :
         483                 :          0 :     parg->tag = 'V';
         484                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
         485                 :            :     assert(stgdict); /* Cannot be NULL for structure/union instances */
         486                 :          0 :     parg->pffi_type = &stgdict->ffi_type_pointer;
         487                 :          0 :     parg->value.p = ptr;
         488                 :          0 :     parg->size = self->b_size;
         489                 :          0 :     parg->obj = obj;
         490                 :          0 :     return parg;
         491                 :            : }
         492                 :            :
         493                 :            : static PyObject *
         494                 :          2 : StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isStruct)
         495                 :            : {
         496                 :            :     PyTypeObject *result;
         497                 :            :     PyObject *fields;
         498                 :            :     StgDictObject *dict;
         499                 :            :
         500                 :            :     /* create the new instance (which is a class,
         501                 :            :        since we are a metatype!) */
         502                 :          2 :     result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
         503         [ -  + ]:          2 :     if (!result)
         504                 :          0 :         return NULL;
         505                 :            :
         506                 :            :     /* keep this for bw compatibility */
         507                 :          2 :     int r = PyDict_Contains(result->tp_dict, &_Py_ID(_abstract_));
         508         [ -  + ]:          2 :     if (r > 0)
         509                 :          0 :         return (PyObject *)result;
         510         [ -  + ]:          2 :     if (r < 0) {
         511                 :          0 :         Py_DECREF(result);
         512                 :          0 :         return NULL;
         513                 :            :     }
         514                 :            :
         515                 :          2 :     dict = (StgDictObject *)_PyObject_CallNoArgs((PyObject *)&PyCStgDict_Type);
         516         [ -  + ]:          2 :     if (!dict) {
         517                 :          0 :         Py_DECREF(result);
         518                 :          0 :         return NULL;
         519                 :            :     }
         520         [ +  + ]:          2 :     if (!isStruct) {
         521                 :          1 :         dict->flags |= TYPEFLAG_HASUNION;
         522                 :            :     }
         523                 :            :     /* replace the class dict by our updated stgdict, which holds info
         524                 :            :        about storage requirements of the instances */
         525         [ -  + ]:          2 :     if (-1 == PyDict_Update((PyObject *)dict, result->tp_dict)) {
         526                 :          0 :         Py_DECREF(result);
         527                 :          0 :         Py_DECREF((PyObject *)dict);
         528                 :          0 :         return NULL;
         529                 :            :     }
         530                 :          2 :     Py_SETREF(result->tp_dict, (PyObject *)dict);
         531                 :          2 :     dict->format = _ctypes_alloc_format_string(NULL, "B");
         532         [ -  + ]:          2 :     if (dict->format == NULL) {
         533                 :          0 :         Py_DECREF(result);
         534                 :          0 :         return NULL;
         535                 :            :     }
         536                 :            :
         537                 :          2 :     dict->paramfunc = StructUnionType_paramfunc;
         538                 :            :
         539                 :          2 :     fields = PyDict_GetItemWithError((PyObject *)dict, &_Py_ID(_fields_));
         540         [ -  + ]:          2 :     if (fields) {
         541         [ #  # ]:          0 :         if (PyObject_SetAttr((PyObject *)result, &_Py_ID(_fields_), fields) < 0) {
         542                 :          0 :             Py_DECREF(result);
         543                 :          0 :             return NULL;
         544                 :            :         }
         545                 :          0 :         return (PyObject *)result;
         546                 :            :     }
         547         [ -  + ]:          2 :     else if (PyErr_Occurred()) {
         548                 :          0 :         Py_DECREF(result);
         549                 :          0 :         return NULL;
         550                 :            :     }
         551                 :            :     else {
         552                 :          2 :         StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base);
         553                 :            :
         554         [ +  - ]:          2 :         if (basedict == NULL)
         555                 :          2 :             return (PyObject *)result;
         556                 :            :         /* copy base dict */
         557         [ #  # ]:          0 :         if (-1 == PyCStgDict_clone(dict, basedict)) {
         558                 :          0 :             Py_DECREF(result);
         559                 :          0 :             return NULL;
         560                 :            :         }
         561                 :          0 :         dict->flags &= ~DICTFLAG_FINAL; /* clear the 'final' flag in the subclass dict */
         562                 :          0 :         basedict->flags |= DICTFLAG_FINAL; /* set the 'final' flag in the baseclass dict */
         563                 :          0 :         return (PyObject *)result;
         564                 :            :     }
         565                 :            : }
         566                 :            :
         567                 :            : static PyObject *
         568                 :          1 : PyCStructType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         569                 :            : {
         570                 :          1 :     return StructUnionType_new(type, args, kwds, 1);
         571                 :            : }
         572                 :            :
         573                 :            : static PyObject *
         574                 :          1 : UnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         575                 :            : {
         576                 :          1 :     return StructUnionType_new(type, args, kwds, 0);
         577                 :            : }
         578                 :            :
         579                 :            : PyDoc_STRVAR(from_address_doc,
         580                 :            : "C.from_address(integer) -> C instance\naccess a C instance at the specified address");
         581                 :            :
         582                 :            : static PyObject *
         583                 :          0 : CDataType_from_address(PyObject *type, PyObject *value)
         584                 :            : {
         585                 :            :     void *buf;
         586         [ #  # ]:          0 :     if (!PyLong_Check(value)) {
         587                 :          0 :         PyErr_SetString(PyExc_TypeError,
         588                 :            :                         "integer expected");
         589                 :          0 :         return NULL;
         590                 :            :     }
         591                 :          0 :     buf = (void *)PyLong_AsVoidPtr(value);
         592         [ #  # ]:          0 :     if (PyErr_Occurred())
         593                 :          0 :         return NULL;
         594                 :          0 :     return PyCData_AtAddress(type, buf);
         595                 :            : }
         596                 :            :
         597                 :            : PyDoc_STRVAR(from_buffer_doc,
         598                 :            : "C.from_buffer(object, offset=0) -> C instance\ncreate a C instance from a writeable buffer");
         599                 :            :
         600                 :            : static int
         601                 :            : KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep);
         602                 :            :
         603                 :            : static PyObject *
         604                 :          0 : CDataType_from_buffer(PyObject *type, PyObject *args)
         605                 :            : {
         606                 :            :     PyObject *obj;
         607                 :            :     PyObject *mv;
         608                 :            :     PyObject *result;
         609                 :            :     Py_buffer *buffer;
         610                 :          0 :     Py_ssize_t offset = 0;
         611                 :            :
         612                 :          0 :     StgDictObject *dict = PyType_stgdict(type);
         613         [ #  # ]:          0 :     if (!dict) {
         614                 :          0 :         PyErr_SetString(PyExc_TypeError, "abstract class");
         615                 :          0 :         return NULL;
         616                 :            :     }
         617                 :            :
         618         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset))
         619                 :          0 :         return NULL;
         620                 :            :
         621                 :          0 :     mv = PyMemoryView_FromObject(obj);
         622         [ #  # ]:          0 :     if (mv == NULL)
         623                 :          0 :         return NULL;
         624                 :            :
         625                 :          0 :     buffer = PyMemoryView_GET_BUFFER(mv);
         626                 :            :
         627         [ #  # ]:          0 :     if (buffer->readonly) {
         628                 :          0 :         PyErr_SetString(PyExc_TypeError,
         629                 :            :             "underlying buffer is not writable");
         630                 :          0 :         Py_DECREF(mv);
         631                 :          0 :         return NULL;
         632                 :            :     }
         633                 :            :
         634         [ #  # ]:          0 :     if (!PyBuffer_IsContiguous(buffer, 'C')) {
         635                 :          0 :         PyErr_SetString(PyExc_TypeError,
         636                 :            :             "underlying buffer is not C contiguous");
         637                 :          0 :         Py_DECREF(mv);
         638                 :          0 :         return NULL;
         639                 :            :     }
         640                 :            :
         641         [ #  # ]:          0 :     if (offset < 0) {
         642                 :          0 :         PyErr_SetString(PyExc_ValueError,
         643                 :            :                         "offset cannot be negative");
         644                 :          0 :         Py_DECREF(mv);
         645                 :          0 :         return NULL;
         646                 :            :     }
         647                 :            :
         648         [ #  # ]:          0 :     if (dict->size > buffer->len - offset) {
         649                 :          0 :         PyErr_Format(PyExc_ValueError,
         650                 :            :                      "Buffer size too small "
         651                 :            :                      "(%zd instead of at least %zd bytes)",
         652                 :          0 :                      buffer->len, dict->size + offset);
         653                 :          0 :         Py_DECREF(mv);
         654                 :          0 :         return NULL;
         655                 :            :     }
         656                 :            :
         657         [ #  # ]:          0 :     if (PySys_Audit("ctypes.cdata/buffer", "nnn",
         658                 :          0 :                     (Py_ssize_t)buffer->buf, buffer->len, offset) < 0) {
         659                 :          0 :         Py_DECREF(mv);
         660                 :          0 :         return NULL;
         661                 :            :     }
         662                 :            :
         663                 :          0 :     result = PyCData_AtAddress(type, (char *)buffer->buf + offset);
         664         [ #  # ]:          0 :     if (result == NULL) {
         665                 :          0 :         Py_DECREF(mv);
         666                 :          0 :         return NULL;
         667                 :            :     }
         668                 :            :
         669         [ #  # ]:          0 :     if (-1 == KeepRef((CDataObject *)result, -1, mv)) {
         670                 :          0 :         Py_DECREF(result);
         671                 :          0 :         return NULL;
         672                 :            :     }
         673                 :            :
         674                 :          0 :     return result;
         675                 :            : }
         676                 :            :
         677                 :            : PyDoc_STRVAR(from_buffer_copy_doc,
         678                 :            : "C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer");
         679                 :            :
         680                 :            : static PyObject *
         681                 :            : GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
         682                 :            :
         683                 :            : static PyObject *
         684                 :          0 : CDataType_from_buffer_copy(PyObject *type, PyObject *args)
         685                 :            : {
         686                 :            :     Py_buffer buffer;
         687                 :          0 :     Py_ssize_t offset = 0;
         688                 :            :     PyObject *result;
         689                 :          0 :     StgDictObject *dict = PyType_stgdict(type);
         690         [ #  # ]:          0 :     if (!dict) {
         691                 :          0 :         PyErr_SetString(PyExc_TypeError, "abstract class");
         692                 :          0 :         return NULL;
         693                 :            :     }
         694                 :            :
         695         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "y*|n:from_buffer_copy", &buffer, &offset))
         696                 :          0 :         return NULL;
         697                 :            :
         698         [ #  # ]:          0 :     if (offset < 0) {
         699                 :          0 :         PyErr_SetString(PyExc_ValueError,
         700                 :            :                         "offset cannot be negative");
         701                 :          0 :         PyBuffer_Release(&buffer);
         702                 :          0 :         return NULL;
         703                 :            :     }
         704                 :            :
         705         [ #  # ]:          0 :     if (dict->size > buffer.len - offset) {
         706                 :          0 :         PyErr_Format(PyExc_ValueError,
         707                 :            :                      "Buffer size too small (%zd instead of at least %zd bytes)",
         708                 :          0 :                      buffer.len, dict->size + offset);
         709                 :          0 :         PyBuffer_Release(&buffer);
         710                 :          0 :         return NULL;
         711                 :            :     }
         712                 :            :
         713         [ #  # ]:          0 :     if (PySys_Audit("ctypes.cdata/buffer", "nnn",
         714                 :          0 :                     (Py_ssize_t)buffer.buf, buffer.len, offset) < 0) {
         715                 :          0 :         PyBuffer_Release(&buffer);
         716                 :          0 :         return NULL;
         717                 :            :     }
         718                 :            :
         719                 :          0 :     result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL);
         720         [ #  # ]:          0 :     if (result != NULL) {
         721                 :          0 :         memcpy(((CDataObject *)result)->b_ptr,
         722                 :          0 :                (char *)buffer.buf + offset, dict->size);
         723                 :            :     }
         724                 :          0 :     PyBuffer_Release(&buffer);
         725                 :          0 :     return result;
         726                 :            : }
         727                 :            :
         728                 :            : PyDoc_STRVAR(in_dll_doc,
         729                 :            : "C.in_dll(dll, name) -> C instance\naccess a C instance in a dll");
         730                 :            :
         731                 :            : static PyObject *
         732                 :          0 : CDataType_in_dll(PyObject *type, PyObject *args)
         733                 :            : {
         734                 :            :     PyObject *dll;
         735                 :            :     char *name;
         736                 :            :     PyObject *obj;
         737                 :            :     void *handle;
         738                 :            :     void *address;
         739                 :            :
         740         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "Os:in_dll", &dll, &name))
         741                 :          0 :         return NULL;
         742         [ #  # ]:          0 :     if (PySys_Audit("ctypes.dlsym", "O", args) < 0) {
         743                 :          0 :         return NULL;
         744                 :            :     }
         745                 :            :
         746                 :          0 :     obj = PyObject_GetAttrString(dll, "_handle");
         747         [ #  # ]:          0 :     if (!obj)
         748                 :          0 :         return NULL;
         749         [ #  # ]:          0 :     if (!PyLong_Check(obj)) {
         750                 :          0 :         PyErr_SetString(PyExc_TypeError,
         751                 :            :                         "the _handle attribute of the second argument must be an integer");
         752                 :          0 :         Py_DECREF(obj);
         753                 :          0 :         return NULL;
         754                 :            :     }
         755                 :          0 :     handle = (void *)PyLong_AsVoidPtr(obj);
         756                 :          0 :     Py_DECREF(obj);
         757         [ #  # ]:          0 :     if (PyErr_Occurred()) {
         758                 :          0 :         PyErr_SetString(PyExc_ValueError,
         759                 :            :                         "could not convert the _handle attribute to a pointer");
         760                 :          0 :         return NULL;
         761                 :            :     }
         762                 :            :
         763                 :            : #ifdef MS_WIN32
         764                 :            :     Py_BEGIN_ALLOW_THREADS
         765                 :            :     address = (void *)GetProcAddress(handle, name);
         766                 :            :     Py_END_ALLOW_THREADS
         767                 :            :     if (!address) {
         768                 :            :         PyErr_Format(PyExc_ValueError,
         769                 :            :                      "symbol '%s' not found",
         770                 :            :                      name);
         771                 :            :         return NULL;
         772                 :            :     }
         773                 :            : #else
         774                 :          0 :     address = (void *)dlsym(handle, name);
         775         [ #  # ]:          0 :     if (!address) {
         776                 :            : #ifdef __CYGWIN__
         777                 :            : /* dlerror() isn't very helpful on cygwin */
         778                 :            :         PyErr_Format(PyExc_ValueError,
         779                 :            :                      "symbol '%s' not found",
         780                 :            :                      name);
         781                 :            : #else
         782                 :          0 :         PyErr_SetString(PyExc_ValueError, dlerror());
         783                 :            : #endif
         784                 :          0 :         return NULL;
         785                 :            :     }
         786                 :            : #endif
         787                 :          0 :     return PyCData_AtAddress(type, address);
         788                 :            : }
         789                 :            :
         790                 :            : PyDoc_STRVAR(from_param_doc,
         791                 :            : "Convert a Python object into a function call parameter.");
         792                 :            :
         793                 :            : static PyObject *
         794                 :          0 : CDataType_from_param(PyObject *type, PyObject *value)
         795                 :            : {
         796                 :            :     PyObject *as_parameter;
         797                 :          0 :     int res = PyObject_IsInstance(value, type);
         798         [ #  # ]:          0 :     if (res == -1)
         799                 :          0 :         return NULL;
         800         [ #  # ]:          0 :     if (res) {
         801                 :          0 :         return Py_NewRef(value);
         802                 :            :     }
         803         [ #  # ]:          0 :     if (PyCArg_CheckExact(value)) {
         804                 :          0 :         PyCArgObject *p = (PyCArgObject *)value;
         805                 :          0 :         PyObject *ob = p->obj;
         806                 :            :         const char *ob_name;
         807                 :            :         StgDictObject *dict;
         808                 :          0 :         dict = PyType_stgdict(type);
         809                 :            :
         810                 :            :         /* If we got a PyCArgObject, we must check if the object packed in it
         811                 :            :            is an instance of the type's dict->proto */
         812   [ #  #  #  # ]:          0 :         if(dict && ob) {
         813                 :          0 :             res = PyObject_IsInstance(ob, dict->proto);
         814         [ #  # ]:          0 :             if (res == -1)
         815                 :          0 :                 return NULL;
         816         [ #  # ]:          0 :             if (res) {
         817                 :          0 :                 return Py_NewRef(value);
         818                 :            :             }
         819                 :            :         }
         820         [ #  # ]:          0 :         ob_name = (ob) ? Py_TYPE(ob)->tp_name : "???";
         821                 :          0 :         PyErr_Format(PyExc_TypeError,
         822                 :            :                      "expected %s instance instead of pointer to %s",
         823                 :            :                      ((PyTypeObject *)type)->tp_name, ob_name);
         824                 :          0 :         return NULL;
         825                 :            :     }
         826                 :            :
         827         [ #  # ]:          0 :     if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
         828                 :          0 :         return NULL;
         829                 :            :     }
         830         [ #  # ]:          0 :     if (as_parameter) {
         831                 :          0 :         value = CDataType_from_param(type, as_parameter);
         832                 :          0 :         Py_DECREF(as_parameter);
         833                 :          0 :         return value;
         834                 :            :     }
         835                 :          0 :     PyErr_Format(PyExc_TypeError,
         836                 :            :                  "expected %s instance instead of %s",
         837                 :            :                  ((PyTypeObject *)type)->tp_name,
         838                 :          0 :                  Py_TYPE(value)->tp_name);
         839                 :          0 :     return NULL;
         840                 :            : }
         841                 :            :
         842                 :            : static PyMethodDef CDataType_methods[] = {
         843                 :            :     { "from_param", CDataType_from_param, METH_O, from_param_doc },
         844                 :            :     { "from_address", CDataType_from_address, METH_O, from_address_doc },
         845                 :            :     { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
         846                 :            :     { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
         847                 :            :     { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc },
         848                 :            :     { NULL, NULL },
         849                 :            : };
         850                 :            :
         851                 :            : static PyObject *
         852                 :          0 : CDataType_repeat(PyObject *self, Py_ssize_t length)
         853                 :            : {
         854         [ #  # ]:          0 :     if (length < 0)
         855                 :          0 :         return PyErr_Format(PyExc_ValueError,
         856                 :            :                             "Array length must be >= 0, not %zd",
         857                 :            :                             length);
         858                 :          0 :     return PyCArrayType_from_ctype(self, length);
         859                 :            : }
         860                 :            :
         861                 :            : static PySequenceMethods CDataType_as_sequence = {
         862                 :            :     0,                          /* inquiry sq_length; */
         863                 :            :     0,                          /* binaryfunc sq_concat; */
         864                 :            :     CDataType_repeat,           /* intargfunc sq_repeat; */
         865                 :            :     0,                          /* intargfunc sq_item; */
         866                 :            :     0,                          /* intintargfunc sq_slice; */
         867                 :            :     0,                          /* intobjargproc sq_ass_item; */
         868                 :            :     0,                          /* intintobjargproc sq_ass_slice; */
         869                 :            :     0,                          /* objobjproc sq_contains; */
         870                 :            :
         871                 :            :     0,                          /* binaryfunc sq_inplace_concat; */
         872                 :            :     0,                          /* intargfunc sq_inplace_repeat; */
         873                 :            : };
         874                 :            :
         875                 :            : static int
         876                 :          2 : CDataType_clear(PyTypeObject *self)
         877                 :            : {
         878                 :          2 :     StgDictObject *dict = PyType_stgdict((PyObject *)self);
         879         [ +  - ]:          2 :     if (dict)
         880         [ +  - ]:          2 :         Py_CLEAR(dict->proto);
         881                 :          2 :     return PyType_Type.tp_clear((PyObject *)self);
         882                 :            : }
         883                 :            :
         884                 :            : static int
         885                 :        364 : CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg)
         886                 :            : {
         887                 :        364 :     StgDictObject *dict = PyType_stgdict((PyObject *)self);
         888         [ +  - ]:        364 :     if (dict)
         889   [ +  +  -  + ]:        364 :         Py_VISIT(dict->proto);
         890                 :        364 :     return PyType_Type.tp_traverse((PyObject *)self, visit, arg);
         891                 :            : }
         892                 :            :
         893                 :            : static int
         894                 :          0 : PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value)
         895                 :            : {
         896                 :            :     /* XXX Should we disallow deleting _fields_? */
         897         [ #  # ]:          0 :     if (-1 == PyType_Type.tp_setattro(self, key, value))
         898                 :          0 :         return -1;
         899                 :            :
         900   [ #  #  #  #  :          0 :     if (value && PyUnicode_Check(key) &&
                       #  # ]
         901                 :          0 :         _PyUnicode_EqualToASCIIString(key, "_fields_"))
         902                 :          0 :         return PyCStructUnionType_update_stgdict(self, value, 1);
         903                 :          0 :     return 0;
         904                 :            : }
         905                 :            :
         906                 :            :
         907                 :            : static int
         908                 :          0 : UnionType_setattro(PyObject *self, PyObject *key, PyObject *value)
         909                 :            : {
         910                 :            :     /* XXX Should we disallow deleting _fields_? */
         911         [ #  # ]:          0 :     if (-1 == PyObject_GenericSetAttr(self, key, value))
         912                 :          0 :         return -1;
         913                 :            :
         914   [ #  #  #  # ]:          0 :     if (PyUnicode_Check(key) &&
         915                 :          0 :         _PyUnicode_EqualToASCIIString(key, "_fields_"))
         916                 :          0 :         return PyCStructUnionType_update_stgdict(self, value, 0);
         917                 :          0 :     return 0;
         918                 :            : }
         919                 :            :
         920                 :            :
         921                 :            : PyTypeObject PyCStructType_Type = {
         922                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         923                 :            :     "_ctypes.PyCStructType",                            /* tp_name */
         924                 :            :     0,                                          /* tp_basicsize */
         925                 :            :     0,                                          /* tp_itemsize */
         926                 :            :     0,                                          /* tp_dealloc */
         927                 :            :     0,                                          /* tp_vectorcall_offset */
         928                 :            :     0,                                          /* tp_getattr */
         929                 :            :     0,                                          /* tp_setattr */
         930                 :            :     0,                                          /* tp_as_async */
         931                 :            :     0,                                          /* tp_repr */
         932                 :            :     0,                                          /* tp_as_number */
         933                 :            :     &CDataType_as_sequence,                     /* tp_as_sequence */
         934                 :            :     0,                                          /* tp_as_mapping */
         935                 :            :     0,                                          /* tp_hash */
         936                 :            :     0,                                          /* tp_call */
         937                 :            :     0,                                          /* tp_str */
         938                 :            :     0,                                          /* tp_getattro */
         939                 :            :     PyCStructType_setattro,                     /* tp_setattro */
         940                 :            :     0,                                          /* tp_as_buffer */
         941                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
         942                 :            :     PyDoc_STR("metatype for the CData Objects"), /* tp_doc */
         943                 :            :     (traverseproc)CDataType_traverse,           /* tp_traverse */
         944                 :            :     (inquiry)CDataType_clear,                   /* tp_clear */
         945                 :            :     0,                                          /* tp_richcompare */
         946                 :            :     0,                                          /* tp_weaklistoffset */
         947                 :            :     0,                                          /* tp_iter */
         948                 :            :     0,                                          /* tp_iternext */
         949                 :            :     CDataType_methods,                          /* tp_methods */
         950                 :            :     0,                                          /* tp_members */
         951                 :            :     0,                                          /* tp_getset */
         952                 :            :     0,                                          /* tp_base */
         953                 :            :     0,                                          /* tp_dict */
         954                 :            :     0,                                          /* tp_descr_get */
         955                 :            :     0,                                          /* tp_descr_set */
         956                 :            :     0,                                          /* tp_dictoffset */
         957                 :            :     0,                                          /* tp_init */
         958                 :            :     0,                                          /* tp_alloc */
         959                 :            :     PyCStructType_new,                                  /* tp_new */
         960                 :            :     0,                                          /* tp_free */
         961                 :            : };
         962                 :            :
         963                 :            : static PyTypeObject UnionType_Type = {
         964                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         965                 :            :     "_ctypes.UnionType",                        /* tp_name */
         966                 :            :     0,                                          /* tp_basicsize */
         967                 :            :     0,                                          /* tp_itemsize */
         968                 :            :     0,                                          /* tp_dealloc */
         969                 :            :     0,                                          /* tp_vectorcall_offset */
         970                 :            :     0,                                          /* tp_getattr */
         971                 :            :     0,                                          /* tp_setattr */
         972                 :            :     0,                                          /* tp_as_async */
         973                 :            :     0,                                          /* tp_repr */
         974                 :            :     0,                                          /* tp_as_number */
         975                 :            :     &CDataType_as_sequence,             /* tp_as_sequence */
         976                 :            :     0,                                          /* tp_as_mapping */
         977                 :            :     0,                                          /* tp_hash */
         978                 :            :     0,                                          /* tp_call */
         979                 :            :     0,                                          /* tp_str */
         980                 :            :     0,                                          /* tp_getattro */
         981                 :            :     UnionType_setattro,                         /* tp_setattro */
         982                 :            :     0,                                          /* tp_as_buffer */
         983                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
         984                 :            :     PyDoc_STR("metatype for the CData Objects"), /* tp_doc */
         985                 :            :     (traverseproc)CDataType_traverse,           /* tp_traverse */
         986                 :            :     (inquiry)CDataType_clear,                   /* tp_clear */
         987                 :            :     0,                                          /* tp_richcompare */
         988                 :            :     0,                                          /* tp_weaklistoffset */
         989                 :            :     0,                                          /* tp_iter */
         990                 :            :     0,                                          /* tp_iternext */
         991                 :            :     CDataType_methods,                          /* tp_methods */
         992                 :            :     0,                                          /* tp_members */
         993                 :            :     0,                                          /* tp_getset */
         994                 :            :     0,                                          /* tp_base */
         995                 :            :     0,                                          /* tp_dict */
         996                 :            :     0,                                          /* tp_descr_get */
         997                 :            :     0,                                          /* tp_descr_set */
         998                 :            :     0,                                          /* tp_dictoffset */
         999                 :            :     0,                                          /* tp_init */
        1000                 :            :     0,                                          /* tp_alloc */
        1001                 :            :     UnionType_new,                              /* tp_new */
        1002                 :            :     0,                                          /* tp_free */
        1003                 :            : };
        1004                 :            :
        1005                 :            :
        1006                 :            : /******************************************************************/
        1007                 :            :
        1008                 :            : /*
        1009                 :            :
        1010                 :            : The PyCPointerType_Type metaclass must ensure that the subclass of Pointer can be
        1011                 :            : created. It must check for a _type_ attribute in the class. Since are no
        1012                 :            : runtime created properties, a CField is probably *not* needed ?
        1013                 :            :
        1014                 :            : class IntPointer(Pointer):
        1015                 :            :     _type_ = "i"
        1016                 :            :
        1017                 :            : The PyCPointer_Type provides the functionality: a contents method/property, a
        1018                 :            : size property/method, and the sequence protocol.
        1019                 :            :
        1020                 :            : */
        1021                 :            :
        1022                 :            : static int
        1023                 :          4 : PyCPointerType_SetProto(StgDictObject *stgdict, PyObject *proto)
        1024                 :            : {
        1025   [ +  -  -  + ]:          4 :     if (!proto || !PyType_Check(proto)) {
        1026                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1027                 :            :                         "_type_ must be a type");
        1028                 :          0 :         return -1;
        1029                 :            :     }
        1030         [ -  + ]:          4 :     if (!PyType_stgdict(proto)) {
        1031                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1032                 :            :                         "_type_ must have storage info");
        1033                 :          0 :         return -1;
        1034                 :            :     }
        1035                 :          4 :     Py_INCREF(proto);
        1036                 :          4 :     Py_XSETREF(stgdict->proto, proto);
        1037                 :          4 :     return 0;
        1038                 :            : }
        1039                 :            :
        1040                 :            : static PyCArgObject *
        1041                 :          0 : PyCPointerType_paramfunc(CDataObject *self)
        1042                 :            : {
        1043                 :            :     PyCArgObject *parg;
        1044                 :            :
        1045                 :          0 :     parg = PyCArgObject_new();
        1046         [ #  # ]:          0 :     if (parg == NULL)
        1047                 :          0 :         return NULL;
        1048                 :            :
        1049                 :          0 :     parg->tag = 'P';
        1050                 :          0 :     parg->pffi_type = &ffi_type_pointer;
        1051                 :          0 :     parg->obj = Py_NewRef(self);
        1052                 :          0 :     parg->value.p = *(void **)self->b_ptr;
        1053                 :          0 :     return parg;
        1054                 :            : }
        1055                 :            :
        1056                 :            : static PyObject *
        1057                 :          4 : PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        1058                 :            : {
        1059                 :            :     PyTypeObject *result;
        1060                 :            :     StgDictObject *stgdict;
        1061                 :            :     PyObject *proto;
        1062                 :            :     PyObject *typedict;
        1063                 :            :
        1064                 :            :
        1065                 :          4 :     typedict = PyTuple_GetItem(args, 2);
        1066         [ -  + ]:          4 :     if (!typedict)
        1067                 :          0 :         return NULL;
        1068                 :            : /*
        1069                 :            :   stgdict items size, align, length contain info about pointers itself,
        1070                 :            :   stgdict->proto has info about the pointed to type!
        1071                 :            : */
        1072                 :          4 :     stgdict = (StgDictObject *)_PyObject_CallNoArgs(
        1073                 :            :         (PyObject *)&PyCStgDict_Type);
        1074         [ -  + ]:          4 :     if (!stgdict)
        1075                 :          0 :         return NULL;
        1076                 :          4 :     stgdict->size = sizeof(void *);
        1077                 :          4 :     stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment;
        1078                 :          4 :     stgdict->length = 1;
        1079                 :          4 :     stgdict->ffi_type_pointer = ffi_type_pointer;
        1080                 :          4 :     stgdict->paramfunc = PyCPointerType_paramfunc;
        1081                 :          4 :     stgdict->flags |= TYPEFLAG_ISPOINTER;
        1082                 :            :
        1083                 :          4 :     proto = PyDict_GetItemWithError(typedict, &_Py_ID(_type_)); /* Borrowed ref */
        1084         [ +  - ]:          4 :     if (proto) {
        1085                 :            :         StgDictObject *itemdict;
        1086                 :            :         const char *current_format;
        1087         [ -  + ]:          4 :         if (-1 == PyCPointerType_SetProto(stgdict, proto)) {
        1088                 :          0 :             Py_DECREF((PyObject *)stgdict);
        1089                 :          0 :             return NULL;
        1090                 :            :         }
        1091                 :          4 :         itemdict = PyType_stgdict(proto);
        1092                 :            :         /* PyCPointerType_SetProto has verified proto has a stgdict. */
        1093                 :            :         assert(itemdict);
        1094                 :            :         /* If itemdict->format is NULL, then this is a pointer to an
        1095                 :            :            incomplete type.  We create a generic format string
        1096                 :            :            'pointer to bytes' in this case.  XXX Better would be to
        1097                 :            :            fix the format string later...
        1098                 :            :         */
        1099         [ +  - ]:          4 :         current_format = itemdict->format ? itemdict->format : "B";
        1100         [ -  + ]:          4 :         if (itemdict->shape != NULL) {
        1101                 :            :             /* pointer to an array: the shape needs to be prefixed */
        1102                 :          0 :             stgdict->format = _ctypes_alloc_format_string_with_shape(
        1103                 :          0 :                 itemdict->ndim, itemdict->shape, "&", current_format);
        1104                 :            :         } else {
        1105                 :          4 :             stgdict->format = _ctypes_alloc_format_string("&", current_format);
        1106                 :            :         }
        1107         [ -  + ]:          4 :         if (stgdict->format == NULL) {
        1108                 :          0 :             Py_DECREF((PyObject *)stgdict);
        1109                 :          0 :             return NULL;
        1110                 :            :         }
        1111                 :            :     }
        1112         [ #  # ]:          0 :     else if (PyErr_Occurred()) {
        1113                 :          0 :         Py_DECREF((PyObject *)stgdict);
        1114                 :          0 :         return NULL;
        1115                 :            :     }
        1116                 :            :
        1117                 :            :     /* create the new instance (which is a class,
        1118                 :            :        since we are a metatype!) */
        1119                 :          4 :     result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
        1120         [ -  + ]:          4 :     if (result == NULL) {
        1121                 :          0 :         Py_DECREF((PyObject *)stgdict);
        1122                 :          0 :         return NULL;
        1123                 :            :     }
        1124                 :            :
        1125                 :            :     /* replace the class dict by our updated spam dict */
        1126         [ -  + ]:          4 :     if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
        1127                 :          0 :         Py_DECREF(result);
        1128                 :          0 :         Py_DECREF((PyObject *)stgdict);
        1129                 :          0 :         return NULL;
        1130                 :            :     }
        1131                 :          4 :     Py_SETREF(result->tp_dict, (PyObject *)stgdict);
        1132                 :            :
        1133                 :          4 :     return (PyObject *)result;
        1134                 :            : }
        1135                 :            :
        1136                 :            :
        1137                 :            : static PyObject *
        1138                 :          0 : PyCPointerType_set_type(PyTypeObject *self, PyObject *type)
        1139                 :            : {
        1140                 :            :     StgDictObject *dict;
        1141                 :            :
        1142                 :            :
        1143                 :          0 :     dict = PyType_stgdict((PyObject *)self);
        1144         [ #  # ]:          0 :     if (!dict) {
        1145                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1146                 :            :                         "abstract class");
        1147                 :          0 :         return NULL;
        1148                 :            :     }
        1149                 :            :
        1150         [ #  # ]:          0 :     if (-1 == PyCPointerType_SetProto(dict, type))
        1151                 :          0 :         return NULL;
        1152                 :            :
        1153         [ #  # ]:          0 :     if (-1 == PyDict_SetItem((PyObject *)dict, &_Py_ID(_type_), type))
        1154                 :          0 :         return NULL;
        1155                 :            :
        1156                 :          0 :     Py_RETURN_NONE;
        1157                 :            : }
        1158                 :            :
        1159                 :            : static PyObject *_byref(PyObject *);
        1160                 :            :
        1161                 :            : static PyObject *
        1162                 :          0 : PyCPointerType_from_param(PyObject *type, PyObject *value)
        1163                 :            : {
        1164                 :            :     StgDictObject *typedict;
        1165                 :            :
        1166         [ #  # ]:          0 :     if (value == Py_None) {
        1167                 :            :         /* ConvParam will convert to a NULL pointer later */
        1168                 :          0 :         return Py_NewRef(value);
        1169                 :            :     }
        1170                 :            :
        1171                 :          0 :     typedict = PyType_stgdict(type);
        1172         [ #  # ]:          0 :     if (!typedict) {
        1173                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1174                 :            :                         "abstract class");
        1175                 :          0 :         return NULL;
        1176                 :            :     }
        1177                 :            :
        1178                 :            :     /* If we expect POINTER(<type>), but receive a <type> instance, accept
        1179                 :            :        it by calling byref(<type>).
        1180                 :            :     */
        1181      [ #  #  # ]:          0 :     switch (PyObject_IsInstance(value, typedict->proto)) {
        1182                 :          0 :     case 1:
        1183                 :          0 :         Py_INCREF(value); /* _byref steals a refcount */
        1184                 :          0 :         return _byref(value);
        1185                 :          0 :     case -1:
        1186                 :          0 :         return NULL;
        1187                 :          0 :     default:
        1188                 :          0 :         break;
        1189                 :            :     }
        1190                 :            :
        1191   [ #  #  #  # ]:          0 :     if (PointerObject_Check(value) || ArrayObject_Check(value)) {
        1192                 :            :         /* Array instances are also pointers when
        1193                 :            :            the item types are the same.
        1194                 :            :         */
        1195                 :          0 :         StgDictObject *v = PyObject_stgdict(value);
        1196                 :            :         assert(v); /* Cannot be NULL for pointer or array objects */
        1197                 :          0 :         int ret = PyObject_IsSubclass(v->proto, typedict->proto);
        1198         [ #  # ]:          0 :         if (ret < 0) {
        1199                 :          0 :             return NULL;
        1200                 :            :         }
        1201         [ #  # ]:          0 :         if (ret) {
        1202                 :          0 :             return Py_NewRef(value);
        1203                 :            :         }
        1204                 :            :     }
        1205                 :          0 :     return CDataType_from_param(type, value);
        1206                 :            : }
        1207                 :            :
        1208                 :            : static PyMethodDef PyCPointerType_methods[] = {
        1209                 :            :     { "from_address", CDataType_from_address, METH_O, from_address_doc },
        1210                 :            :     { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
        1211                 :            :     { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
        1212                 :            :     { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc},
        1213                 :            :     { "from_param", (PyCFunction)PyCPointerType_from_param, METH_O, from_param_doc},
        1214                 :            :     { "set_type", (PyCFunction)PyCPointerType_set_type, METH_O },
        1215                 :            :     { NULL, NULL },
        1216                 :            : };
        1217                 :            :
        1218                 :            : PyTypeObject PyCPointerType_Type = {
        1219                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        1220                 :            :     "_ctypes.PyCPointerType",                                   /* tp_name */
        1221                 :            :     0,                                          /* tp_basicsize */
        1222                 :            :     0,                                          /* tp_itemsize */
        1223                 :            :     0,                                          /* tp_dealloc */
        1224                 :            :     0,                                          /* tp_vectorcall_offset */
        1225                 :            :     0,                                          /* tp_getattr */
        1226                 :            :     0,                                          /* tp_setattr */
        1227                 :            :     0,                                          /* tp_as_async */
        1228                 :            :     0,                                          /* tp_repr */
        1229                 :            :     0,                                          /* tp_as_number */
        1230                 :            :     &CDataType_as_sequence,             /* tp_as_sequence */
        1231                 :            :     0,                                          /* tp_as_mapping */
        1232                 :            :     0,                                          /* tp_hash */
        1233                 :            :     0,                                          /* tp_call */
        1234                 :            :     0,                                          /* tp_str */
        1235                 :            :     0,                                          /* tp_getattro */
        1236                 :            :     0,                                          /* tp_setattro */
        1237                 :            :     0,                                          /* tp_as_buffer */
        1238                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
        1239                 :            :     PyDoc_STR("metatype for the Pointer Objects"), /* tp_doc */
        1240                 :            :     (traverseproc)CDataType_traverse,           /* tp_traverse */
        1241                 :            :     (inquiry)CDataType_clear,                   /* tp_clear */
        1242                 :            :     0,                                          /* tp_richcompare */
        1243                 :            :     0,                                          /* tp_weaklistoffset */
        1244                 :            :     0,                                          /* tp_iter */
        1245                 :            :     0,                                          /* tp_iternext */
        1246                 :            :     PyCPointerType_methods,                     /* tp_methods */
        1247                 :            :     0,                                          /* tp_members */
        1248                 :            :     0,                                          /* tp_getset */
        1249                 :            :     0,                                          /* tp_base */
        1250                 :            :     0,                                          /* tp_dict */
        1251                 :            :     0,                                          /* tp_descr_get */
        1252                 :            :     0,                                          /* tp_descr_set */
        1253                 :            :     0,                                          /* tp_dictoffset */
        1254                 :            :     0,                                          /* tp_init */
        1255                 :            :     0,                                          /* tp_alloc */
        1256                 :            :     PyCPointerType_new,                         /* tp_new */
        1257                 :            :     0,                                          /* tp_free */
        1258                 :            : };
        1259                 :            :
        1260                 :            :
        1261                 :            : /******************************************************************/
        1262                 :            : /*
        1263                 :            :   PyCArrayType_Type
        1264                 :            : */
        1265                 :            : /*
        1266                 :            :   PyCArrayType_new ensures that the new Array subclass created has a _length_
        1267                 :            :   attribute, and a _type_ attribute.
        1268                 :            : */
        1269                 :            :
        1270                 :            : static int
        1271                 :          0 : CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
        1272                 :            : {
        1273                 :            :     char *ptr;
        1274                 :            :     Py_ssize_t size;
        1275                 :            :     Py_buffer view;
        1276                 :            :
        1277         [ #  # ]:          0 :     if (value == NULL) {
        1278                 :          0 :         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
        1279                 :          0 :         return -1;
        1280                 :            :     }
        1281         [ #  # ]:          0 :     if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0)
        1282                 :          0 :         return -1;
        1283                 :          0 :     size = view.len;
        1284                 :          0 :     ptr = view.buf;
        1285         [ #  # ]:          0 :     if (size > self->b_size) {
        1286                 :          0 :         PyErr_SetString(PyExc_ValueError,
        1287                 :            :                         "byte string too long");
        1288                 :          0 :         goto fail;
        1289                 :            :     }
        1290                 :            :
        1291                 :          0 :     memcpy(self->b_ptr, ptr, size);
        1292                 :            :
        1293                 :          0 :     PyBuffer_Release(&view);
        1294                 :          0 :     return 0;
        1295                 :          0 :  fail:
        1296                 :          0 :     PyBuffer_Release(&view);
        1297                 :          0 :     return -1;
        1298                 :            : }
        1299                 :            :
        1300                 :            : static PyObject *
        1301                 :          0 : CharArray_get_raw(CDataObject *self, void *Py_UNUSED(ignored))
        1302                 :            : {
        1303                 :          0 :     return PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
        1304                 :            : }
        1305                 :            :
        1306                 :            : static PyObject *
        1307                 :          0 : CharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))
        1308                 :            : {
        1309                 :            :     Py_ssize_t i;
        1310                 :          0 :     char *ptr = self->b_ptr;
        1311         [ #  # ]:          0 :     for (i = 0; i < self->b_size; ++i)
        1312         [ #  # ]:          0 :         if (*ptr++ == '\0')
        1313                 :          0 :             break;
        1314                 :          0 :     return PyBytes_FromStringAndSize(self->b_ptr, i);
        1315                 :            : }
        1316                 :            :
        1317                 :            : static int
        1318                 :          0 : CharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
        1319                 :            : {
        1320                 :            :     const char *ptr;
        1321                 :            :     Py_ssize_t size;
        1322                 :            :
        1323         [ #  # ]:          0 :     if (value == NULL) {
        1324                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1325                 :            :                         "can't delete attribute");
        1326                 :          0 :         return -1;
        1327                 :            :     }
        1328                 :            :
        1329         [ #  # ]:          0 :     if (!PyBytes_Check(value)) {
        1330                 :          0 :         PyErr_Format(PyExc_TypeError,
        1331                 :            :                      "bytes expected instead of %s instance",
        1332                 :          0 :                      Py_TYPE(value)->tp_name);
        1333                 :          0 :         return -1;
        1334                 :            :     } else
        1335                 :          0 :         Py_INCREF(value);
        1336                 :          0 :     size = PyBytes_GET_SIZE(value);
        1337         [ #  # ]:          0 :     if (size > self->b_size) {
        1338                 :          0 :         PyErr_SetString(PyExc_ValueError,
        1339                 :            :                         "byte string too long");
        1340                 :          0 :         Py_DECREF(value);
        1341                 :          0 :         return -1;
        1342                 :            :     }
        1343                 :            :
        1344                 :          0 :     ptr = PyBytes_AS_STRING(value);
        1345                 :          0 :     memcpy(self->b_ptr, ptr, size);
        1346         [ #  # ]:          0 :     if (size < self->b_size)
        1347                 :          0 :         self->b_ptr[size] = '\0';
        1348                 :          0 :     Py_DECREF(value);
        1349                 :            :
        1350                 :          0 :     return 0;
        1351                 :            : }
        1352                 :            :
        1353                 :            : static PyGetSetDef CharArray_getsets[] = {
        1354                 :            :     { "raw", (getter)CharArray_get_raw, (setter)CharArray_set_raw,
        1355                 :            :       "value", NULL },
        1356                 :            :     { "value", (getter)CharArray_get_value, (setter)CharArray_set_value,
        1357                 :            :       "string value"},
        1358                 :            :     { NULL, NULL }
        1359                 :            : };
        1360                 :            :
        1361                 :            : static PyObject *
        1362                 :          0 : WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))
        1363                 :            : {
        1364                 :            :     Py_ssize_t i;
        1365                 :          0 :     wchar_t *ptr = (wchar_t *)self->b_ptr;
        1366         [ #  # ]:          0 :     for (i = 0; i < self->b_size/(Py_ssize_t)sizeof(wchar_t); ++i)
        1367         [ #  # ]:          0 :         if (*ptr++ == (wchar_t)0)
        1368                 :          0 :             break;
        1369                 :          0 :     return PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
        1370                 :            : }
        1371                 :            :
        1372                 :            : static int
        1373                 :          0 : WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
        1374                 :            : {
        1375         [ #  # ]:          0 :     if (value == NULL) {
        1376                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1377                 :            :                         "can't delete attribute");
        1378                 :          0 :         return -1;
        1379                 :            :     }
        1380         [ #  # ]:          0 :     if (!PyUnicode_Check(value)) {
        1381                 :          0 :         PyErr_Format(PyExc_TypeError,
        1382                 :            :                         "unicode string expected instead of %s instance",
        1383                 :          0 :                         Py_TYPE(value)->tp_name);
        1384                 :          0 :         return -1;
        1385                 :            :     }
        1386                 :            :
        1387                 :          0 :     Py_ssize_t size = self->b_size / sizeof(wchar_t);
        1388                 :          0 :     Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0);
        1389         [ #  # ]:          0 :     if (len < 0) {
        1390                 :          0 :         return -1;
        1391                 :            :     }
        1392                 :            :     // PyUnicode_AsWideChar() returns number of wchars including trailing null byte,
        1393                 :            :     // when it is called with NULL.
        1394                 :            :     assert(len > 0);
        1395         [ #  # ]:          0 :     if (len - 1 > size) {
        1396                 :          0 :         PyErr_SetString(PyExc_ValueError, "string too long");
        1397                 :          0 :         return -1;
        1398                 :            :     }
        1399         [ #  # ]:          0 :     if (PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size) < 0) {
        1400                 :          0 :         return -1;
        1401                 :            :     }
        1402                 :          0 :     return 0;
        1403                 :            : }
        1404                 :            :
        1405                 :            : static PyGetSetDef WCharArray_getsets[] = {
        1406                 :            :     { "value", (getter)WCharArray_get_value, (setter)WCharArray_set_value,
        1407                 :            :       "string value"},
        1408                 :            :     { NULL, NULL }
        1409                 :            : };
        1410                 :            :
        1411                 :            : /*
        1412                 :            :   The next function is copied from Python's typeobject.c.
        1413                 :            :
        1414                 :            :   It is used to attach getsets to a type *after* it
        1415                 :            :   has been created: Arrays of characters have additional getsets to treat them
        1416                 :            :   as strings.
        1417                 :            :  */
        1418                 :            :
        1419                 :            : static int
        1420                 :          0 : add_getset(PyTypeObject *type, PyGetSetDef *gsp)
        1421                 :            : {
        1422                 :          0 :     PyObject *dict = type->tp_dict;
        1423         [ #  # ]:          0 :     for (; gsp->name != NULL; gsp++) {
        1424                 :            :         PyObject *descr;
        1425                 :          0 :         descr = PyDescr_NewGetSet(type, gsp);
        1426         [ #  # ]:          0 :         if (descr == NULL)
        1427                 :          0 :             return -1;
        1428         [ #  # ]:          0 :         if (PyDict_SetItemString(dict, gsp->name, descr) < 0) {
        1429                 :          0 :             Py_DECREF(descr);
        1430                 :          0 :             return -1;
        1431                 :            :         }
        1432                 :          0 :         Py_DECREF(descr);
        1433                 :            :     }
        1434                 :          0 :     return 0;
        1435                 :            : }
        1436                 :            :
        1437                 :            : static PyCArgObject *
        1438                 :          0 : PyCArrayType_paramfunc(CDataObject *self)
        1439                 :            : {
        1440                 :          0 :     PyCArgObject *p = PyCArgObject_new();
        1441         [ #  # ]:          0 :     if (p == NULL)
        1442                 :          0 :         return NULL;
        1443                 :          0 :     p->tag = 'P';
        1444                 :          0 :     p->pffi_type = &ffi_type_pointer;
        1445                 :          0 :     p->value.p = (char *)self->b_ptr;
        1446                 :          0 :     p->obj = Py_NewRef(self);
        1447                 :          0 :     return p;
        1448                 :            : }
        1449                 :            :
        1450                 :            : static PyObject *
        1451                 :          0 : PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        1452                 :            : {
        1453                 :            :     PyTypeObject *result;
        1454                 :            :     StgDictObject *stgdict;
        1455                 :            :     StgDictObject *itemdict;
        1456                 :            :     PyObject *length_attr, *type_attr;
        1457                 :            :     Py_ssize_t length;
        1458                 :            :     Py_ssize_t itemsize, itemalign;
        1459                 :            :
        1460                 :            :     /* create the new instance (which is a class,
        1461                 :            :        since we are a metatype!) */
        1462                 :          0 :     result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
        1463         [ #  # ]:          0 :     if (result == NULL)
        1464                 :          0 :         return NULL;
        1465                 :            :
        1466                 :            :     /* Initialize these variables to NULL so that we can simplify error
        1467                 :            :        handling by using Py_XDECREF.  */
        1468                 :          0 :     stgdict = NULL;
        1469                 :          0 :     type_attr = NULL;
        1470                 :            :
        1471         [ #  # ]:          0 :     if (_PyObject_LookupAttr((PyObject *)result, &_Py_ID(_length_), &length_attr) < 0) {
        1472                 :          0 :         goto error;
        1473                 :            :     }
        1474         [ #  # ]:          0 :     if (!length_attr) {
        1475                 :          0 :         PyErr_SetString(PyExc_AttributeError,
        1476                 :            :                         "class must define a '_length_' attribute");
        1477                 :          0 :         goto error;
        1478                 :            :     }
        1479                 :            :
        1480         [ #  # ]:          0 :     if (!PyLong_Check(length_attr)) {
        1481                 :          0 :         Py_DECREF(length_attr);
        1482                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1483                 :            :                         "The '_length_' attribute must be an integer");
        1484                 :          0 :         goto error;
        1485                 :            :     }
        1486                 :            :
        1487         [ #  # ]:          0 :     if (_PyLong_Sign(length_attr) == -1) {
        1488                 :          0 :         Py_DECREF(length_attr);
        1489                 :          0 :         PyErr_SetString(PyExc_ValueError,
        1490                 :            :                         "The '_length_' attribute must not be negative");
        1491                 :          0 :         goto error;
        1492                 :            :     }
        1493                 :            :
        1494                 :          0 :     length = PyLong_AsSsize_t(length_attr);
        1495                 :          0 :     Py_DECREF(length_attr);
        1496   [ #  #  #  # ]:          0 :     if (length == -1 && PyErr_Occurred()) {
        1497         [ #  # ]:          0 :         if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
        1498                 :          0 :             PyErr_SetString(PyExc_OverflowError,
        1499                 :            :                             "The '_length_' attribute is too large");
        1500                 :            :         }
        1501                 :          0 :         goto error;
        1502                 :            :     }
        1503                 :            :
        1504         [ #  # ]:          0 :     if (_PyObject_LookupAttr((PyObject *)result, &_Py_ID(_type_), &type_attr) < 0) {
        1505                 :          0 :         goto error;
        1506                 :            :     }
        1507         [ #  # ]:          0 :     if (!type_attr) {
        1508                 :          0 :         PyErr_SetString(PyExc_AttributeError,
        1509                 :            :                         "class must define a '_type_' attribute");
        1510                 :          0 :         goto error;
        1511                 :            :     }
        1512                 :            :
        1513                 :          0 :     stgdict = (StgDictObject *)_PyObject_CallNoArgs(
        1514                 :            :         (PyObject *)&PyCStgDict_Type);
        1515         [ #  # ]:          0 :     if (!stgdict)
        1516                 :          0 :         goto error;
        1517                 :            :
        1518                 :          0 :     itemdict = PyType_stgdict(type_attr);
        1519         [ #  # ]:          0 :     if (!itemdict) {
        1520                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1521                 :            :                         "_type_ must have storage info");
        1522                 :          0 :         goto error;
        1523                 :            :     }
        1524                 :            :
        1525                 :            :     assert(itemdict->format);
        1526                 :          0 :     stgdict->format = _ctypes_alloc_format_string(NULL, itemdict->format);
        1527         [ #  # ]:          0 :     if (stgdict->format == NULL)
        1528                 :          0 :         goto error;
        1529                 :          0 :     stgdict->ndim = itemdict->ndim + 1;
        1530                 :          0 :     stgdict->shape = PyMem_Malloc(sizeof(Py_ssize_t) * stgdict->ndim);
        1531         [ #  # ]:          0 :     if (stgdict->shape == NULL) {
        1532                 :          0 :         PyErr_NoMemory();
        1533                 :          0 :         goto error;
        1534                 :            :     }
        1535                 :          0 :     stgdict->shape[0] = length;
        1536         [ #  # ]:          0 :     if (stgdict->ndim > 1) {
        1537                 :          0 :         memmove(&stgdict->shape[1], itemdict->shape,
        1538                 :          0 :             sizeof(Py_ssize_t) * (stgdict->ndim - 1));
        1539                 :            :     }
        1540                 :            :
        1541                 :          0 :     itemsize = itemdict->size;
        1542   [ #  #  #  # ]:          0 :     if (itemsize != 0 && length > PY_SSIZE_T_MAX / itemsize) {
        1543                 :          0 :         PyErr_SetString(PyExc_OverflowError,
        1544                 :            :                         "array too large");
        1545                 :          0 :         goto error;
        1546                 :            :     }
        1547                 :            :
        1548                 :          0 :     itemalign = itemdict->align;
        1549                 :            :
        1550         [ #  # ]:          0 :     if (itemdict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
        1551                 :          0 :         stgdict->flags |= TYPEFLAG_HASPOINTER;
        1552                 :            :
        1553                 :          0 :     stgdict->size = itemsize * length;
        1554                 :          0 :     stgdict->align = itemalign;
        1555                 :          0 :     stgdict->length = length;
        1556                 :          0 :     stgdict->proto = type_attr;
        1557                 :          0 :     type_attr = NULL;
        1558                 :            :
        1559                 :          0 :     stgdict->paramfunc = &PyCArrayType_paramfunc;
        1560                 :            :
        1561                 :            :     /* Arrays are passed as pointers to function calls. */
        1562                 :          0 :     stgdict->ffi_type_pointer = ffi_type_pointer;
        1563                 :            :
        1564                 :            :     /* replace the class dict by our updated spam dict */
        1565         [ #  # ]:          0 :     if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict))
        1566                 :          0 :         goto error;
        1567                 :          0 :     Py_SETREF(result->tp_dict, (PyObject *)stgdict);  /* steal the reference */
        1568                 :          0 :     stgdict = NULL;
        1569                 :            :
        1570                 :            :     /* Special case for character arrays.
        1571                 :            :        A permanent annoyance: char arrays are also strings!
        1572                 :            :     */
        1573         [ #  # ]:          0 :     if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
        1574         [ #  # ]:          0 :         if (-1 == add_getset(result, CharArray_getsets))
        1575                 :          0 :             goto error;
        1576                 :            :     }
        1577         [ #  # ]:          0 :     else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
        1578         [ #  # ]:          0 :         if (-1 == add_getset(result, WCharArray_getsets))
        1579                 :          0 :             goto error;
        1580                 :            :     }
        1581                 :            :
        1582                 :          0 :     return (PyObject *)result;
        1583                 :          0 : error:
        1584                 :          0 :     Py_XDECREF((PyObject*)stgdict);
        1585                 :          0 :     Py_XDECREF(type_attr);
        1586                 :          0 :     Py_DECREF(result);
        1587                 :          0 :     return NULL;
        1588                 :            : }
        1589                 :            :
        1590                 :            : PyTypeObject PyCArrayType_Type = {
        1591                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        1592                 :            :     "_ctypes.PyCArrayType",                     /* tp_name */
        1593                 :            :     0,                                          /* tp_basicsize */
        1594                 :            :     0,                                          /* tp_itemsize */
        1595                 :            :     0,                                          /* tp_dealloc */
        1596                 :            :     0,                                          /* tp_vectorcall_offset */
        1597                 :            :     0,                                          /* tp_getattr */
        1598                 :            :     0,                                          /* tp_setattr */
        1599                 :            :     0,                                          /* tp_as_async */
        1600                 :            :     0,                                          /* tp_repr */
        1601                 :            :     0,                                          /* tp_as_number */
        1602                 :            :     &CDataType_as_sequence,                     /* tp_as_sequence */
        1603                 :            :     0,                                          /* tp_as_mapping */
        1604                 :            :     0,                                          /* tp_hash */
        1605                 :            :     0,                                          /* tp_call */
        1606                 :            :     0,                                          /* tp_str */
        1607                 :            :     0,                                          /* tp_getattro */
        1608                 :            :     0,                                          /* tp_setattro */
        1609                 :            :     0,                                          /* tp_as_buffer */
        1610                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        1611                 :            :     PyDoc_STR("metatype for the Array Objects"), /* tp_doc */
        1612                 :            :     0,                                          /* tp_traverse */
        1613                 :            :     0,                                          /* tp_clear */
        1614                 :            :     0,                                          /* tp_richcompare */
        1615                 :            :     0,                                          /* tp_weaklistoffset */
        1616                 :            :     0,                                          /* tp_iter */
        1617                 :            :     0,                                          /* tp_iternext */
        1618                 :            :     CDataType_methods,                          /* tp_methods */
        1619                 :            :     0,                                          /* tp_members */
        1620                 :            :     0,                                          /* tp_getset */
        1621                 :            :     0,                                          /* tp_base */
        1622                 :            :     0,                                          /* tp_dict */
        1623                 :            :     0,                                          /* tp_descr_get */
        1624                 :            :     0,                                          /* tp_descr_set */
        1625                 :            :     0,                                          /* tp_dictoffset */
        1626                 :            :     0,                                          /* tp_init */
        1627                 :            :     0,                                          /* tp_alloc */
        1628                 :            :     PyCArrayType_new,                                   /* tp_new */
        1629                 :            :     0,                                          /* tp_free */
        1630                 :            : };
        1631                 :            :
        1632                 :            :
        1633                 :            : /******************************************************************/
        1634                 :            : /*
        1635                 :            :   PyCSimpleType_Type
        1636                 :            : */
        1637                 :            : /*
        1638                 :            :
        1639                 :            : PyCSimpleType_new ensures that the new Simple_Type subclass created has a valid
        1640                 :            : _type_ attribute.
        1641                 :            :
        1642                 :            : */
        1643                 :            :
        1644                 :            : static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g";
        1645                 :            :
        1646                 :            : static PyObject *
        1647                 :          0 : c_wchar_p_from_param(PyObject *type, PyObject *value)
        1648                 :            : {
        1649                 :            :     PyObject *as_parameter;
        1650                 :            :     int res;
        1651         [ #  # ]:          0 :     if (value == Py_None) {
        1652                 :          0 :         Py_RETURN_NONE;
        1653                 :            :     }
        1654         [ #  # ]:          0 :     if (PyUnicode_Check(value)) {
        1655                 :            :         PyCArgObject *parg;
        1656                 :          0 :         struct fielddesc *fd = _ctypes_get_fielddesc("Z");
        1657                 :            :
        1658                 :          0 :         parg = PyCArgObject_new();
        1659         [ #  # ]:          0 :         if (parg == NULL)
        1660                 :          0 :             return NULL;
        1661                 :          0 :         parg->pffi_type = &ffi_type_pointer;
        1662                 :          0 :         parg->tag = 'Z';
        1663                 :          0 :         parg->obj = fd->setfunc(&parg->value, value, 0);
        1664         [ #  # ]:          0 :         if (parg->obj == NULL) {
        1665                 :          0 :             Py_DECREF(parg);
        1666                 :          0 :             return NULL;
        1667                 :            :         }
        1668                 :          0 :         return (PyObject *)parg;
        1669                 :            :     }
        1670                 :          0 :     res = PyObject_IsInstance(value, type);
        1671         [ #  # ]:          0 :     if (res == -1)
        1672                 :          0 :         return NULL;
        1673         [ #  # ]:          0 :     if (res) {
        1674                 :          0 :         return Py_NewRef(value);
        1675                 :            :     }
        1676   [ #  #  #  # ]:          0 :     if (ArrayObject_Check(value) || PointerObject_Check(value)) {
        1677                 :            :         /* c_wchar array instance or pointer(c_wchar(...)) */
        1678                 :          0 :         StgDictObject *dt = PyObject_stgdict(value);
        1679                 :            :         StgDictObject *dict;
        1680                 :            :         assert(dt); /* Cannot be NULL for pointer or array objects */
        1681   [ #  #  #  # ]:          0 :         dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL;
        1682   [ #  #  #  # ]:          0 :         if (dict && (dict->setfunc == _ctypes_get_fielddesc("u")->setfunc)) {
        1683                 :          0 :             return Py_NewRef(value);
        1684                 :            :         }
        1685                 :            :     }
        1686         [ #  # ]:          0 :     if (PyCArg_CheckExact(value)) {
        1687                 :            :         /* byref(c_char(...)) */
        1688                 :          0 :         PyCArgObject *a = (PyCArgObject *)value;
        1689                 :          0 :         StgDictObject *dict = PyObject_stgdict(a->obj);
        1690   [ #  #  #  # ]:          0 :         if (dict && (dict->setfunc == _ctypes_get_fielddesc("u")->setfunc)) {
        1691                 :          0 :             return Py_NewRef(value);
        1692                 :            :         }
        1693                 :            :     }
        1694                 :            :
        1695         [ #  # ]:          0 :     if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
        1696                 :          0 :         return NULL;
        1697                 :            :     }
        1698         [ #  # ]:          0 :     if (as_parameter) {
        1699                 :          0 :         value = c_wchar_p_from_param(type, as_parameter);
        1700                 :          0 :         Py_DECREF(as_parameter);
        1701                 :          0 :         return value;
        1702                 :            :     }
        1703                 :            :     /* XXX better message */
        1704                 :          0 :     PyErr_SetString(PyExc_TypeError,
        1705                 :            :                     "wrong type");
        1706                 :          0 :     return NULL;
        1707                 :            : }
        1708                 :            :
        1709                 :            : static PyObject *
        1710                 :          0 : c_char_p_from_param(PyObject *type, PyObject *value)
        1711                 :            : {
        1712                 :            :     PyObject *as_parameter;
        1713                 :            :     int res;
        1714         [ #  # ]:          0 :     if (value == Py_None) {
        1715                 :          0 :         Py_RETURN_NONE;
        1716                 :            :     }
        1717         [ #  # ]:          0 :     if (PyBytes_Check(value)) {
        1718                 :            :         PyCArgObject *parg;
        1719                 :          0 :         struct fielddesc *fd = _ctypes_get_fielddesc("z");
        1720                 :            :
        1721                 :          0 :         parg = PyCArgObject_new();
        1722         [ #  # ]:          0 :         if (parg == NULL)
        1723                 :          0 :             return NULL;
        1724                 :          0 :         parg->pffi_type = &ffi_type_pointer;
        1725                 :          0 :         parg->tag = 'z';
        1726                 :          0 :         parg->obj = fd->setfunc(&parg->value, value, 0);
        1727         [ #  # ]:          0 :         if (parg->obj == NULL) {
        1728                 :          0 :             Py_DECREF(parg);
        1729                 :          0 :             return NULL;
        1730                 :            :         }
        1731                 :          0 :         return (PyObject *)parg;
        1732                 :            :     }
        1733                 :          0 :     res = PyObject_IsInstance(value, type);
        1734         [ #  # ]:          0 :     if (res == -1)
        1735                 :          0 :         return NULL;
        1736         [ #  # ]:          0 :     if (res) {
        1737                 :          0 :         return Py_NewRef(value);
        1738                 :            :     }
        1739   [ #  #  #  # ]:          0 :     if (ArrayObject_Check(value) || PointerObject_Check(value)) {
        1740                 :            :         /* c_char array instance or pointer(c_char(...)) */
        1741                 :          0 :         StgDictObject *dt = PyObject_stgdict(value);
        1742                 :            :         StgDictObject *dict;
        1743                 :            :         assert(dt); /* Cannot be NULL for pointer or array objects */
        1744   [ #  #  #  # ]:          0 :         dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL;
        1745   [ #  #  #  # ]:          0 :         if (dict && (dict->setfunc == _ctypes_get_fielddesc("c")->setfunc)) {
        1746                 :          0 :             return Py_NewRef(value);
        1747                 :            :         }
        1748                 :            :     }
        1749         [ #  # ]:          0 :     if (PyCArg_CheckExact(value)) {
        1750                 :            :         /* byref(c_char(...)) */
        1751                 :          0 :         PyCArgObject *a = (PyCArgObject *)value;
        1752                 :          0 :         StgDictObject *dict = PyObject_stgdict(a->obj);
        1753   [ #  #  #  # ]:          0 :         if (dict && (dict->setfunc == _ctypes_get_fielddesc("c")->setfunc)) {
        1754                 :          0 :             return Py_NewRef(value);
        1755                 :            :         }
        1756                 :            :     }
        1757                 :            :
        1758         [ #  # ]:          0 :     if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
        1759                 :          0 :         return NULL;
        1760                 :            :     }
        1761         [ #  # ]:          0 :     if (as_parameter) {
        1762                 :          0 :         value = c_char_p_from_param(type, as_parameter);
        1763                 :          0 :         Py_DECREF(as_parameter);
        1764                 :          0 :         return value;
        1765                 :            :     }
        1766                 :            :     /* XXX better message */
        1767                 :          0 :     PyErr_SetString(PyExc_TypeError,
        1768                 :            :                     "wrong type");
        1769                 :          0 :     return NULL;
        1770                 :            : }
        1771                 :            :
        1772                 :            : static PyObject *
        1773                 :          0 : c_void_p_from_param(PyObject *type, PyObject *value)
        1774                 :            : {
        1775                 :            :     StgDictObject *stgd;
        1776                 :            :     PyObject *as_parameter;
        1777                 :            :     int res;
        1778                 :            :
        1779                 :            : /* None */
        1780         [ #  # ]:          0 :     if (value == Py_None) {
        1781                 :          0 :         Py_RETURN_NONE;
        1782                 :            :     }
        1783                 :            :     /* Should probably allow buffer interface as well */
        1784                 :            : /* int, long */
        1785         [ #  # ]:          0 :     if (PyLong_Check(value)) {
        1786                 :            :         PyCArgObject *parg;
        1787                 :          0 :         struct fielddesc *fd = _ctypes_get_fielddesc("P");
        1788                 :            :
        1789                 :          0 :         parg = PyCArgObject_new();
        1790         [ #  # ]:          0 :         if (parg == NULL)
        1791                 :          0 :             return NULL;
        1792                 :          0 :         parg->pffi_type = &ffi_type_pointer;
        1793                 :          0 :         parg->tag = 'P';
        1794                 :          0 :         parg->obj = fd->setfunc(&parg->value, value, 0);
        1795         [ #  # ]:          0 :         if (parg->obj == NULL) {
        1796                 :          0 :             Py_DECREF(parg);
        1797                 :          0 :             return NULL;
        1798                 :            :         }
        1799                 :          0 :         return (PyObject *)parg;
        1800                 :            :     }
        1801                 :            :     /* XXX struni: remove later */
        1802                 :            : /* bytes */
        1803         [ #  # ]:          0 :     if (PyBytes_Check(value)) {
        1804                 :            :         PyCArgObject *parg;
        1805                 :          0 :         struct fielddesc *fd = _ctypes_get_fielddesc("z");
        1806                 :            :
        1807                 :          0 :         parg = PyCArgObject_new();
        1808         [ #  # ]:          0 :         if (parg == NULL)
        1809                 :          0 :             return NULL;
        1810                 :          0 :         parg->pffi_type = &ffi_type_pointer;
        1811                 :          0 :         parg->tag = 'z';
        1812                 :          0 :         parg->obj = fd->setfunc(&parg->value, value, 0);
        1813         [ #  # ]:          0 :         if (parg->obj == NULL) {
        1814                 :          0 :             Py_DECREF(parg);
        1815                 :          0 :             return NULL;
        1816                 :            :         }
        1817                 :          0 :         return (PyObject *)parg;
        1818                 :            :     }
        1819                 :            : /* unicode */
        1820         [ #  # ]:          0 :     if (PyUnicode_Check(value)) {
        1821                 :            :         PyCArgObject *parg;
        1822                 :          0 :         struct fielddesc *fd = _ctypes_get_fielddesc("Z");
        1823                 :            :
        1824                 :          0 :         parg = PyCArgObject_new();
        1825         [ #  # ]:          0 :         if (parg == NULL)
        1826                 :          0 :             return NULL;
        1827                 :          0 :         parg->pffi_type = &ffi_type_pointer;
        1828                 :          0 :         parg->tag = 'Z';
        1829                 :          0 :         parg->obj = fd->setfunc(&parg->value, value, 0);
        1830         [ #  # ]:          0 :         if (parg->obj == NULL) {
        1831                 :          0 :             Py_DECREF(parg);
        1832                 :          0 :             return NULL;
        1833                 :            :         }
        1834                 :          0 :         return (PyObject *)parg;
        1835                 :            :     }
        1836                 :            : /* c_void_p instance (or subclass) */
        1837                 :          0 :     res = PyObject_IsInstance(value, type);
        1838         [ #  # ]:          0 :     if (res == -1)
        1839                 :          0 :         return NULL;
        1840         [ #  # ]:          0 :     if (res) {
        1841                 :            :         /* c_void_p instances */
        1842                 :          0 :         return Py_NewRef(value);
        1843                 :            :     }
        1844                 :            : /* ctypes array or pointer instance */
        1845   [ #  #  #  # ]:          0 :     if (ArrayObject_Check(value) || PointerObject_Check(value)) {
        1846                 :            :         /* Any array or pointer is accepted */
        1847                 :          0 :         return Py_NewRef(value);
        1848                 :            :     }
        1849                 :            : /* byref(...) */
        1850         [ #  # ]:          0 :     if (PyCArg_CheckExact(value)) {
        1851                 :            :         /* byref(c_xxx()) */
        1852                 :          0 :         PyCArgObject *a = (PyCArgObject *)value;
        1853         [ #  # ]:          0 :         if (a->tag == 'P') {
        1854                 :          0 :             return Py_NewRef(value);
        1855                 :            :         }
        1856                 :            :     }
        1857                 :            : /* function pointer */
        1858         [ #  # ]:          0 :     if (PyCFuncPtrObject_Check(value)) {
        1859                 :            :         PyCArgObject *parg;
        1860                 :            :         PyCFuncPtrObject *func;
        1861                 :          0 :         func = (PyCFuncPtrObject *)value;
        1862                 :          0 :         parg = PyCArgObject_new();
        1863         [ #  # ]:          0 :         if (parg == NULL)
        1864                 :          0 :             return NULL;
        1865                 :          0 :         parg->pffi_type = &ffi_type_pointer;
        1866                 :          0 :         parg->tag = 'P';
        1867                 :          0 :         Py_INCREF(value);
        1868                 :          0 :         parg->value.p = *(void **)func->b_ptr;
        1869                 :          0 :         parg->obj = value;
        1870                 :          0 :         return (PyObject *)parg;
        1871                 :            :     }
        1872                 :            : /* c_char_p, c_wchar_p */
        1873                 :          0 :     stgd = PyObject_stgdict(value);
        1874   [ #  #  #  #  :          0 :     if (stgd && CDataObject_Check(value) && stgd->proto && PyUnicode_Check(stgd->proto)) {
                 #  #  #  # ]
        1875                 :            :         PyCArgObject *parg;
        1876                 :            :
        1877         [ #  # ]:          0 :         switch (PyUnicode_AsUTF8(stgd->proto)[0]) {
        1878                 :          0 :         case 'z': /* c_char_p */
        1879                 :            :         case 'Z': /* c_wchar_p */
        1880                 :          0 :             parg = PyCArgObject_new();
        1881         [ #  # ]:          0 :             if (parg == NULL)
        1882                 :          0 :                 return NULL;
        1883                 :          0 :             parg->pffi_type = &ffi_type_pointer;
        1884                 :          0 :             parg->tag = 'Z';
        1885                 :          0 :             parg->obj = Py_NewRef(value);
        1886                 :            :             /* Remember: b_ptr points to where the pointer is stored! */
        1887                 :          0 :             parg->value.p = *(void **)(((CDataObject *)value)->b_ptr);
        1888                 :          0 :             return (PyObject *)parg;
        1889                 :            :         }
        1890                 :            :     }
        1891                 :            :
        1892         [ #  # ]:          0 :     if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
        1893                 :          0 :         return NULL;
        1894                 :            :     }
        1895         [ #  # ]:          0 :     if (as_parameter) {
        1896                 :          0 :         value = c_void_p_from_param(type, as_parameter);
        1897                 :          0 :         Py_DECREF(as_parameter);
        1898                 :          0 :         return value;
        1899                 :            :     }
        1900                 :            :     /* XXX better message */
        1901                 :          0 :     PyErr_SetString(PyExc_TypeError,
        1902                 :            :                     "wrong type");
        1903                 :          0 :     return NULL;
        1904                 :            : }
        1905                 :            :
        1906                 :            : static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_O };
        1907                 :            : static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_O };
        1908                 :            : static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_O };
        1909                 :            :
        1910                 :          8 : static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject *kwds,
        1911                 :            :                                    PyObject *proto, struct fielddesc *fmt)
        1912                 :            : {
        1913                 :            :     PyTypeObject *result;
        1914                 :            :     StgDictObject *stgdict;
        1915                 :          8 :     PyObject *name = PyTuple_GET_ITEM(args, 0);
        1916                 :            :     PyObject *newname;
        1917                 :            :     PyObject *swapped_args;
        1918                 :            :     static PyObject *suffix;
        1919                 :            :     Py_ssize_t i;
        1920                 :            :
        1921                 :          8 :     swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
        1922         [ -  + ]:          8 :     if (!swapped_args)
        1923                 :          0 :         return NULL;
        1924                 :            :
        1925         [ +  + ]:          8 :     if (suffix == NULL)
        1926                 :            : #ifdef WORDS_BIGENDIAN
        1927                 :            :         suffix = PyUnicode_InternFromString("_le");
        1928                 :            : #else
        1929                 :          1 :         suffix = PyUnicode_InternFromString("_be");
        1930                 :            : #endif
        1931         [ -  + ]:          8 :     if (suffix == NULL) {
        1932                 :          0 :         Py_DECREF(swapped_args);
        1933                 :          0 :         return NULL;
        1934                 :            :     }
        1935                 :            :
        1936                 :          8 :     newname = PyUnicode_Concat(name, suffix);
        1937         [ -  + ]:          8 :     if (newname == NULL) {
        1938                 :          0 :         Py_DECREF(swapped_args);
        1939                 :          0 :         return NULL;
        1940                 :            :     }
        1941                 :            :
        1942                 :          8 :     PyTuple_SET_ITEM(swapped_args, 0, newname);
        1943         [ +  + ]:         24 :     for (i=1; i<PyTuple_GET_SIZE(args); ++i) {
        1944                 :         16 :         PyObject *v = PyTuple_GET_ITEM(args, i);
        1945                 :         16 :         Py_INCREF(v);
        1946                 :         16 :         PyTuple_SET_ITEM(swapped_args, i, v);
        1947                 :            :     }
        1948                 :            :
        1949                 :            :     /* create the new instance (which is a class,
        1950                 :            :        since we are a metatype!) */
        1951                 :          8 :     result = (PyTypeObject *)PyType_Type.tp_new(type, swapped_args, kwds);
        1952                 :          8 :     Py_DECREF(swapped_args);
        1953         [ -  + ]:          8 :     if (result == NULL)
        1954                 :          0 :         return NULL;
        1955                 :            :
        1956                 :          8 :     stgdict = (StgDictObject *)_PyObject_CallNoArgs(
        1957                 :            :         (PyObject *)&PyCStgDict_Type);
        1958         [ -  + ]:          8 :     if (!stgdict) {
        1959                 :          0 :         Py_DECREF(result);
        1960                 :          0 :         return NULL;
        1961                 :            :     }
        1962                 :            :
        1963                 :          8 :     stgdict->ffi_type_pointer = *fmt->pffi_type;
        1964                 :          8 :     stgdict->align = fmt->pffi_type->alignment;
        1965                 :          8 :     stgdict->length = 0;
        1966                 :          8 :     stgdict->size = fmt->pffi_type->size;
        1967                 :          8 :     stgdict->setfunc = fmt->setfunc_swapped;
        1968                 :          8 :     stgdict->getfunc = fmt->getfunc_swapped;
        1969                 :            :
        1970                 :          8 :     stgdict->proto = Py_NewRef(proto);
        1971                 :            :
        1972                 :            :     /* replace the class dict by our updated spam dict */
        1973         [ -  + ]:          8 :     if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
        1974                 :          0 :         Py_DECREF(result);
        1975                 :          0 :         Py_DECREF((PyObject *)stgdict);
        1976                 :          0 :         return NULL;
        1977                 :            :     }
        1978                 :          8 :     Py_SETREF(result->tp_dict, (PyObject *)stgdict);
        1979                 :            :
        1980                 :          8 :     return (PyObject *)result;
        1981                 :            : }
        1982                 :            :
        1983                 :            : static PyCArgObject *
        1984                 :          0 : PyCSimpleType_paramfunc(CDataObject *self)
        1985                 :            : {
        1986                 :            :     StgDictObject *dict;
        1987                 :            :     const char *fmt;
        1988                 :            :     PyCArgObject *parg;
        1989                 :            :     struct fielddesc *fd;
        1990                 :            :
        1991                 :          0 :     dict = PyObject_stgdict((PyObject *)self);
        1992                 :            :     assert(dict); /* Cannot be NULL for CDataObject instances */
        1993                 :          0 :     fmt = PyUnicode_AsUTF8(dict->proto);
        1994                 :            :     assert(fmt);
        1995                 :            :
        1996                 :          0 :     fd = _ctypes_get_fielddesc(fmt);
        1997                 :            :     assert(fd);
        1998                 :            :
        1999                 :          0 :     parg = PyCArgObject_new();
        2000         [ #  # ]:          0 :     if (parg == NULL)
        2001                 :          0 :         return NULL;
        2002                 :            :
        2003                 :          0 :     parg->tag = fmt[0];
        2004                 :          0 :     parg->pffi_type = fd->pffi_type;
        2005                 :          0 :     parg->obj = Py_NewRef(self);
        2006                 :          0 :     memcpy(&parg->value, self->b_ptr, self->b_size);
        2007                 :          0 :     return parg;
        2008                 :            : }
        2009                 :            :
        2010                 :            : static PyObject *
        2011                 :         18 : PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        2012                 :            : {
        2013                 :            :     PyTypeObject *result;
        2014                 :            :     StgDictObject *stgdict;
        2015                 :            :     PyObject *proto;
        2016                 :            :     const char *proto_str;
        2017                 :            :     Py_ssize_t proto_len;
        2018                 :            :     PyMethodDef *ml;
        2019                 :            :     struct fielddesc *fmt;
        2020                 :            :
        2021                 :            :     /* create the new instance (which is a class,
        2022                 :            :        since we are a metatype!) */
        2023                 :         18 :     result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
        2024         [ -  + ]:         18 :     if (result == NULL)
        2025                 :          0 :         return NULL;
        2026                 :            :
        2027         [ -  + ]:         18 :     if (_PyObject_LookupAttr((PyObject *)result, &_Py_ID(_type_), &proto) < 0) {
        2028                 :          0 :         return NULL;
        2029                 :            :     }
        2030         [ -  + ]:         18 :     if (!proto) {
        2031                 :          0 :         PyErr_SetString(PyExc_AttributeError,
        2032                 :            :                         "class must define a '_type_' attribute");
        2033                 :          0 :   error:
        2034                 :          0 :         Py_XDECREF(proto);
        2035                 :          0 :         Py_DECREF(result);
        2036                 :          0 :         return NULL;
        2037                 :            :     }
        2038         [ +  - ]:         18 :     if (PyUnicode_Check(proto)) {
        2039                 :         18 :         proto_str = PyUnicode_AsUTF8AndSize(proto, &proto_len);
        2040         [ -  + ]:         18 :         if (!proto_str)
        2041                 :          0 :             goto error;
        2042                 :            :     } else {
        2043                 :          0 :         PyErr_SetString(PyExc_TypeError,
        2044                 :            :             "class must define a '_type_' string attribute");
        2045                 :          0 :         goto error;
        2046                 :            :     }
        2047         [ -  + ]:         18 :     if (proto_len != 1) {
        2048                 :          0 :         PyErr_SetString(PyExc_ValueError,
        2049                 :            :                         "class must define a '_type_' attribute "
        2050                 :            :                         "which must be a string of length 1");
        2051                 :          0 :         goto error;
        2052                 :            :     }
        2053         [ -  + ]:         18 :     if (!strchr(SIMPLE_TYPE_CHARS, *proto_str)) {
        2054                 :          0 :         PyErr_Format(PyExc_AttributeError,
        2055                 :            :                      "class must define a '_type_' attribute which must be\n"
        2056                 :            :                      "a single character string containing one of '%s'.",
        2057                 :            :                      SIMPLE_TYPE_CHARS);
        2058                 :          0 :         goto error;
        2059                 :            :     }
        2060                 :         18 :     fmt = _ctypes_get_fielddesc(proto_str);
        2061         [ -  + ]:         18 :     if (fmt == NULL) {
        2062                 :          0 :         PyErr_Format(PyExc_ValueError,
        2063                 :            :                      "_type_ '%s' not supported", proto_str);
        2064                 :          0 :         goto error;
        2065                 :            :     }
        2066                 :            :
        2067                 :         18 :     stgdict = (StgDictObject *)_PyObject_CallNoArgs(
        2068                 :            :         (PyObject *)&PyCStgDict_Type);
        2069         [ -  + ]:         18 :     if (!stgdict)
        2070                 :          0 :         goto error;
        2071                 :            :
        2072                 :         18 :     stgdict->ffi_type_pointer = *fmt->pffi_type;
        2073                 :         18 :     stgdict->align = fmt->pffi_type->alignment;
        2074                 :         18 :     stgdict->length = 0;
        2075                 :         18 :     stgdict->size = fmt->pffi_type->size;
        2076                 :         18 :     stgdict->setfunc = fmt->setfunc;
        2077                 :         18 :     stgdict->getfunc = fmt->getfunc;
        2078                 :            : #ifdef WORDS_BIGENDIAN
        2079                 :            :     stgdict->format = _ctypes_alloc_format_string_for_type(proto_str[0], 1);
        2080                 :            : #else
        2081                 :         18 :     stgdict->format = _ctypes_alloc_format_string_for_type(proto_str[0], 0);
        2082                 :            : #endif
        2083         [ -  + ]:         18 :     if (stgdict->format == NULL) {
        2084                 :          0 :         Py_DECREF(result);
        2085                 :          0 :         Py_DECREF(proto);
        2086                 :          0 :         Py_DECREF((PyObject *)stgdict);
        2087                 :          0 :         return NULL;
        2088                 :            :     }
        2089                 :            :
        2090                 :         18 :     stgdict->paramfunc = PyCSimpleType_paramfunc;
        2091                 :            : /*
        2092                 :            :     if (result->tp_base != &Simple_Type) {
        2093                 :            :         stgdict->setfunc = NULL;
        2094                 :            :         stgdict->getfunc = NULL;
        2095                 :            :     }
        2096                 :            : */
        2097                 :            :
        2098                 :            :     /* This consumes the refcount on proto which we have */
        2099                 :         18 :     stgdict->proto = proto;
        2100                 :            :
        2101                 :            :     /* replace the class dict by our updated spam dict */
        2102         [ -  + ]:         18 :     if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
        2103                 :          0 :         Py_DECREF(result);
        2104                 :          0 :         Py_DECREF((PyObject *)stgdict);
        2105                 :          0 :         return NULL;
        2106                 :            :     }
        2107                 :         18 :     Py_SETREF(result->tp_dict, (PyObject *)stgdict);
        2108                 :            :
        2109                 :            :     /* Install from_param class methods in ctypes base classes.
        2110                 :            :        Overrides the PyCSimpleType_from_param generic method.
        2111                 :            :      */
        2112         [ +  - ]:         18 :     if (result->tp_base == &Simple_Type) {
        2113   [ +  +  +  +  :         18 :         switch (*proto_str) {
                          + ]
        2114                 :          1 :         case 'z': /* c_char_p */
        2115                 :          1 :             ml = &c_char_p_method;
        2116                 :          1 :             stgdict->flags |= TYPEFLAG_ISPOINTER;
        2117                 :          1 :             break;
        2118                 :          1 :         case 'Z': /* c_wchar_p */
        2119                 :          1 :             ml = &c_wchar_p_method;
        2120                 :          1 :             stgdict->flags |= TYPEFLAG_ISPOINTER;
        2121                 :          1 :             break;
        2122                 :          1 :         case 'P': /* c_void_p */
        2123                 :          1 :             ml = &c_void_p_method;
        2124                 :          1 :             stgdict->flags |= TYPEFLAG_ISPOINTER;
        2125                 :          1 :             break;
        2126                 :          1 :         case 's':
        2127                 :            :         case 'X':
        2128                 :            :         case 'O':
        2129                 :          1 :             ml = NULL;
        2130                 :          1 :             stgdict->flags |= TYPEFLAG_ISPOINTER;
        2131                 :          1 :             break;
        2132                 :         14 :         default:
        2133                 :         14 :             ml = NULL;
        2134                 :         14 :             break;
        2135                 :            :         }
        2136                 :            :
        2137         [ +  + ]:         18 :         if (ml) {
        2138                 :            :             PyObject *meth;
        2139                 :            :             int x;
        2140                 :          3 :             meth = PyDescr_NewClassMethod(result, ml);
        2141         [ -  + ]:          3 :             if (!meth) {
        2142                 :          0 :                 Py_DECREF(result);
        2143                 :          0 :                 return NULL;
        2144                 :            :             }
        2145                 :          3 :             x = PyDict_SetItemString(result->tp_dict,
        2146                 :            :                                      ml->ml_name,
        2147                 :            :                                      meth);
        2148                 :          3 :             Py_DECREF(meth);
        2149         [ -  + ]:          3 :             if (x == -1) {
        2150                 :          0 :                 Py_DECREF(result);
        2151                 :          0 :                 return NULL;
        2152                 :            :             }
        2153                 :            :         }
        2154                 :            :     }
        2155                 :            :
        2156   [ +  -  +  +  :         18 :     if (type == &PyCSimpleType_Type && fmt->setfunc_swapped && fmt->getfunc_swapped) {
                       +  - ]
        2157                 :          8 :         PyObject *swapped = CreateSwappedType(type, args, kwds,
        2158                 :            :                                               proto, fmt);
        2159                 :            :         StgDictObject *sw_dict;
        2160         [ -  + ]:          8 :         if (swapped == NULL) {
        2161                 :          0 :             Py_DECREF(result);
        2162                 :          0 :             return NULL;
        2163                 :            :         }
        2164                 :          8 :         sw_dict = PyType_stgdict(swapped);
        2165                 :            : #ifdef WORDS_BIGENDIAN
        2166                 :            :         PyObject_SetAttrString((PyObject *)result, "__ctype_le__", swapped);
        2167                 :            :         PyObject_SetAttrString((PyObject *)result, "__ctype_be__", (PyObject *)result);
        2168                 :            :         PyObject_SetAttrString(swapped, "__ctype_be__", (PyObject *)result);
        2169                 :            :         PyObject_SetAttrString(swapped, "__ctype_le__", swapped);
        2170                 :            :         /* We are creating the type for the OTHER endian */
        2171                 :            :         sw_dict->format = _ctypes_alloc_format_string("<", stgdict->format+1);
        2172                 :            : #else
        2173                 :          8 :         PyObject_SetAttrString((PyObject *)result, "__ctype_be__", swapped);
        2174                 :          8 :         PyObject_SetAttrString((PyObject *)result, "__ctype_le__", (PyObject *)result);
        2175                 :          8 :         PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result);
        2176                 :          8 :         PyObject_SetAttrString(swapped, "__ctype_be__", swapped);
        2177                 :            :         /* We are creating the type for the OTHER endian */
        2178                 :          8 :         sw_dict->format = _ctypes_alloc_format_string(">", stgdict->format+1);
        2179                 :            : #endif
        2180                 :          8 :         Py_DECREF(swapped);
        2181         [ -  + ]:          8 :         if (PyErr_Occurred()) {
        2182                 :          0 :             Py_DECREF(result);
        2183                 :          0 :             return NULL;
        2184                 :            :         }
        2185                 :            :     };
        2186                 :            :
        2187                 :         18 :     return (PyObject *)result;
        2188                 :            : }
        2189                 :            :
        2190                 :            : /*
        2191                 :            :  * This is a *class method*.
        2192                 :            :  * Convert a parameter into something that ConvParam can handle.
        2193                 :            :  */
        2194                 :            : static PyObject *
        2195                 :          0 : PyCSimpleType_from_param(PyObject *type, PyObject *value)
        2196                 :            : {
        2197                 :            :     StgDictObject *dict;
        2198                 :            :     const char *fmt;
        2199                 :            :     PyCArgObject *parg;
        2200                 :            :     struct fielddesc *fd;
        2201                 :            :     PyObject *as_parameter;
        2202                 :            :     int res;
        2203                 :            :
        2204                 :            :     /* If the value is already an instance of the requested type,
        2205                 :            :        we can use it as is */
        2206                 :          0 :     res = PyObject_IsInstance(value, type);
        2207         [ #  # ]:          0 :     if (res == -1)
        2208                 :          0 :         return NULL;
        2209         [ #  # ]:          0 :     if (res) {
        2210                 :          0 :         return Py_NewRef(value);
        2211                 :            :     }
        2212                 :            :
        2213                 :          0 :     dict = PyType_stgdict(type);
        2214         [ #  # ]:          0 :     if (!dict) {
        2215                 :          0 :         PyErr_SetString(PyExc_TypeError,
        2216                 :            :                         "abstract class");
        2217                 :          0 :         return NULL;
        2218                 :            :     }
        2219                 :            :
        2220                 :            :     /* I think we can rely on this being a one-character string */
        2221                 :          0 :     fmt = PyUnicode_AsUTF8(dict->proto);
        2222                 :            :     assert(fmt);
        2223                 :            :
        2224                 :          0 :     fd = _ctypes_get_fielddesc(fmt);
        2225                 :            :     assert(fd);
        2226                 :            :
        2227                 :          0 :     parg = PyCArgObject_new();
        2228         [ #  # ]:          0 :     if (parg == NULL)
        2229                 :          0 :         return NULL;
        2230                 :            :
        2231                 :          0 :     parg->tag = fmt[0];
        2232                 :          0 :     parg->pffi_type = fd->pffi_type;
        2233                 :          0 :     parg->obj = fd->setfunc(&parg->value, value, 0);
        2234         [ #  # ]:          0 :     if (parg->obj)
        2235                 :          0 :         return (PyObject *)parg;
        2236                 :          0 :     PyObject *exc = PyErr_GetRaisedException();
        2237                 :          0 :     Py_DECREF(parg);
        2238                 :            :
        2239         [ #  # ]:          0 :     if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
        2240                 :          0 :         Py_XDECREF(exc);
        2241                 :          0 :         return NULL;
        2242                 :            :     }
        2243         [ #  # ]:          0 :     if (as_parameter) {
        2244         [ #  # ]:          0 :         if (_Py_EnterRecursiveCall("while processing _as_parameter_")) {
        2245                 :          0 :             Py_DECREF(as_parameter);
        2246                 :          0 :             Py_XDECREF(exc);
        2247                 :          0 :             return NULL;
        2248                 :            :         }
        2249                 :          0 :         value = PyCSimpleType_from_param(type, as_parameter);
        2250                 :          0 :         _Py_LeaveRecursiveCall();
        2251                 :          0 :         Py_DECREF(as_parameter);
        2252                 :          0 :         Py_XDECREF(exc);
        2253                 :          0 :         return value;
        2254                 :            :     }
        2255         [ #  # ]:          0 :     if (exc) {
        2256                 :          0 :         PyErr_SetRaisedException(exc);
        2257                 :            :     }
        2258                 :            :     else {
        2259                 :          0 :         PyErr_SetString(PyExc_TypeError, "wrong type");
        2260                 :            :     }
        2261                 :          0 :     return NULL;
        2262                 :            : }
        2263                 :            :
        2264                 :            : static PyMethodDef PyCSimpleType_methods[] = {
        2265                 :            :     { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc },
        2266                 :            :     { "from_address", CDataType_from_address, METH_O, from_address_doc },
        2267                 :            :     { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
        2268                 :            :     { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
        2269                 :            :     { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc},
        2270                 :            :     { NULL, NULL },
        2271                 :            : };
        2272                 :            :
        2273                 :            : PyTypeObject PyCSimpleType_Type = {
        2274                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        2275                 :            :     "_ctypes.PyCSimpleType",                                    /* tp_name */
        2276                 :            :     0,                                          /* tp_basicsize */
        2277                 :            :     0,                                          /* tp_itemsize */
        2278                 :            :     0,                                          /* tp_dealloc */
        2279                 :            :     0,                                          /* tp_vectorcall_offset */
        2280                 :            :     0,                                          /* tp_getattr */
        2281                 :            :     0,                                          /* tp_setattr */
        2282                 :            :     0,                                          /* tp_as_async */
        2283                 :            :     0,                                          /* tp_repr */
        2284                 :            :     0,                                          /* tp_as_number */
        2285                 :            :     &CDataType_as_sequence,             /* tp_as_sequence */
        2286                 :            :     0,                                          /* tp_as_mapping */
        2287                 :            :     0,                                          /* tp_hash */
        2288                 :            :     0,                                          /* tp_call */
        2289                 :            :     0,                                          /* tp_str */
        2290                 :            :     0,                                          /* tp_getattro */
        2291                 :            :     0,                                          /* tp_setattro */
        2292                 :            :     0,                                          /* tp_as_buffer */
        2293                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        2294                 :            :     PyDoc_STR("metatype for the PyCSimpleType Objects"), /* tp_doc */
        2295                 :            :     0,                                          /* tp_traverse */
        2296                 :            :     0,                                          /* tp_clear */
        2297                 :            :     0,                                          /* tp_richcompare */
        2298                 :            :     0,                                          /* tp_weaklistoffset */
        2299                 :            :     0,                                          /* tp_iter */
        2300                 :            :     0,                                          /* tp_iternext */
        2301                 :            :     PyCSimpleType_methods,                      /* tp_methods */
        2302                 :            :     0,                                          /* tp_members */
        2303                 :            :     0,                                          /* tp_getset */
        2304                 :            :     0,                                          /* tp_base */
        2305                 :            :     0,                                          /* tp_dict */
        2306                 :            :     0,                                          /* tp_descr_get */
        2307                 :            :     0,                                          /* tp_descr_set */
        2308                 :            :     0,                                          /* tp_dictoffset */
        2309                 :            :     0,                                          /* tp_init */
        2310                 :            :     0,                                          /* tp_alloc */
        2311                 :            :     PyCSimpleType_new,                                  /* tp_new */
        2312                 :            :     0,                                          /* tp_free */
        2313                 :            : };
        2314                 :            :
        2315                 :            : /******************************************************************/
        2316                 :            : /*
        2317                 :            :   PyCFuncPtrType_Type
        2318                 :            :  */
        2319                 :            :
        2320                 :            : static PyObject *
        2321                 :          5 : converters_from_argtypes(PyObject *ob)
        2322                 :            : {
        2323                 :            :     PyObject *converters;
        2324                 :            :     Py_ssize_t i;
        2325                 :            :
        2326                 :          5 :     ob = PySequence_Tuple(ob); /* new reference */
        2327         [ -  + ]:          5 :     if (!ob) {
        2328                 :          0 :         PyErr_SetString(PyExc_TypeError,
        2329                 :            :                         "_argtypes_ must be a sequence of types");
        2330                 :          0 :         return NULL;
        2331                 :            :     }
        2332                 :            :
        2333                 :          5 :     Py_ssize_t nArgs = PyTuple_GET_SIZE(ob);
        2334         [ -  + ]:          5 :     if (nArgs > CTYPES_MAX_ARGCOUNT) {
        2335                 :          0 :         Py_DECREF(ob);
        2336                 :          0 :         PyErr_Format(PyExc_ArgError,
        2337                 :            :                      "_argtypes_ has too many arguments (%zi), maximum is %i",
        2338                 :            :                      nArgs, CTYPES_MAX_ARGCOUNT);
        2339                 :          0 :         return NULL;
        2340                 :            :     }
        2341                 :            :
        2342                 :          5 :     converters = PyTuple_New(nArgs);
        2343         [ -  + ]:          5 :     if (!converters) {
        2344                 :          0 :         Py_DECREF(ob);
        2345                 :          0 :         return NULL;
        2346                 :            :     }
        2347                 :            :
        2348                 :            :     /* I have to check if this is correct. Using c_char, which has a size
        2349                 :            :        of 1, will be assumed to be pushed as only one byte!
        2350                 :            :        Aren't these promoted to integers by the C compiler and pushed as 4 bytes?
        2351                 :            :     */
        2352                 :            :
        2353         [ +  + ]:         18 :     for (i = 0; i < nArgs; ++i) {
        2354                 :            :         PyObject *cnv;
        2355                 :         13 :         PyObject *tp = PyTuple_GET_ITEM(ob, i);
        2356                 :            : /*
        2357                 :            :  *      The following checks, relating to bpo-16575 and bpo-16576, have been
        2358                 :            :  *      disabled. The reason is that, although there is a definite problem with
        2359                 :            :  *      how libffi handles unions (https://github.com/libffi/libffi/issues/33),
        2360                 :            :  *      there are numerous libraries which pass structures containing unions
        2361                 :            :  *      by values - especially on Windows but examples also exist on Linux
        2362                 :            :  *      (https://bugs.python.org/msg359834).
        2363                 :            :  *
        2364                 :            :  *      It may not be possible to get proper support for unions and bitfields
        2365                 :            :  *      until support is forthcoming in libffi, but for now, adding the checks
        2366                 :            :  *      has caused problems in otherwise-working software, which suggests it
        2367                 :            :  *      is better to disable the checks.
        2368                 :            :  *
        2369                 :            :  *      Although specific examples reported relate specifically to unions and
        2370                 :            :  *      not bitfields, the bitfields check is also being disabled as a
        2371                 :            :  *      precaution.
        2372                 :            :
        2373                 :            :         StgDictObject *stgdict = PyType_stgdict(tp);
        2374                 :            :
        2375                 :            :         if (stgdict != NULL) {
        2376                 :            :             if (stgdict->flags & TYPEFLAG_HASUNION) {
        2377                 :            :                 Py_DECREF(converters);
        2378                 :            :                 Py_DECREF(ob);
        2379                 :            :                 if (!PyErr_Occurred()) {
        2380                 :            :                     PyErr_Format(PyExc_TypeError,
        2381                 :            :                                  "item %zd in _argtypes_ passes a union by "
        2382                 :            :                                  "value, which is unsupported.",
        2383                 :            :                                  i + 1);
        2384                 :            :                 }
        2385                 :            :                 return NULL;
        2386                 :            :             }
        2387                 :            :             if (stgdict->flags & TYPEFLAG_HASBITFIELD) {
        2388                 :            :                 Py_DECREF(converters);
        2389                 :            :                 Py_DECREF(ob);
        2390                 :            :                 if (!PyErr_Occurred()) {
        2391                 :            :                     PyErr_Format(PyExc_TypeError,
        2392                 :            :                                  "item %zd in _argtypes_ passes a struct/"
        2393                 :            :                                  "union with a bitfield by value, which is "
        2394                 :            :                                  "unsupported.",
        2395                 :            :                                  i + 1);
        2396                 :            :                 }
        2397                 :            :                 return NULL;
        2398                 :            :             }
        2399                 :            :         }
        2400                 :            :  */
        2401                 :            :
        2402         [ -  + ]:         13 :         if (_PyObject_LookupAttr(tp, &_Py_ID(from_param), &cnv) <= 0) {
        2403                 :          0 :             Py_DECREF(converters);
        2404                 :          0 :             Py_DECREF(ob);
        2405         [ #  # ]:          0 :             if (!PyErr_Occurred()) {
        2406                 :          0 :                 PyErr_Format(PyExc_TypeError,
        2407                 :            :                              "item %zd in _argtypes_ has no from_param method",
        2408                 :            :                              i+1);
        2409                 :            :             }
        2410                 :          0 :             return NULL;
        2411                 :            :         }
        2412                 :         13 :         PyTuple_SET_ITEM(converters, i, cnv);
        2413                 :            :     }
        2414                 :          5 :     Py_DECREF(ob);
        2415                 :          5 :     return converters;
        2416                 :            : }
        2417                 :            :
        2418                 :            : static int
        2419                 :          6 : make_funcptrtype_dict(StgDictObject *stgdict)
        2420                 :            : {
        2421                 :            :     PyObject *ob;
        2422                 :          6 :     PyObject *converters = NULL;
        2423                 :            :
        2424                 :          6 :     stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment;
        2425                 :          6 :     stgdict->length = 1;
        2426                 :          6 :     stgdict->size = sizeof(void *);
        2427                 :          6 :     stgdict->setfunc = NULL;
        2428                 :          6 :     stgdict->getfunc = NULL;
        2429                 :          6 :     stgdict->ffi_type_pointer = ffi_type_pointer;
        2430                 :            :
        2431                 :          6 :     ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_flags_));
        2432   [ +  -  -  + ]:          6 :     if (!ob || !PyLong_Check(ob)) {
        2433         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
        2434                 :          0 :             PyErr_SetString(PyExc_TypeError,
        2435                 :            :                 "class must define _flags_ which must be an integer");
        2436                 :            :         }
        2437                 :          0 :         return -1;
        2438                 :            :     }
        2439                 :          6 :     stgdict->flags = PyLong_AsUnsignedLongMask(ob) | TYPEFLAG_ISPOINTER;
        2440                 :            :
        2441                 :            :     /* _argtypes_ is optional... */
        2442                 :          6 :     ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_argtypes_));
        2443         [ +  + ]:          6 :     if (ob) {
        2444                 :          5 :         converters = converters_from_argtypes(ob);
        2445         [ -  + ]:          5 :         if (!converters)
        2446                 :          0 :             return -1;
        2447                 :          5 :         stgdict->argtypes = Py_NewRef(ob);
        2448                 :          5 :         stgdict->converters = converters;
        2449                 :            :     }
        2450         [ -  + ]:          1 :     else if (PyErr_Occurred()) {
        2451                 :          0 :         return -1;
        2452                 :            :     }
        2453                 :            :
        2454                 :          6 :     ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_restype_));
        2455         [ +  - ]:          6 :     if (ob) {
        2456   [ +  -  -  +  :          6 :         if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) {
                       -  - ]
        2457                 :          0 :             PyErr_SetString(PyExc_TypeError,
        2458                 :            :                 "_restype_ must be a type, a callable, or None");
        2459                 :          0 :             return -1;
        2460                 :            :         }
        2461                 :          6 :         stgdict->restype = Py_NewRef(ob);
        2462         [ -  + ]:          6 :         if (_PyObject_LookupAttr(ob, &_Py_ID(_check_retval_),
        2463                 :            :                                    &stgdict->checker) < 0)
        2464                 :            :         {
        2465                 :          0 :             return -1;
        2466                 :            :         }
        2467                 :            :     }
        2468         [ #  # ]:          0 :     else if (PyErr_Occurred()) {
        2469                 :          0 :         return -1;
        2470                 :            :     }
        2471                 :            : /* XXX later, maybe.
        2472                 :            :     ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__errcheck_);
        2473                 :            :     if (ob) {
        2474                 :            :         if (!PyCallable_Check(ob)) {
        2475                 :            :             PyErr_SetString(PyExc_TypeError,
        2476                 :            :                 "_errcheck_ must be callable");
        2477                 :            :             return -1;
        2478                 :            :         }
        2479                 :            :         stgdict->errcheck = Py_NewRef(ob);
        2480                 :            :     }
        2481                 :            :     else if (PyErr_Occurred()) {
        2482                 :            :         return -1;
        2483                 :            :     }
        2484                 :            : */
        2485                 :          6 :     return 0;
        2486                 :            : }
        2487                 :            :
        2488                 :            : static PyCArgObject *
        2489                 :          0 : PyCFuncPtrType_paramfunc(CDataObject *self)
        2490                 :            : {
        2491                 :            :     PyCArgObject *parg;
        2492                 :            :
        2493                 :          0 :     parg = PyCArgObject_new();
        2494         [ #  # ]:          0 :     if (parg == NULL)
        2495                 :          0 :         return NULL;
        2496                 :            :
        2497                 :          0 :     parg->tag = 'P';
        2498                 :          0 :     parg->pffi_type = &ffi_type_pointer;
        2499                 :          0 :     parg->obj = Py_NewRef(self);
        2500                 :          0 :     parg->value.p = *(void **)self->b_ptr;
        2501                 :          0 :     return parg;
        2502                 :            : }
        2503                 :            :
        2504                 :            : static PyObject *
        2505                 :          6 : PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        2506                 :            : {
        2507                 :            :     PyTypeObject *result;
        2508                 :            :     StgDictObject *stgdict;
        2509                 :            :
        2510                 :          6 :     stgdict = (StgDictObject *)_PyObject_CallNoArgs(
        2511                 :            :         (PyObject *)&PyCStgDict_Type);
        2512         [ -  + ]:          6 :     if (!stgdict)
        2513                 :          0 :         return NULL;
        2514                 :            :
        2515                 :          6 :     stgdict->paramfunc = PyCFuncPtrType_paramfunc;
        2516                 :            :     /* We do NOT expose the function signature in the format string.  It
        2517                 :            :        is impossible, generally, because the only requirement for the
        2518                 :            :        argtypes items is that they have a .from_param method - we do not
        2519                 :            :        know the types of the arguments (although, in practice, most
        2520                 :            :        argtypes would be a ctypes type).
        2521                 :            :     */
        2522                 :          6 :     stgdict->format = _ctypes_alloc_format_string(NULL, "X{}");
        2523         [ -  + ]:          6 :     if (stgdict->format == NULL) {
        2524                 :          0 :         Py_DECREF((PyObject *)stgdict);
        2525                 :          0 :         return NULL;
        2526                 :            :     }
        2527                 :          6 :     stgdict->flags |= TYPEFLAG_ISPOINTER;
        2528                 :            :
        2529                 :            :     /* create the new instance (which is a class,
        2530                 :            :        since we are a metatype!) */
        2531                 :          6 :     result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
        2532         [ -  + ]:          6 :     if (result == NULL) {
        2533                 :          0 :         Py_DECREF((PyObject *)stgdict);
        2534                 :          0 :         return NULL;
        2535                 :            :     }
        2536                 :            :
        2537                 :            :     /* replace the class dict by our updated storage dict */
        2538         [ -  + ]:          6 :     if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
        2539                 :          0 :         Py_DECREF(result);
        2540                 :          0 :         Py_DECREF((PyObject *)stgdict);
        2541                 :          0 :         return NULL;
        2542                 :            :     }
        2543                 :          6 :     Py_SETREF(result->tp_dict, (PyObject *)stgdict);
        2544                 :            :
        2545         [ -  + ]:          6 :     if (-1 == make_funcptrtype_dict(stgdict)) {
        2546                 :          0 :         Py_DECREF(result);
        2547                 :          0 :         return NULL;
        2548                 :            :     }
        2549                 :            :
        2550                 :          6 :     return (PyObject *)result;
        2551                 :            : }
        2552                 :            :
        2553                 :            : PyTypeObject PyCFuncPtrType_Type = {
        2554                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        2555                 :            :     "_ctypes.PyCFuncPtrType",                           /* tp_name */
        2556                 :            :     0,                                          /* tp_basicsize */
        2557                 :            :     0,                                          /* tp_itemsize */
        2558                 :            :     0,                                          /* tp_dealloc */
        2559                 :            :     0,                                          /* tp_vectorcall_offset */
        2560                 :            :     0,                                          /* tp_getattr */
        2561                 :            :     0,                                          /* tp_setattr */
        2562                 :            :     0,                                          /* tp_as_async */
        2563                 :            :     0,                                          /* tp_repr */
        2564                 :            :     0,                                          /* tp_as_number */
        2565                 :            :     &CDataType_as_sequence,                     /* tp_as_sequence */
        2566                 :            :     0,                                          /* tp_as_mapping */
        2567                 :            :     0,                                          /* tp_hash */
        2568                 :            :     0,                                          /* tp_call */
        2569                 :            :     0,                                          /* tp_str */
        2570                 :            :     0,                                          /* tp_getattro */
        2571                 :            :     0,                                          /* tp_setattro */
        2572                 :            :     0,                                          /* tp_as_buffer */
        2573                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
        2574                 :            :     PyDoc_STR("metatype for C function pointers"), /* tp_doc */
        2575                 :            :     (traverseproc)CDataType_traverse,           /* tp_traverse */
        2576                 :            :     (inquiry)CDataType_clear,                   /* tp_clear */
        2577                 :            :     0,                                          /* tp_richcompare */
        2578                 :            :     0,                                          /* tp_weaklistoffset */
        2579                 :            :     0,                                          /* tp_iter */
        2580                 :            :     0,                                          /* tp_iternext */
        2581                 :            :     CDataType_methods,                          /* tp_methods */
        2582                 :            :     0,                                          /* tp_members */
        2583                 :            :     0,                                          /* tp_getset */
        2584                 :            :     0,                                          /* tp_base */
        2585                 :            :     0,                                          /* tp_dict */
        2586                 :            :     0,                                          /* tp_descr_get */
        2587                 :            :     0,                                          /* tp_descr_set */
        2588                 :            :     0,                                          /* tp_dictoffset */
        2589                 :            :     0,                                          /* tp_init */
        2590                 :            :     0,                                          /* tp_alloc */
        2591                 :            :     PyCFuncPtrType_new,                         /* tp_new */
        2592                 :            :     0,                                          /* tp_free */
        2593                 :            : };
        2594                 :            :
        2595                 :            :
        2596                 :            : /*****************************************************************
        2597                 :            :  * Code to keep needed objects alive
        2598                 :            :  */
        2599                 :            :
        2600                 :            : static CDataObject *
        2601                 :          0 : PyCData_GetContainer(CDataObject *self)
        2602                 :            : {
        2603         [ #  # ]:          0 :     while (self->b_base)
        2604                 :          0 :         self = self->b_base;
        2605         [ #  # ]:          0 :     if (self->b_objects == NULL) {
        2606         [ #  # ]:          0 :         if (self->b_length) {
        2607                 :          0 :             self->b_objects = PyDict_New();
        2608         [ #  # ]:          0 :             if (self->b_objects == NULL)
        2609                 :          0 :                 return NULL;
        2610                 :            :         } else {
        2611                 :          0 :             self->b_objects = Py_NewRef(Py_None);
        2612                 :            :         }
        2613                 :            :     }
        2614                 :          0 :     return self;
        2615                 :            : }
        2616                 :            :
        2617                 :            : static PyObject *
        2618                 :          0 : GetKeepedObjects(CDataObject *target)
        2619                 :            : {
        2620                 :            :     CDataObject *container;
        2621                 :          0 :     container = PyCData_GetContainer(target);
        2622         [ #  # ]:          0 :     if (container == NULL)
        2623                 :          0 :         return NULL;
        2624                 :          0 :     return container->b_objects;
        2625                 :            : }
        2626                 :            :
        2627                 :            : static PyObject *
        2628                 :          0 : unique_key(CDataObject *target, Py_ssize_t index)
        2629                 :            : {
        2630                 :            :     char string[256];
        2631                 :          0 :     char *cp = string;
        2632                 :            :     size_t bytes_left;
        2633                 :            :
        2634                 :            :     Py_BUILD_ASSERT(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2);
        2635                 :          0 :     cp += sprintf(cp, "%x", Py_SAFE_DOWNCAST(index, Py_ssize_t, int));
        2636         [ #  # ]:          0 :     while (target->b_base) {
        2637                 :          0 :         bytes_left = sizeof(string) - (cp - string) - 1;
        2638                 :            :         /* Hex format needs 2 characters per byte */
        2639         [ #  # ]:          0 :         if (bytes_left < sizeof(Py_ssize_t) * 2) {
        2640                 :          0 :             PyErr_SetString(PyExc_ValueError,
        2641                 :            :                             "ctypes object structure too deep");
        2642                 :          0 :             return NULL;
        2643                 :            :         }
        2644                 :          0 :         cp += sprintf(cp, ":%x", Py_SAFE_DOWNCAST(target->b_index, Py_ssize_t, int));
        2645                 :          0 :         target = target->b_base;
        2646                 :            :     }
        2647                 :          0 :     return PyUnicode_FromStringAndSize(string, cp-string);
        2648                 :            : }
        2649                 :            :
        2650                 :            : /*
        2651                 :            :  * Keep a reference to 'keep' in the 'target', at index 'index'.
        2652                 :            :  *
        2653                 :            :  * If 'keep' is None, do nothing.
        2654                 :            :  *
        2655                 :            :  * Otherwise create a dictionary (if it does not yet exist) id the root
        2656                 :            :  * objects 'b_objects' item, which will store the 'keep' object under a unique
        2657                 :            :  * key.
        2658                 :            :  *
        2659                 :            :  * The unique_key helper travels the target's b_base pointer down to the root,
        2660                 :            :  * building a string containing hex-formatted indexes found during traversal,
        2661                 :            :  * separated by colons.
        2662                 :            :  *
        2663                 :            :  * The index tuple is used as a key into the root object's b_objects dict.
        2664                 :            :  *
        2665                 :            :  * Note: This function steals a refcount of the third argument, even if it
        2666                 :            :  * fails!
        2667                 :            :  */
        2668                 :            : static int
        2669                 :          0 : KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
        2670                 :            : {
        2671                 :            :     int result;
        2672                 :            :     CDataObject *ob;
        2673                 :            :     PyObject *key;
        2674                 :            :
        2675                 :            : /* Optimization: no need to store None */
        2676         [ #  # ]:          0 :     if (keep == Py_None) {
        2677                 :          0 :         Py_DECREF(Py_None);
        2678                 :          0 :         return 0;
        2679                 :            :     }
        2680                 :          0 :     ob = PyCData_GetContainer(target);
        2681         [ #  # ]:          0 :     if (ob == NULL) {
        2682                 :          0 :         Py_DECREF(keep);
        2683                 :          0 :         return -1;
        2684                 :            :     }
        2685   [ #  #  #  # ]:          0 :     if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
        2686                 :          0 :         Py_XSETREF(ob->b_objects, keep); /* refcount consumed */
        2687                 :          0 :         return 0;
        2688                 :            :     }
        2689                 :          0 :     key = unique_key(target, index);
        2690         [ #  # ]:          0 :     if (key == NULL) {
        2691                 :          0 :         Py_DECREF(keep);
        2692                 :          0 :         return -1;
        2693                 :            :     }
        2694                 :          0 :     result = PyDict_SetItem(ob->b_objects, key, keep);
        2695                 :          0 :     Py_DECREF(key);
        2696                 :          0 :     Py_DECREF(keep);
        2697                 :          0 :     return result;
        2698                 :            : }
        2699                 :            :
        2700                 :            : /******************************************************************/
        2701                 :            : /*
        2702                 :            :   PyCData_Type
        2703                 :            :  */
        2704                 :            : static int
        2705                 :        180 : PyCData_traverse(CDataObject *self, visitproc visit, void *arg)
        2706                 :            : {
        2707   [ -  +  -  - ]:        180 :     Py_VISIT(self->b_objects);
        2708   [ -  +  -  - ]:        180 :     Py_VISIT((PyObject *)self->b_base);
        2709                 :        180 :     return 0;
        2710                 :            : }
        2711                 :            :
        2712                 :            : static int
        2713                 :          0 : PyCData_clear(CDataObject *self)
        2714                 :            : {
        2715         [ #  # ]:          0 :     Py_CLEAR(self->b_objects);
        2716         [ #  # ]:          0 :     if ((self->b_needsfree)
        2717         [ #  # ]:          0 :         && _CDataObject_HasExternalBuffer(self))
        2718                 :          0 :         PyMem_Free(self->b_ptr);
        2719                 :          0 :     self->b_ptr = NULL;
        2720         [ #  # ]:          0 :     Py_CLEAR(self->b_base);
        2721                 :          0 :     return 0;
        2722                 :            : }
        2723                 :            :
        2724                 :            : static void
        2725                 :          0 : PyCData_dealloc(PyObject *self)
        2726                 :            : {
        2727                 :          0 :     PyCData_clear((CDataObject *)self);
        2728                 :          0 :     Py_TYPE(self)->tp_free(self);
        2729                 :          0 : }
        2730                 :            :
        2731                 :            : static PyMemberDef PyCData_members[] = {
        2732                 :            :     { "_b_base_", T_OBJECT,
        2733                 :            :       offsetof(CDataObject, b_base), READONLY,
        2734                 :            :       "the base object" },
        2735                 :            :     { "_b_needsfree_", T_INT,
        2736                 :            :       offsetof(CDataObject, b_needsfree), READONLY,
        2737                 :            :       "whether the object owns the memory or not" },
        2738                 :            :     { "_objects", T_OBJECT,
        2739                 :            :       offsetof(CDataObject, b_objects), READONLY,
        2740                 :            :       "internal objects tree (NEVER CHANGE THIS OBJECT!)"},
        2741                 :            :     { NULL },
        2742                 :            : };
        2743                 :            :
        2744                 :            : /* Find the innermost type of an array type, returning a borrowed reference */
        2745                 :            : static PyObject *
        2746                 :          0 : PyCData_item_type(PyObject *type)
        2747                 :            : {
        2748         [ #  # ]:          0 :     if (PyCArrayTypeObject_Check(type)) {
        2749                 :            :         StgDictObject *stg_dict;
        2750                 :            :         PyObject *elem_type;
        2751                 :            :
        2752                 :            :         /* asserts used here as these are all guaranteed by construction */
        2753                 :          0 :         stg_dict = PyType_stgdict(type);
        2754                 :            :         assert(stg_dict);
        2755                 :          0 :         elem_type = stg_dict->proto;
        2756                 :            :         assert(elem_type);
        2757                 :          0 :         return PyCData_item_type(elem_type);
        2758                 :            :     }
        2759                 :            :     else {
        2760                 :          0 :         return type;
        2761                 :            :     }
        2762                 :            : }
        2763                 :            :
        2764                 :            : static int
        2765                 :          0 : PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
        2766                 :            : {
        2767                 :          0 :     CDataObject *self = (CDataObject *)myself;
        2768                 :          0 :     StgDictObject *dict = PyObject_stgdict(myself);
        2769                 :          0 :     PyObject *item_type = PyCData_item_type((PyObject*)Py_TYPE(myself));
        2770                 :          0 :     StgDictObject *item_dict = PyType_stgdict(item_type);
        2771                 :            :
        2772         [ #  # ]:          0 :     if (view == NULL) return 0;
        2773                 :            :
        2774                 :          0 :     view->buf = self->b_ptr;
        2775                 :          0 :     view->obj = Py_NewRef(myself);
        2776                 :          0 :     view->len = self->b_size;
        2777                 :          0 :     view->readonly = 0;
        2778                 :            :     /* use default format character if not set */
        2779         [ #  # ]:          0 :     view->format = dict->format ? dict->format : "B";
        2780                 :          0 :     view->ndim = dict->ndim;
        2781                 :          0 :     view->shape = dict->shape;
        2782                 :          0 :     view->itemsize = item_dict->size;
        2783                 :          0 :     view->strides = NULL;
        2784                 :          0 :     view->suboffsets = NULL;
        2785                 :          0 :     view->internal = NULL;
        2786                 :          0 :     return 0;
        2787                 :            : }
        2788                 :            :
        2789                 :            : static PyBufferProcs PyCData_as_buffer = {
        2790                 :            :     PyCData_NewGetBuffer,
        2791                 :            :     NULL,
        2792                 :            : };
        2793                 :            :
        2794                 :            : /*
        2795                 :            :  * CData objects are mutable, so they cannot be hashable!
        2796                 :            :  */
        2797                 :            : static Py_hash_t
        2798                 :          0 : PyCData_nohash(PyObject *self)
        2799                 :            : {
        2800                 :          0 :     PyErr_SetString(PyExc_TypeError, "unhashable type");
        2801                 :          0 :     return -1;
        2802                 :            : }
        2803                 :            :
        2804                 :            : static PyObject *
        2805                 :          0 : PyCData_reduce(PyObject *myself, PyObject *args)
        2806                 :            : {
        2807                 :          0 :     CDataObject *self = (CDataObject *)myself;
        2808                 :            :
        2809         [ #  # ]:          0 :     if (PyObject_stgdict(myself)->flags & (TYPEFLAG_ISPOINTER|TYPEFLAG_HASPOINTER)) {
        2810                 :          0 :         PyErr_SetString(PyExc_ValueError,
        2811                 :            :                         "ctypes objects containing pointers cannot be pickled");
        2812                 :          0 :         return NULL;
        2813                 :            :     }
        2814                 :          0 :     PyObject *dict = PyObject_GetAttrString(myself, "__dict__");
        2815         [ #  # ]:          0 :     if (dict == NULL) {
        2816                 :          0 :         return NULL;
        2817                 :            :     }
        2818                 :          0 :     return Py_BuildValue("O(O(NN))", _unpickle, Py_TYPE(myself), dict,
        2819                 :          0 :                          PyBytes_FromStringAndSize(self->b_ptr, self->b_size));
        2820                 :            : }
        2821                 :            :
        2822                 :            : static PyObject *
        2823                 :          0 : PyCData_setstate(PyObject *myself, PyObject *args)
        2824                 :            : {
        2825                 :            :     void *data;
        2826                 :            :     Py_ssize_t len;
        2827                 :            :     int res;
        2828                 :            :     PyObject *dict, *mydict;
        2829                 :          0 :     CDataObject *self = (CDataObject *)myself;
        2830         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O!s#",
        2831                 :            :                           &PyDict_Type, &dict, &data, &len))
        2832                 :            :     {
        2833                 :          0 :         return NULL;
        2834                 :            :     }
        2835         [ #  # ]:          0 :     if (len > self->b_size)
        2836                 :          0 :         len = self->b_size;
        2837                 :          0 :     memmove(self->b_ptr, data, len);
        2838                 :          0 :     mydict = PyObject_GetAttrString(myself, "__dict__");
        2839         [ #  # ]:          0 :     if (mydict == NULL) {
        2840                 :          0 :         return NULL;
        2841                 :            :     }
        2842         [ #  # ]:          0 :     if (!PyDict_Check(mydict)) {
        2843                 :          0 :         PyErr_Format(PyExc_TypeError,
        2844                 :            :                      "%.200s.__dict__ must be a dictionary, not %.200s",
        2845                 :          0 :                      Py_TYPE(myself)->tp_name, Py_TYPE(mydict)->tp_name);
        2846                 :          0 :         Py_DECREF(mydict);
        2847                 :          0 :         return NULL;
        2848                 :            :     }
        2849                 :          0 :     res = PyDict_Update(mydict, dict);
        2850                 :          0 :     Py_DECREF(mydict);
        2851         [ #  # ]:          0 :     if (res == -1)
        2852                 :          0 :         return NULL;
        2853                 :          0 :     Py_RETURN_NONE;
        2854                 :            : }
        2855                 :            :
        2856                 :            : /*
        2857                 :            :  * default __ctypes_from_outparam__ method returns self.
        2858                 :            :  */
        2859                 :            : static PyObject *
        2860                 :          0 : PyCData_from_outparam(PyObject *self, PyObject *args)
        2861                 :            : {
        2862                 :          0 :     return Py_NewRef(self);
        2863                 :            : }
        2864                 :            :
        2865                 :            : static PyMethodDef PyCData_methods[] = {
        2866                 :            :     { "__ctypes_from_outparam__", PyCData_from_outparam, METH_NOARGS, },
        2867                 :            :     { "__reduce__", PyCData_reduce, METH_NOARGS, },
        2868                 :            :     { "__setstate__", PyCData_setstate, METH_VARARGS, },
        2869                 :            :     { NULL, NULL },
        2870                 :            : };
        2871                 :            :
        2872                 :            : PyTypeObject PyCData_Type = {
        2873                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        2874                 :            :     "_ctypes._CData",
        2875                 :            :     sizeof(CDataObject),                        /* tp_basicsize */
        2876                 :            :     0,                                          /* tp_itemsize */
        2877                 :            :     PyCData_dealloc,                                    /* tp_dealloc */
        2878                 :            :     0,                                          /* tp_vectorcall_offset */
        2879                 :            :     0,                                          /* tp_getattr */
        2880                 :            :     0,                                          /* tp_setattr */
        2881                 :            :     0,                                          /* tp_as_async */
        2882                 :            :     0,                                          /* tp_repr */
        2883                 :            :     0,                                          /* tp_as_number */
        2884                 :            :     0,                                          /* tp_as_sequence */
        2885                 :            :     0,                                          /* tp_as_mapping */
        2886                 :            :     PyCData_nohash,                             /* tp_hash */
        2887                 :            :     0,                                          /* tp_call */
        2888                 :            :     0,                                          /* tp_str */
        2889                 :            :     0,                                          /* tp_getattro */
        2890                 :            :     0,                                          /* tp_setattro */
        2891                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        2892                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        2893                 :            :     PyDoc_STR("XXX to be provided"),            /* tp_doc */
        2894                 :            :     (traverseproc)PyCData_traverse,             /* tp_traverse */
        2895                 :            :     (inquiry)PyCData_clear,                     /* tp_clear */
        2896                 :            :     0,                                          /* tp_richcompare */
        2897                 :            :     0,                                          /* tp_weaklistoffset */
        2898                 :            :     0,                                          /* tp_iter */
        2899                 :            :     0,                                          /* tp_iternext */
        2900                 :            :     PyCData_methods,                                    /* tp_methods */
        2901                 :            :     PyCData_members,                                    /* tp_members */
        2902                 :            :     0,                                          /* tp_getset */
        2903                 :            :     0,                                          /* tp_base */
        2904                 :            :     0,                                          /* tp_dict */
        2905                 :            :     0,                                          /* tp_descr_get */
        2906                 :            :     0,                                          /* tp_descr_set */
        2907                 :            :     0,                                          /* tp_dictoffset */
        2908                 :            :     0,                                          /* tp_init */
        2909                 :            :     0,                                          /* tp_alloc */
        2910                 :            :     0,                                          /* tp_new */
        2911                 :            :     0,                                          /* tp_free */
        2912                 :            : };
        2913                 :            :
        2914                 :          5 : static int PyCData_MallocBuffer(CDataObject *obj, StgDictObject *dict)
        2915                 :            : {
        2916         [ +  - ]:          5 :     if ((size_t)dict->size <= sizeof(obj->b_value)) {
        2917                 :            :         /* No need to call malloc, can use the default buffer */
        2918                 :          5 :         obj->b_ptr = (char *)&obj->b_value;
        2919                 :            :         /* The b_needsfree flag does not mean that we actually did
        2920                 :            :            call PyMem_Malloc to allocate the memory block; instead it
        2921                 :            :            means we are the *owner* of the memory and are responsible
        2922                 :            :            for freeing resources associated with the memory.  This is
        2923                 :            :            also the reason that b_needsfree is exposed to Python.
        2924                 :            :          */
        2925                 :          5 :         obj->b_needsfree = 1;
        2926                 :            :     } else {
        2927                 :            :         /* In python 2.4, and ctypes 0.9.6, the malloc call took about
        2928                 :            :            33% of the creation time for c_int().
        2929                 :            :         */
        2930                 :          0 :         obj->b_ptr = (char *)PyMem_Malloc(dict->size);
        2931         [ #  # ]:          0 :         if (obj->b_ptr == NULL) {
        2932                 :          0 :             PyErr_NoMemory();
        2933                 :          0 :             return -1;
        2934                 :            :         }
        2935                 :          0 :         obj->b_needsfree = 1;
        2936                 :          0 :         memset(obj->b_ptr, 0, dict->size);
        2937                 :            :     }
        2938                 :          5 :     obj->b_size = dict->size;
        2939                 :          5 :     return 0;
        2940                 :            : }
        2941                 :            :
        2942                 :            : PyObject *
        2943                 :          0 : PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr)
        2944                 :            : {
        2945                 :            :     CDataObject *cmem;
        2946                 :            :     StgDictObject *dict;
        2947                 :            :
        2948                 :            :     assert(PyType_Check(type));
        2949                 :          0 :     dict = PyType_stgdict(type);
        2950         [ #  # ]:          0 :     if (!dict) {
        2951                 :          0 :         PyErr_SetString(PyExc_TypeError,
        2952                 :            :                         "abstract class");
        2953                 :          0 :         return NULL;
        2954                 :            :     }
        2955                 :          0 :     dict->flags |= DICTFLAG_FINAL;
        2956                 :          0 :     cmem = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
        2957         [ #  # ]:          0 :     if (cmem == NULL)
        2958                 :          0 :         return NULL;
        2959                 :            :     assert(CDataObject_Check(cmem));
        2960                 :            :
        2961                 :          0 :     cmem->b_length = dict->length;
        2962                 :          0 :     cmem->b_size = dict->size;
        2963         [ #  # ]:          0 :     if (base) { /* use base's buffer */
        2964                 :            :         assert(CDataObject_Check(base));
        2965                 :          0 :         cmem->b_ptr = adr;
        2966                 :          0 :         cmem->b_needsfree = 0;
        2967                 :          0 :         cmem->b_base = (CDataObject *)Py_NewRef(base);
        2968                 :          0 :         cmem->b_index = index;
        2969                 :            :     } else { /* copy contents of adr */
        2970         [ #  # ]:          0 :         if (-1 == PyCData_MallocBuffer(cmem, dict)) {
        2971                 :          0 :             Py_DECREF(cmem);
        2972                 :          0 :             return NULL;
        2973                 :            :         }
        2974                 :          0 :         memcpy(cmem->b_ptr, adr, dict->size);
        2975                 :          0 :         cmem->b_index = index;
        2976                 :            :     }
        2977                 :          0 :     return (PyObject *)cmem;
        2978                 :            : }
        2979                 :            :
        2980                 :            : /*
        2981                 :            :  Box a memory block into a CData instance.
        2982                 :            : */
        2983                 :            : PyObject *
        2984                 :          0 : PyCData_AtAddress(PyObject *type, void *buf)
        2985                 :            : {
        2986                 :            :     CDataObject *pd;
        2987                 :            :     StgDictObject *dict;
        2988                 :            :
        2989         [ #  # ]:          0 :     if (PySys_Audit("ctypes.cdata", "n", (Py_ssize_t)buf) < 0) {
        2990                 :          0 :         return NULL;
        2991                 :            :     }
        2992                 :            :
        2993                 :            :     assert(PyType_Check(type));
        2994                 :          0 :     dict = PyType_stgdict(type);
        2995         [ #  # ]:          0 :     if (!dict) {
        2996                 :          0 :         PyErr_SetString(PyExc_TypeError,
        2997                 :            :                         "abstract class");
        2998                 :          0 :         return NULL;
        2999                 :            :     }
        3000                 :          0 :     dict->flags |= DICTFLAG_FINAL;
        3001                 :            :
        3002                 :          0 :     pd = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
        3003         [ #  # ]:          0 :     if (!pd)
        3004                 :          0 :         return NULL;
        3005                 :            :     assert(CDataObject_Check(pd));
        3006                 :          0 :     pd->b_ptr = (char *)buf;
        3007                 :          0 :     pd->b_length = dict->length;
        3008                 :          0 :     pd->b_size = dict->size;
        3009                 :          0 :     return (PyObject *)pd;
        3010                 :            : }
        3011                 :            :
        3012                 :            : /*
        3013                 :            :   This function returns TRUE for c_int, c_void_p, and these kind of
        3014                 :            :   classes.  FALSE otherwise FALSE also for subclasses of c_int and
        3015                 :            :   such.
        3016                 :            : */
        3017                 :          0 : int _ctypes_simple_instance(PyObject *obj)
        3018                 :            : {
        3019                 :          0 :     PyTypeObject *type = (PyTypeObject *)obj;
        3020                 :            :
        3021         [ #  # ]:          0 :     if (PyCSimpleTypeObject_Check(type))
        3022                 :          0 :         return type->tp_base != &Simple_Type;
        3023                 :          0 :     return 0;
        3024                 :            : }
        3025                 :            :
        3026                 :            : PyObject *
        3027                 :          0 : PyCData_get(PyObject *type, GETFUNC getfunc, PyObject *src,
        3028                 :            :           Py_ssize_t index, Py_ssize_t size, char *adr)
        3029                 :            : {
        3030                 :            :     StgDictObject *dict;
        3031         [ #  # ]:          0 :     if (getfunc)
        3032                 :          0 :         return getfunc(adr, size);
        3033                 :            :     assert(type);
        3034                 :          0 :     dict = PyType_stgdict(type);
        3035   [ #  #  #  #  :          0 :     if (dict && dict->getfunc && !_ctypes_simple_instance(type))
                       #  # ]
        3036                 :          0 :         return dict->getfunc(adr, size);
        3037                 :          0 :     return PyCData_FromBaseObj(type, src, index, adr);
        3038                 :            : }
        3039                 :            :
        3040                 :            : /*
        3041                 :            :   Helper function for PyCData_set below.
        3042                 :            : */
        3043                 :            : static PyObject *
        3044                 :          0 : _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
        3045                 :            :            Py_ssize_t size, char *ptr)
        3046                 :            : {
        3047                 :            :     CDataObject *src;
        3048                 :            :     int err;
        3049                 :            :
        3050         [ #  # ]:          0 :     if (setfunc)
        3051                 :          0 :         return setfunc(ptr, value, size);
        3052                 :            :
        3053         [ #  # ]:          0 :     if (!CDataObject_Check(value)) {
        3054                 :          0 :         StgDictObject *dict = PyType_stgdict(type);
        3055   [ #  #  #  # ]:          0 :         if (dict && dict->setfunc)
        3056                 :          0 :             return dict->setfunc(ptr, value, size);
        3057                 :            :         /*
        3058                 :            :            If value is a tuple, we try to call the type with the tuple
        3059                 :            :            and use the result!
        3060                 :            :         */
        3061                 :            :         assert(PyType_Check(type));
        3062         [ #  # ]:          0 :         if (PyTuple_Check(value)) {
        3063                 :            :             PyObject *ob;
        3064                 :            :             PyObject *result;
        3065                 :          0 :             ob = PyObject_CallObject(type, value);
        3066         [ #  # ]:          0 :             if (ob == NULL) {
        3067                 :          0 :                 _ctypes_extend_error(PyExc_RuntimeError, "(%s) ",
        3068                 :            :                                   ((PyTypeObject *)type)->tp_name);
        3069                 :          0 :                 return NULL;
        3070                 :            :             }
        3071                 :          0 :             result = _PyCData_set(dst, type, setfunc, ob,
        3072                 :            :                                 size, ptr);
        3073                 :          0 :             Py_DECREF(ob);
        3074                 :          0 :             return result;
        3075   [ #  #  #  # ]:          0 :         } else if (value == Py_None && PyCPointerTypeObject_Check(type)) {
        3076                 :          0 :             *(void **)ptr = NULL;
        3077                 :          0 :             Py_RETURN_NONE;
        3078                 :            :         } else {
        3079                 :          0 :             PyErr_Format(PyExc_TypeError,
        3080                 :            :                          "expected %s instance, got %s",
        3081                 :            :                          ((PyTypeObject *)type)->tp_name,
        3082                 :          0 :                          Py_TYPE(value)->tp_name);
        3083                 :          0 :             return NULL;
        3084                 :            :         }
        3085                 :            :     }
        3086                 :          0 :     src = (CDataObject *)value;
        3087                 :            :
        3088                 :          0 :     err = PyObject_IsInstance(value, type);
        3089         [ #  # ]:          0 :     if (err == -1)
        3090                 :          0 :         return NULL;
        3091         [ #  # ]:          0 :     if (err) {
        3092                 :          0 :         memcpy(ptr,
        3093                 :          0 :                src->b_ptr,
        3094                 :            :                size);
        3095                 :            :
        3096                 :          0 :         if (PyCPointerTypeObject_Check(type)) {
        3097                 :            :             /* XXX */
        3098                 :            :         }
        3099                 :            :
        3100                 :          0 :         value = GetKeepedObjects(src);
        3101         [ #  # ]:          0 :         if (value == NULL)
        3102                 :          0 :             return NULL;
        3103                 :            :
        3104                 :          0 :         return Py_NewRef(value);
        3105                 :            :     }
        3106                 :            :
        3107         [ #  # ]:          0 :     if (PyCPointerTypeObject_Check(type)
        3108         [ #  # ]:          0 :         && ArrayObject_Check(value)) {
        3109                 :            :         StgDictObject *p1, *p2;
        3110                 :            :         PyObject *keep;
        3111                 :          0 :         p1 = PyObject_stgdict(value);
        3112                 :            :         assert(p1); /* Cannot be NULL for array instances */
        3113                 :          0 :         p2 = PyType_stgdict(type);
        3114                 :            :         assert(p2); /* Cannot be NULL for pointer types */
        3115                 :            :
        3116         [ #  # ]:          0 :         if (p1->proto != p2->proto) {
        3117                 :          0 :             PyErr_Format(PyExc_TypeError,
        3118                 :            :                          "incompatible types, %s instance instead of %s instance",
        3119                 :          0 :                          Py_TYPE(value)->tp_name,
        3120                 :            :                          ((PyTypeObject *)type)->tp_name);
        3121                 :          0 :             return NULL;
        3122                 :            :         }
        3123                 :          0 :         *(void **)ptr = src->b_ptr;
        3124                 :            :
        3125                 :          0 :         keep = GetKeepedObjects(src);
        3126         [ #  # ]:          0 :         if (keep == NULL)
        3127                 :          0 :             return NULL;
        3128                 :            :
        3129                 :            :         /*
        3130                 :            :           We are assigning an array object to a field which represents
        3131                 :            :           a pointer. This has the same effect as converting an array
        3132                 :            :           into a pointer. So, again, we have to keep the whole object
        3133                 :            :           pointed to (which is the array in this case) alive, and not
        3134                 :            :           only it's object list.  So we create a tuple, containing
        3135                 :            :           b_objects list PLUS the array itself, and return that!
        3136                 :            :         */
        3137                 :          0 :         return PyTuple_Pack(2, keep, value);
        3138                 :            :     }
        3139                 :          0 :     PyErr_Format(PyExc_TypeError,
        3140                 :            :                  "incompatible types, %s instance instead of %s instance",
        3141                 :          0 :                  Py_TYPE(value)->tp_name,
        3142                 :            :                  ((PyTypeObject *)type)->tp_name);
        3143                 :          0 :     return NULL;
        3144                 :            : }
        3145                 :            :
        3146                 :            : /*
        3147                 :            :  * Set a slice in object 'dst', which has the type 'type',
        3148                 :            :  * to the value 'value'.
        3149                 :            :  */
        3150                 :            : int
        3151                 :          0 : PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
        3152                 :            :           Py_ssize_t index, Py_ssize_t size, char *ptr)
        3153                 :            : {
        3154                 :          0 :     CDataObject *mem = (CDataObject *)dst;
        3155                 :            :     PyObject *result;
        3156                 :            :
        3157         [ #  # ]:          0 :     if (!CDataObject_Check(dst)) {
        3158                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3159                 :            :                         "not a ctype instance");
        3160                 :          0 :         return -1;
        3161                 :            :     }
        3162                 :            :
        3163                 :          0 :     result = _PyCData_set(mem, type, setfunc, value,
        3164                 :            :                         size, ptr);
        3165         [ #  # ]:          0 :     if (result == NULL)
        3166                 :          0 :         return -1;
        3167                 :            :
        3168                 :            :     /* KeepRef steals a refcount from it's last argument */
        3169                 :            :     /* If KeepRef fails, we are stumped.  The dst memory block has already
        3170                 :            :        been changed */
        3171                 :          0 :     return KeepRef(mem, index, result);
        3172                 :            : }
        3173                 :            :
        3174                 :            :
        3175                 :            : /******************************************************************/
        3176                 :            : static PyObject *
        3177                 :          5 : GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        3178                 :            : {
        3179                 :            :     CDataObject *obj;
        3180                 :            :     StgDictObject *dict;
        3181                 :            :
        3182                 :          5 :     dict = PyType_stgdict((PyObject *)type);
        3183         [ -  + ]:          5 :     if (!dict) {
        3184                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3185                 :            :                         "abstract class");
        3186                 :          0 :         return NULL;
        3187                 :            :     }
        3188                 :          5 :     dict->flags |= DICTFLAG_FINAL;
        3189                 :            :
        3190                 :          5 :     obj = (CDataObject *)type->tp_alloc(type, 0);
        3191         [ -  + ]:          5 :     if (!obj)
        3192                 :          0 :         return NULL;
        3193                 :            :
        3194                 :          5 :     obj->b_base = NULL;
        3195                 :          5 :     obj->b_index = 0;
        3196                 :          5 :     obj->b_objects = NULL;
        3197                 :          5 :     obj->b_length = dict->length;
        3198                 :            :
        3199         [ -  + ]:          5 :     if (-1 == PyCData_MallocBuffer(obj, dict)) {
        3200                 :          0 :         Py_DECREF(obj);
        3201                 :          0 :         return NULL;
        3202                 :            :     }
        3203                 :          5 :     return (PyObject *)obj;
        3204                 :            : }
        3205                 :            : /*****************************************************************/
        3206                 :            : /*
        3207                 :            :   PyCFuncPtr_Type
        3208                 :            : */
        3209                 :            :
        3210                 :            : static int
        3211                 :          0 : PyCFuncPtr_set_errcheck(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored))
        3212                 :            : {
        3213   [ #  #  #  # ]:          0 :     if (ob && !PyCallable_Check(ob)) {
        3214                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3215                 :            :                         "the errcheck attribute must be callable");
        3216                 :          0 :         return -1;
        3217                 :            :     }
        3218                 :          0 :     Py_XINCREF(ob);
        3219                 :          0 :     Py_XSETREF(self->errcheck, ob);
        3220                 :          0 :     return 0;
        3221                 :            : }
        3222                 :            :
        3223                 :            : static PyObject *
        3224                 :          0 : PyCFuncPtr_get_errcheck(PyCFuncPtrObject *self, void *Py_UNUSED(ignored))
        3225                 :            : {
        3226         [ #  # ]:          0 :     if (self->errcheck) {
        3227                 :          0 :         return Py_NewRef(self->errcheck);
        3228                 :            :     }
        3229                 :          0 :     Py_RETURN_NONE;
        3230                 :            : }
        3231                 :            :
        3232                 :            : static int
        3233                 :          0 : PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored))
        3234                 :            : {
        3235                 :            :     PyObject *checker, *oldchecker;
        3236         [ #  # ]:          0 :     if (ob == NULL) {
        3237                 :          0 :         oldchecker = self->checker;
        3238                 :          0 :         self->checker = NULL;
        3239         [ #  # ]:          0 :         Py_CLEAR(self->restype);
        3240                 :          0 :         Py_XDECREF(oldchecker);
        3241                 :          0 :         return 0;
        3242                 :            :     }
        3243   [ #  #  #  #  :          0 :     if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) {
                       #  # ]
        3244                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3245                 :            :                         "restype must be a type, a callable, or None");
        3246                 :          0 :         return -1;
        3247                 :            :     }
        3248         [ #  # ]:          0 :     if (_PyObject_LookupAttr(ob, &_Py_ID(_check_retval_), &checker) < 0) {
        3249                 :          0 :         return -1;
        3250                 :            :     }
        3251                 :          0 :     oldchecker = self->checker;
        3252                 :          0 :     self->checker = checker;
        3253                 :          0 :     Py_INCREF(ob);
        3254                 :          0 :     Py_XSETREF(self->restype, ob);
        3255                 :          0 :     Py_XDECREF(oldchecker);
        3256                 :          0 :     return 0;
        3257                 :            : }
        3258                 :            :
        3259                 :            : static PyObject *
        3260                 :          0 : PyCFuncPtr_get_restype(PyCFuncPtrObject *self, void *Py_UNUSED(ignored))
        3261                 :            : {
        3262                 :            :     StgDictObject *dict;
        3263         [ #  # ]:          0 :     if (self->restype) {
        3264                 :          0 :         return Py_NewRef(self->restype);
        3265                 :            :     }
        3266                 :          0 :     dict = PyObject_stgdict((PyObject *)self);
        3267                 :            :     assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
        3268         [ #  # ]:          0 :     if (dict->restype) {
        3269                 :          0 :         return Py_NewRef(dict->restype);
        3270                 :            :     } else {
        3271                 :          0 :         Py_RETURN_NONE;
        3272                 :            :     }
        3273                 :            : }
        3274                 :            :
        3275                 :            : static int
        3276                 :          0 : PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored))
        3277                 :            : {
        3278                 :            :     PyObject *converters;
        3279                 :            :
        3280   [ #  #  #  # ]:          0 :     if (ob == NULL || ob == Py_None) {
        3281         [ #  # ]:          0 :         Py_CLEAR(self->converters);
        3282         [ #  # ]:          0 :         Py_CLEAR(self->argtypes);
        3283                 :            :     } else {
        3284                 :          0 :         converters = converters_from_argtypes(ob);
        3285         [ #  # ]:          0 :         if (!converters)
        3286                 :          0 :             return -1;
        3287                 :          0 :         Py_XSETREF(self->converters, converters);
        3288                 :          0 :         Py_INCREF(ob);
        3289                 :          0 :         Py_XSETREF(self->argtypes, ob);
        3290                 :            :     }
        3291                 :          0 :     return 0;
        3292                 :            : }
        3293                 :            :
        3294                 :            : static PyObject *
        3295                 :          0 : PyCFuncPtr_get_argtypes(PyCFuncPtrObject *self, void *Py_UNUSED(ignored))
        3296                 :            : {
        3297                 :            :     StgDictObject *dict;
        3298         [ #  # ]:          0 :     if (self->argtypes) {
        3299                 :          0 :         return Py_NewRef(self->argtypes);
        3300                 :            :     }
        3301                 :          0 :     dict = PyObject_stgdict((PyObject *)self);
        3302                 :            :     assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
        3303         [ #  # ]:          0 :     if (dict->argtypes) {
        3304                 :          0 :         return Py_NewRef(dict->argtypes);
        3305                 :            :     } else {
        3306                 :          0 :         Py_RETURN_NONE;
        3307                 :            :     }
        3308                 :            : }
        3309                 :            :
        3310                 :            : static PyGetSetDef PyCFuncPtr_getsets[] = {
        3311                 :            :     { "errcheck", (getter)PyCFuncPtr_get_errcheck, (setter)PyCFuncPtr_set_errcheck,
        3312                 :            :       "a function to check for errors", NULL },
        3313                 :            :     { "restype", (getter)PyCFuncPtr_get_restype, (setter)PyCFuncPtr_set_restype,
        3314                 :            :       "specify the result type", NULL },
        3315                 :            :     { "argtypes", (getter)PyCFuncPtr_get_argtypes,
        3316                 :            :       (setter)PyCFuncPtr_set_argtypes,
        3317                 :            :       "specify the argument types", NULL },
        3318                 :            :     { NULL, NULL }
        3319                 :            : };
        3320                 :            :
        3321                 :            : #ifdef MS_WIN32
        3322                 :            : static PPROC FindAddress(void *handle, const char *name, PyObject *type)
        3323                 :            : {
        3324                 :            :     PPROC address;
        3325                 :            : #ifdef MS_WIN64
        3326                 :            :     /* win64 has no stdcall calling conv, so it should
        3327                 :            :        also not have the name mangling of it.
        3328                 :            :     */
        3329                 :            :     Py_BEGIN_ALLOW_THREADS
        3330                 :            :     address = (PPROC)GetProcAddress(handle, name);
        3331                 :            :     Py_END_ALLOW_THREADS
        3332                 :            :     return address;
        3333                 :            : #else
        3334                 :            :     char *mangled_name;
        3335                 :            :     int i;
        3336                 :            :     StgDictObject *dict;
        3337                 :            :
        3338                 :            :     Py_BEGIN_ALLOW_THREADS
        3339                 :            :     address = (PPROC)GetProcAddress(handle, name);
        3340                 :            :     Py_END_ALLOW_THREADS
        3341                 :            :     if (address)
        3342                 :            :         return address;
        3343                 :            :     if (((size_t)name & ~0xFFFF) == 0) {
        3344                 :            :         return NULL;
        3345                 :            :     }
        3346                 :            :
        3347                 :            :     dict = PyType_stgdict((PyObject *)type);
        3348                 :            :     /* It should not happen that dict is NULL, but better be safe */
        3349                 :            :     if (dict==NULL || dict->flags & FUNCFLAG_CDECL)
        3350                 :            :         return address;
        3351                 :            :
        3352                 :            :     /* for stdcall, try mangled names:
        3353                 :            :        funcname -> _funcname@<n>
        3354                 :            :        where n is 0, 4, 8, 12, ..., 128
        3355                 :            :      */
        3356                 :            :     mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
        3357                 :            :     if (!mangled_name)
        3358                 :            :         return NULL;
        3359                 :            :     for (i = 0; i < 32; ++i) {
        3360                 :            :         sprintf(mangled_name, "_%s@%d", name, i*4);
        3361                 :            :         Py_BEGIN_ALLOW_THREADS
        3362                 :            :         address = (PPROC)GetProcAddress(handle, mangled_name);
        3363                 :            :         Py_END_ALLOW_THREADS
        3364                 :            :         if (address)
        3365                 :            :             return address;
        3366                 :            :     }
        3367                 :            :     return NULL;
        3368                 :            : #endif
        3369                 :            : }
        3370                 :            : #endif
        3371                 :            :
        3372                 :            : /* Return 1 if usable, 0 else and exception set. */
        3373                 :            : static int
        3374                 :          0 : _check_outarg_type(PyObject *arg, Py_ssize_t index)
        3375                 :            : {
        3376                 :            :     StgDictObject *dict;
        3377                 :            :
        3378         [ #  # ]:          0 :     if (PyCPointerTypeObject_Check(arg))
        3379                 :          0 :         return 1;
        3380                 :            :
        3381         [ #  # ]:          0 :     if (PyCArrayTypeObject_Check(arg))
        3382                 :          0 :         return 1;
        3383                 :            :
        3384                 :          0 :     dict = PyType_stgdict(arg);
        3385         [ #  # ]:          0 :     if (dict
        3386                 :            :         /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
        3387         [ #  # ]:          0 :         && PyUnicode_Check(dict->proto)
        3388                 :            : /* We only allow c_void_p, c_char_p and c_wchar_p as a simple output parameter type */
        3389         [ #  # ]:          0 :         && (strchr("PzZ", PyUnicode_AsUTF8(dict->proto)[0]))) {
        3390                 :          0 :         return 1;
        3391                 :            :     }
        3392                 :            :
        3393         [ #  # ]:          0 :     PyErr_Format(PyExc_TypeError,
        3394                 :            :                  "'out' parameter %d must be a pointer type, not %s",
        3395                 :            :                  Py_SAFE_DOWNCAST(index, Py_ssize_t, int),
        3396                 :          0 :                  PyType_Check(arg) ?
        3397                 :            :                  ((PyTypeObject *)arg)->tp_name :
        3398                 :          0 :              Py_TYPE(arg)->tp_name);
        3399                 :          0 :     return 0;
        3400                 :            : }
        3401                 :            :
        3402                 :            : /* Returns 1 on success, 0 on error */
        3403                 :            : static int
        3404                 :          0 : _validate_paramflags(PyTypeObject *type, PyObject *paramflags)
        3405                 :            : {
        3406                 :            :     Py_ssize_t i, len;
        3407                 :            :     StgDictObject *dict;
        3408                 :            :     PyObject *argtypes;
        3409                 :            :
        3410                 :          0 :     dict = PyType_stgdict((PyObject *)type);
        3411         [ #  # ]:          0 :     if (!dict) {
        3412                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3413                 :            :                         "abstract class");
        3414                 :          0 :         return 0;
        3415                 :            :     }
        3416                 :          0 :     argtypes = dict->argtypes;
        3417                 :            :
        3418   [ #  #  #  # ]:          0 :     if (paramflags == NULL || dict->argtypes == NULL)
        3419                 :          0 :         return 1;
        3420                 :            :
        3421         [ #  # ]:          0 :     if (!PyTuple_Check(paramflags)) {
        3422                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3423                 :            :                         "paramflags must be a tuple or None");
        3424                 :          0 :         return 0;
        3425                 :            :     }
        3426                 :            :
        3427                 :          0 :     len = PyTuple_GET_SIZE(paramflags);
        3428         [ #  # ]:          0 :     if (len != PyTuple_GET_SIZE(dict->argtypes)) {
        3429                 :          0 :         PyErr_SetString(PyExc_ValueError,
        3430                 :            :                         "paramflags must have the same length as argtypes");
        3431                 :          0 :         return 0;
        3432                 :            :     }
        3433                 :            :
        3434         [ #  # ]:          0 :     for (i = 0; i < len; ++i) {
        3435                 :          0 :         PyObject *item = PyTuple_GET_ITEM(paramflags, i);
        3436                 :            :         int flag;
        3437                 :          0 :         PyObject *name = Py_None;
        3438                 :            :         PyObject *defval;
        3439                 :            :         PyObject *typ;
        3440         [ #  # ]:          0 :         if (!PyArg_ParseTuple(item, "i|OO", &flag, &name, &defval) ||
        3441   [ #  #  #  # ]:          0 :             !(name == Py_None || PyUnicode_Check(name)))
        3442                 :            :         {
        3443                 :          0 :             PyErr_SetString(PyExc_TypeError,
        3444                 :            :                    "paramflags must be a sequence of (int [,string [,value]]) tuples");
        3445                 :          0 :             return 0;
        3446                 :            :         }
        3447                 :          0 :         typ = PyTuple_GET_ITEM(argtypes, i);
        3448      [ #  #  # ]:          0 :         switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
        3449                 :          0 :         case 0:
        3450                 :            :         case PARAMFLAG_FIN:
        3451                 :            :         case PARAMFLAG_FIN | PARAMFLAG_FLCID:
        3452                 :            :         case PARAMFLAG_FIN | PARAMFLAG_FOUT:
        3453                 :          0 :             break;
        3454                 :          0 :         case PARAMFLAG_FOUT:
        3455         [ #  # ]:          0 :             if (!_check_outarg_type(typ, i+1))
        3456                 :          0 :                 return 0;
        3457                 :          0 :             break;
        3458                 :          0 :         default:
        3459                 :          0 :             PyErr_Format(PyExc_TypeError,
        3460                 :            :                          "paramflag value %d not supported",
        3461                 :            :                          flag);
        3462                 :          0 :             return 0;
        3463                 :            :         }
        3464                 :            :     }
        3465                 :          0 :     return 1;
        3466                 :            : }
        3467                 :            :
        3468                 :            : static int
        3469                 :          0 : _get_name(PyObject *obj, const char **pname)
        3470                 :            : {
        3471                 :            : #ifdef MS_WIN32
        3472                 :            :     if (PyLong_Check(obj)) {
        3473                 :            :         /* We have to use MAKEINTRESOURCEA for Windows CE.
        3474                 :            :            Works on Windows as well, of course.
        3475                 :            :         */
        3476                 :            :         *pname = MAKEINTRESOURCEA(PyLong_AsUnsignedLongMask(obj) & 0xFFFF);
        3477                 :            :         return 1;
        3478                 :            :     }
        3479                 :            : #endif
        3480         [ #  # ]:          0 :     if (PyBytes_Check(obj)) {
        3481                 :          0 :         *pname = PyBytes_AS_STRING(obj);
        3482                 :          0 :         return *pname ? 1 : 0;
        3483                 :            :     }
        3484         [ #  # ]:          0 :     if (PyUnicode_Check(obj)) {
        3485                 :          0 :         *pname = PyUnicode_AsUTF8(obj);
        3486                 :          0 :         return *pname ? 1 : 0;
        3487                 :            :     }
        3488                 :          0 :     PyErr_SetString(PyExc_TypeError,
        3489                 :            :                     "function name must be string, bytes object or integer");
        3490                 :          0 :     return 0;
        3491                 :            : }
        3492                 :            :
        3493                 :            :
        3494                 :            : static PyObject *
        3495                 :          0 : PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
        3496                 :            : {
        3497                 :            :     const char *name;
        3498                 :            :     int (* address)(void);
        3499                 :            :     PyObject *ftuple;
        3500                 :            :     PyObject *dll;
        3501                 :            :     PyObject *obj;
        3502                 :            :     PyCFuncPtrObject *self;
        3503                 :            :     void *handle;
        3504                 :          0 :     PyObject *paramflags = NULL;
        3505                 :            :
        3506         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O|O", &ftuple, &paramflags))
        3507                 :          0 :         return NULL;
        3508         [ #  # ]:          0 :     if (paramflags == Py_None)
        3509                 :          0 :         paramflags = NULL;
        3510                 :            :
        3511                 :          0 :     ftuple = PySequence_Tuple(ftuple);
        3512         [ #  # ]:          0 :     if (!ftuple)
        3513                 :            :         /* Here ftuple is a borrowed reference */
        3514                 :          0 :         return NULL;
        3515                 :            :
        3516         [ #  # ]:          0 :     if (!PyArg_ParseTuple(ftuple, "O&O;illegal func_spec argument",
        3517                 :            :                           _get_name, &name, &dll))
        3518                 :            :     {
        3519                 :          0 :         Py_DECREF(ftuple);
        3520                 :          0 :         return NULL;
        3521                 :            :     }
        3522                 :            :
        3523                 :            : #ifdef MS_WIN32
        3524                 :            :     if (PySys_Audit("ctypes.dlsym",
        3525                 :            :                     ((uintptr_t)name & ~0xFFFF) ? "Os" : "On",
        3526                 :            :                     dll, name) < 0) {
        3527                 :            :         Py_DECREF(ftuple);
        3528                 :            :         return NULL;
        3529                 :            :     }
        3530                 :            : #else
        3531         [ #  # ]:          0 :     if (PySys_Audit("ctypes.dlsym", "Os", dll, name) < 0) {
        3532                 :          0 :         Py_DECREF(ftuple);
        3533                 :          0 :         return NULL;
        3534                 :            :     }
        3535                 :            : #endif
        3536                 :            :
        3537                 :          0 :     obj = PyObject_GetAttrString(dll, "_handle");
        3538         [ #  # ]:          0 :     if (!obj) {
        3539                 :          0 :         Py_DECREF(ftuple);
        3540                 :          0 :         return NULL;
        3541                 :            :     }
        3542         [ #  # ]:          0 :     if (!PyLong_Check(obj)) {
        3543                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3544                 :            :                         "the _handle attribute of the second argument must be an integer");
        3545                 :          0 :         Py_DECREF(ftuple);
        3546                 :          0 :         Py_DECREF(obj);
        3547                 :          0 :         return NULL;
        3548                 :            :     }
        3549                 :          0 :     handle = (void *)PyLong_AsVoidPtr(obj);
        3550                 :          0 :     Py_DECREF(obj);
        3551         [ #  # ]:          0 :     if (PyErr_Occurred()) {
        3552                 :          0 :         PyErr_SetString(PyExc_ValueError,
        3553                 :            :                         "could not convert the _handle attribute to a pointer");
        3554                 :          0 :         Py_DECREF(ftuple);
        3555                 :          0 :         return NULL;
        3556                 :            :     }
        3557                 :            :
        3558                 :            : #ifdef MS_WIN32
        3559                 :            :     address = FindAddress(handle, name, (PyObject *)type);
        3560                 :            :     if (!address) {
        3561                 :            :         if (!IS_INTRESOURCE(name))
        3562                 :            :             PyErr_Format(PyExc_AttributeError,
        3563                 :            :                          "function '%s' not found",
        3564                 :            :                          name);
        3565                 :            :         else
        3566                 :            :             PyErr_Format(PyExc_AttributeError,
        3567                 :            :                          "function ordinal %d not found",
        3568                 :            :                          (WORD)(size_t)name);
        3569                 :            :         Py_DECREF(ftuple);
        3570                 :            :         return NULL;
        3571                 :            :     }
        3572                 :            : #else
        3573                 :          0 :     address = (PPROC)dlsym(handle, name);
        3574         [ #  # ]:          0 :     if (!address) {
        3575                 :            : #ifdef __CYGWIN__
        3576                 :            : /* dlerror() isn't very helpful on cygwin */
        3577                 :            :         PyErr_Format(PyExc_AttributeError,
        3578                 :            :                      "function '%s' not found",
        3579                 :            :                      name);
        3580                 :            : #else
        3581                 :          0 :         PyErr_SetString(PyExc_AttributeError, dlerror());
        3582                 :            : #endif
        3583                 :          0 :         Py_DECREF(ftuple);
        3584                 :          0 :         return NULL;
        3585                 :            :     }
        3586                 :            : #endif
        3587         [ #  # ]:          0 :     if (!_validate_paramflags(type, paramflags)) {
        3588                 :          0 :         Py_DECREF(ftuple);
        3589                 :          0 :         return NULL;
        3590                 :            :     }
        3591                 :            :
        3592                 :          0 :     self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
        3593         [ #  # ]:          0 :     if (!self) {
        3594                 :          0 :         Py_DECREF(ftuple);
        3595                 :          0 :         return NULL;
        3596                 :            :     }
        3597                 :            :
        3598                 :          0 :     self->paramflags = Py_XNewRef(paramflags);
        3599                 :            :
        3600                 :          0 :     *(void **)self->b_ptr = address;
        3601                 :          0 :     Py_INCREF(dll);
        3602                 :          0 :     Py_DECREF(ftuple);
        3603         [ #  # ]:          0 :     if (-1 == KeepRef((CDataObject *)self, 0, dll)) {
        3604                 :          0 :         Py_DECREF((PyObject *)self);
        3605                 :          0 :         return NULL;
        3606                 :            :     }
        3607                 :            :
        3608                 :          0 :     self->callable = Py_NewRef(self);
        3609                 :          0 :     return (PyObject *)self;
        3610                 :            : }
        3611                 :            :
        3612                 :            : #ifdef MS_WIN32
        3613                 :            : static PyObject *
        3614                 :            : PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
        3615                 :            : {
        3616                 :            :     PyCFuncPtrObject *self;
        3617                 :            :     int index;
        3618                 :            :     char *name = NULL;
        3619                 :            :     PyObject *paramflags = NULL;
        3620                 :            :     GUID *iid = NULL;
        3621                 :            :     Py_ssize_t iid_len = 0;
        3622                 :            :
        3623                 :            :     if (!PyArg_ParseTuple(args, "is|Oz#", &index, &name, &paramflags, &iid, &iid_len))
        3624                 :            :         return NULL;
        3625                 :            :     if (paramflags == Py_None)
        3626                 :            :         paramflags = NULL;
        3627                 :            :
        3628                 :            :     if (!_validate_paramflags(type, paramflags))
        3629                 :            :         return NULL;
        3630                 :            :
        3631                 :            :     self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
        3632                 :            :     self->index = index + 0x1000;
        3633                 :            :     self->paramflags = Py_XNewRef(paramflags);
        3634                 :            :     if (iid_len == sizeof(GUID))
        3635                 :            :         self->iid = iid;
        3636                 :            :     return (PyObject *)self;
        3637                 :            : }
        3638                 :            : #endif
        3639                 :            :
        3640                 :            : /*
        3641                 :            :   PyCFuncPtr_new accepts different argument lists in addition to the standard
        3642                 :            :   _basespec_ keyword arg:
        3643                 :            :
        3644                 :            :   one argument form
        3645                 :            :   "i" - function address
        3646                 :            :   "O" - must be a callable, creates a C callable function
        3647                 :            :
        3648                 :            :   two or more argument forms (the third argument is a paramflags tuple)
        3649                 :            :   "(sO)|..." - (function name, dll object (with an integer handle)), paramflags
        3650                 :            :   "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags
        3651                 :            :   "is|..." - vtable index, method name, creates callable calling COM vtbl
        3652                 :            : */
        3653                 :            : static PyObject *
        3654                 :          5 : PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        3655                 :            : {
        3656                 :            :     PyCFuncPtrObject *self;
        3657                 :            :     PyObject *callable;
        3658                 :            :     StgDictObject *dict;
        3659                 :            :     CThunkObject *thunk;
        3660                 :            :
        3661         [ -  + ]:          5 :     if (PyTuple_GET_SIZE(args) == 0)
        3662                 :          0 :         return GenericPyCData_new(type, args, kwds);
        3663                 :            :
        3664   [ +  -  -  + ]:          5 :     if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0)))
        3665                 :          0 :         return PyCFuncPtr_FromDll(type, args, kwds);
        3666                 :            :
        3667                 :            : #ifdef MS_WIN32
        3668                 :            :     if (2 <= PyTuple_GET_SIZE(args) && PyLong_Check(PyTuple_GET_ITEM(args, 0)))
        3669                 :            :         return PyCFuncPtr_FromVtblIndex(type, args, kwds);
        3670                 :            : #endif
        3671                 :            :
        3672         [ +  - ]:          5 :     if (1 == PyTuple_GET_SIZE(args)
        3673         [ +  - ]:          5 :         && (PyLong_Check(PyTuple_GET_ITEM(args, 0)))) {
        3674                 :            :         CDataObject *ob;
        3675                 :          5 :         void *ptr = PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, 0));
        3676   [ -  +  -  - ]:          5 :         if (ptr == NULL && PyErr_Occurred())
        3677                 :          0 :             return NULL;
        3678                 :          5 :         ob = (CDataObject *)GenericPyCData_new(type, args, kwds);
        3679         [ -  + ]:          5 :         if (ob == NULL)
        3680                 :          0 :             return NULL;
        3681                 :          5 :         *(void **)ob->b_ptr = ptr;
        3682                 :          5 :         return (PyObject *)ob;
        3683                 :            :     }
        3684                 :            :
        3685         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O", &callable))
        3686                 :          0 :         return NULL;
        3687         [ #  # ]:          0 :     if (!PyCallable_Check(callable)) {
        3688                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3689                 :            :                         "argument must be callable or integer function address");
        3690                 :          0 :         return NULL;
        3691                 :            :     }
        3692                 :            :
        3693                 :            :     /* XXX XXX This would allow passing additional options.  For COM
        3694                 :            :        method *implementations*, we would probably want different
        3695                 :            :        behaviour than in 'normal' callback functions: return a HRESULT if
        3696                 :            :        an exception occurs in the callback, and print the traceback not
        3697                 :            :        only on the console, but also to OutputDebugString() or something
        3698                 :            :        like that.
        3699                 :            :     */
        3700                 :            : /*
        3701                 :            :     if (kwds && _PyDict_GetItemIdWithError(kwds, &PyId_options)) {
        3702                 :            :         ...
        3703                 :            :     }
        3704                 :            :     else if (PyErr_Occurred()) {
        3705                 :            :         return NULL;
        3706                 :            :     }
        3707                 :            : */
        3708                 :            :
        3709                 :          0 :     dict = PyType_stgdict((PyObject *)type);
        3710                 :            :     /* XXXX Fails if we do: 'PyCFuncPtr(lambda x: x)' */
        3711   [ #  #  #  # ]:          0 :     if (!dict || !dict->argtypes) {
        3712                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3713                 :            :                "cannot construct instance of this class:"
        3714                 :            :             " no argtypes");
        3715                 :          0 :         return NULL;
        3716                 :            :     }
        3717                 :            :
        3718                 :          0 :     thunk = _ctypes_alloc_callback(callable,
        3719                 :            :                                   dict->argtypes,
        3720                 :            :                                   dict->restype,
        3721                 :            :                                   dict->flags);
        3722         [ #  # ]:          0 :     if (!thunk)
        3723                 :          0 :         return NULL;
        3724                 :            :
        3725                 :          0 :     self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
        3726         [ #  # ]:          0 :     if (self == NULL) {
        3727                 :          0 :         Py_DECREF(thunk);
        3728                 :          0 :         return NULL;
        3729                 :            :     }
        3730                 :            :
        3731                 :          0 :     self->callable = Py_NewRef(callable);
        3732                 :            :
        3733                 :          0 :     self->thunk = thunk;
        3734                 :          0 :     *(void **)self->b_ptr = (void *)thunk->pcl_exec;
        3735                 :            :
        3736                 :          0 :     Py_INCREF((PyObject *)thunk); /* for KeepRef */
        3737         [ #  # ]:          0 :     if (-1 == KeepRef((CDataObject *)self, 0, (PyObject *)thunk)) {
        3738                 :          0 :         Py_DECREF((PyObject *)self);
        3739                 :          0 :         return NULL;
        3740                 :            :     }
        3741                 :          0 :     return (PyObject *)self;
        3742                 :            : }
        3743                 :            :
        3744                 :            :
        3745                 :            : /*
        3746                 :            :   _byref consumes a refcount to its argument
        3747                 :            : */
        3748                 :            : static PyObject *
        3749                 :          0 : _byref(PyObject *obj)
        3750                 :            : {
        3751                 :            :     PyCArgObject *parg;
        3752         [ #  # ]:          0 :     if (!CDataObject_Check(obj)) {
        3753                 :          0 :         PyErr_SetString(PyExc_TypeError,
        3754                 :            :                         "expected CData instance");
        3755                 :          0 :         return NULL;
        3756                 :            :     }
        3757                 :            :
        3758                 :          0 :     parg = PyCArgObject_new();
        3759         [ #  # ]:          0 :     if (parg == NULL) {
        3760                 :          0 :         Py_DECREF(obj);
        3761                 :          0 :         return NULL;
        3762                 :            :     }
        3763                 :            :
        3764                 :          0 :     parg->tag = 'P';
        3765                 :          0 :     parg->pffi_type = &ffi_type_pointer;
        3766                 :          0 :     parg->obj = obj;
        3767                 :          0 :     parg->value.p = ((CDataObject *)obj)->b_ptr;
        3768                 :          0 :     return (PyObject *)parg;
        3769                 :            : }
        3770                 :            :
        3771                 :            : static PyObject *
        3772                 :          0 : _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObject *kwds)
        3773                 :            : {
        3774                 :            :     PyObject *v;
        3775                 :            :
        3776         [ #  # ]:          0 :     if (*pindex < PyTuple_GET_SIZE(inargs)) {
        3777                 :          0 :         v = PyTuple_GET_ITEM(inargs, *pindex);
        3778                 :          0 :         ++*pindex;
        3779                 :          0 :         return Py_NewRef(v);
        3780                 :            :     }
        3781   [ #  #  #  # ]:          0 :     if (kwds && name) {
        3782                 :          0 :         v = PyDict_GetItemWithError(kwds, name);
        3783         [ #  # ]:          0 :         if (v) {
        3784                 :          0 :             ++*pindex;
        3785                 :          0 :             return Py_NewRef(v);
        3786                 :            :         }
        3787         [ #  # ]:          0 :         else if (PyErr_Occurred()) {
        3788                 :          0 :             return NULL;
        3789                 :            :         }
        3790                 :            :     }
        3791         [ #  # ]:          0 :     if (defval) {
        3792                 :          0 :         return Py_NewRef(defval);
        3793                 :            :     }
        3794                 :            :     /* we can't currently emit a better error message */
        3795         [ #  # ]:          0 :     if (name)
        3796                 :          0 :         PyErr_Format(PyExc_TypeError,
        3797                 :            :                      "required argument '%S' missing", name);
        3798                 :            :     else
        3799                 :          0 :         PyErr_Format(PyExc_TypeError,
        3800                 :            :                      "not enough arguments");
        3801                 :          0 :     return NULL;
        3802                 :            : }
        3803                 :            :
        3804                 :            : /*
        3805                 :            :  This function implements higher level functionality plus the ability to call
        3806                 :            :  functions with keyword arguments by looking at parameter flags.  parameter
        3807                 :            :  flags is a tuple of 1, 2 or 3-tuples.  The first entry in each is an integer
        3808                 :            :  specifying the direction of the data transfer for this parameter - 'in',
        3809                 :            :  'out' or 'inout' (zero means the same as 'in').  The second entry is the
        3810                 :            :  parameter name, and the third is the default value if the parameter is
        3811                 :            :  missing in the function call.
        3812                 :            :
        3813                 :            :  This function builds and returns a new tuple 'callargs' which contains the
        3814                 :            :  parameters to use in the call.  Items on this tuple are copied from the
        3815                 :            :  'inargs' tuple for 'in' and 'in, out' parameters, and constructed from the
        3816                 :            :  'argtypes' tuple for 'out' parameters.  It also calculates numretvals which
        3817                 :            :  is the number of return values for the function, outmask/inoutmask are
        3818                 :            :  bitmasks containing indexes into the callargs tuple specifying which
        3819                 :            :  parameters have to be returned.  _build_result builds the return value of the
        3820                 :            :  function.
        3821                 :            : */
        3822                 :            : static PyObject *
        3823                 :          0 : _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes,
        3824                 :            :                 PyObject *inargs, PyObject *kwds,
        3825                 :            :                 int *poutmask, int *pinoutmask, unsigned int *pnumretvals)
        3826                 :            : {
        3827                 :          0 :     PyObject *paramflags = self->paramflags;
        3828                 :            :     PyObject *callargs;
        3829                 :            :     StgDictObject *dict;
        3830                 :            :     Py_ssize_t i, len;
        3831                 :          0 :     int inargs_index = 0;
        3832                 :            :     /* It's a little bit difficult to determine how many arguments the
        3833                 :            :     function call requires/accepts.  For simplicity, we count the consumed
        3834                 :            :     args and compare this to the number of supplied args. */
        3835                 :            :     Py_ssize_t actual_args;
        3836                 :            :
        3837                 :          0 :     *poutmask = 0;
        3838                 :          0 :     *pinoutmask = 0;
        3839                 :          0 :     *pnumretvals = 0;
        3840                 :            :
        3841                 :            :     /* Trivial cases, where we either return inargs itself, or a slice of it. */
        3842   [ #  #  #  #  :          0 :     if (argtypes == NULL || paramflags == NULL || PyTuple_GET_SIZE(argtypes) == 0) {
                       #  # ]
        3843                 :            : #ifdef MS_WIN32
        3844                 :            :         if (self->index)
        3845                 :            :             return PyTuple_GetSlice(inargs, 1, PyTuple_GET_SIZE(inargs));
        3846                 :            : #endif
        3847                 :          0 :         return Py_NewRef(inargs);
        3848                 :            :     }
        3849                 :            :
        3850                 :          0 :     len = PyTuple_GET_SIZE(argtypes);
        3851                 :          0 :     callargs = PyTuple_New(len); /* the argument tuple we build */
        3852         [ #  # ]:          0 :     if (callargs == NULL)
        3853                 :          0 :         return NULL;
        3854                 :            :
        3855                 :            : #ifdef MS_WIN32
        3856                 :            :     /* For a COM method, skip the first arg */
        3857                 :            :     if (self->index) {
        3858                 :            :         inargs_index = 1;
        3859                 :            :     }
        3860                 :            : #endif
        3861         [ #  # ]:          0 :     for (i = 0; i < len; ++i) {
        3862                 :          0 :         PyObject *item = PyTuple_GET_ITEM(paramflags, i);
        3863                 :            :         PyObject *ob;
        3864                 :            :         unsigned int flag;
        3865                 :          0 :         PyObject *name = NULL;
        3866                 :          0 :         PyObject *defval = NULL;
        3867                 :            :
        3868                 :            :         /* This way seems to be ~2 us faster than the PyArg_ParseTuple
        3869                 :            :            calls below. */
        3870                 :            :         /* We HAVE already checked that the tuple can be parsed with "i|ZO", so... */
        3871                 :          0 :         Py_ssize_t tsize = PyTuple_GET_SIZE(item);
        3872                 :          0 :         flag = PyLong_AsUnsignedLongMask(PyTuple_GET_ITEM(item, 0));
        3873         [ #  # ]:          0 :         name = tsize > 1 ? PyTuple_GET_ITEM(item, 1) : NULL;
        3874         [ #  # ]:          0 :         defval = tsize > 2 ? PyTuple_GET_ITEM(item, 2) : NULL;
        3875                 :            :
        3876   [ #  #  #  #  :          0 :         switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
                          # ]
        3877                 :          0 :         case PARAMFLAG_FIN | PARAMFLAG_FLCID:
        3878                 :            :             /* ['in', 'lcid'] parameter.  Always taken from defval,
        3879                 :            :              if given, else the integer 0. */
        3880         [ #  # ]:          0 :             if (defval == NULL) {
        3881                 :          0 :                 defval = _PyLong_GetZero();
        3882                 :            :             }
        3883                 :          0 :             Py_INCREF(defval);
        3884                 :          0 :             PyTuple_SET_ITEM(callargs, i, defval);
        3885                 :          0 :             break;
        3886                 :          0 :         case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
        3887                 :          0 :             *pinoutmask |= (1 << i); /* mark as inout arg */
        3888                 :          0 :             (*pnumretvals)++;
        3889                 :            :             /* fall through */
        3890                 :          0 :         case 0:
        3891                 :            :         case PARAMFLAG_FIN:
        3892                 :            :             /* 'in' parameter.  Copy it from inargs. */
        3893                 :          0 :             ob =_get_arg(&inargs_index, name, defval, inargs, kwds);
        3894         [ #  # ]:          0 :             if (ob == NULL)
        3895                 :          0 :                 goto error;
        3896                 :          0 :             PyTuple_SET_ITEM(callargs, i, ob);
        3897                 :          0 :             break;
        3898                 :          0 :         case PARAMFLAG_FOUT:
        3899                 :            :             /* XXX Refactor this code into a separate function. */
        3900                 :            :             /* 'out' parameter.
        3901                 :            :                argtypes[i] must be a POINTER to a c type.
        3902                 :            :
        3903                 :            :                Cannot by supplied in inargs, but a defval will be used
        3904                 :            :                if available.  XXX Should we support getting it from kwds?
        3905                 :            :             */
        3906         [ #  # ]:          0 :             if (defval) {
        3907                 :            :                 /* XXX Using mutable objects as defval will
        3908                 :            :                    make the function non-threadsafe, unless we
        3909                 :            :                    copy the object in each invocation */
        3910                 :          0 :                 Py_INCREF(defval);
        3911                 :          0 :                 PyTuple_SET_ITEM(callargs, i, defval);
        3912                 :          0 :                 *poutmask |= (1 << i); /* mark as out arg */
        3913                 :          0 :                 (*pnumretvals)++;
        3914                 :          0 :                 break;
        3915                 :            :             }
        3916                 :          0 :             ob = PyTuple_GET_ITEM(argtypes, i);
        3917                 :          0 :             dict = PyType_stgdict(ob);
        3918         [ #  # ]:          0 :             if (dict == NULL) {
        3919                 :            :                 /* Cannot happen: _validate_paramflags()
        3920                 :            :                   would not accept such an object */
        3921                 :          0 :                 PyErr_Format(PyExc_RuntimeError,
        3922                 :            :                              "NULL stgdict unexpected");
        3923                 :          0 :                 goto error;
        3924                 :            :             }
        3925         [ #  # ]:          0 :             if (PyUnicode_Check(dict->proto)) {
        3926                 :          0 :                 PyErr_Format(
        3927                 :            :                     PyExc_TypeError,
        3928                 :            :                     "%s 'out' parameter must be passed as default value",
        3929                 :            :                     ((PyTypeObject *)ob)->tp_name);
        3930                 :          0 :                 goto error;
        3931                 :            :             }
        3932         [ #  # ]:          0 :             if (PyCArrayTypeObject_Check(ob))
        3933                 :          0 :                 ob = _PyObject_CallNoArgs(ob);
        3934                 :            :             else
        3935                 :            :                 /* Create an instance of the pointed-to type */
        3936                 :          0 :                 ob = _PyObject_CallNoArgs(dict->proto);
        3937                 :            :             /*
        3938                 :            :                XXX Is the following correct any longer?
        3939                 :            :                We must not pass a byref() to the array then but
        3940                 :            :                the array instance itself. Then, we cannot retrieve
        3941                 :            :                the result from the PyCArgObject.
        3942                 :            :             */
        3943         [ #  # ]:          0 :             if (ob == NULL)
        3944                 :          0 :                 goto error;
        3945                 :            :             /* The .from_param call that will occur later will pass this
        3946                 :            :                as a byref parameter. */
        3947                 :          0 :             PyTuple_SET_ITEM(callargs, i, ob);
        3948                 :          0 :             *poutmask |= (1 << i); /* mark as out arg */
        3949                 :          0 :             (*pnumretvals)++;
        3950                 :          0 :             break;
        3951                 :          0 :         default:
        3952                 :          0 :             PyErr_Format(PyExc_ValueError,
        3953                 :            :                          "paramflag %u not yet implemented", flag);
        3954                 :          0 :             goto error;
        3955                 :            :             break;
        3956                 :            :         }
        3957                 :            :     }
        3958                 :            :
        3959                 :            :     /* We have counted the arguments we have consumed in 'inargs_index'.  This
        3960                 :            :        must be the same as len(inargs) + len(kwds), otherwise we have
        3961                 :            :        either too much or not enough arguments. */
        3962                 :            :
        3963         [ #  # ]:          0 :     actual_args = PyTuple_GET_SIZE(inargs) + (kwds ? PyDict_GET_SIZE(kwds) : 0);
        3964         [ #  # ]:          0 :     if (actual_args != inargs_index) {
        3965                 :            :         /* When we have default values or named parameters, this error
        3966                 :            :            message is misleading.  See unittests/test_paramflags.py
        3967                 :            :          */
        3968                 :          0 :         PyErr_Format(PyExc_TypeError,
        3969                 :            :                      "call takes exactly %d arguments (%zd given)",
        3970                 :            :                      inargs_index, actual_args);
        3971                 :          0 :         goto error;
        3972                 :            :     }
        3973                 :            :
        3974                 :            :     /* outmask is a bitmask containing indexes into callargs.  Items at
        3975                 :            :        these indexes contain values to return.
        3976                 :            :      */
        3977                 :          0 :     return callargs;
        3978                 :          0 :   error:
        3979                 :          0 :     Py_DECREF(callargs);
        3980                 :          0 :     return NULL;
        3981                 :            : }
        3982                 :            :
        3983                 :            : /* See also:
        3984                 :            :    http://msdn.microsoft.com/library/en-us/com/html/769127a1-1a14-4ed4-9d38-7cf3e571b661.asp
        3985                 :            : */
        3986                 :            : /*
        3987                 :            :   Build return value of a function.
        3988                 :            :
        3989                 :            :   Consumes the refcount on result and callargs.
        3990                 :            : */
        3991                 :            : static PyObject *
        3992                 :          0 : _build_result(PyObject *result, PyObject *callargs,
        3993                 :            :               int outmask, int inoutmask, unsigned int numretvals)
        3994                 :            : {
        3995                 :            :     unsigned int i, index;
        3996                 :            :     int bit;
        3997                 :          0 :     PyObject *tup = NULL;
        3998                 :            :
        3999         [ #  # ]:          0 :     if (callargs == NULL)
        4000                 :          0 :         return result;
        4001   [ #  #  #  # ]:          0 :     if (result == NULL || numretvals == 0) {
        4002                 :          0 :         Py_DECREF(callargs);
        4003                 :          0 :         return result;
        4004                 :            :     }
        4005                 :          0 :     Py_DECREF(result);
        4006                 :            :
        4007                 :            :     /* tup will not be allocated if numretvals == 1 */
        4008                 :            :     /* allocate tuple to hold the result */
        4009         [ #  # ]:          0 :     if (numretvals > 1) {
        4010                 :          0 :         tup = PyTuple_New(numretvals);
        4011         [ #  # ]:          0 :         if (tup == NULL) {
        4012                 :          0 :             Py_DECREF(callargs);
        4013                 :          0 :             return NULL;
        4014                 :            :         }
        4015                 :            :     }
        4016                 :            :
        4017                 :          0 :     index = 0;
        4018         [ #  # ]:          0 :     for (bit = 1, i = 0; i < 32; ++i, bit <<= 1) {
        4019                 :            :         PyObject *v;
        4020         [ #  # ]:          0 :         if (bit & inoutmask) {
        4021                 :          0 :             v = PyTuple_GET_ITEM(callargs, i);
        4022                 :          0 :             Py_INCREF(v);
        4023         [ #  # ]:          0 :             if (numretvals == 1) {
        4024                 :          0 :                 Py_DECREF(callargs);
        4025                 :          0 :                 return v;
        4026                 :            :             }
        4027                 :          0 :             PyTuple_SET_ITEM(tup, index, v);
        4028                 :          0 :             index++;
        4029         [ #  # ]:          0 :         } else if (bit & outmask) {
        4030                 :            :
        4031                 :          0 :             v = PyTuple_GET_ITEM(callargs, i);
        4032                 :          0 :             v = PyObject_CallMethodNoArgs(v, &_Py_ID(__ctypes_from_outparam__));
        4033   [ #  #  #  # ]:          0 :             if (v == NULL || numretvals == 1) {
        4034                 :          0 :                 Py_DECREF(callargs);
        4035                 :          0 :                 return v;
        4036                 :            :             }
        4037                 :          0 :             PyTuple_SET_ITEM(tup, index, v);
        4038                 :          0 :             index++;
        4039                 :            :         }
        4040         [ #  # ]:          0 :         if (index == numretvals)
        4041                 :          0 :             break;
        4042                 :            :     }
        4043                 :            :
        4044                 :          0 :     Py_DECREF(callargs);
        4045                 :          0 :     return tup;
        4046                 :            : }
        4047                 :            :
        4048                 :            : static PyObject *
        4049                 :          0 : PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
        4050                 :            : {
        4051                 :            :     PyObject *restype;
        4052                 :            :     PyObject *converters;
        4053                 :            :     PyObject *checker;
        4054                 :            :     PyObject *argtypes;
        4055                 :          0 :     StgDictObject *dict = PyObject_stgdict((PyObject *)self);
        4056                 :            :     PyObject *result;
        4057                 :            :     PyObject *callargs;
        4058                 :            :     PyObject *errcheck;
        4059                 :            : #ifdef MS_WIN32
        4060                 :            :     IUnknown *piunk = NULL;
        4061                 :            : #endif
        4062                 :          0 :     void *pProc = NULL;
        4063                 :            :
        4064                 :            :     int inoutmask;
        4065                 :            :     int outmask;
        4066                 :            :     unsigned int numretvals;
        4067                 :            :
        4068                 :            :     assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
        4069         [ #  # ]:          0 :     restype = self->restype ? self->restype : dict->restype;
        4070         [ #  # ]:          0 :     converters = self->converters ? self->converters : dict->converters;
        4071         [ #  # ]:          0 :     checker = self->checker ? self->checker : dict->checker;
        4072         [ #  # ]:          0 :     argtypes = self->argtypes ? self->argtypes : dict->argtypes;
        4073                 :            : /* later, we probably want to have an errcheck field in stgdict */
        4074                 :          0 :     errcheck = self->errcheck /* ? self->errcheck : dict->errcheck */;
        4075                 :            :
        4076                 :            :
        4077                 :          0 :     pProc = *(void **)self->b_ptr;
        4078                 :            : #ifdef MS_WIN32
        4079                 :            :     if (self->index) {
        4080                 :            :         /* It's a COM method */
        4081                 :            :         CDataObject *this;
        4082                 :            :         this = (CDataObject *)PyTuple_GetItem(inargs, 0); /* borrowed ref! */
        4083                 :            :         if (!this) {
        4084                 :            :             PyErr_SetString(PyExc_ValueError,
        4085                 :            :                             "native com method call without 'this' parameter");
        4086                 :            :             return NULL;
        4087                 :            :         }
        4088                 :            :         if (!CDataObject_Check(this)) {
        4089                 :            :             PyErr_SetString(PyExc_TypeError,
        4090                 :            :                             "Expected a COM this pointer as first argument");
        4091                 :            :             return NULL;
        4092                 :            :         }
        4093                 :            :         /* there should be more checks? No, in Python */
        4094                 :            :         /* First arg is a pointer to an interface instance */
        4095                 :            :         if (!this->b_ptr || *(void **)this->b_ptr == NULL) {
        4096                 :            :             PyErr_SetString(PyExc_ValueError,
        4097                 :            :                             "NULL COM pointer access");
        4098                 :            :             return NULL;
        4099                 :            :         }
        4100                 :            :         piunk = *(IUnknown **)this->b_ptr;
        4101                 :            :         if (NULL == piunk->lpVtbl) {
        4102                 :            :             PyErr_SetString(PyExc_ValueError,
        4103                 :            :                             "COM method call without VTable");
        4104                 :            :             return NULL;
        4105                 :            :         }
        4106                 :            :         pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000];
        4107                 :            :     }
        4108                 :            : #endif
        4109                 :          0 :     callargs = _build_callargs(self, argtypes,
        4110                 :            :                                inargs, kwds,
        4111                 :            :                                &outmask, &inoutmask, &numretvals);
        4112         [ #  # ]:          0 :     if (callargs == NULL)
        4113                 :          0 :         return NULL;
        4114                 :            :
        4115         [ #  # ]:          0 :     if (converters) {
        4116                 :          0 :         int required = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(converters),
        4117                 :            :                                         Py_ssize_t, int);
        4118                 :          0 :         int actual = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(callargs),
        4119                 :            :                                       Py_ssize_t, int);
        4120                 :            :
        4121         [ #  # ]:          0 :         if ((dict->flags & FUNCFLAG_CDECL) == FUNCFLAG_CDECL) {
        4122                 :            :             /* For cdecl functions, we allow more actual arguments
        4123                 :            :                than the length of the argtypes tuple.
        4124                 :            :             */
        4125         [ #  # ]:          0 :             if (required > actual) {
        4126                 :          0 :                 Py_DECREF(callargs);
        4127         [ #  # ]:          0 :                 PyErr_Format(PyExc_TypeError,
        4128                 :            :               "this function takes at least %d argument%s (%d given)",
        4129                 :            :                                  required,
        4130                 :            :                                  required == 1 ? "" : "s",
        4131                 :            :                                  actual);
        4132                 :          0 :                 return NULL;
        4133                 :            :             }
        4134         [ #  # ]:          0 :         } else if (required != actual) {
        4135                 :          0 :             Py_DECREF(callargs);
        4136         [ #  # ]:          0 :             PyErr_Format(PyExc_TypeError,
        4137                 :            :                  "this function takes %d argument%s (%d given)",
        4138                 :            :                      required,
        4139                 :            :                      required == 1 ? "" : "s",
        4140                 :            :                      actual);
        4141                 :          0 :             return NULL;
        4142                 :            :         }
        4143                 :            :     }
        4144                 :            :
        4145                 :          0 :     result = _ctypes_callproc(pProc,
        4146                 :            :                        callargs,
        4147                 :            : #ifdef MS_WIN32
        4148                 :            :                        piunk,
        4149                 :            :                        self->iid,
        4150                 :            : #endif
        4151                 :            :                        dict->flags,
        4152                 :            :                        converters,
        4153                 :            :                        restype,
        4154                 :            :                        checker);
        4155                 :            : /* The 'errcheck' protocol */
        4156   [ #  #  #  # ]:          0 :     if (result != NULL && errcheck) {
        4157                 :          0 :         PyObject *v = PyObject_CallFunctionObjArgs(errcheck,
        4158                 :            :                                                    result,
        4159                 :            :                                                    self,
        4160                 :            :                                                    callargs,
        4161                 :            :                                                    NULL);
        4162                 :            :         /* If the errcheck function failed, return NULL.
        4163                 :            :            If the errcheck function returned callargs unchanged,
        4164                 :            :            continue normal processing.
        4165                 :            :            If the errcheck function returned something else,
        4166                 :            :            use that as result.
        4167                 :            :         */
        4168   [ #  #  #  # ]:          0 :         if (v == NULL || v != callargs) {
        4169                 :          0 :             Py_DECREF(result);
        4170                 :          0 :             Py_DECREF(callargs);
        4171                 :          0 :             return v;
        4172                 :            :         }
        4173                 :          0 :         Py_DECREF(v);
        4174                 :            :     }
        4175                 :            :
        4176                 :          0 :     return _build_result(result, callargs,
        4177                 :            :                          outmask, inoutmask, numretvals);
        4178                 :            : }
        4179                 :            :
        4180                 :            : static int
        4181                 :        180 : PyCFuncPtr_traverse(PyCFuncPtrObject *self, visitproc visit, void *arg)
        4182                 :            : {
        4183   [ -  +  -  - ]:        180 :     Py_VISIT(self->callable);
        4184   [ -  +  -  - ]:        180 :     Py_VISIT(self->restype);
        4185   [ -  +  -  - ]:        180 :     Py_VISIT(self->checker);
        4186   [ -  +  -  - ]:        180 :     Py_VISIT(self->errcheck);
        4187   [ -  +  -  - ]:        180 :     Py_VISIT(self->argtypes);
        4188   [ -  +  -  - ]:        180 :     Py_VISIT(self->converters);
        4189   [ -  +  -  - ]:        180 :     Py_VISIT(self->paramflags);
        4190   [ -  +  -  - ]:        180 :     Py_VISIT(self->thunk);
        4191                 :        180 :     return PyCData_traverse((CDataObject *)self, visit, arg);
        4192                 :            : }
        4193                 :            :
        4194                 :            : static int
        4195                 :          0 : PyCFuncPtr_clear(PyCFuncPtrObject *self)
        4196                 :            : {
        4197         [ #  # ]:          0 :     Py_CLEAR(self->callable);
        4198         [ #  # ]:          0 :     Py_CLEAR(self->restype);
        4199         [ #  # ]:          0 :     Py_CLEAR(self->checker);
        4200         [ #  # ]:          0 :     Py_CLEAR(self->errcheck);
        4201         [ #  # ]:          0 :     Py_CLEAR(self->argtypes);
        4202         [ #  # ]:          0 :     Py_CLEAR(self->converters);
        4203         [ #  # ]:          0 :     Py_CLEAR(self->paramflags);
        4204         [ #  # ]:          0 :     Py_CLEAR(self->thunk);
        4205                 :          0 :     return PyCData_clear((CDataObject *)self);
        4206                 :            : }
        4207                 :            :
        4208                 :            : static void
        4209                 :          0 : PyCFuncPtr_dealloc(PyCFuncPtrObject *self)
        4210                 :            : {
        4211                 :          0 :     PyCFuncPtr_clear(self);
        4212                 :          0 :     Py_TYPE(self)->tp_free((PyObject *)self);
        4213                 :          0 : }
        4214                 :            :
        4215                 :            : static PyObject *
        4216                 :          0 : PyCFuncPtr_repr(PyCFuncPtrObject *self)
        4217                 :            : {
        4218                 :            : #ifdef MS_WIN32
        4219                 :            :     if (self->index)
        4220                 :            :         return PyUnicode_FromFormat("<COM method offset %d: %s at %p>",
        4221                 :            :                                    self->index - 0x1000,
        4222                 :            :                                    Py_TYPE(self)->tp_name,
        4223                 :            :                                    self);
        4224                 :            : #endif
        4225                 :          0 :     return PyUnicode_FromFormat("<%s object at %p>",
        4226                 :          0 :                                Py_TYPE(self)->tp_name,
        4227                 :            :                                self);
        4228                 :            : }
        4229                 :            :
        4230                 :            : static int
        4231                 :          0 : PyCFuncPtr_bool(PyCFuncPtrObject *self)
        4232                 :            : {
        4233                 :          0 :     return ((*(void **)self->b_ptr != NULL)
        4234                 :            : #ifdef MS_WIN32
        4235                 :            :         || (self->index != 0)
        4236                 :            : #endif
        4237                 :            :         );
        4238                 :            : }
        4239                 :            :
        4240                 :            : static PyNumberMethods PyCFuncPtr_as_number = {
        4241                 :            :     0, /* nb_add */
        4242                 :            :     0, /* nb_subtract */
        4243                 :            :     0, /* nb_multiply */
        4244                 :            :     0, /* nb_remainder */
        4245                 :            :     0, /* nb_divmod */
        4246                 :            :     0, /* nb_power */
        4247                 :            :     0, /* nb_negative */
        4248                 :            :     0, /* nb_positive */
        4249                 :            :     0, /* nb_absolute */
        4250                 :            :     (inquiry)PyCFuncPtr_bool, /* nb_bool */
        4251                 :            : };
        4252                 :            :
        4253                 :            : PyTypeObject PyCFuncPtr_Type = {
        4254                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        4255                 :            :     "_ctypes.CFuncPtr",
        4256                 :            :     sizeof(PyCFuncPtrObject),                           /* tp_basicsize */
        4257                 :            :     0,                                          /* tp_itemsize */
        4258                 :            :     (destructor)PyCFuncPtr_dealloc,             /* tp_dealloc */
        4259                 :            :     0,                                          /* tp_vectorcall_offset */
        4260                 :            :     0,                                          /* tp_getattr */
        4261                 :            :     0,                                          /* tp_setattr */
        4262                 :            :     0,                                          /* tp_as_async */
        4263                 :            :     (reprfunc)PyCFuncPtr_repr,                  /* tp_repr */
        4264                 :            :     &PyCFuncPtr_as_number,                      /* tp_as_number */
        4265                 :            :     0,                                          /* tp_as_sequence */
        4266                 :            :     0,                                          /* tp_as_mapping */
        4267                 :            :     0,                                          /* tp_hash */
        4268                 :            :     (ternaryfunc)PyCFuncPtr_call,               /* tp_call */
        4269                 :            :     0,                                          /* tp_str */
        4270                 :            :     0,                                          /* tp_getattro */
        4271                 :            :     0,                                          /* tp_setattro */
        4272                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        4273                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        4274                 :            :     PyDoc_STR("Function Pointer"),              /* tp_doc */
        4275                 :            :     (traverseproc)PyCFuncPtr_traverse,          /* tp_traverse */
        4276                 :            :     (inquiry)PyCFuncPtr_clear,                  /* tp_clear */
        4277                 :            :     0,                                          /* tp_richcompare */
        4278                 :            :     0,                                          /* tp_weaklistoffset */
        4279                 :            :     0,                                          /* tp_iter */
        4280                 :            :     0,                                          /* tp_iternext */
        4281                 :            :     0,                                          /* tp_methods */
        4282                 :            :     0,                                          /* tp_members */
        4283                 :            :     PyCFuncPtr_getsets,                         /* tp_getset */
        4284                 :            :     0,                                          /* tp_base */
        4285                 :            :     0,                                          /* tp_dict */
        4286                 :            :     0,                                          /* tp_descr_get */
        4287                 :            :     0,                                          /* tp_descr_set */
        4288                 :            :     0,                                          /* tp_dictoffset */
        4289                 :            :     0,                                          /* tp_init */
        4290                 :            :     0,                                          /* tp_alloc */
        4291                 :            :     PyCFuncPtr_new,                             /* tp_new */
        4292                 :            :     0,                                          /* tp_free */
        4293                 :            : };
        4294                 :            :
        4295                 :            : /*****************************************************************/
        4296                 :            : /*
        4297                 :            :   Struct_Type
        4298                 :            : */
        4299                 :            : /*
        4300                 :            :   This function is called to initialize a Structure or Union with positional
        4301                 :            :   arguments. It calls itself recursively for all Structure or Union base
        4302                 :            :   classes, then retrieves the _fields_ member to associate the argument
        4303                 :            :   position with the correct field name.
        4304                 :            :
        4305                 :            :   Returns -1 on error, or the index of next argument on success.
        4306                 :            :  */
        4307                 :            : static Py_ssize_t
        4308                 :          0 : _init_pos_args(PyObject *self, PyTypeObject *type,
        4309                 :            :                PyObject *args, PyObject *kwds,
        4310                 :            :                Py_ssize_t index)
        4311                 :            : {
        4312                 :            :     StgDictObject *dict;
        4313                 :            :     PyObject *fields;
        4314                 :            :     Py_ssize_t i;
        4315                 :            :
        4316         [ #  # ]:          0 :     if (PyType_stgdict((PyObject *)type->tp_base)) {
        4317                 :          0 :         index = _init_pos_args(self, type->tp_base,
        4318                 :            :                                args, kwds,
        4319                 :            :                                index);
        4320         [ #  # ]:          0 :         if (index == -1)
        4321                 :          0 :             return -1;
        4322                 :            :     }
        4323                 :            :
        4324                 :          0 :     dict = PyType_stgdict((PyObject *)type);
        4325                 :          0 :     fields = PyDict_GetItemWithError((PyObject *)dict, &_Py_ID(_fields_));
        4326         [ #  # ]:          0 :     if (fields == NULL) {
        4327         [ #  # ]:          0 :         if (PyErr_Occurred()) {
        4328                 :          0 :             return -1;
        4329                 :            :         }
        4330                 :          0 :         return index;
        4331                 :            :     }
        4332                 :            :
        4333                 :          0 :     for (i = 0;
        4334   [ #  #  #  # ]:          0 :          i < dict->length && (i+index) < PyTuple_GET_SIZE(args);
        4335                 :          0 :          ++i) {
        4336                 :          0 :         PyObject *pair = PySequence_GetItem(fields, i);
        4337                 :            :         PyObject *name, *val;
        4338                 :            :         int res;
        4339         [ #  # ]:          0 :         if (!pair)
        4340                 :          0 :             return -1;
        4341                 :          0 :         name = PySequence_GetItem(pair, 0);
        4342         [ #  # ]:          0 :         if (!name) {
        4343                 :          0 :             Py_DECREF(pair);
        4344                 :          0 :             return -1;
        4345                 :            :         }
        4346                 :          0 :         val = PyTuple_GET_ITEM(args, i + index);
        4347         [ #  # ]:          0 :         if (kwds) {
        4348                 :          0 :             res = PyDict_Contains(kwds, name);
        4349         [ #  # ]:          0 :             if (res != 0) {
        4350         [ #  # ]:          0 :                 if (res > 0) {
        4351                 :          0 :                     PyErr_Format(PyExc_TypeError,
        4352                 :            :                                  "duplicate values for field %R",
        4353                 :            :                                  name);
        4354                 :            :                 }
        4355                 :          0 :                 Py_DECREF(pair);
        4356                 :          0 :                 Py_DECREF(name);
        4357                 :          0 :                 return -1;
        4358                 :            :             }
        4359                 :            :         }
        4360                 :            :
        4361                 :          0 :         res = PyObject_SetAttr(self, name, val);
        4362                 :          0 :         Py_DECREF(pair);
        4363                 :          0 :         Py_DECREF(name);
        4364         [ #  # ]:          0 :         if (res == -1)
        4365                 :          0 :             return -1;
        4366                 :            :     }
        4367                 :          0 :     return index + dict->length;
        4368                 :            : }
        4369                 :            :
        4370                 :            : static int
        4371                 :          0 : Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
        4372                 :            : {
        4373                 :            : /* Optimization possible: Store the attribute names _fields_[x][0]
        4374                 :            :  * in C accessible fields somewhere ?
        4375                 :            :  */
        4376         [ #  # ]:          0 :     if (!PyTuple_Check(args)) {
        4377                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4378                 :            :                         "args not a tuple?");
        4379                 :          0 :         return -1;
        4380                 :            :     }
        4381         [ #  # ]:          0 :     if (PyTuple_GET_SIZE(args)) {
        4382                 :          0 :         Py_ssize_t res = _init_pos_args(self, Py_TYPE(self),
        4383                 :            :                                         args, kwds, 0);
        4384         [ #  # ]:          0 :         if (res == -1)
        4385                 :          0 :             return -1;
        4386         [ #  # ]:          0 :         if (res < PyTuple_GET_SIZE(args)) {
        4387                 :          0 :             PyErr_SetString(PyExc_TypeError,
        4388                 :            :                             "too many initializers");
        4389                 :          0 :             return -1;
        4390                 :            :         }
        4391                 :            :     }
        4392                 :            :
        4393         [ #  # ]:          0 :     if (kwds) {
        4394                 :            :         PyObject *key, *value;
        4395                 :          0 :         Py_ssize_t pos = 0;
        4396         [ #  # ]:          0 :         while(PyDict_Next(kwds, &pos, &key, &value)) {
        4397         [ #  # ]:          0 :             if (-1 == PyObject_SetAttr(self, key, value))
        4398                 :          0 :                 return -1;
        4399                 :            :         }
        4400                 :            :     }
        4401                 :          0 :     return 0;
        4402                 :            : }
        4403                 :            :
        4404                 :            : static PyTypeObject Struct_Type = {
        4405                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        4406                 :            :     "_ctypes.Structure",
        4407                 :            :     sizeof(CDataObject),                        /* tp_basicsize */
        4408                 :            :     0,                                          /* tp_itemsize */
        4409                 :            :     0,                                          /* tp_dealloc */
        4410                 :            :     0,                                          /* tp_vectorcall_offset */
        4411                 :            :     0,                                          /* tp_getattr */
        4412                 :            :     0,                                          /* tp_setattr */
        4413                 :            :     0,                                          /* tp_as_async */
        4414                 :            :     0,                                          /* tp_repr */
        4415                 :            :     0,                                          /* tp_as_number */
        4416                 :            :     0,                                          /* tp_as_sequence */
        4417                 :            :     0,                                          /* tp_as_mapping */
        4418                 :            :     0,                                          /* tp_hash */
        4419                 :            :     0,                                          /* tp_call */
        4420                 :            :     0,                                          /* tp_str */
        4421                 :            :     0,                                          /* tp_getattro */
        4422                 :            :     0,                                          /* tp_setattro */
        4423                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        4424                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        4425                 :            :     PyDoc_STR("Structure base class"),          /* tp_doc */
        4426                 :            :     (traverseproc)PyCData_traverse,             /* tp_traverse */
        4427                 :            :     (inquiry)PyCData_clear,                     /* tp_clear */
        4428                 :            :     0,                                          /* tp_richcompare */
        4429                 :            :     0,                                          /* tp_weaklistoffset */
        4430                 :            :     0,                                          /* tp_iter */
        4431                 :            :     0,                                          /* tp_iternext */
        4432                 :            :     0,                                          /* tp_methods */
        4433                 :            :     0,                                          /* tp_members */
        4434                 :            :     0,                                          /* tp_getset */
        4435                 :            :     0,                                          /* tp_base */
        4436                 :            :     0,                                          /* tp_dict */
        4437                 :            :     0,                                          /* tp_descr_get */
        4438                 :            :     0,                                          /* tp_descr_set */
        4439                 :            :     0,                                          /* tp_dictoffset */
        4440                 :            :     Struct_init,                                /* tp_init */
        4441                 :            :     0,                                          /* tp_alloc */
        4442                 :            :     GenericPyCData_new,                         /* tp_new */
        4443                 :            :     0,                                          /* tp_free */
        4444                 :            : };
        4445                 :            :
        4446                 :            : static PyTypeObject Union_Type = {
        4447                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        4448                 :            :     "_ctypes.Union",
        4449                 :            :     sizeof(CDataObject),                        /* tp_basicsize */
        4450                 :            :     0,                                          /* tp_itemsize */
        4451                 :            :     0,                                          /* tp_dealloc */
        4452                 :            :     0,                                          /* tp_vectorcall_offset */
        4453                 :            :     0,                                          /* tp_getattr */
        4454                 :            :     0,                                          /* tp_setattr */
        4455                 :            :     0,                                          /* tp_as_async */
        4456                 :            :     0,                                          /* tp_repr */
        4457                 :            :     0,                                          /* tp_as_number */
        4458                 :            :     0,                                          /* tp_as_sequence */
        4459                 :            :     0,                                          /* tp_as_mapping */
        4460                 :            :     0,                                          /* tp_hash */
        4461                 :            :     0,                                          /* tp_call */
        4462                 :            :     0,                                          /* tp_str */
        4463                 :            :     0,                                          /* tp_getattro */
        4464                 :            :     0,                                          /* tp_setattro */
        4465                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        4466                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        4467                 :            :     PyDoc_STR("Union base class"),              /* tp_doc */
        4468                 :            :     (traverseproc)PyCData_traverse,             /* tp_traverse */
        4469                 :            :     (inquiry)PyCData_clear,                     /* tp_clear */
        4470                 :            :     0,                                          /* tp_richcompare */
        4471                 :            :     0,                                          /* tp_weaklistoffset */
        4472                 :            :     0,                                          /* tp_iter */
        4473                 :            :     0,                                          /* tp_iternext */
        4474                 :            :     0,                                          /* tp_methods */
        4475                 :            :     0,                                          /* tp_members */
        4476                 :            :     0,                                          /* tp_getset */
        4477                 :            :     0,                                          /* tp_base */
        4478                 :            :     0,                                          /* tp_dict */
        4479                 :            :     0,                                          /* tp_descr_get */
        4480                 :            :     0,                                          /* tp_descr_set */
        4481                 :            :     0,                                          /* tp_dictoffset */
        4482                 :            :     Struct_init,                                /* tp_init */
        4483                 :            :     0,                                          /* tp_alloc */
        4484                 :            :     GenericPyCData_new,                         /* tp_new */
        4485                 :            :     0,                                          /* tp_free */
        4486                 :            : };
        4487                 :            :
        4488                 :            :
        4489                 :            : /******************************************************************/
        4490                 :            : /*
        4491                 :            :   PyCArray_Type
        4492                 :            : */
        4493                 :            : static int
        4494                 :          0 : Array_init(CDataObject *self, PyObject *args, PyObject *kw)
        4495                 :            : {
        4496                 :            :     Py_ssize_t i;
        4497                 :            :     Py_ssize_t n;
        4498                 :            :
        4499         [ #  # ]:          0 :     if (!PyTuple_Check(args)) {
        4500                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4501                 :            :                         "args not a tuple?");
        4502                 :          0 :         return -1;
        4503                 :            :     }
        4504                 :          0 :     n = PyTuple_GET_SIZE(args);
        4505         [ #  # ]:          0 :     for (i = 0; i < n; ++i) {
        4506                 :            :         PyObject *v;
        4507                 :          0 :         v = PyTuple_GET_ITEM(args, i);
        4508         [ #  # ]:          0 :         if (-1 == PySequence_SetItem((PyObject *)self, i, v))
        4509                 :          0 :             return -1;
        4510                 :            :     }
        4511                 :          0 :     return 0;
        4512                 :            : }
        4513                 :            :
        4514                 :            : static PyObject *
        4515                 :          0 : Array_item(PyObject *myself, Py_ssize_t index)
        4516                 :            : {
        4517                 :          0 :     CDataObject *self = (CDataObject *)myself;
        4518                 :            :     Py_ssize_t offset, size;
        4519                 :            :     StgDictObject *stgdict;
        4520                 :            :
        4521                 :            :
        4522   [ #  #  #  # ]:          0 :     if (index < 0 || index >= self->b_length) {
        4523                 :          0 :         PyErr_SetString(PyExc_IndexError,
        4524                 :            :                         "invalid index");
        4525                 :          0 :         return NULL;
        4526                 :            :     }
        4527                 :            :
        4528                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
        4529                 :            :     assert(stgdict); /* Cannot be NULL for array instances */
        4530                 :            :     /* Would it be clearer if we got the item size from
        4531                 :            :        stgdict->proto's stgdict?
        4532                 :            :     */
        4533                 :          0 :     size = stgdict->size / stgdict->length;
        4534                 :          0 :     offset = index * size;
        4535                 :            :
        4536                 :          0 :     return PyCData_get(stgdict->proto, stgdict->getfunc, (PyObject *)self,
        4537                 :          0 :                      index, size, self->b_ptr + offset);
        4538                 :            : }
        4539                 :            :
        4540                 :            : static PyObject *
        4541                 :          0 : Array_subscript(PyObject *myself, PyObject *item)
        4542                 :            : {
        4543                 :          0 :     CDataObject *self = (CDataObject *)myself;
        4544                 :            :
        4545         [ #  # ]:          0 :     if (PyIndex_Check(item)) {
        4546                 :          0 :         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
        4547                 :            :
        4548   [ #  #  #  # ]:          0 :         if (i == -1 && PyErr_Occurred())
        4549                 :          0 :             return NULL;
        4550         [ #  # ]:          0 :         if (i < 0)
        4551                 :          0 :             i += self->b_length;
        4552                 :          0 :         return Array_item(myself, i);
        4553                 :            :     }
        4554         [ #  # ]:          0 :     else if (PySlice_Check(item)) {
        4555                 :            :         StgDictObject *stgdict, *itemdict;
        4556                 :            :         PyObject *proto;
        4557                 :            :         PyObject *np;
        4558                 :            :         Py_ssize_t start, stop, step, slicelen, i;
        4559                 :            :         size_t cur;
        4560                 :            :
        4561         [ #  # ]:          0 :         if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
        4562                 :          0 :             return NULL;
        4563                 :            :         }
        4564                 :          0 :         slicelen = PySlice_AdjustIndices(self->b_length, &start, &stop, step);
        4565                 :            :
        4566                 :          0 :         stgdict = PyObject_stgdict((PyObject *)self);
        4567                 :            :         assert(stgdict); /* Cannot be NULL for array object instances */
        4568                 :          0 :         proto = stgdict->proto;
        4569                 :          0 :         itemdict = PyType_stgdict(proto);
        4570                 :            :         assert(itemdict); /* proto is the item type of the array, a
        4571                 :            :                              ctypes type, so this cannot be NULL */
        4572                 :            :
        4573         [ #  # ]:          0 :         if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
        4574                 :          0 :             char *ptr = (char *)self->b_ptr;
        4575                 :            :             char *dest;
        4576                 :            :
        4577         [ #  # ]:          0 :             if (slicelen <= 0)
        4578                 :          0 :                 return PyBytes_FromStringAndSize("", 0);
        4579         [ #  # ]:          0 :             if (step == 1) {
        4580                 :          0 :                 return PyBytes_FromStringAndSize(ptr + start,
        4581                 :            :                                                  slicelen);
        4582                 :            :             }
        4583                 :          0 :             dest = (char *)PyMem_Malloc(slicelen);
        4584                 :            :
        4585         [ #  # ]:          0 :             if (dest == NULL)
        4586                 :          0 :                 return PyErr_NoMemory();
        4587                 :            :
        4588         [ #  # ]:          0 :             for (cur = start, i = 0; i < slicelen;
        4589                 :          0 :                  cur += step, i++) {
        4590                 :          0 :                 dest[i] = ptr[cur];
        4591                 :            :             }
        4592                 :            :
        4593                 :          0 :             np = PyBytes_FromStringAndSize(dest, slicelen);
        4594                 :          0 :             PyMem_Free(dest);
        4595                 :          0 :             return np;
        4596                 :            :         }
        4597         [ #  # ]:          0 :         if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
        4598                 :          0 :             wchar_t *ptr = (wchar_t *)self->b_ptr;
        4599                 :            :             wchar_t *dest;
        4600                 :            :
        4601         [ #  # ]:          0 :             if (slicelen <= 0)
        4602                 :          0 :                 return PyUnicode_New(0, 0);
        4603         [ #  # ]:          0 :             if (step == 1) {
        4604                 :          0 :                 return PyUnicode_FromWideChar(ptr + start,
        4605                 :            :                                               slicelen);
        4606                 :            :             }
        4607                 :            :
        4608         [ #  # ]:          0 :             dest = PyMem_New(wchar_t, slicelen);
        4609         [ #  # ]:          0 :             if (dest == NULL) {
        4610                 :          0 :                 PyErr_NoMemory();
        4611                 :          0 :                 return NULL;
        4612                 :            :             }
        4613                 :            :
        4614         [ #  # ]:          0 :             for (cur = start, i = 0; i < slicelen;
        4615                 :          0 :                  cur += step, i++) {
        4616                 :          0 :                 dest[i] = ptr[cur];
        4617                 :            :             }
        4618                 :            :
        4619                 :          0 :             np = PyUnicode_FromWideChar(dest, slicelen);
        4620                 :          0 :             PyMem_Free(dest);
        4621                 :          0 :             return np;
        4622                 :            :         }
        4623                 :            :
        4624                 :          0 :         np = PyList_New(slicelen);
        4625         [ #  # ]:          0 :         if (np == NULL)
        4626                 :          0 :             return NULL;
        4627                 :            :
        4628         [ #  # ]:          0 :         for (cur = start, i = 0; i < slicelen;
        4629                 :          0 :              cur += step, i++) {
        4630                 :          0 :             PyObject *v = Array_item(myself, cur);
        4631         [ #  # ]:          0 :             if (v == NULL) {
        4632                 :          0 :                 Py_DECREF(np);
        4633                 :          0 :                 return NULL;
        4634                 :            :             }
        4635                 :          0 :             PyList_SET_ITEM(np, i, v);
        4636                 :            :         }
        4637                 :          0 :         return np;
        4638                 :            :     }
        4639                 :            :     else {
        4640                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4641                 :            :                         "indices must be integers");
        4642                 :          0 :         return NULL;
        4643                 :            :     }
        4644                 :            :
        4645                 :            : }
        4646                 :            :
        4647                 :            : static int
        4648                 :          0 : Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value)
        4649                 :            : {
        4650                 :          0 :     CDataObject *self = (CDataObject *)myself;
        4651                 :            :     Py_ssize_t size, offset;
        4652                 :            :     StgDictObject *stgdict;
        4653                 :            :     char *ptr;
        4654                 :            :
        4655         [ #  # ]:          0 :     if (value == NULL) {
        4656                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4657                 :            :                         "Array does not support item deletion");
        4658                 :          0 :         return -1;
        4659                 :            :     }
        4660                 :            :
        4661                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
        4662                 :            :     assert(stgdict); /* Cannot be NULL for array object instances */
        4663   [ #  #  #  # ]:          0 :     if (index < 0 || index >= stgdict->length) {
        4664                 :          0 :         PyErr_SetString(PyExc_IndexError,
        4665                 :            :                         "invalid index");
        4666                 :          0 :         return -1;
        4667                 :            :     }
        4668                 :          0 :     size = stgdict->size / stgdict->length;
        4669                 :          0 :     offset = index * size;
        4670                 :          0 :     ptr = self->b_ptr + offset;
        4671                 :            :
        4672                 :          0 :     return PyCData_set((PyObject *)self, stgdict->proto, stgdict->setfunc, value,
        4673                 :            :                      index, size, ptr);
        4674                 :            : }
        4675                 :            :
        4676                 :            : static int
        4677                 :          0 : Array_ass_subscript(PyObject *myself, PyObject *item, PyObject *value)
        4678                 :            : {
        4679                 :          0 :     CDataObject *self = (CDataObject *)myself;
        4680                 :            :
        4681         [ #  # ]:          0 :     if (value == NULL) {
        4682                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4683                 :            :                         "Array does not support item deletion");
        4684                 :          0 :         return -1;
        4685                 :            :     }
        4686                 :            :
        4687         [ #  # ]:          0 :     if (PyIndex_Check(item)) {
        4688                 :          0 :         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
        4689                 :            :
        4690   [ #  #  #  # ]:          0 :         if (i == -1 && PyErr_Occurred())
        4691                 :          0 :             return -1;
        4692         [ #  # ]:          0 :         if (i < 0)
        4693                 :          0 :             i += self->b_length;
        4694                 :          0 :         return Array_ass_item(myself, i, value);
        4695                 :            :     }
        4696         [ #  # ]:          0 :     else if (PySlice_Check(item)) {
        4697                 :            :         Py_ssize_t start, stop, step, slicelen, otherlen, i;
        4698                 :            :         size_t cur;
        4699                 :            :
        4700         [ #  # ]:          0 :         if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
        4701                 :          0 :             return -1;
        4702                 :            :         }
        4703                 :          0 :         slicelen = PySlice_AdjustIndices(self->b_length, &start, &stop, step);
        4704   [ #  #  #  # ]:          0 :         if ((step < 0 && start < stop) ||
        4705   [ #  #  #  # ]:          0 :             (step > 0 && start > stop))
        4706                 :          0 :             stop = start;
        4707                 :            :
        4708                 :          0 :         otherlen = PySequence_Length(value);
        4709         [ #  # ]:          0 :         if (otherlen != slicelen) {
        4710                 :          0 :             PyErr_SetString(PyExc_ValueError,
        4711                 :            :                 "Can only assign sequence of same size");
        4712                 :          0 :             return -1;
        4713                 :            :         }
        4714         [ #  # ]:          0 :         for (cur = start, i = 0; i < otherlen; cur += step, i++) {
        4715                 :          0 :             PyObject *item = PySequence_GetItem(value, i);
        4716                 :            :             int result;
        4717         [ #  # ]:          0 :             if (item == NULL)
        4718                 :          0 :                 return -1;
        4719                 :          0 :             result = Array_ass_item(myself, cur, item);
        4720                 :          0 :             Py_DECREF(item);
        4721         [ #  # ]:          0 :             if (result == -1)
        4722                 :          0 :                 return -1;
        4723                 :            :         }
        4724                 :          0 :         return 0;
        4725                 :            :     }
        4726                 :            :     else {
        4727                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4728                 :            :                         "indices must be integer");
        4729                 :          0 :         return -1;
        4730                 :            :     }
        4731                 :            : }
        4732                 :            :
        4733                 :            : static Py_ssize_t
        4734                 :          0 : Array_length(PyObject *myself)
        4735                 :            : {
        4736                 :          0 :     CDataObject *self = (CDataObject *)myself;
        4737                 :          0 :     return self->b_length;
        4738                 :            : }
        4739                 :            :
        4740                 :            : static PyMethodDef Array_methods[] = {
        4741                 :            :     {"__class_getitem__",    Py_GenericAlias,
        4742                 :            :     METH_O|METH_CLASS,       PyDoc_STR("See PEP 585")},
        4743                 :            :     { NULL, NULL }
        4744                 :            : };
        4745                 :            :
        4746                 :            : static PySequenceMethods Array_as_sequence = {
        4747                 :            :     Array_length,                               /* sq_length; */
        4748                 :            :     0,                                          /* sq_concat; */
        4749                 :            :     0,                                          /* sq_repeat; */
        4750                 :            :     Array_item,                                 /* sq_item; */
        4751                 :            :     0,                                          /* sq_slice; */
        4752                 :            :     Array_ass_item,                             /* sq_ass_item; */
        4753                 :            :     0,                                          /* sq_ass_slice; */
        4754                 :            :     0,                                          /* sq_contains; */
        4755                 :            :
        4756                 :            :     0,                                          /* sq_inplace_concat; */
        4757                 :            :     0,                                          /* sq_inplace_repeat; */
        4758                 :            : };
        4759                 :            :
        4760                 :            : static PyMappingMethods Array_as_mapping = {
        4761                 :            :     Array_length,
        4762                 :            :     Array_subscript,
        4763                 :            :     Array_ass_subscript,
        4764                 :            : };
        4765                 :            :
        4766                 :            : PyTypeObject PyCArray_Type = {
        4767                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        4768                 :            :     "_ctypes.Array",
        4769                 :            :     sizeof(CDataObject),                        /* tp_basicsize */
        4770                 :            :     0,                                          /* tp_itemsize */
        4771                 :            :     0,                                          /* tp_dealloc */
        4772                 :            :     0,                                          /* tp_vectorcall_offset */
        4773                 :            :     0,                                          /* tp_getattr */
        4774                 :            :     0,                                          /* tp_setattr */
        4775                 :            :     0,                                          /* tp_as_async */
        4776                 :            :     0,                                          /* tp_repr */
        4777                 :            :     0,                                          /* tp_as_number */
        4778                 :            :     &Array_as_sequence,                         /* tp_as_sequence */
        4779                 :            :     &Array_as_mapping,                          /* tp_as_mapping */
        4780                 :            :     0,                                          /* tp_hash */
        4781                 :            :     0,                                          /* tp_call */
        4782                 :            :     0,                                          /* tp_str */
        4783                 :            :     0,                                          /* tp_getattro */
        4784                 :            :     0,                                          /* tp_setattro */
        4785                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        4786                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        4787                 :            :     PyDoc_STR("XXX to be provided"),            /* tp_doc */
        4788                 :            :     (traverseproc)PyCData_traverse,             /* tp_traverse */
        4789                 :            :     (inquiry)PyCData_clear,                     /* tp_clear */
        4790                 :            :     0,                                          /* tp_richcompare */
        4791                 :            :     0,                                          /* tp_weaklistoffset */
        4792                 :            :     0,                                          /* tp_iter */
        4793                 :            :     0,                                          /* tp_iternext */
        4794                 :            :     Array_methods,                              /* tp_methods */
        4795                 :            :     0,                                          /* tp_members */
        4796                 :            :     0,                                          /* tp_getset */
        4797                 :            :     0,                                          /* tp_base */
        4798                 :            :     0,                                          /* tp_dict */
        4799                 :            :     0,                                          /* tp_descr_get */
        4800                 :            :     0,                                          /* tp_descr_set */
        4801                 :            :     0,                                          /* tp_dictoffset */
        4802                 :            :     (initproc)Array_init,                       /* tp_init */
        4803                 :            :     0,                                          /* tp_alloc */
        4804                 :            :     GenericPyCData_new,                         /* tp_new */
        4805                 :            :     0,                                          /* tp_free */
        4806                 :            : };
        4807                 :            :
        4808                 :            : PyObject *
        4809                 :          0 : PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
        4810                 :            : {
        4811                 :            :     static PyObject *cache;
        4812                 :            :     PyObject *key;
        4813                 :            :     PyObject *result;
        4814                 :            :     char name[256];
        4815                 :            :     PyObject *len;
        4816                 :            :
        4817         [ #  # ]:          0 :     if (cache == NULL) {
        4818                 :          0 :         cache = PyDict_New();
        4819         [ #  # ]:          0 :         if (cache == NULL)
        4820                 :          0 :             return NULL;
        4821                 :            :     }
        4822                 :          0 :     len = PyLong_FromSsize_t(length);
        4823         [ #  # ]:          0 :     if (len == NULL)
        4824                 :          0 :         return NULL;
        4825                 :          0 :     key = PyTuple_Pack(2, itemtype, len);
        4826                 :          0 :     Py_DECREF(len);
        4827         [ #  # ]:          0 :     if (!key)
        4828                 :          0 :         return NULL;
        4829                 :          0 :     result = PyDict_GetItemProxy(cache, key);
        4830         [ #  # ]:          0 :     if (result) {
        4831                 :          0 :         Py_INCREF(result);
        4832                 :          0 :         Py_DECREF(key);
        4833                 :          0 :         return result;
        4834                 :            :     }
        4835         [ #  # ]:          0 :     else if (PyErr_Occurred()) {
        4836                 :          0 :         Py_DECREF(key);
        4837                 :          0 :         return NULL;
        4838                 :            :     }
        4839                 :            :
        4840         [ #  # ]:          0 :     if (!PyType_Check(itemtype)) {
        4841                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4842                 :            :                         "Expected a type object");
        4843                 :          0 :         Py_DECREF(key);
        4844                 :          0 :         return NULL;
        4845                 :            :     }
        4846                 :            : #ifdef MS_WIN64
        4847                 :            :     sprintf(name, "%.200s_Array_%Id",
        4848                 :            :         ((PyTypeObject *)itemtype)->tp_name, length);
        4849                 :            : #else
        4850                 :          0 :     sprintf(name, "%.200s_Array_%ld",
        4851                 :            :         ((PyTypeObject *)itemtype)->tp_name, (long)length);
        4852                 :            : #endif
        4853                 :            :
        4854                 :          0 :     result = PyObject_CallFunction((PyObject *)&PyCArrayType_Type,
        4855                 :            :                                    "s(O){s:n,s:O}",
        4856                 :            :                                    name,
        4857                 :            :                                    &PyCArray_Type,
        4858                 :            :                                    "_length_",
        4859                 :            :                                    length,
        4860                 :            :                                    "_type_",
        4861                 :            :                                    itemtype
        4862                 :            :         );
        4863         [ #  # ]:          0 :     if (result == NULL) {
        4864                 :          0 :         Py_DECREF(key);
        4865                 :          0 :         return NULL;
        4866                 :            :     }
        4867         [ #  # ]:          0 :     if (-1 == PyDict_SetItemProxy(cache, key, result)) {
        4868                 :          0 :         Py_DECREF(key);
        4869                 :          0 :         Py_DECREF(result);
        4870                 :          0 :         return NULL;
        4871                 :            :     }
        4872                 :          0 :     Py_DECREF(key);
        4873                 :          0 :     return result;
        4874                 :            : }
        4875                 :            :
        4876                 :            :
        4877                 :            : /******************************************************************/
        4878                 :            : /*
        4879                 :            :   Simple_Type
        4880                 :            : */
        4881                 :            :
        4882                 :            : static int
        4883                 :          0 : Simple_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
        4884                 :            : {
        4885                 :            :     PyObject *result;
        4886                 :          0 :     StgDictObject *dict = PyObject_stgdict((PyObject *)self);
        4887                 :            :
        4888         [ #  # ]:          0 :     if (value == NULL) {
        4889                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4890                 :            :                         "can't delete attribute");
        4891                 :          0 :         return -1;
        4892                 :            :     }
        4893                 :            :     assert(dict); /* Cannot be NULL for CDataObject instances */
        4894                 :            :     assert(dict->setfunc);
        4895                 :          0 :     result = dict->setfunc(self->b_ptr, value, dict->size);
        4896         [ #  # ]:          0 :     if (!result)
        4897                 :          0 :         return -1;
        4898                 :            :
        4899                 :            :     /* consumes the refcount the setfunc returns */
        4900                 :          0 :     return KeepRef(self, 0, result);
        4901                 :            : }
        4902                 :            :
        4903                 :            : static int
        4904                 :          0 : Simple_init(CDataObject *self, PyObject *args, PyObject *kw)
        4905                 :            : {
        4906                 :          0 :     PyObject *value = NULL;
        4907         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "__init__", 0, 1, &value))
        4908                 :          0 :         return -1;
        4909         [ #  # ]:          0 :     if (value)
        4910                 :          0 :         return Simple_set_value(self, value, NULL);
        4911                 :          0 :     return 0;
        4912                 :            : }
        4913                 :            :
        4914                 :            : static PyObject *
        4915                 :          0 : Simple_get_value(CDataObject *self, void *Py_UNUSED(ignored))
        4916                 :            : {
        4917                 :            :     StgDictObject *dict;
        4918                 :          0 :     dict = PyObject_stgdict((PyObject *)self);
        4919                 :            :     assert(dict); /* Cannot be NULL for CDataObject instances */
        4920                 :            :     assert(dict->getfunc);
        4921                 :          0 :     return dict->getfunc(self->b_ptr, self->b_size);
        4922                 :            : }
        4923                 :            :
        4924                 :            : static PyGetSetDef Simple_getsets[] = {
        4925                 :            :     { "value", (getter)Simple_get_value, (setter)Simple_set_value,
        4926                 :            :       "current value", NULL },
        4927                 :            :     { NULL, NULL }
        4928                 :            : };
        4929                 :            :
        4930                 :            : static PyObject *
        4931                 :          0 : Simple_from_outparm(PyObject *self, PyObject *args)
        4932                 :            : {
        4933         [ #  # ]:          0 :     if (_ctypes_simple_instance((PyObject *)Py_TYPE(self))) {
        4934                 :          0 :         return Py_NewRef(self);
        4935                 :            :     }
        4936                 :            :     /* call stgdict->getfunc */
        4937                 :          0 :     return Simple_get_value((CDataObject *)self, NULL);
        4938                 :            : }
        4939                 :            :
        4940                 :            : static PyMethodDef Simple_methods[] = {
        4941                 :            :     { "__ctypes_from_outparam__", Simple_from_outparm, METH_NOARGS, },
        4942                 :            :     { NULL, NULL },
        4943                 :            : };
        4944                 :            :
        4945                 :          0 : static int Simple_bool(CDataObject *self)
        4946                 :            : {
        4947                 :          0 :     return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size);
        4948                 :            : }
        4949                 :            :
        4950                 :            : static PyNumberMethods Simple_as_number = {
        4951                 :            :     0, /* nb_add */
        4952                 :            :     0, /* nb_subtract */
        4953                 :            :     0, /* nb_multiply */
        4954                 :            :     0, /* nb_remainder */
        4955                 :            :     0, /* nb_divmod */
        4956                 :            :     0, /* nb_power */
        4957                 :            :     0, /* nb_negative */
        4958                 :            :     0, /* nb_positive */
        4959                 :            :     0, /* nb_absolute */
        4960                 :            :     (inquiry)Simple_bool, /* nb_bool */
        4961                 :            : };
        4962                 :            :
        4963                 :            : /* "%s(%s)" % (self.__class__.__name__, self.value) */
        4964                 :            : static PyObject *
        4965                 :          0 : Simple_repr(CDataObject *self)
        4966                 :            : {
        4967                 :            :     PyObject *val, *result;
        4968                 :            :
        4969         [ #  # ]:          0 :     if (Py_TYPE(self)->tp_base != &Simple_Type) {
        4970                 :          0 :         return PyUnicode_FromFormat("<%s object at %p>",
        4971                 :          0 :                                    Py_TYPE(self)->tp_name, self);
        4972                 :            :     }
        4973                 :            :
        4974                 :          0 :     val = Simple_get_value(self, NULL);
        4975         [ #  # ]:          0 :     if (val == NULL)
        4976                 :          0 :         return NULL;
        4977                 :            :
        4978                 :          0 :     result = PyUnicode_FromFormat("%s(%R)",
        4979                 :          0 :                                   Py_TYPE(self)->tp_name, val);
        4980                 :          0 :     Py_DECREF(val);
        4981                 :          0 :     return result;
        4982                 :            : }
        4983                 :            :
        4984                 :            : static PyTypeObject Simple_Type = {
        4985                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        4986                 :            :     "_ctypes._SimpleCData",
        4987                 :            :     sizeof(CDataObject),                        /* tp_basicsize */
        4988                 :            :     0,                                          /* tp_itemsize */
        4989                 :            :     0,                                          /* tp_dealloc */
        4990                 :            :     0,                                          /* tp_vectorcall_offset */
        4991                 :            :     0,                                          /* tp_getattr */
        4992                 :            :     0,                                          /* tp_setattr */
        4993                 :            :     0,                                          /* tp_as_async */
        4994                 :            :     (reprfunc)&Simple_repr,                     /* tp_repr */
        4995                 :            :     &Simple_as_number,                          /* tp_as_number */
        4996                 :            :     0,                                          /* tp_as_sequence */
        4997                 :            :     0,                                          /* tp_as_mapping */
        4998                 :            :     0,                                          /* tp_hash */
        4999                 :            :     0,                                          /* tp_call */
        5000                 :            :     0,                                          /* tp_str */
        5001                 :            :     0,                                          /* tp_getattro */
        5002                 :            :     0,                                          /* tp_setattro */
        5003                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        5004                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        5005                 :            :     PyDoc_STR("XXX to be provided"),            /* tp_doc */
        5006                 :            :     (traverseproc)PyCData_traverse,             /* tp_traverse */
        5007                 :            :     (inquiry)PyCData_clear,                     /* tp_clear */
        5008                 :            :     0,                                          /* tp_richcompare */
        5009                 :            :     0,                                          /* tp_weaklistoffset */
        5010                 :            :     0,                                          /* tp_iter */
        5011                 :            :     0,                                          /* tp_iternext */
        5012                 :            :     Simple_methods,                             /* tp_methods */
        5013                 :            :     0,                                          /* tp_members */
        5014                 :            :     Simple_getsets,                             /* tp_getset */
        5015                 :            :     0,                                          /* tp_base */
        5016                 :            :     0,                                          /* tp_dict */
        5017                 :            :     0,                                          /* tp_descr_get */
        5018                 :            :     0,                                          /* tp_descr_set */
        5019                 :            :     0,                                          /* tp_dictoffset */
        5020                 :            :     (initproc)Simple_init,                      /* tp_init */
        5021                 :            :     0,                                          /* tp_alloc */
        5022                 :            :     GenericPyCData_new,                         /* tp_new */
        5023                 :            :     0,                                          /* tp_free */
        5024                 :            : };
        5025                 :            :
        5026                 :            : /******************************************************************/
        5027                 :            : /*
        5028                 :            :   PyCPointer_Type
        5029                 :            : */
        5030                 :            : static PyObject *
        5031                 :          0 : Pointer_item(PyObject *myself, Py_ssize_t index)
        5032                 :            : {
        5033                 :          0 :     CDataObject *self = (CDataObject *)myself;
        5034                 :            :     Py_ssize_t size;
        5035                 :            :     Py_ssize_t offset;
        5036                 :            :     StgDictObject *stgdict, *itemdict;
        5037                 :            :     PyObject *proto;
        5038                 :            :
        5039         [ #  # ]:          0 :     if (*(void **)self->b_ptr == NULL) {
        5040                 :          0 :         PyErr_SetString(PyExc_ValueError,
        5041                 :            :                         "NULL pointer access");
        5042                 :          0 :         return NULL;
        5043                 :            :     }
        5044                 :            :
        5045                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
        5046                 :            :     assert(stgdict); /* Cannot be NULL for pointer object instances */
        5047                 :            :
        5048                 :          0 :     proto = stgdict->proto;
        5049                 :            :     assert(proto);
        5050                 :          0 :     itemdict = PyType_stgdict(proto);
        5051                 :            :     assert(itemdict); /* proto is the item type of the pointer, a ctypes
        5052                 :            :                          type, so this cannot be NULL */
        5053                 :            :
        5054                 :          0 :     size = itemdict->size;
        5055                 :          0 :     offset = index * itemdict->size;
        5056                 :            :
        5057                 :          0 :     return PyCData_get(proto, stgdict->getfunc, (PyObject *)self,
        5058                 :          0 :                      index, size, (*(char **)self->b_ptr) + offset);
        5059                 :            : }
        5060                 :            :
        5061                 :            : static int
        5062                 :          0 : Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value)
        5063                 :            : {
        5064                 :          0 :     CDataObject *self = (CDataObject *)myself;
        5065                 :            :     Py_ssize_t size;
        5066                 :            :     Py_ssize_t offset;
        5067                 :            :     StgDictObject *stgdict, *itemdict;
        5068                 :            :     PyObject *proto;
        5069                 :            :
        5070         [ #  # ]:          0 :     if (value == NULL) {
        5071                 :          0 :         PyErr_SetString(PyExc_TypeError,
        5072                 :            :                         "Pointer does not support item deletion");
        5073                 :          0 :         return -1;
        5074                 :            :     }
        5075                 :            :
        5076         [ #  # ]:          0 :     if (*(void **)self->b_ptr == NULL) {
        5077                 :          0 :         PyErr_SetString(PyExc_ValueError,
        5078                 :            :                         "NULL pointer access");
        5079                 :          0 :         return -1;
        5080                 :            :     }
        5081                 :            :
        5082                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
        5083                 :            :     assert(stgdict); /* Cannot be NULL for pointer instances */
        5084                 :            :
        5085                 :          0 :     proto = stgdict->proto;
        5086                 :            :     assert(proto);
        5087                 :            :
        5088                 :          0 :     itemdict = PyType_stgdict(proto);
        5089                 :            :     assert(itemdict); /* Cannot be NULL because the itemtype of a pointer
        5090                 :            :                          is always a ctypes type */
        5091                 :            :
        5092                 :          0 :     size = itemdict->size;
        5093                 :          0 :     offset = index * itemdict->size;
        5094                 :            :
        5095                 :          0 :     return PyCData_set((PyObject *)self, proto, stgdict->setfunc, value,
        5096                 :          0 :                      index, size, (*(char **)self->b_ptr) + offset);
        5097                 :            : }
        5098                 :            :
        5099                 :            : static PyObject *
        5100                 :          0 : Pointer_get_contents(CDataObject *self, void *closure)
        5101                 :            : {
        5102                 :            :     StgDictObject *stgdict;
        5103                 :            :
        5104         [ #  # ]:          0 :     if (*(void **)self->b_ptr == NULL) {
        5105                 :          0 :         PyErr_SetString(PyExc_ValueError,
        5106                 :            :                         "NULL pointer access");
        5107                 :          0 :         return NULL;
        5108                 :            :     }
        5109                 :            :
        5110                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
        5111                 :            :     assert(stgdict); /* Cannot be NULL for pointer instances */
        5112                 :          0 :     return PyCData_FromBaseObj(stgdict->proto,
        5113                 :            :                              (PyObject *)self, 0,
        5114                 :          0 :                              *(void **)self->b_ptr);
        5115                 :            : }
        5116                 :            :
        5117                 :            : static int
        5118                 :          0 : Pointer_set_contents(CDataObject *self, PyObject *value, void *closure)
        5119                 :            : {
        5120                 :            :     StgDictObject *stgdict;
        5121                 :            :     CDataObject *dst;
        5122                 :            :     PyObject *keep;
        5123                 :            :
        5124         [ #  # ]:          0 :     if (value == NULL) {
        5125                 :          0 :         PyErr_SetString(PyExc_TypeError,
        5126                 :            :                         "Pointer does not support item deletion");
        5127                 :          0 :         return -1;
        5128                 :            :     }
        5129                 :          0 :     stgdict = PyObject_stgdict((PyObject *)self);
        5130                 :            :     assert(stgdict); /* Cannot be NULL for pointer instances */
        5131                 :            :     assert(stgdict->proto);
        5132         [ #  # ]:          0 :     if (!CDataObject_Check(value)) {
        5133                 :          0 :         int res = PyObject_IsInstance(value, stgdict->proto);
        5134         [ #  # ]:          0 :         if (res == -1)
        5135                 :          0 :             return -1;
        5136         [ #  # ]:          0 :         if (!res) {
        5137                 :          0 :             PyErr_Format(PyExc_TypeError,
        5138                 :            :                          "expected %s instead of %s",
        5139                 :          0 :                          ((PyTypeObject *)(stgdict->proto))->tp_name,
        5140                 :          0 :                          Py_TYPE(value)->tp_name);
        5141                 :          0 :             return -1;
        5142                 :            :         }
        5143                 :            :     }
        5144                 :            :
        5145                 :          0 :     dst = (CDataObject *)value;
        5146                 :          0 :     *(void **)self->b_ptr = dst->b_ptr;
        5147                 :            :
        5148                 :            :     /*
        5149                 :            :        A Pointer instance must keep the value it points to alive.  So, a
        5150                 :            :        pointer instance has b_length set to 2 instead of 1, and we set
        5151                 :            :        'value' itself as the second item of the b_objects list, additionally.
        5152                 :            :     */
        5153                 :          0 :     Py_INCREF(value);
        5154         [ #  # ]:          0 :     if (-1 == KeepRef(self, 1, value))
        5155                 :          0 :         return -1;
        5156                 :            :
        5157                 :          0 :     keep = GetKeepedObjects(dst);
        5158         [ #  # ]:          0 :     if (keep == NULL)
        5159                 :          0 :         return -1;
        5160                 :            :
        5161                 :          0 :     Py_INCREF(keep);
        5162                 :          0 :     return KeepRef(self, 0, keep);
        5163                 :            : }
        5164                 :            :
        5165                 :            : static PyGetSetDef Pointer_getsets[] = {
        5166                 :            :     { "contents", (getter)Pointer_get_contents,
        5167                 :            :       (setter)Pointer_set_contents,
        5168                 :            :       "the object this pointer points to (read-write)", NULL },
        5169                 :            :     { NULL, NULL }
        5170                 :            : };
        5171                 :            :
        5172                 :            : static int
        5173                 :          0 : Pointer_init(CDataObject *self, PyObject *args, PyObject *kw)
        5174                 :            : {
        5175                 :          0 :     PyObject *value = NULL;
        5176                 :            :
        5177         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "POINTER", 0, 1, &value))
        5178                 :          0 :         return -1;
        5179         [ #  # ]:          0 :     if (value == NULL)
        5180                 :          0 :         return 0;
        5181                 :          0 :     return Pointer_set_contents(self, value, NULL);
        5182                 :            : }
        5183                 :            :
        5184                 :            : static PyObject *
        5185                 :          0 : Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
        5186                 :            : {
        5187                 :          0 :     StgDictObject *dict = PyType_stgdict((PyObject *)type);
        5188   [ #  #  #  # ]:          0 :     if (!dict || !dict->proto) {
        5189                 :          0 :         PyErr_SetString(PyExc_TypeError,
        5190                 :            :                         "Cannot create instance: has no _type_");
        5191                 :          0 :         return NULL;
        5192                 :            :     }
        5193                 :          0 :     return GenericPyCData_new(type, args, kw);
        5194                 :            : }
        5195                 :            :
        5196                 :            : static PyObject *
        5197                 :          0 : Pointer_subscript(PyObject *myself, PyObject *item)
        5198                 :            : {
        5199                 :          0 :     CDataObject *self = (CDataObject *)myself;
        5200         [ #  # ]:          0 :     if (PyIndex_Check(item)) {
        5201                 :          0 :         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
        5202   [ #  #  #  # ]:          0 :         if (i == -1 && PyErr_Occurred())
        5203                 :          0 :             return NULL;
        5204                 :          0 :         return Pointer_item(myself, i);
        5205                 :            :     }
        5206         [ #  # ]:          0 :     else if (PySlice_Check(item)) {
        5207                 :          0 :         PySliceObject *slice = (PySliceObject *)item;
        5208                 :            :         Py_ssize_t start, stop, step;
        5209                 :            :         PyObject *np;
        5210                 :            :         StgDictObject *stgdict, *itemdict;
        5211                 :            :         PyObject *proto;
        5212                 :            :         Py_ssize_t i, len;
        5213                 :            :         size_t cur;
        5214                 :            :
        5215                 :            :         /* Since pointers have no length, and we want to apply
        5216                 :            :            different semantics to negative indices than normal
        5217                 :            :            slicing, we have to dissect the slice object ourselves.*/
        5218         [ #  # ]:          0 :         if (slice->step == Py_None) {
        5219                 :          0 :             step = 1;
        5220                 :            :         }
        5221                 :            :         else {
        5222                 :          0 :             step = PyNumber_AsSsize_t(slice->step,
        5223                 :            :                                       PyExc_ValueError);
        5224   [ #  #  #  # ]:          0 :             if (step == -1 && PyErr_Occurred())
        5225                 :          0 :                 return NULL;
        5226         [ #  # ]:          0 :             if (step == 0) {
        5227                 :          0 :                 PyErr_SetString(PyExc_ValueError,
        5228                 :            :                                 "slice step cannot be zero");
        5229                 :          0 :                 return NULL;
        5230                 :            :             }
        5231                 :            :         }
        5232         [ #  # ]:          0 :         if (slice->start == Py_None) {
        5233         [ #  # ]:          0 :             if (step < 0) {
        5234                 :          0 :                 PyErr_SetString(PyExc_ValueError,
        5235                 :            :                                 "slice start is required "
        5236                 :            :                                 "for step < 0");
        5237                 :          0 :                 return NULL;
        5238                 :            :             }
        5239                 :          0 :             start = 0;
        5240                 :            :         }
        5241                 :            :         else {
        5242                 :          0 :             start = PyNumber_AsSsize_t(slice->start,
        5243                 :            :                                        PyExc_ValueError);
        5244   [ #  #  #  # ]:          0 :             if (start == -1 && PyErr_Occurred())
        5245                 :          0 :                 return NULL;
        5246                 :            :         }
        5247         [ #  # ]:          0 :         if (slice->stop == Py_None) {
        5248                 :          0 :             PyErr_SetString(PyExc_ValueError,
        5249                 :            :                             "slice stop is required");
        5250                 :          0 :             return NULL;
        5251                 :            :         }
        5252                 :          0 :         stop = PyNumber_AsSsize_t(slice->stop,
        5253                 :            :                                   PyExc_ValueError);
        5254   [ #  #  #  # ]:          0 :         if (stop == -1 && PyErr_Occurred())
        5255                 :          0 :             return NULL;
        5256   [ #  #  #  #  :          0 :         if ((step > 0 && start > stop) ||
                       #  # ]
        5257         [ #  # ]:          0 :             (step < 0 && start < stop))
        5258                 :          0 :             len = 0;
        5259         [ #  # ]:          0 :         else if (step > 0)
        5260                 :          0 :             len = (stop - start - 1) / step + 1;
        5261                 :            :         else
        5262                 :          0 :             len = (stop - start + 1) / step + 1;
        5263                 :            :
        5264                 :          0 :         stgdict = PyObject_stgdict((PyObject *)self);
        5265                 :            :         assert(stgdict); /* Cannot be NULL for pointer instances */
        5266                 :          0 :         proto = stgdict->proto;
        5267                 :            :         assert(proto);
        5268                 :          0 :         itemdict = PyType_stgdict(proto);
        5269                 :            :         assert(itemdict);
        5270         [ #  # ]:          0 :         if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
        5271                 :          0 :             char *ptr = *(char **)self->b_ptr;
        5272                 :            :             char *dest;
        5273                 :            :
        5274         [ #  # ]:          0 :             if (len <= 0)
        5275                 :          0 :                 return PyBytes_FromStringAndSize("", 0);
        5276         [ #  # ]:          0 :             if (step == 1) {
        5277                 :          0 :                 return PyBytes_FromStringAndSize(ptr + start,
        5278                 :            :                                                  len);
        5279                 :            :             }
        5280                 :          0 :             dest = (char *)PyMem_Malloc(len);
        5281         [ #  # ]:          0 :             if (dest == NULL)
        5282                 :          0 :                 return PyErr_NoMemory();
        5283         [ #  # ]:          0 :             for (cur = start, i = 0; i < len; cur += step, i++) {
        5284                 :          0 :                 dest[i] = ptr[cur];
        5285                 :            :             }
        5286                 :          0 :             np = PyBytes_FromStringAndSize(dest, len);
        5287                 :          0 :             PyMem_Free(dest);
        5288                 :          0 :             return np;
        5289                 :            :         }
        5290         [ #  # ]:          0 :         if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
        5291                 :          0 :             wchar_t *ptr = *(wchar_t **)self->b_ptr;
        5292                 :            :             wchar_t *dest;
        5293                 :            :
        5294         [ #  # ]:          0 :             if (len <= 0)
        5295                 :          0 :                 return PyUnicode_New(0, 0);
        5296         [ #  # ]:          0 :             if (step == 1) {
        5297                 :          0 :                 return PyUnicode_FromWideChar(ptr + start,
        5298                 :            :                                               len);
        5299                 :            :             }
        5300         [ #  # ]:          0 :             dest = PyMem_New(wchar_t, len);
        5301         [ #  # ]:          0 :             if (dest == NULL)
        5302                 :          0 :                 return PyErr_NoMemory();
        5303         [ #  # ]:          0 :             for (cur = start, i = 0; i < len; cur += step, i++) {
        5304                 :          0 :                 dest[i] = ptr[cur];
        5305                 :            :             }
        5306                 :          0 :             np = PyUnicode_FromWideChar(dest, len);
        5307                 :          0 :             PyMem_Free(dest);
        5308                 :          0 :             return np;
        5309                 :            :         }
        5310                 :            :
        5311                 :          0 :         np = PyList_New(len);
        5312         [ #  # ]:          0 :         if (np == NULL)
        5313                 :          0 :             return NULL;
        5314                 :            :
        5315         [ #  # ]:          0 :         for (cur = start, i = 0; i < len; cur += step, i++) {
        5316                 :          0 :             PyObject *v = Pointer_item(myself, cur);
        5317                 :          0 :             PyList_SET_ITEM(np, i, v);
        5318                 :            :         }
        5319                 :          0 :         return np;
        5320                 :            :     }
        5321                 :            :     else {
        5322                 :          0 :         PyErr_SetString(PyExc_TypeError,
        5323                 :            :                         "Pointer indices must be integer");
        5324                 :          0 :         return NULL;
        5325                 :            :     }
        5326                 :            : }
        5327                 :            :
        5328                 :            : static PySequenceMethods Pointer_as_sequence = {
        5329                 :            :     0,                                          /* inquiry sq_length; */
        5330                 :            :     0,                                          /* binaryfunc sq_concat; */
        5331                 :            :     0,                                          /* intargfunc sq_repeat; */
        5332                 :            :     Pointer_item,                               /* intargfunc sq_item; */
        5333                 :            :     0,                                          /* intintargfunc sq_slice; */
        5334                 :            :     Pointer_ass_item,                           /* intobjargproc sq_ass_item; */
        5335                 :            :     0,                                          /* intintobjargproc sq_ass_slice; */
        5336                 :            :     0,                                          /* objobjproc sq_contains; */
        5337                 :            :     /* Added in release 2.0 */
        5338                 :            :     0,                                          /* binaryfunc sq_inplace_concat; */
        5339                 :            :     0,                                          /* intargfunc sq_inplace_repeat; */
        5340                 :            : };
        5341                 :            :
        5342                 :            : static PyMappingMethods Pointer_as_mapping = {
        5343                 :            :     0,
        5344                 :            :     Pointer_subscript,
        5345                 :            : };
        5346                 :            :
        5347                 :            : static int
        5348                 :          0 : Pointer_bool(CDataObject *self)
        5349                 :            : {
        5350                 :          0 :     return (*(void **)self->b_ptr != NULL);
        5351                 :            : }
        5352                 :            :
        5353                 :            : static PyNumberMethods Pointer_as_number = {
        5354                 :            :     0, /* nb_add */
        5355                 :            :     0, /* nb_subtract */
        5356                 :            :     0, /* nb_multiply */
        5357                 :            :     0, /* nb_remainder */
        5358                 :            :     0, /* nb_divmod */
        5359                 :            :     0, /* nb_power */
        5360                 :            :     0, /* nb_negative */
        5361                 :            :     0, /* nb_positive */
        5362                 :            :     0, /* nb_absolute */
        5363                 :            :     (inquiry)Pointer_bool, /* nb_bool */
        5364                 :            : };
        5365                 :            :
        5366                 :            : PyTypeObject PyCPointer_Type = {
        5367                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        5368                 :            :     "_ctypes._Pointer",
        5369                 :            :     sizeof(CDataObject),                        /* tp_basicsize */
        5370                 :            :     0,                                          /* tp_itemsize */
        5371                 :            :     0,                                          /* tp_dealloc */
        5372                 :            :     0,                                          /* tp_vectorcall_offset */
        5373                 :            :     0,                                          /* tp_getattr */
        5374                 :            :     0,                                          /* tp_setattr */
        5375                 :            :     0,                                          /* tp_as_async */
        5376                 :            :     0,                                          /* tp_repr */
        5377                 :            :     &Pointer_as_number,                         /* tp_as_number */
        5378                 :            :     &Pointer_as_sequence,                       /* tp_as_sequence */
        5379                 :            :     &Pointer_as_mapping,                        /* tp_as_mapping */
        5380                 :            :     0,                                          /* tp_hash */
        5381                 :            :     0,                                          /* tp_call */
        5382                 :            :     0,                                          /* tp_str */
        5383                 :            :     0,                                          /* tp_getattro */
        5384                 :            :     0,                                          /* tp_setattro */
        5385                 :            :     &PyCData_as_buffer,                         /* tp_as_buffer */
        5386                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        5387                 :            :     PyDoc_STR("XXX to be provided"),            /* tp_doc */
        5388                 :            :     (traverseproc)PyCData_traverse,             /* tp_traverse */
        5389                 :            :     (inquiry)PyCData_clear,                     /* tp_clear */
        5390                 :            :     0,                                          /* tp_richcompare */
        5391                 :            :     0,                                          /* tp_weaklistoffset */
        5392                 :            :     0,                                          /* tp_iter */
        5393                 :            :     0,                                          /* tp_iternext */
        5394                 :            :     0,                                          /* tp_methods */
        5395                 :            :     0,                                          /* tp_members */
        5396                 :            :     Pointer_getsets,                            /* tp_getset */
        5397                 :            :     0,                                          /* tp_base */
        5398                 :            :     0,                                          /* tp_dict */
        5399                 :            :     0,                                          /* tp_descr_get */
        5400                 :            :     0,                                          /* tp_descr_set */
        5401                 :            :     0,                                          /* tp_dictoffset */
        5402                 :            :     (initproc)Pointer_init,                     /* tp_init */
        5403                 :            :     0,                                          /* tp_alloc */
        5404                 :            :     Pointer_new,                                /* tp_new */
        5405                 :            :     0,                                          /* tp_free */
        5406                 :            : };
        5407                 :            :
        5408                 :            :
        5409                 :            : /******************************************************************/
        5410                 :            : /*
        5411                 :            :  *  Module initialization.
        5412                 :            :  */
        5413                 :            :
        5414                 :            : PyDoc_STRVAR(_ctypes__doc__,
        5415                 :            : "Create and manipulate C compatible data types in Python.");
        5416                 :            :
        5417                 :            : #ifdef MS_WIN32
        5418                 :            :
        5419                 :            : PyDoc_STRVAR(comerror_doc, "Raised when a COM method call failed.");
        5420                 :            :
        5421                 :            : int
        5422                 :            : comerror_init(PyObject *self, PyObject *args, PyObject *kwds)
        5423                 :            : {
        5424                 :            :     PyObject *hresult, *text, *details;
        5425                 :            :     PyObject *a;
        5426                 :            :     int status;
        5427                 :            :
        5428                 :            :     if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
        5429                 :            :         return -1;
        5430                 :            :
        5431                 :            :     if (!PyArg_ParseTuple(args, "OOO:COMError", &hresult, &text, &details))
        5432                 :            :         return -1;
        5433                 :            :
        5434                 :            :     a = PySequence_GetSlice(args, 1, PyTuple_GET_SIZE(args));
        5435                 :            :     if (!a)
        5436                 :            :         return -1;
        5437                 :            :     status = PyObject_SetAttrString(self, "args", a);
        5438                 :            :     Py_DECREF(a);
        5439                 :            :     if (status < 0)
        5440                 :            :         return -1;
        5441                 :            :
        5442                 :            :     if (PyObject_SetAttrString(self, "hresult", hresult) < 0)
        5443                 :            :         return -1;
        5444                 :            :
        5445                 :            :     if (PyObject_SetAttrString(self, "text", text) < 0)
        5446                 :            :         return -1;
        5447                 :            :
        5448                 :            :     if (PyObject_SetAttrString(self, "details", details) < 0)
        5449                 :            :         return -1;
        5450                 :            :
        5451                 :            :     Py_INCREF(args);
        5452                 :            :     Py_SETREF(((PyBaseExceptionObject *)self)->args, args);
        5453                 :            :
        5454                 :            :     return 0;
        5455                 :            : }
        5456                 :            :
        5457                 :            : static PyTypeObject PyComError_Type = {
        5458                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        5459                 :            :     "_ctypes.COMError",         /* tp_name */
        5460                 :            :     sizeof(PyBaseExceptionObject), /* tp_basicsize */
        5461                 :            :     0,                          /* tp_itemsize */
        5462                 :            :     0,                          /* tp_dealloc */
        5463                 :            :     0,                          /* tp_vectorcall_offset */
        5464                 :            :     0,                          /* tp_getattr */
        5465                 :            :     0,                          /* tp_setattr */
        5466                 :            :     0,                          /* tp_as_async */
        5467                 :            :     0,                          /* tp_repr */
        5468                 :            :     0,                          /* tp_as_number */
        5469                 :            :     0,                          /* tp_as_sequence */
        5470                 :            :     0,                          /* tp_as_mapping */
        5471                 :            :     0,                          /* tp_hash */
        5472                 :            :     0,                          /* tp_call */
        5473                 :            :     0,                          /* tp_str */
        5474                 :            :     0,                          /* tp_getattro */
        5475                 :            :     0,                          /* tp_setattro */
        5476                 :            :     0,                          /* tp_as_buffer */
        5477                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */
        5478                 :            :     PyDoc_STR(comerror_doc),    /* tp_doc */
        5479                 :            :     0,                          /* tp_traverse */
        5480                 :            :     0,                          /* tp_clear */
        5481                 :            :     0,                          /* tp_richcompare */
        5482                 :            :     0,                          /* tp_weaklistoffset */
        5483                 :            :     0,                          /* tp_iter */
        5484                 :            :     0,                          /* tp_iternext */
        5485                 :            :     0,                          /* tp_methods */
        5486                 :            :     0,                          /* tp_members */
        5487                 :            :     0,                          /* tp_getset */
        5488                 :            :     0,                          /* tp_base */
        5489                 :            :     0,                          /* tp_dict */
        5490                 :            :     0,                          /* tp_descr_get */
        5491                 :            :     0,                          /* tp_descr_set */
        5492                 :            :     0,                          /* tp_dictoffset */
        5493                 :            :     (initproc)comerror_init,    /* tp_init */
        5494                 :            :     0,                          /* tp_alloc */
        5495                 :            :     0,                          /* tp_new */
        5496                 :            : };
        5497                 :            : #endif  // MS_WIN32
        5498                 :            :
        5499                 :            : static PyObject *
        5500                 :          0 : string_at(const char *ptr, int size)
        5501                 :            : {
        5502         [ #  # ]:          0 :     if (PySys_Audit("ctypes.string_at", "ni", (Py_ssize_t)ptr, size) < 0) {
        5503                 :          0 :         return NULL;
        5504                 :            :     }
        5505         [ #  # ]:          0 :     if (size == -1)
        5506                 :          0 :         return PyBytes_FromStringAndSize(ptr, strlen(ptr));
        5507                 :          0 :     return PyBytes_FromStringAndSize(ptr, size);
        5508                 :            : }
        5509                 :            :
        5510                 :            : static int
        5511                 :          0 : cast_check_pointertype(PyObject *arg)
        5512                 :            : {
        5513                 :            :     StgDictObject *dict;
        5514                 :            :
        5515         [ #  # ]:          0 :     if (PyCPointerTypeObject_Check(arg))
        5516                 :          0 :         return 1;
        5517         [ #  # ]:          0 :     if (PyCFuncPtrTypeObject_Check(arg))
        5518                 :          0 :         return 1;
        5519                 :          0 :     dict = PyType_stgdict(arg);
        5520   [ #  #  #  # ]:          0 :     if (dict != NULL && dict->proto != NULL) {
        5521         [ #  # ]:          0 :         if (PyUnicode_Check(dict->proto)
        5522         [ #  # ]:          0 :             && (strchr("sPzUZXO", PyUnicode_AsUTF8(dict->proto)[0]))) {
        5523                 :            :             /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
        5524                 :          0 :             return 1;
        5525                 :            :         }
        5526                 :            :     }
        5527         [ #  # ]:          0 :     PyErr_Format(PyExc_TypeError,
        5528                 :            :                  "cast() argument 2 must be a pointer type, not %s",
        5529                 :          0 :                  PyType_Check(arg)
        5530                 :            :                  ? ((PyTypeObject *)arg)->tp_name
        5531                 :          0 :                  : Py_TYPE(arg)->tp_name);
        5532                 :          0 :     return 0;
        5533                 :            : }
        5534                 :            :
        5535                 :            : static PyObject *
        5536                 :          0 : cast(void *ptr, PyObject *src, PyObject *ctype)
        5537                 :            : {
        5538                 :            :     CDataObject *result;
        5539         [ #  # ]:          0 :     if (0 == cast_check_pointertype(ctype))
        5540                 :          0 :         return NULL;
        5541                 :          0 :     result = (CDataObject *)_PyObject_CallNoArgs(ctype);
        5542         [ #  # ]:          0 :     if (result == NULL)
        5543                 :          0 :         return NULL;
        5544                 :            :
        5545                 :            :     /*
        5546                 :            :       The casted objects '_objects' member:
        5547                 :            :
        5548                 :            :       It must certainly contain the source objects one.
        5549                 :            :       It must contain the source object itself.
        5550                 :            :      */
        5551         [ #  # ]:          0 :     if (CDataObject_Check(src)) {
        5552                 :          0 :         CDataObject *obj = (CDataObject *)src;
        5553                 :            :         CDataObject *container;
        5554                 :            :
        5555                 :            :         /* PyCData_GetContainer will initialize src.b_objects, we need
        5556                 :            :            this so it can be shared */
        5557                 :          0 :         container = PyCData_GetContainer(obj);
        5558         [ #  # ]:          0 :         if (container == NULL)
        5559                 :          0 :             goto failed;
        5560                 :            :
        5561                 :            :         /* But we need a dictionary! */
        5562         [ #  # ]:          0 :         if (obj->b_objects == Py_None) {
        5563                 :          0 :             Py_DECREF(Py_None);
        5564                 :          0 :             obj->b_objects = PyDict_New();
        5565         [ #  # ]:          0 :             if (obj->b_objects == NULL)
        5566                 :          0 :                 goto failed;
        5567                 :            :         }
        5568                 :          0 :         result->b_objects = Py_XNewRef(obj->b_objects);
        5569   [ #  #  #  # ]:          0 :         if (result->b_objects && PyDict_CheckExact(result->b_objects)) {
        5570                 :            :             PyObject *index;
        5571                 :            :             int rc;
        5572                 :          0 :             index = PyLong_FromVoidPtr((void *)src);
        5573         [ #  # ]:          0 :             if (index == NULL)
        5574                 :          0 :                 goto failed;
        5575                 :          0 :             rc = PyDict_SetItem(result->b_objects, index, src);
        5576                 :          0 :             Py_DECREF(index);
        5577         [ #  # ]:          0 :             if (rc == -1)
        5578                 :          0 :                 goto failed;
        5579                 :            :         }
        5580                 :            :     }
        5581                 :            :     /* Should we assert that result is a pointer type? */
        5582                 :          0 :     memcpy(result->b_ptr, &ptr, sizeof(void *));
        5583                 :          0 :     return (PyObject *)result;
        5584                 :            :
        5585                 :          0 :   failed:
        5586                 :          0 :     Py_DECREF(result);
        5587                 :          0 :     return NULL;
        5588                 :            : }
        5589                 :            :
        5590                 :            :
        5591                 :            : static PyObject *
        5592                 :          0 : wstring_at(const wchar_t *ptr, int size)
        5593                 :            : {
        5594                 :          0 :     Py_ssize_t ssize = size;
        5595         [ #  # ]:          0 :     if (PySys_Audit("ctypes.wstring_at", "nn", (Py_ssize_t)ptr, ssize) < 0) {
        5596                 :          0 :         return NULL;
        5597                 :            :     }
        5598         [ #  # ]:          0 :     if (ssize == -1)
        5599                 :          0 :         ssize = wcslen(ptr);
        5600                 :          0 :     return PyUnicode_FromWideChar(ptr, ssize);
        5601                 :            : }
        5602                 :            :
        5603                 :            :
        5604                 :            : static struct PyModuleDef _ctypesmodule = {
        5605                 :            :     PyModuleDef_HEAD_INIT,
        5606                 :            :     .m_name = "_ctypes",
        5607                 :            :     .m_doc = _ctypes__doc__,
        5608                 :            :     .m_size = -1,
        5609                 :            :     .m_methods = _ctypes_module_methods,
        5610                 :            : };
        5611                 :            :
        5612                 :            :
        5613                 :            : static int
        5614                 :          2 : _ctypes_add_types(PyObject *mod)
        5615                 :            : {
        5616                 :            : #define TYPE_READY(TYPE) \
        5617                 :            :     if (PyType_Ready(TYPE) < 0) { \
        5618                 :            :         return -1; \
        5619                 :            :     }
        5620                 :            :
        5621                 :            : #define TYPE_READY_BASE(TYPE_EXPR, TP_BASE) \
        5622                 :            :     do { \
        5623                 :            :         PyTypeObject *type = (TYPE_EXPR); \
        5624                 :            :         type->tp_base = (TP_BASE); \
        5625                 :            :         TYPE_READY(type); \
        5626                 :            :     } while (0)
        5627                 :            :
        5628                 :            : #define MOD_ADD_TYPE(TYPE_EXPR, TP_TYPE, TP_BASE) \
        5629                 :            :     do { \
        5630                 :            :         PyTypeObject *type = (TYPE_EXPR); \
        5631                 :            :         Py_SET_TYPE(type, TP_TYPE); \
        5632                 :            :         type->tp_base = TP_BASE; \
        5633                 :            :         if (PyModule_AddType(mod, type) < 0) { \
        5634                 :            :             return -1; \
        5635                 :            :         } \
        5636                 :            :     } while (0)
        5637                 :            :
        5638                 :            :     /* Note:
        5639                 :            :        ob_type is the metatype (the 'type'), defaults to PyType_Type,
        5640                 :            :        tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
        5641                 :            :     */
        5642         [ -  + ]:          2 :     TYPE_READY(&PyCArg_Type);
        5643         [ -  + ]:          2 :     TYPE_READY(&PyCThunk_Type);
        5644         [ -  + ]:          2 :     TYPE_READY(&PyCData_Type);
        5645                 :            :     /* StgDict is derived from PyDict_Type */
        5646         [ -  + ]:          2 :     TYPE_READY_BASE(&PyCStgDict_Type, &PyDict_Type);
        5647                 :            :
        5648                 :            :     /*************************************************
        5649                 :            :      *
        5650                 :            :      * Metaclasses
        5651                 :            :      */
        5652         [ -  + ]:          2 :     TYPE_READY_BASE(&PyCStructType_Type, &PyType_Type);
        5653         [ -  + ]:          2 :     TYPE_READY_BASE(&UnionType_Type, &PyType_Type);
        5654         [ -  + ]:          2 :     TYPE_READY_BASE(&PyCPointerType_Type, &PyType_Type);
        5655         [ -  + ]:          2 :     TYPE_READY_BASE(&PyCArrayType_Type, &PyType_Type);
        5656         [ -  + ]:          2 :     TYPE_READY_BASE(&PyCSimpleType_Type, &PyType_Type);
        5657         [ -  + ]:          2 :     TYPE_READY_BASE(&PyCFuncPtrType_Type, &PyType_Type);
        5658                 :            :
        5659                 :            :     /*************************************************
        5660                 :            :      *
        5661                 :            :      * Classes using a custom metaclass
        5662                 :            :      */
        5663                 :            :
        5664         [ -  + ]:          2 :     MOD_ADD_TYPE(&Struct_Type, &PyCStructType_Type, &PyCData_Type);
        5665         [ -  + ]:          2 :     MOD_ADD_TYPE(&Union_Type, &UnionType_Type, &PyCData_Type);
        5666         [ -  + ]:          2 :     MOD_ADD_TYPE(&PyCPointer_Type, &PyCPointerType_Type, &PyCData_Type);
        5667         [ -  + ]:          2 :     MOD_ADD_TYPE(&PyCArray_Type, &PyCArrayType_Type, &PyCData_Type);
        5668         [ -  + ]:          2 :     MOD_ADD_TYPE(&Simple_Type, &PyCSimpleType_Type, &PyCData_Type);
        5669         [ -  + ]:          2 :     MOD_ADD_TYPE(&PyCFuncPtr_Type, &PyCFuncPtrType_Type, &PyCData_Type);
        5670                 :            :
        5671                 :            :     /*************************************************
        5672                 :            :      *
        5673                 :            :      * Simple classes
        5674                 :            :      */
        5675                 :            :
        5676                 :            :     /* PyCField_Type is derived from PyBaseObject_Type */
        5677         [ -  + ]:          2 :     TYPE_READY(&PyCField_Type);
        5678                 :            :
        5679                 :            :     /*************************************************
        5680                 :            :      *
        5681                 :            :      * Other stuff
        5682                 :            :      */
        5683                 :            :
        5684                 :          2 :     DictRemover_Type.tp_new = PyType_GenericNew;
        5685         [ -  + ]:          2 :     TYPE_READY(&DictRemover_Type);
        5686         [ -  + ]:          2 :     TYPE_READY(&StructParam_Type);
        5687                 :            :
        5688                 :            : #ifdef MS_WIN32
        5689                 :            :     TYPE_READY_BASE(&PyComError_Type, (PyTypeObject*)PyExc_Exception);
        5690                 :            : #endif
        5691                 :            :
        5692                 :            : #undef TYPE_READY
        5693                 :            : #undef TYPE_READY_BASE
        5694                 :            : #undef MOD_ADD_TYPE
        5695                 :          2 :     return 0;
        5696                 :            : }
        5697                 :            :
        5698                 :            :
        5699                 :            : static int
        5700                 :          2 : _ctypes_add_objects(PyObject *mod)
        5701                 :            : {
        5702                 :            : #define MOD_ADD(name, expr) \
        5703                 :            :     do { \
        5704                 :            :         PyObject *obj = (expr); \
        5705                 :            :         if (obj == NULL) { \
        5706                 :            :             return -1; \
        5707                 :            :         } \
        5708                 :            :         if (PyModule_AddObjectRef(mod, name, obj) < 0) { \
        5709                 :            :             Py_DECREF(obj); \
        5710                 :            :             return -1; \
        5711                 :            :         } \
        5712                 :            :         Py_DECREF(obj); \
        5713                 :            :     } while (0)
        5714                 :            :
        5715   [ -  +  -  + ]:          2 :     MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache));
        5716                 :            :
        5717                 :            : #ifdef MS_WIN32
        5718                 :            :     MOD_ADD("COMError", Py_NewRef(ComError));
        5719                 :            :     MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT));
        5720                 :            :     MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL));
        5721                 :            : #endif
        5722   [ -  +  -  + ]:          2 :     MOD_ADD("FUNCFLAG_CDECL", PyLong_FromLong(FUNCFLAG_CDECL));
        5723   [ -  +  -  + ]:          2 :     MOD_ADD("FUNCFLAG_USE_ERRNO", PyLong_FromLong(FUNCFLAG_USE_ERRNO));
        5724   [ -  +  -  + ]:          2 :     MOD_ADD("FUNCFLAG_USE_LASTERROR", PyLong_FromLong(FUNCFLAG_USE_LASTERROR));
        5725   [ -  +  -  + ]:          2 :     MOD_ADD("FUNCFLAG_PYTHONAPI", PyLong_FromLong(FUNCFLAG_PYTHONAPI));
        5726   [ -  +  -  + ]:          2 :     MOD_ADD("__version__", PyUnicode_FromString("1.1.0"));
        5727                 :            :
        5728   [ -  +  -  + ]:          2 :     MOD_ADD("_memmove_addr", PyLong_FromVoidPtr(memmove));
        5729   [ -  +  -  + ]:          2 :     MOD_ADD("_memset_addr", PyLong_FromVoidPtr(memset));
        5730   [ -  +  -  + ]:          2 :     MOD_ADD("_string_at_addr", PyLong_FromVoidPtr(string_at));
        5731   [ -  +  -  + ]:          2 :     MOD_ADD("_cast_addr", PyLong_FromVoidPtr(cast));
        5732   [ -  +  -  + ]:          2 :     MOD_ADD("_wstring_at_addr", PyLong_FromVoidPtr(wstring_at));
        5733                 :            :
        5734                 :            : /* If RTLD_LOCAL is not defined (Windows!), set it to zero. */
        5735                 :            : #if !HAVE_DECL_RTLD_LOCAL
        5736                 :            : #  define RTLD_LOCAL 0
        5737                 :            : #endif
        5738                 :            :
        5739                 :            : /* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as
        5740                 :            :    RTLD_LOCAL. */
        5741                 :            : #if !HAVE_DECL_RTLD_GLOBAL
        5742                 :            : #  define RTLD_GLOBAL RTLD_LOCAL
        5743                 :            : #endif
        5744   [ -  +  -  + ]:          2 :     MOD_ADD("RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL));
        5745   [ -  +  -  + ]:          2 :     MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL));
        5746   [ -  +  -  + ]:          2 :     MOD_ADD("CTYPES_MAX_ARGCOUNT", PyLong_FromLong(CTYPES_MAX_ARGCOUNT));
        5747   [ -  +  -  + ]:          2 :     MOD_ADD("ArgumentError", Py_NewRef(PyExc_ArgError));
        5748   [ -  +  -  + ]:          2 :     MOD_ADD("SIZEOF_TIME_T", PyLong_FromSsize_t(SIZEOF_TIME_T));
        5749                 :          2 :     return 0;
        5750                 :            : #undef MOD_ADD
        5751                 :            : }
        5752                 :            :
        5753                 :            :
        5754                 :            : static int
        5755                 :          2 : _ctypes_mod_exec(PyObject *mod)
        5756                 :            : {
        5757                 :          2 :     _unpickle = PyObject_GetAttrString(mod, "_unpickle");
        5758         [ -  + ]:          2 :     if (_unpickle == NULL) {
        5759                 :          0 :         return -1;
        5760                 :            :     }
        5761                 :            :
        5762                 :          2 :     _ctypes_ptrtype_cache = PyDict_New();
        5763         [ -  + ]:          2 :     if (_ctypes_ptrtype_cache == NULL) {
        5764                 :          0 :         return -1;
        5765                 :            :     }
        5766                 :            :
        5767                 :          2 :     PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL);
        5768         [ -  + ]:          2 :     if (!PyExc_ArgError) {
        5769                 :          0 :         return -1;
        5770                 :            :     }
        5771                 :            :
        5772         [ -  + ]:          2 :     if (_ctypes_add_types(mod) < 0) {
        5773                 :          0 :         return -1;
        5774                 :            :     }
        5775                 :            : #ifdef MS_WIN32
        5776                 :            :     ComError = (PyObject*)&PyComError_Type;
        5777                 :            : #endif
        5778                 :            :
        5779         [ -  + ]:          2 :     if (_ctypes_add_objects(mod) < 0) {
        5780                 :          0 :         return -1;
        5781                 :            :     }
        5782                 :          2 :     return 0;
        5783                 :            : }
        5784                 :            :
        5785                 :            :
        5786                 :            : PyMODINIT_FUNC
        5787                 :          2 : PyInit__ctypes(void)
        5788                 :            : {
        5789                 :          2 :     PyObject *mod = PyModule_Create(&_ctypesmodule);
        5790         [ -  + ]:          2 :     if (!mod) {
        5791                 :          0 :         return NULL;
        5792                 :            :     }
        5793                 :            :
        5794         [ -  + ]:          2 :     if (_ctypes_mod_exec(mod) < 0) {
        5795                 :          0 :         Py_DECREF(mod);
        5796                 :          0 :         return NULL;
        5797                 :            :     }
        5798                 :          2 :     return mod;
        5799                 :            : }
        5800                 :            :
        5801                 :            : /*
        5802                 :            :  Local Variables:
        5803                 :            :  compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~"
        5804                 :            :  End:
        5805                 :            : */

Generated by: LCOV version 1.14