diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/cffi/c | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/cffi/c')
-rw-r--r-- | contrib/python/cffi/c/_cffi_backend.c | 3456 | ||||
-rw-r--r-- | contrib/python/cffi/c/call_python.c | 94 | ||||
-rw-r--r-- | contrib/python/cffi/c/cdlopen.c | 44 | ||||
-rw-r--r-- | contrib/python/cffi/c/cffi1_module.c | 18 | ||||
-rw-r--r-- | contrib/python/cffi/c/cglob.c | 2 | ||||
-rw-r--r-- | contrib/python/cffi/c/ffi_obj.c | 102 | ||||
-rw-r--r-- | contrib/python/cffi/c/file_emulator.h | 2 | ||||
-rw-r--r-- | contrib/python/cffi/c/lib_obj.c | 92 | ||||
-rw-r--r-- | contrib/python/cffi/c/libffi_msvc/ffi.c | 46 | ||||
-rw-r--r-- | contrib/python/cffi/c/libffi_msvc/prep_cif.c | 8 | ||||
-rw-r--r-- | contrib/python/cffi/c/minibuffer.h | 250 | ||||
-rw-r--r-- | contrib/python/cffi/c/misc_thread_common.h | 530 | ||||
-rw-r--r-- | contrib/python/cffi/c/misc_win32.h | 18 | ||||
-rw-r--r-- | contrib/python/cffi/c/parse_c_type.c | 34 | ||||
-rw-r--r-- | contrib/python/cffi/c/realize_c_type.c | 88 | ||||
-rw-r--r-- | contrib/python/cffi/c/test_c.py | 2028 | ||||
-rw-r--r-- | contrib/python/cffi/c/wchar_helper.h | 290 | ||||
-rw-r--r-- | contrib/python/cffi/c/wchar_helper_3.h | 298 |
18 files changed, 3700 insertions, 3700 deletions
diff --git a/contrib/python/cffi/c/_cffi_backend.c b/contrib/python/cffi/c/_cffi_backend.c index a92402b6a22..db7fad8e088 100644 --- a/contrib/python/cffi/c/_cffi_backend.c +++ b/contrib/python/cffi/c/_cffi_backend.c @@ -2,7 +2,7 @@ #include <Python.h> #include "structmember.h" -#define CFFI_VERSION "1.15.0" +#define CFFI_VERSION "1.15.0" #ifdef MS_WIN32 #include <windows.h> @@ -61,66 +61,66 @@ #endif -/* Define the following macro ONLY if you trust libffi's version of - * ffi_closure_alloc() more than the code in malloc_closure.h. - * IMPORTANT: DO NOT ENABLE THIS ON LINUX, unless you understand exactly - * why I recommend against it and decide that you trust it more than my - * analysis below. - * - * There are two versions of this code: one inside libffi itself, and - * one inside malloc_closure.h here. Both should be fine as long as the - * Linux distribution does _not_ enable extra security features. If it - * does, then the code in malloc_closure.h will cleanly crash because - * there is no reasonable way to obtain a read-write-execute memory - * page. On the other hand, the code in libffi will appear to - * work---but will actually randomly crash after a fork() if the child - * does not immediately call exec(). This second crash is of the kind - * that can be turned into an attack vector by a motivated attacker. - * So, _enabling_ extra security features _opens_ an attack vector. - * That sounds like a horribly bad idea to me, and is the reason for why - * I prefer CFFI crashing cleanly. - * - * Currently, we use libffi's ffi_closure_alloc() on NetBSD. It is - * known that on the NetBSD kernel, a different strategy is used which - * should not be open to the fork() bug. - * - * This is also used on macOS, provided we are executing on macOS 10.15 or - * above. It's a mess because it needs runtime checks in that case. - */ -#ifdef __NetBSD__ - -# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1 -# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1 -# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1 -# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1 -# define CFFI_CHECK_FFI_PREP_CIF_VAR 0 -# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0 - -#elif defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) - -# define CFFI_CHECK_FFI_CLOSURE_ALLOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) -# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1 -# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) -# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1 -# define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) -# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1 - -#else - -# define CFFI_CHECK_FFI_CLOSURE_ALLOC 0 -# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 0 -# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 0 -# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 0 -# define CFFI_CHECK_FFI_PREP_CIF_VAR 0 -# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0 - -#endif - -/* always includes this, even if it turns out not to be used on NetBSD - because calls are behind "if (0)" */ -#include "malloc_closure.h" - - +/* Define the following macro ONLY if you trust libffi's version of + * ffi_closure_alloc() more than the code in malloc_closure.h. + * IMPORTANT: DO NOT ENABLE THIS ON LINUX, unless you understand exactly + * why I recommend against it and decide that you trust it more than my + * analysis below. + * + * There are two versions of this code: one inside libffi itself, and + * one inside malloc_closure.h here. Both should be fine as long as the + * Linux distribution does _not_ enable extra security features. If it + * does, then the code in malloc_closure.h will cleanly crash because + * there is no reasonable way to obtain a read-write-execute memory + * page. On the other hand, the code in libffi will appear to + * work---but will actually randomly crash after a fork() if the child + * does not immediately call exec(). This second crash is of the kind + * that can be turned into an attack vector by a motivated attacker. + * So, _enabling_ extra security features _opens_ an attack vector. + * That sounds like a horribly bad idea to me, and is the reason for why + * I prefer CFFI crashing cleanly. + * + * Currently, we use libffi's ffi_closure_alloc() on NetBSD. It is + * known that on the NetBSD kernel, a different strategy is used which + * should not be open to the fork() bug. + * + * This is also used on macOS, provided we are executing on macOS 10.15 or + * above. It's a mess because it needs runtime checks in that case. + */ +#ifdef __NetBSD__ + +# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1 +# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1 +# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1 +# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1 +# define CFFI_CHECK_FFI_PREP_CIF_VAR 0 +# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0 + +#elif defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) + +# define CFFI_CHECK_FFI_CLOSURE_ALLOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) +# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1 +# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) +# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1 +# define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) +# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1 + +#else + +# define CFFI_CHECK_FFI_CLOSURE_ALLOC 0 +# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 0 +# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 0 +# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 0 +# define CFFI_CHECK_FFI_PREP_CIF_VAR 0 +# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0 + +#endif + +/* always includes this, even if it turns out not to be used on NetBSD + because calls are behind "if (0)" */ +#include "malloc_closure.h" + + #if PY_MAJOR_VERSION >= 3 # define STR_OR_BYTES "bytes" # define PyText_Type PyUnicode_Type @@ -129,11 +129,11 @@ # define PyText_FromFormat PyUnicode_FromFormat # define PyText_AsUTF8 _PyUnicode_AsString /* PyUnicode_AsUTF8 in Py3.3 */ # define PyText_AS_UTF8 _PyUnicode_AsString -# if PY_VERSION_HEX >= 0x03030000 -# define PyText_GetSize PyUnicode_GetLength -# else -# define PyText_GetSize PyUnicode_GetSize -# endif +# if PY_VERSION_HEX >= 0x03030000 +# define PyText_GetSize PyUnicode_GetLength +# else +# define PyText_GetSize PyUnicode_GetSize +# endif # define PyText_FromString PyUnicode_FromString # define PyText_FromStringAndSize PyUnicode_FromStringAndSize # define PyText_InternInPlace PyUnicode_InternInPlace @@ -176,50 +176,50 @@ (PyCObject_FromVoidPtr(pointer, destructor)) #endif -#if PY_VERSION_HEX < 0x030900a4 -# define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val)) -#endif - -#if PY_VERSION_HEX >= 0x03080000 -# define USE_WRITEUNRAISABLEMSG -#endif - +#if PY_VERSION_HEX < 0x030900a4 +# define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val)) +#endif + +#if PY_VERSION_HEX >= 0x03080000 +# define USE_WRITEUNRAISABLEMSG +#endif + /************************************************************/ /* base type flag: exactly one of the following: */ -#define CT_PRIMITIVE_SIGNED 0x001 /* signed integer */ -#define CT_PRIMITIVE_UNSIGNED 0x002 /* unsigned integer */ -#define CT_PRIMITIVE_CHAR 0x004 /* char, wchar_t, charN_t */ -#define CT_PRIMITIVE_FLOAT 0x008 /* float, double, long double */ -#define CT_POINTER 0x010 /* pointer, excluding ptr-to-func */ -#define CT_ARRAY 0x020 /* array */ -#define CT_STRUCT 0x040 /* struct */ -#define CT_UNION 0x080 /* union */ -#define CT_FUNCTIONPTR 0x100 /* pointer to function */ -#define CT_VOID 0x200 /* void */ -#define CT_PRIMITIVE_COMPLEX 0x400 /* float _Complex, double _Complex */ +#define CT_PRIMITIVE_SIGNED 0x001 /* signed integer */ +#define CT_PRIMITIVE_UNSIGNED 0x002 /* unsigned integer */ +#define CT_PRIMITIVE_CHAR 0x004 /* char, wchar_t, charN_t */ +#define CT_PRIMITIVE_FLOAT 0x008 /* float, double, long double */ +#define CT_POINTER 0x010 /* pointer, excluding ptr-to-func */ +#define CT_ARRAY 0x020 /* array */ +#define CT_STRUCT 0x040 /* struct */ +#define CT_UNION 0x080 /* union */ +#define CT_FUNCTIONPTR 0x100 /* pointer to function */ +#define CT_VOID 0x200 /* void */ +#define CT_PRIMITIVE_COMPLEX 0x400 /* float _Complex, double _Complex */ /* other flags that may also be set in addition to the base flag: */ -#define CT_IS_VOIDCHAR_PTR 0x00001000 -#define CT_PRIMITIVE_FITS_LONG 0x00002000 -#define CT_IS_OPAQUE 0x00004000 -#define CT_IS_ENUM 0x00008000 -#define CT_IS_PTR_TO_OWNED 0x00010000 /* only owned if CDataOwning_Type */ -#define CT_CUSTOM_FIELD_POS 0x00020000 -#define CT_IS_LONGDOUBLE 0x00040000 -#define CT_IS_BOOL 0x00080000 -#define CT_IS_FILE 0x00100000 -#define CT_IS_VOID_PTR 0x00200000 -#define CT_WITH_VAR_ARRAY 0x00400000 /* with open-ended array, anywhere */ -/* unused 0x00800000 */ -#define CT_LAZY_FIELD_LIST 0x01000000 -#define CT_WITH_PACKED_CHANGE 0x02000000 -#define CT_IS_SIGNED_WCHAR 0x04000000 +#define CT_IS_VOIDCHAR_PTR 0x00001000 +#define CT_PRIMITIVE_FITS_LONG 0x00002000 +#define CT_IS_OPAQUE 0x00004000 +#define CT_IS_ENUM 0x00008000 +#define CT_IS_PTR_TO_OWNED 0x00010000 /* only owned if CDataOwning_Type */ +#define CT_CUSTOM_FIELD_POS 0x00020000 +#define CT_IS_LONGDOUBLE 0x00040000 +#define CT_IS_BOOL 0x00080000 +#define CT_IS_FILE 0x00100000 +#define CT_IS_VOID_PTR 0x00200000 +#define CT_WITH_VAR_ARRAY 0x00400000 /* with open-ended array, anywhere */ +/* unused 0x00800000 */ +#define CT_LAZY_FIELD_LIST 0x01000000 +#define CT_WITH_PACKED_CHANGE 0x02000000 +#define CT_IS_SIGNED_WCHAR 0x04000000 #define CT_PRIMITIVE_ANY (CT_PRIMITIVE_SIGNED | \ CT_PRIMITIVE_UNSIGNED | \ CT_PRIMITIVE_CHAR | \ - CT_PRIMITIVE_FLOAT | \ - CT_PRIMITIVE_COMPLEX) + CT_PRIMITIVE_FLOAT | \ + CT_PRIMITIVE_COMPLEX) typedef struct _ctypedescr { PyObject_VAR_HEAD @@ -274,14 +274,14 @@ static PyTypeObject CField_Type; static PyTypeObject CData_Type; static PyTypeObject CDataOwning_Type; static PyTypeObject CDataOwningGC_Type; -static PyTypeObject CDataFromBuf_Type; +static PyTypeObject CDataFromBuf_Type; static PyTypeObject CDataGCP_Type; #define CTypeDescr_Check(ob) (Py_TYPE(ob) == &CTypeDescr_Type) #define CData_Check(ob) (Py_TYPE(ob) == &CData_Type || \ Py_TYPE(ob) == &CDataOwning_Type || \ Py_TYPE(ob) == &CDataOwningGC_Type || \ - Py_TYPE(ob) == &CDataFromBuf_Type || \ + Py_TYPE(ob) == &CDataFromBuf_Type || \ Py_TYPE(ob) == &CDataGCP_Type) #define CDataOwn_Check(ob) (Py_TYPE(ob) == &CDataOwning_Type || \ Py_TYPE(ob) == &CDataOwningGC_Type) @@ -314,14 +314,14 @@ typedef struct { typedef struct { CDataObject head; - PyObject *structobj; /* for ffi.new_handle() or ffi.new("struct *") */ + PyObject *structobj; /* for ffi.new_handle() or ffi.new("struct *") */ } CDataObject_own_structptr; typedef struct { CDataObject head; Py_ssize_t length; /* same as CDataObject_own_length up to here */ Py_buffer *bufferview; -} CDataObject_frombuf; +} CDataObject_frombuf; typedef struct { CDataObject head; @@ -331,11 +331,11 @@ typedef struct { } CDataObject_gcp; typedef struct { - CDataObject head; - ffi_closure *closure; -} CDataObject_closure; - -typedef struct { + CDataObject head; + ffi_closure *closure; +} CDataObject_closure; + +typedef struct { ffi_cif cif; /* the following information is used when doing the call: - a buffer of size 'exchange_size' is malloced @@ -363,14 +363,14 @@ typedef struct { # include "file_emulator.h" #endif -#ifdef PyUnicode_KIND /* Python >= 3.3 */ -# include "wchar_helper_3.h" -#else +#ifdef PyUnicode_KIND /* Python >= 3.3 */ +# include "wchar_helper_3.h" +#else # include "wchar_helper.h" #endif -#include "../cffi/_cffi_errors.h" - +#include "../cffi/_cffi_errors.h" + typedef struct _cffi_allocator_s { PyObject *ca_alloc, *ca_free; int ca_dont_clear; @@ -439,10 +439,10 @@ ctypedescr_dealloc(CTypeDescrObject *ct) if (ct->ct_unique_key != NULL) { /* revive dead object temporarily for DelItem */ - Py_SET_REFCNT(ct, 43); + Py_SET_REFCNT(ct, 43); PyDict_DelItem(unique_cache, ct->ct_unique_key); assert(Py_REFCNT(ct) == 42); - Py_SET_REFCNT(ct, 0); + Py_SET_REFCNT(ct, 0); Py_DECREF(ct->ct_unique_key); } Py_XDECREF(ct->ct_itemdescr); @@ -539,8 +539,8 @@ static PyObject *ctypeget_length(CTypeDescrObject *ct, void *context) static PyObject * get_field_name(CTypeDescrObject *ct, CFieldObject *cf); /* forward */ -/* returns 0 if the struct ctype is opaque, 1 if it is not, or -1 if - an exception occurs */ +/* returns 0 if the struct ctype is opaque, 1 if it is not, or -1 if + an exception occurs */ #define force_lazy_struct(ct) \ ((ct)->ct_stuff != NULL ? 1 : do_realize_lazy_struct(ct)) @@ -688,7 +688,7 @@ static PyMethodDef ctypedescr_methods[] = { static PyTypeObject CTypeDescr_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.CType", + "_cffi_backend.CType", offsetof(CTypeDescrObject, ct_name), sizeof(char), (destructor)ctypedescr_dealloc, /* tp_dealloc */ @@ -929,21 +929,21 @@ read_raw_unsigned_data(char *target, int size) return 0; } -#ifdef __GNUC__ -/* This is a workaround for what I think is a GCC bug on several - platforms. See issue #378. */ -__attribute__((noinline)) -#endif -void _cffi_memcpy(char *target, const void *src, size_t size) -{ - memcpy(target, src, size); -} - +#ifdef __GNUC__ +/* This is a workaround for what I think is a GCC bug on several + platforms. See issue #378. */ +__attribute__((noinline)) +#endif +void _cffi_memcpy(char *target, const void *src, size_t size) +{ + memcpy(target, src, size); +} + #define _write_raw_data(type) \ do { \ if (size == sizeof(type)) { \ type r = (type)source; \ - _cffi_memcpy(target, &r, sizeof(type)); \ + _cffi_memcpy(target, &r, sizeof(type)); \ return; \ } \ } while(0) @@ -977,26 +977,26 @@ read_raw_longdouble_data(char *target) return 0; } -static Py_complex -read_raw_complex_data(char *target, int size) -{ - Py_complex r = {0.0, 0.0}; - if (size == 2*sizeof(float)) { - float real_part, imag_part; - memcpy(&real_part, target + 0, sizeof(float)); - memcpy(&imag_part, target + sizeof(float), sizeof(float)); - r.real = real_part; - r.imag = imag_part; - return r; - } - if (size == 2*sizeof(double)) { - memcpy(&r, target, 2*sizeof(double)); - return r; - } - Py_FatalError("read_raw_complex_data: bad complex size"); - return r; -} - +static Py_complex +read_raw_complex_data(char *target, int size) +{ + Py_complex r = {0.0, 0.0}; + if (size == 2*sizeof(float)) { + float real_part, imag_part; + memcpy(&real_part, target + 0, sizeof(float)); + memcpy(&imag_part, target + sizeof(float), sizeof(float)); + r.real = real_part; + r.imag = imag_part; + return r; + } + if (size == 2*sizeof(double)) { + memcpy(&r, target, 2*sizeof(double)); + return r; + } + Py_FatalError("read_raw_complex_data: bad complex size"); + return r; +} + static void write_raw_float_data(char *target, double source, int size) { @@ -1012,25 +1012,25 @@ write_raw_longdouble_data(char *target, long double source) _write_raw_data(long double); } -#define _write_raw_complex_data(type) \ - do { \ - if (size == 2*sizeof(type)) { \ - type r = (type)source.real; \ - type i = (type)source.imag; \ - _cffi_memcpy(target, &r, sizeof(type)); \ - _cffi_memcpy(target+sizeof(type), &i, sizeof(type)); \ - return; \ - } \ - } while(0) - -static void -write_raw_complex_data(char *target, Py_complex source, int size) -{ - _write_raw_complex_data(float); - _write_raw_complex_data(double); - Py_FatalError("write_raw_complex_data: bad complex size"); -} - +#define _write_raw_complex_data(type) \ + do { \ + if (size == 2*sizeof(type)) { \ + type r = (type)source.real; \ + type i = (type)source.imag; \ + _cffi_memcpy(target, &r, sizeof(type)); \ + _cffi_memcpy(target+sizeof(type), &i, sizeof(type)); \ + return; \ + } \ + } while(0) + +static void +write_raw_complex_data(char *target, Py_complex source, int size) +{ + _write_raw_complex_data(float); + _write_raw_complex_data(double); + Py_FatalError("write_raw_complex_data: bad complex size"); +} + static PyObject * new_simple_cdata(char *data, CTypeDescrObject *ct) { @@ -1105,23 +1105,23 @@ convert_to_object(char *data, CTypeDescrObject *ct) /*READ(data, ct->ct_size)*/ value = read_raw_unsigned_data(data, ct->ct_size); - if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) { - if (ct->ct_flags & CT_IS_BOOL) { - PyObject *x; - switch ((int)value) { - case 0: x = Py_False; break; - case 1: x = Py_True; break; - default: - PyErr_Format(PyExc_ValueError, - "got a _Bool of value %d, expected 0 or 1", - (int)value); - return NULL; - } - Py_INCREF(x); - return x; - } + if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) { + if (ct->ct_flags & CT_IS_BOOL) { + PyObject *x; + switch ((int)value) { + case 0: x = Py_False; break; + case 1: x = Py_True; break; + default: + PyErr_Format(PyExc_ValueError, + "got a _Bool of value %d, expected 0 or 1", + (int)value); + return NULL; + } + Py_INCREF(x); + return x; + } return PyInt_FromLong((long)value); - } + } else return PyLong_FromUnsignedLongLong(value); } @@ -1141,19 +1141,19 @@ convert_to_object(char *data, CTypeDescrObject *ct) } else if (ct->ct_flags & CT_PRIMITIVE_CHAR) { /*READ(data, ct->ct_size)*/ - switch (ct->ct_size) { - case sizeof(char): + switch (ct->ct_size) { + case sizeof(char): return PyBytes_FromStringAndSize(data, 1); - case 2: - return _my_PyUnicode_FromChar16((cffi_char16_t *)data, 1); - case 4: - return _my_PyUnicode_FromChar32((cffi_char32_t *)data, 1); - } - } - else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { - Py_complex value = read_raw_complex_data(data, ct->ct_size); - return PyComplex_FromCComplex(value); + case 2: + return _my_PyUnicode_FromChar16((cffi_char16_t *)data, 1); + case 4: + return _my_PyUnicode_FromChar32((cffi_char32_t *)data, 1); + } } + else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { + Py_complex value = read_raw_complex_data(data, ct->ct_size); + return PyComplex_FromCComplex(value); + } PyErr_Format(PyExc_SystemError, "convert_to_object: '%s'", ct->ct_name); @@ -1227,65 +1227,65 @@ static int _convert_to_char(PyObject *init) return -1; } -static cffi_char16_t _convert_to_char16_t(PyObject *init) +static cffi_char16_t _convert_to_char16_t(PyObject *init) { - char err_got[80]; - err_got[0] = 0; - - if (PyUnicode_Check(init)) { - cffi_char16_t ordinal; - if (_my_PyUnicode_AsSingleChar16(init, &ordinal, err_got) == 0) - return ordinal; - } - if (CData_Check(init) && - (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) && - (((CDataObject *)init)->c_type->ct_size == 2)) { - char *data = ((CDataObject *)init)->c_data; - /*READ(data, 2)*/ - return *(cffi_char16_t *)data; - } - PyErr_Format(PyExc_TypeError, - "initializer for ctype 'char16_t' must be a unicode string " - "of length 1, not %.200s", - err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got); - return (cffi_char16_t)-1; -} - -static cffi_char32_t _convert_to_char32_t(PyObject *init) -{ - char err_got[80]; - err_got[0] = 0; - + char err_got[80]; + err_got[0] = 0; + if (PyUnicode_Check(init)) { - cffi_char32_t ordinal; - if (_my_PyUnicode_AsSingleChar32(init, &ordinal, err_got) == 0) + cffi_char16_t ordinal; + if (_my_PyUnicode_AsSingleChar16(init, &ordinal, err_got) == 0) return ordinal; } if (CData_Check(init) && (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) && - (((CDataObject *)init)->c_type->ct_size == 4)) { + (((CDataObject *)init)->c_type->ct_size == 2)) { char *data = ((CDataObject *)init)->c_data; - /*READ(data, 4)*/ - return *(cffi_char32_t *)data; + /*READ(data, 2)*/ + return *(cffi_char16_t *)data; } PyErr_Format(PyExc_TypeError, - "initializer for ctype 'char32_t' must be a unicode string " - "of length 1, not %.200s", - err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got); - return (cffi_char32_t)-1; + "initializer for ctype 'char16_t' must be a unicode string " + "of length 1, not %.200s", + err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got); + return (cffi_char16_t)-1; } -static int _convert_error(PyObject *init, CTypeDescrObject *ct, +static cffi_char32_t _convert_to_char32_t(PyObject *init) +{ + char err_got[80]; + err_got[0] = 0; + + if (PyUnicode_Check(init)) { + cffi_char32_t ordinal; + if (_my_PyUnicode_AsSingleChar32(init, &ordinal, err_got) == 0) + return ordinal; + } + if (CData_Check(init) && + (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) && + (((CDataObject *)init)->c_type->ct_size == 4)) { + char *data = ((CDataObject *)init)->c_data; + /*READ(data, 4)*/ + return *(cffi_char32_t *)data; + } + PyErr_Format(PyExc_TypeError, + "initializer for ctype 'char32_t' must be a unicode string " + "of length 1, not %.200s", + err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got); + return (cffi_char32_t)-1; +} + +static int _convert_error(PyObject *init, CTypeDescrObject *ct, const char *expected) { if (CData_Check(init)) { - CTypeDescrObject *ct2 = ((CDataObject *)init)->c_type; - if (strcmp(ct->ct_name, ct2->ct_name) != 0) + CTypeDescrObject *ct2 = ((CDataObject *)init)->c_type; + if (strcmp(ct->ct_name, ct2->ct_name) != 0) PyErr_Format(PyExc_TypeError, "initializer for ctype '%s' must be a %s, " "not cdata '%s'", - ct->ct_name, expected, ct2->ct_name); - else if (ct != ct2) { + ct->ct_name, expected, ct2->ct_name); + else if (ct != ct2) { /* in case we'd give the error message "initializer for ctype 'A' must be a pointer to same type, not cdata 'B'", but with A=B, then give instead a different error @@ -1294,21 +1294,21 @@ static int _convert_error(PyObject *init, CTypeDescrObject *ct, "initializer for ctype '%s' appears indeed to be '%s'," " but the types are different (check that you are not" " e.g. mixing up different ffi instances)", - ct->ct_name, ct2->ct_name); - } - else - { - PyErr_Format(PyExc_SystemError, - "initializer for ctype '%s' is correct, but we get " - "an internal mismatch--please report a bug", - ct->ct_name); + ct->ct_name, ct2->ct_name); } + else + { + PyErr_Format(PyExc_SystemError, + "initializer for ctype '%s' is correct, but we get " + "an internal mismatch--please report a bug", + ct->ct_name); + } } else PyErr_Format(PyExc_TypeError, "initializer for ctype '%s' must be a %s, " "not %.200s", - ct->ct_name, expected, Py_TYPE(init)->tp_name); + ct->ct_name, expected, Py_TYPE(init)->tp_name); return -1; } @@ -1318,7 +1318,7 @@ static int /* forward */ convert_from_object_bitfield(char *data, CFieldObject *cf, PyObject *init); static Py_ssize_t -get_new_array_length(CTypeDescrObject *ctitem, PyObject **pvalue) +get_new_array_length(CTypeDescrObject *ctitem, PyObject **pvalue) { PyObject *value = *pvalue; @@ -1331,24 +1331,24 @@ get_new_array_length(CTypeDescrObject *ctitem, PyObject **pvalue) } else if (PyUnicode_Check(value)) { /* from a unicode, we add the null terminator */ - int length; - if (ctitem->ct_size == 2) - length = _my_PyUnicode_SizeAsChar16(value); - else - length = _my_PyUnicode_SizeAsChar32(value); - return length + 1; + int length; + if (ctitem->ct_size == 2) + length = _my_PyUnicode_SizeAsChar16(value); + else + length = _my_PyUnicode_SizeAsChar32(value); + return length + 1; } else { Py_ssize_t explicitlength; explicitlength = PyNumber_AsSsize_t(value, PyExc_OverflowError); if (explicitlength < 0) { - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "expected new array length or list/tuple/str, " - "not %.200s", Py_TYPE(value)->tp_name); - } - else + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) + PyErr_Format(PyExc_TypeError, + "expected new array length or list/tuple/str, " + "not %.200s", Py_TYPE(value)->tp_name); + } + else PyErr_SetString(PyExc_ValueError, "negative array length"); return -1; } @@ -1368,46 +1368,46 @@ convert_field_from_object(char *data, CFieldObject *cf, PyObject *value) } static int -add_varsize_length(Py_ssize_t offset, Py_ssize_t itemsize, - Py_ssize_t varsizelength, Py_ssize_t *optvarsize) -{ - /* update '*optvarsize' to account for an array of 'varsizelength' - elements, each of size 'itemsize', that starts at 'offset'. */ - Py_ssize_t size = ADD_WRAPAROUND(offset, - MUL_WRAPAROUND(itemsize, varsizelength)); - if (size < 0 || - ((size - offset) / itemsize) != varsizelength) { - PyErr_SetString(PyExc_OverflowError, - "array size would overflow a Py_ssize_t"); - return -1; - } - if (size > *optvarsize) - *optvarsize = size; - return 0; -} - -static int -convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init, - Py_ssize_t *optvarsize); /* forward */ - -static int +add_varsize_length(Py_ssize_t offset, Py_ssize_t itemsize, + Py_ssize_t varsizelength, Py_ssize_t *optvarsize) +{ + /* update '*optvarsize' to account for an array of 'varsizelength' + elements, each of size 'itemsize', that starts at 'offset'. */ + Py_ssize_t size = ADD_WRAPAROUND(offset, + MUL_WRAPAROUND(itemsize, varsizelength)); + if (size < 0 || + ((size - offset) / itemsize) != varsizelength) { + PyErr_SetString(PyExc_OverflowError, + "array size would overflow a Py_ssize_t"); + return -1; + } + if (size > *optvarsize) + *optvarsize = size; + return 0; +} + +static int +convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init, + Py_ssize_t *optvarsize); /* forward */ + +static int convert_vfield_from_object(char *data, CFieldObject *cf, PyObject *value, Py_ssize_t *optvarsize) { /* a special case for var-sized C99 arrays */ if ((cf->cf_type->ct_flags & CT_ARRAY) && cf->cf_type->ct_size < 0) { - Py_ssize_t varsizelength = get_new_array_length( - cf->cf_type->ct_itemdescr, &value); + Py_ssize_t varsizelength = get_new_array_length( + cf->cf_type->ct_itemdescr, &value); if (varsizelength < 0) return -1; if (optvarsize != NULL) { /* in this mode, the only purpose of this function is to compute the real size of the structure from a var-sized C99 array */ assert(data == NULL); - return add_varsize_length(cf->cf_offset, - cf->cf_type->ct_itemdescr->ct_size, - varsizelength, - optvarsize); + return add_varsize_length(cf->cf_offset, + cf->cf_type->ct_itemdescr->ct_size, + varsizelength, + optvarsize); } /* if 'value' was only an integer, get_new_array_length() returns it and convert 'value' to be None. Detect if this was the case, @@ -1416,44 +1416,44 @@ convert_vfield_from_object(char *data, CFieldObject *cf, PyObject *value, if (value == Py_None) return 0; } - if (optvarsize == NULL) { + if (optvarsize == NULL) { return convert_field_from_object(data, cf, value); - } - else if ((cf->cf_type->ct_flags & CT_WITH_VAR_ARRAY) != 0 && - !CData_Check(value)) { - Py_ssize_t subsize = cf->cf_type->ct_size; - if (convert_struct_from_object(NULL, cf->cf_type, value, &subsize) < 0) - return -1; - return add_varsize_length(cf->cf_offset, 1, subsize, optvarsize); - } + } + else if ((cf->cf_type->ct_flags & CT_WITH_VAR_ARRAY) != 0 && + !CData_Check(value)) { + Py_ssize_t subsize = cf->cf_type->ct_size; + if (convert_struct_from_object(NULL, cf->cf_type, value, &subsize) < 0) + return -1; + return add_varsize_length(cf->cf_offset, 1, subsize, optvarsize); + } else return 0; } static int -must_be_array_of_zero_or_one(const char *data, Py_ssize_t n) -{ - Py_ssize_t i; - for (i = 0; i < n; i++) { - if (((unsigned char)data[i]) > 1) { - PyErr_SetString(PyExc_ValueError, - "an array of _Bool can only contain \\x00 or \\x01"); - return -1; - } - } - return 0; -} - -static Py_ssize_t -get_array_length(CDataObject *cd) -{ - if (cd->c_type->ct_length < 0) - return ((CDataObject_own_length *)cd)->length; - else - return cd->c_type->ct_length; -} - -static int +must_be_array_of_zero_or_one(const char *data, Py_ssize_t n) +{ + Py_ssize_t i; + for (i = 0; i < n; i++) { + if (((unsigned char)data[i]) > 1) { + PyErr_SetString(PyExc_ValueError, + "an array of _Bool can only contain \\x00 or \\x01"); + return -1; + } + } + return 0; +} + +static Py_ssize_t +get_array_length(CDataObject *cd) +{ + if (cd->c_type->ct_length < 0) + return ((CDataObject_own_length *)cd)->length; + else + return cd->c_type->ct_length; +} + +static int convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init) { /* used by convert_from_object(), and also to decode lists/tuples/unicodes @@ -1500,9 +1500,9 @@ convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init) if (n != ct->ct_length) n++; srcdata = PyBytes_AS_STRING(init); - if (ctitem->ct_flags & CT_IS_BOOL) - if (must_be_array_of_zero_or_one(srcdata, n) < 0) - return -1; + if (ctitem->ct_flags & CT_IS_BOOL) + if (must_be_array_of_zero_or_one(srcdata, n) < 0) + return -1; memcpy(data, srcdata, n); return 0; } @@ -1512,12 +1512,12 @@ convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init) expected = "unicode or list or tuple"; goto cannot_convert; } - - if (ctitem->ct_size == 4) - n = _my_PyUnicode_SizeAsChar32(init); - else - n = _my_PyUnicode_SizeAsChar16(init); - + + if (ctitem->ct_size == 4) + n = _my_PyUnicode_SizeAsChar32(init); + else + n = _my_PyUnicode_SizeAsChar16(init); + if (ct->ct_length >= 0 && n > ct->ct_length) { PyErr_Format(PyExc_IndexError, "initializer unicode is too long for '%s' " @@ -1526,10 +1526,10 @@ convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init) } if (n != ct->ct_length) n++; - if (ctitem->ct_size == 4) - return _my_PyUnicode_AsChar32(init, (cffi_char32_t *)data, n); - else - return _my_PyUnicode_AsChar16(init, (cffi_char16_t *)data, n); + if (ctitem->ct_size == 4) + return _my_PyUnicode_AsChar32(init, (cffi_char32_t *)data, n); + else + return _my_PyUnicode_AsChar16(init, (cffi_char16_t *)data, n); } } else { @@ -1538,24 +1538,24 @@ convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init) } cannot_convert: - if ((ct->ct_flags & CT_ARRAY) && CData_Check(init)) - { - CDataObject *cd = (CDataObject *)init; - if (cd->c_type == ct) - { - Py_ssize_t n = get_array_length(cd); - memcpy(data, cd->c_data, n * ctitem->ct_size); - return 0; - } - } - return _convert_error(init, ct, expected); + if ((ct->ct_flags & CT_ARRAY) && CData_Check(init)) + { + CDataObject *cd = (CDataObject *)init; + if (cd->c_type == ct) + { + Py_ssize_t n = get_array_length(cd); + memcpy(data, cd->c_data, n * ctitem->ct_size); + return 0; + } + } + return _convert_error(init, ct, expected); } static int convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init, Py_ssize_t *optvarsize) { - /* does not accept 'init' being already a CData */ + /* does not accept 'init' being already a CData */ const char *expected; if (force_lazy_struct(ct) <= 0) { @@ -1602,7 +1602,7 @@ convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init, } expected = optvarsize == NULL ? "list or tuple or dict or struct-cdata" : "list or tuple or dict"; - return _convert_error(init, ct, expected); + return _convert_error(init, ct, expected); } #ifdef __GNUC__ @@ -1652,8 +1652,8 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) /* for backward compatibility, accept "char *" as either source of target. This is not what C does, though, so emit a warning that will eventually turn into an - error. The warning is turned off if both types are - pointers to single bytes. */ + error. The warning is turned off if both types are + pointers to single bytes. */ char *msg = (ct->ct_flags & CT_IS_VOIDCHAR_PTR ? "implicit cast to 'char *' from a different pointer type: " "will be forbidden in the future (check that the types " @@ -1663,12 +1663,12 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) "will be forbidden in the future (check that the types " "are as you expect; use an explicit ffi.cast() if they " "are correct)"); - if ((ct->ct_flags & ctinit->ct_flags & CT_POINTER) && - ct->ct_itemdescr->ct_size == 1 && - ctinit->ct_itemdescr->ct_size == 1) { - /* no warning */ - } - else if (PyErr_WarnEx(PyExc_UserWarning, msg, 1)) + if ((ct->ct_flags & ctinit->ct_flags & CT_POINTER) && + ct->ct_itemdescr->ct_size == 1 && + ctinit->ct_itemdescr->ct_size == 1) { + /* no warning */ + } + else if (PyErr_WarnEx(PyExc_UserWarning, msg, 1)) return -1; } else { @@ -1695,15 +1695,15 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) unsigned PY_LONG_LONG value = _my_PyLong_AsUnsignedLongLong(init, 1); if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) return -1; - if (ct->ct_flags & CT_IS_BOOL) { - if (value > 1ULL) /* value != 0 && value != 1 */ - goto overflow; - } - else { - write_raw_integer_data(buf, value, ct->ct_size); - if (value != read_raw_unsigned_data(buf, ct->ct_size)) + if (ct->ct_flags & CT_IS_BOOL) { + if (value > 1ULL) /* value != 0 && value != 1 */ goto overflow; - } + } + else { + write_raw_integer_data(buf, value, ct->ct_size); + if (value != read_raw_unsigned_data(buf, ct->ct_size)) + goto overflow; + } write_raw_integer_data(data, value, ct->ct_size); return 0; } @@ -1729,29 +1729,29 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) return 0; } if (ct->ct_flags & CT_PRIMITIVE_CHAR) { - switch (ct->ct_size) { - case sizeof(char): { + switch (ct->ct_size) { + case sizeof(char): { int res = _convert_to_char(init); if (res < 0) return -1; data[0] = res; return 0; } - case 2: { - cffi_char16_t res = _convert_to_char16_t(init); - if (res == (cffi_char16_t)-1 && PyErr_Occurred()) - return -1; - *(cffi_char16_t *)data = res; - return 0; - } - case 4: { - cffi_char32_t res = _convert_to_char32_t(init); - if (res == (cffi_char32_t)-1 && PyErr_Occurred()) + case 2: { + cffi_char16_t res = _convert_to_char16_t(init); + if (res == (cffi_char16_t)-1 && PyErr_Occurred()) return -1; - *(cffi_char32_t *)data = res; + *(cffi_char16_t *)data = res; return 0; } - } + case 4: { + cffi_char32_t res = _convert_to_char32_t(init); + if (res == (cffi_char32_t)-1 && PyErr_Occurred()) + return -1; + *(cffi_char32_t *)data = res; + return 0; + } + } } if (ct->ct_flags & (CT_STRUCT|CT_UNION)) { @@ -1763,13 +1763,13 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) } return convert_struct_from_object(data, ct, init, NULL); } - if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { - Py_complex value = PyComplex_AsCComplex(init); - if (PyErr_Occurred()) - return -1; - write_raw_complex_data(data, value, ct->ct_size); - return 0; - } + if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { + Py_complex value = PyComplex_AsCComplex(init); + if (PyErr_Occurred()) + return -1; + write_raw_complex_data(data, value, ct->ct_size); + return 0; + } PyErr_Format(PyExc_SystemError, "convert_from_object: '%s'", ct->ct_name); return -1; @@ -1778,7 +1778,7 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) return _convert_overflow(init, ct->ct_name); cannot_convert: - return _convert_error(init, ct, expected); + return _convert_error(init, ct, expected); } static int @@ -1890,7 +1890,7 @@ static void cdataowning_dealloc(CDataObject *cd) assert(!(cd->c_type->ct_flags & (CT_IS_VOID_PTR | CT_FUNCTIONPTR))); if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) { - /* for ffi.new("struct *") */ + /* for ffi.new("struct *") */ Py_DECREF(((CDataObject_own_structptr *)cd)->structobj); } #if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK) @@ -1918,31 +1918,31 @@ static void cdataowninggc_dealloc(CDataObject *cd) Py_DECREF(x); } else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */ - ffi_closure *closure = ((CDataObject_closure *)cd)->closure; + ffi_closure *closure = ((CDataObject_closure *)cd)->closure; PyObject *args = (PyObject *)(closure->user_data); Py_XDECREF(args); -#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE - if (CFFI_CHECK_FFI_CLOSURE_ALLOC) { - ffi_closure_free(closure); - } else -#endif - cffi_closure_free(closure); +#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE + if (CFFI_CHECK_FFI_CLOSURE_ALLOC) { + ffi_closure_free(closure); + } else +#endif + cffi_closure_free(closure); } - else { - Py_FatalError("cdata CDataOwningGC_Type with unexpected type flags"); + else { + Py_FatalError("cdata CDataOwningGC_Type with unexpected type flags"); } cdata_dealloc(cd); } -static void cdatafrombuf_dealloc(CDataObject *cd) -{ - Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; - cdata_dealloc(cd); - - PyBuffer_Release(view); - PyObject_Free(view); -} - +static void cdatafrombuf_dealloc(CDataObject *cd) +{ + Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; + cdata_dealloc(cd); + + PyBuffer_Release(view); + PyObject_Free(view); +} + static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg) { if (cd->c_type->ct_flags & CT_IS_VOID_PTR) { /* a handle */ @@ -1950,20 +1950,20 @@ static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg) Py_VISIT(x); } else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */ - ffi_closure *closure = ((CDataObject_closure *)cd)->closure; + ffi_closure *closure = ((CDataObject_closure *)cd)->closure; PyObject *args = (PyObject *)(closure->user_data); Py_VISIT(args); } return 0; } -static int cdatafrombuf_traverse(CDataObject *cd, visitproc visit, void *arg) -{ - Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; - Py_VISIT(view->obj); - return 0; -} - +static int cdatafrombuf_traverse(CDataObject *cd, visitproc visit, void *arg) +{ + Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; + Py_VISIT(view->obj); + return 0; +} + static int cdataowninggc_clear(CDataObject *cd) { if (cd->c_type->ct_flags & CT_IS_VOID_PTR) { /* a handle */ @@ -1974,7 +1974,7 @@ static int cdataowninggc_clear(CDataObject *cd) Py_DECREF(x); } else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */ - ffi_closure *closure = ((CDataObject_closure *)cd)->closure; + ffi_closure *closure = ((CDataObject_closure *)cd)->closure; PyObject *args = (PyObject *)(closure->user_data); closure->user_data = NULL; Py_XDECREF(args); @@ -1982,16 +1982,16 @@ static int cdataowninggc_clear(CDataObject *cd) return 0; } -static int cdatafrombuf_clear(CDataObject *cd) -{ - Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; - PyBuffer_Release(view); - return 0; -} - +static int cdatafrombuf_clear(CDataObject *cd) +{ + Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; + PyBuffer_Release(view); + return 0; +} + /* forward */ -static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, - char *objdescr, PyObject *obj, +static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, + char *objdescr, PyObject *obj, char *extra_error_line); @@ -2011,15 +2011,15 @@ static void gcp_finalize(PyObject *destructor, PyObject *origobj) Py_DECREF(result); } else { - PyObject *t, *v, *tb; - PyErr_Fetch(&t, &v, &tb); - /* Don't use error capture here, because it is very much - * like errors at __del__(), and these ones are not captured - * either */ - /* ecap = _cffi_start_error_capture(); */ - _my_PyErr_WriteUnraisable(t, v, tb, "From callback for ffi.gc ", + PyObject *t, *v, *tb; + PyErr_Fetch(&t, &v, &tb); + /* Don't use error capture here, because it is very much + * like errors at __del__(), and these ones are not captured + * either */ + /* ecap = _cffi_start_error_capture(); */ + _my_PyErr_WriteUnraisable(t, v, tb, "From callback for ffi.gc ", origobj, NULL); - /* _cffi_stop_error_capture(ecap); */ + /* _cffi_stop_error_capture(ecap); */ } Py_DECREF(destructor); @@ -2167,35 +2167,35 @@ static Py_ssize_t _cdata_var_byte_size(CDataObject *cd) return -1; } -static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name) -{ - Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; - const char *obj_tp_name; - if (view->obj == NULL) { - return PyText_FromFormat( - "<cdata '%s' buffer RELEASED>", - cd_type_name); - } - - obj_tp_name = Py_TYPE(view->obj)->tp_name; - if (cd->c_type->ct_flags & CT_ARRAY) - { - Py_ssize_t buflen = get_array_length(cd); - return PyText_FromFormat( - "<cdata '%s' buffer len %zd from '%.200s' object>", - cd_type_name, - buflen, - obj_tp_name); - } - else - { - return PyText_FromFormat( - "<cdata '%s' buffer from '%.200s' object>", - cd_type_name, - obj_tp_name); - } -} - +static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name) +{ + Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; + const char *obj_tp_name; + if (view->obj == NULL) { + return PyText_FromFormat( + "<cdata '%s' buffer RELEASED>", + cd_type_name); + } + + obj_tp_name = Py_TYPE(view->obj)->tp_name; + if (cd->c_type->ct_flags & CT_ARRAY) + { + Py_ssize_t buflen = get_array_length(cd); + return PyText_FromFormat( + "<cdata '%s' buffer len %zd from '%.200s' object>", + cd_type_name, + buflen, + obj_tp_name); + } + else + { + return PyText_FromFormat( + "<cdata '%s' buffer from '%.200s' object>", + cd_type_name, + obj_tp_name); + } +} + static PyObject *cdataowning_repr(CDataObject *cd) { Py_ssize_t size = _cdata_var_byte_size(cd); @@ -2218,21 +2218,21 @@ static PyObject *cdataowninggc_repr(CDataObject *cd) return _cdata_repr2(cd, "handle to", x); } else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) { /* a callback */ - ffi_closure *closure = ((CDataObject_closure *)cd)->closure; - PyObject *args = (PyObject *)closure->user_data; + ffi_closure *closure = ((CDataObject_closure *)cd)->closure; + PyObject *args = (PyObject *)closure->user_data; if (args == NULL) return cdata_repr(cd); else return _cdata_repr2(cd, "calling", PyTuple_GET_ITEM(args, 1)); } - return cdataowning_repr(cd); /* but should be unreachable */ -} - -static PyObject *cdatafrombuf_repr(CDataObject *cd) -{ - return _frombuf_repr(cd, cd->c_type->ct_name); + return cdataowning_repr(cd); /* but should be unreachable */ } +static PyObject *cdatafrombuf_repr(CDataObject *cd) +{ + return _frombuf_repr(cd, cd->c_type->ct_name); +} + static int cdata_nonzero(CDataObject *cd) { if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) { @@ -2246,11 +2246,11 @@ static int cdata_nonzero(CDataObject *cd) return read_raw_longdouble_data(cd->c_data) != 0.0; return read_raw_float_data(cd->c_data, cd->c_type->ct_size) != 0.0; } - if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { - Py_complex value = read_raw_complex_data(cd->c_data, - cd->c_type->ct_size); - return value.real != 0.0 || value.imag != 0.0; - } + if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { + Py_complex value = read_raw_complex_data(cd->c_data, + cd->c_type->ct_size); + return value.real != 0.0 || value.imag != 0.0; + } } return cd->c_data != NULL; } @@ -2267,26 +2267,26 @@ static PyObject *cdata_int(CDataObject *cd) return PyInt_FromLong(value); } if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) { - PyObject *result = convert_to_object(cd->c_data, cd->c_type); - if (result != NULL && PyBool_Check(result)) - result = PyInt_FromLong(PyInt_AsLong(result)); - return result; + PyObject *result = convert_to_object(cd->c_data, cd->c_type); + if (result != NULL && PyBool_Check(result)) + result = PyInt_FromLong(PyInt_AsLong(result)); + return result; } else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) { /*READ(cd->c_data, cd->c_type->ct_size)*/ - switch (cd->c_type->ct_size) { - case sizeof(char): + switch (cd->c_type->ct_size) { + case sizeof(char): return PyInt_FromLong((unsigned char)cd->c_data[0]); - case 2: - return PyInt_FromLong((long)*(cffi_char16_t *)cd->c_data); - case 4: - if (cd->c_type->ct_flags & CT_IS_SIGNED_WCHAR) - return PyInt_FromLong((long)*(int32_t *)cd->c_data); - else if (sizeof(long) > 4) - return PyInt_FromLong(*(uint32_t *)cd->c_data); - else - return PyLong_FromUnsignedLong(*(uint32_t *)cd->c_data); - } + case 2: + return PyInt_FromLong((long)*(cffi_char16_t *)cd->c_data); + case 4: + if (cd->c_type->ct_flags & CT_IS_SIGNED_WCHAR) + return PyInt_FromLong((long)*(int32_t *)cd->c_data); + else if (sizeof(long) > 4) + return PyInt_FromLong(*(uint32_t *)cd->c_data); + else + return PyLong_FromUnsignedLong(*(uint32_t *)cd->c_data); + } } else if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) { PyObject *o = cdata_float(cd); @@ -2336,101 +2336,101 @@ static PyObject *cdata_float(CDataObject *cd) static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op) { - int v_is_ptr, w_is_ptr; + int v_is_ptr, w_is_ptr; PyObject *pyres; assert(CData_Check(v)); - - /* Comparisons involving a primitive cdata work differently than - * comparisons involving a struct/array/pointer. - * - * If v or w is a struct/array/pointer, then the other must be too - * (otherwise we return NotImplemented and leave the case to - * Python). If both are, then we compare the addresses. - * - * If v and/or w is a primitive cdata, then we convert the cdata(s) - * to regular Python objects and redo the comparison there. - */ - - v_is_ptr = !(((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY); - w_is_ptr = CData_Check(w) && - !(((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY); - - if (v_is_ptr && w_is_ptr) { - int res; - char *v_cdata = ((CDataObject *)v)->c_data; - char *w_cdata = ((CDataObject *)w)->c_data; - - switch (op) { - case Py_EQ: res = (v_cdata == w_cdata); break; - case Py_NE: res = (v_cdata != w_cdata); break; - case Py_LT: res = (v_cdata < w_cdata); break; - case Py_LE: res = (v_cdata <= w_cdata); break; - case Py_GT: res = (v_cdata > w_cdata); break; - case Py_GE: res = (v_cdata >= w_cdata); break; - default: res = -1; - } - pyres = res ? Py_True : Py_False; - } - else if (v_is_ptr || w_is_ptr) { + + /* Comparisons involving a primitive cdata work differently than + * comparisons involving a struct/array/pointer. + * + * If v or w is a struct/array/pointer, then the other must be too + * (otherwise we return NotImplemented and leave the case to + * Python). If both are, then we compare the addresses. + * + * If v and/or w is a primitive cdata, then we convert the cdata(s) + * to regular Python objects and redo the comparison there. + */ + + v_is_ptr = !(((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY); + w_is_ptr = CData_Check(w) && + !(((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY); + + if (v_is_ptr && w_is_ptr) { + int res; + char *v_cdata = ((CDataObject *)v)->c_data; + char *w_cdata = ((CDataObject *)w)->c_data; + + switch (op) { + case Py_EQ: res = (v_cdata == w_cdata); break; + case Py_NE: res = (v_cdata != w_cdata); break; + case Py_LT: res = (v_cdata < w_cdata); break; + case Py_LE: res = (v_cdata <= w_cdata); break; + case Py_GT: res = (v_cdata > w_cdata); break; + case Py_GE: res = (v_cdata >= w_cdata); break; + default: res = -1; + } + pyres = res ? Py_True : Py_False; + } + else if (v_is_ptr || w_is_ptr) { pyres = Py_NotImplemented; } - else { - PyObject *aa[2]; - int i; - - aa[0] = v; Py_INCREF(v); - aa[1] = w; Py_INCREF(w); - pyres = NULL; - - for (i = 0; i < 2; i++) { - v = aa[i]; - if (!CData_Check(v)) - continue; - w = convert_to_object(((CDataObject *)v)->c_data, - ((CDataObject *)v)->c_type); - if (w == NULL) - goto error; - if (CData_Check(w)) { - Py_DECREF(w); - PyErr_Format(PyExc_NotImplementedError, - "cannot use <cdata '%s'> in a comparison", - ((CDataObject *)v)->c_type->ct_name); - goto error; - } - aa[i] = w; - Py_DECREF(v); - } - pyres = PyObject_RichCompare(aa[0], aa[1], op); - error: - Py_DECREF(aa[1]); - Py_DECREF(aa[0]); - return pyres; - } + else { + PyObject *aa[2]; + int i; + + aa[0] = v; Py_INCREF(v); + aa[1] = w; Py_INCREF(w); + pyres = NULL; + + for (i = 0; i < 2; i++) { + v = aa[i]; + if (!CData_Check(v)) + continue; + w = convert_to_object(((CDataObject *)v)->c_data, + ((CDataObject *)v)->c_type); + if (w == NULL) + goto error; + if (CData_Check(w)) { + Py_DECREF(w); + PyErr_Format(PyExc_NotImplementedError, + "cannot use <cdata '%s'> in a comparison", + ((CDataObject *)v)->c_type->ct_name); + goto error; + } + aa[i] = w; + Py_DECREF(v); + } + pyres = PyObject_RichCompare(aa[0], aa[1], op); + error: + Py_DECREF(aa[1]); + Py_DECREF(aa[0]); + return pyres; + } Py_INCREF(pyres); return pyres; } -#if PY_MAJOR_VERSION < 3 -typedef long Py_hash_t; -#endif - -static Py_hash_t cdata_hash(PyObject *v) -{ - if (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) { - PyObject *vv = convert_to_object(((CDataObject *)v)->c_data, - ((CDataObject *)v)->c_type); - if (vv == NULL) - return -1; - if (!CData_Check(vv)) { - Py_hash_t hash = PyObject_Hash(vv); - Py_DECREF(vv); - return hash; - } - Py_DECREF(vv); - } - return _Py_HashPointer(((CDataObject *)v)->c_data); +#if PY_MAJOR_VERSION < 3 +typedef long Py_hash_t; +#endif + +static Py_hash_t cdata_hash(PyObject *v) +{ + if (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) { + PyObject *vv = convert_to_object(((CDataObject *)v)->c_data, + ((CDataObject *)v)->c_type); + if (vv == NULL) + return -1; + if (!CData_Check(vv)) { + Py_hash_t hash = PyObject_Hash(vv); + Py_DECREF(vv); + return hash; + } + Py_DECREF(vv); + } + return _Py_HashPointer(((CDataObject *)v)->c_data); } static Py_ssize_t @@ -2472,7 +2472,7 @@ _cdata_get_indexed_ptr(CDataObject *cd, PyObject *key) else if (cd->c_type->ct_flags & CT_ARRAY) { if (i < 0) { PyErr_SetString(PyExc_IndexError, - "negative index"); + "negative index"); return NULL; } if (i >= get_array_length(cd)) { @@ -2525,7 +2525,7 @@ _cdata_getslicearg(CDataObject *cd, PySliceObject *slice, Py_ssize_t bounds[]) if (ct->ct_flags & CT_ARRAY) { if (start < 0) { PyErr_SetString(PyExc_IndexError, - "negative index"); + "negative index"); return NULL; } if (stop > get_array_length(cd)) { @@ -2813,26 +2813,26 @@ cdata_sub(PyObject *v, PyObject *w) return _cdata_add_or_sub(v, w, -1); } -static void -_cdata_attr_errmsg(char *errmsg, CDataObject *cd, PyObject *attr) -{ - const char *text; - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return; - PyErr_Clear(); - text = PyText_AsUTF8(attr); - if (text == NULL) - return; - PyErr_Format(PyExc_AttributeError, errmsg, cd->c_type->ct_name, text); -} - +static void +_cdata_attr_errmsg(char *errmsg, CDataObject *cd, PyObject *attr) +{ + const char *text; + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return; + PyErr_Clear(); + text = PyText_AsUTF8(attr); + if (text == NULL) + return; + PyErr_Format(PyExc_AttributeError, errmsg, cd->c_type->ct_name, text); +} + static PyObject * cdata_getattro(CDataObject *cd, PyObject *attr) { CFieldObject *cf; CTypeDescrObject *ct = cd->c_type; - char *errmsg = "cdata '%s' has no attribute '%s'"; - PyObject *x; + char *errmsg = "cdata '%s' has no attribute '%s'"; + PyObject *x; if (ct->ct_flags & CT_POINTER) ct = ct->ct_itemdescr; @@ -2864,19 +2864,19 @@ cdata_getattro(CDataObject *cd, PyObject *attr) return new_simple_cdata(data, (CTypeDescrObject *)cf->cf_type->ct_stuff); } - errmsg = "cdata '%s' has no field '%s'"; + errmsg = "cdata '%s' has no field '%s'"; break; case -1: return NULL; default: - errmsg = "cdata '%s' points to an opaque type: cannot read fields"; + errmsg = "cdata '%s' points to an opaque type: cannot read fields"; break; } } - x = PyObject_GenericGetAttr((PyObject *)cd, attr); - if (x == NULL) - _cdata_attr_errmsg(errmsg, cd, attr); - return x; + x = PyObject_GenericGetAttr((PyObject *)cd, attr); + if (x == NULL) + _cdata_attr_errmsg(errmsg, cd, attr); + return x; } static int @@ -2884,8 +2884,8 @@ cdata_setattro(CDataObject *cd, PyObject *attr, PyObject *value) { CFieldObject *cf; CTypeDescrObject *ct = cd->c_type; - char *errmsg = "cdata '%s' has no attribute '%s'"; - int x; + char *errmsg = "cdata '%s' has no attribute '%s'"; + int x; if (ct->ct_flags & CT_POINTER) ct = ct->ct_itemdescr; @@ -2905,27 +2905,27 @@ cdata_setattro(CDataObject *cd, PyObject *attr, PyObject *value) return -1; } } - errmsg = "cdata '%s' has no field '%s'"; + errmsg = "cdata '%s' has no field '%s'"; break; case -1: return -1; default: - errmsg = "cdata '%s' points to an opaque type: cannot write fields"; + errmsg = "cdata '%s' points to an opaque type: cannot write fields"; break; } } - x = PyObject_GenericSetAttr((PyObject *)cd, attr, value); - if (x < 0) - _cdata_attr_errmsg(errmsg, cd, attr); - return x; + x = PyObject_GenericSetAttr((PyObject *)cd, attr, value); + if (x < 0) + _cdata_attr_errmsg(errmsg, cd, attr); + return x; } static PyObject * convert_struct_to_owning_object(char *data, CTypeDescrObject *ct); /*forward*/ static cif_description_t * -fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi); - /*forward*/ +fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi); + /*forward*/ static PyObject *new_primitive_type(const char *name); /*forward*/ @@ -2968,10 +2968,10 @@ _prepare_pointer_call_argument(CTypeDescrObject *ctptr, PyObject *init, length = PyBytes_GET_SIZE(init) + 1; #else *output_data = PyBytes_AS_STRING(init); - if (ctitem->ct_flags & CT_IS_BOOL) - if (must_be_array_of_zero_or_one(*output_data, - PyBytes_GET_SIZE(init)) < 0) - return -1; + if (ctitem->ct_flags & CT_IS_BOOL) + if (must_be_array_of_zero_or_one(*output_data, + PyBytes_GET_SIZE(init)) < 0) + return -1; return 0; #endif } @@ -2983,11 +2983,11 @@ _prepare_pointer_call_argument(CTypeDescrObject *ctptr, PyObject *init, } else if (PyUnicode_Check(init)) { /* from a unicode, we add the null terminator */ - if (ctitem->ct_size == 2) - length = _my_PyUnicode_SizeAsChar16(init); - else - length = _my_PyUnicode_SizeAsChar32(init); - length += 1; + if (ctitem->ct_size == 2) + length = _my_PyUnicode_SizeAsChar16(init); + else + length = _my_PyUnicode_SizeAsChar32(init); + length += 1; } else if ((ctitem->ct_flags & CT_IS_FILE) && PyFile_Check(init)) { *output_data = (char *)PyFile_AsFile(init); @@ -3028,22 +3028,22 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds) CTypeDescrObject *fresult; char *resultdata; char *errormsg; - struct freeme_s { - struct freeme_s *next; - union_alignment alignment; - } *freeme = NULL; + struct freeme_s { + struct freeme_s *next; + union_alignment alignment; + } *freeme = NULL; if (!(cd->c_type->ct_flags & CT_FUNCTIONPTR)) { PyErr_Format(PyExc_TypeError, "cdata '%s' is not callable", cd->c_type->ct_name); return NULL; } - if (cd->c_data == NULL) { - PyErr_Format(PyExc_RuntimeError, - "cannot call null pointer pointer from cdata '%s'", - cd->c_type->ct_name); - return NULL; - } + if (cd->c_data == NULL) { + PyErr_Format(PyExc_RuntimeError, + "cannot call null pointer pointer from cdata '%s'", + cd->c_type->ct_name); + return NULL; + } if (kwds != NULL && PyDict_Size(kwds) != 0) { PyErr_SetString(PyExc_TypeError, "a cdata function cannot be called with keyword arguments"); @@ -3118,7 +3118,7 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds) #else fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0)); #endif - cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi); + cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi); if (cif_descr == NULL) goto error; } @@ -3152,21 +3152,21 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds) else if (datasize < 0) goto error; else { - if (datasize <= 512) { - tmpbuf = alloca(datasize); - } - else { - struct freeme_s *fp = (struct freeme_s *)PyObject_Malloc( - offsetof(struct freeme_s, alignment) + - (size_t)datasize); - if (fp == NULL) { - PyErr_NoMemory(); - goto error; - } - fp->next = freeme; - freeme = fp; - tmpbuf = (char *)&fp->alignment; - } + if (datasize <= 512) { + tmpbuf = alloca(datasize); + } + else { + struct freeme_s *fp = (struct freeme_s *)PyObject_Malloc( + offsetof(struct freeme_s, alignment) + + (size_t)datasize); + if (fp == NULL) { + PyErr_NoMemory(); + goto error; + } + fp->next = freeme; + freeme = fp; + tmpbuf = (char *)&fp->alignment; + } memset(tmpbuf, 0, datasize); *(char **)data = tmpbuf; if (convert_array_from_object(tmpbuf, argtype, obj) < 0) @@ -3211,11 +3211,11 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds) /* fall-through */ error: - while (freeme != NULL) { - void *p = (void *)freeme; - freeme = freeme->next; - PyObject_Free(p); - } + while (freeme != NULL) { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } if (buffer) PyObject_Free(buffer); if (fvarargs != NULL) { @@ -3247,92 +3247,92 @@ static PyObject *cdata_dir(PyObject *cd, PyObject *noarg) } } -static PyObject *cdata_complex(PyObject *cd_, PyObject *noarg) -{ - CDataObject *cd = (CDataObject *)cd_; - - if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { - Py_complex value = read_raw_complex_data(cd->c_data, cd->c_type->ct_size); - PyObject *op = PyComplex_FromCComplex(value); - return op; - } - /* <cdata 'float'> or <cdata 'int'> cannot be directly converted by - calling complex(), just like <cdata 'int'> cannot be directly - converted by calling float() */ - - PyErr_Format(PyExc_TypeError, "complex() not supported on cdata '%s'", - cd->c_type->ct_name); - return NULL; -} - -static int explicit_release_case(PyObject *cd) -{ - CTypeDescrObject *ct = ((CDataObject *)cd)->c_type; - if (Py_TYPE(cd) == &CDataOwning_Type) { - if ((ct->ct_flags & (CT_POINTER | CT_ARRAY)) != 0) /* ffi.new() */ - return 0; - } - else if (Py_TYPE(cd) == &CDataFromBuf_Type) { - return 1; /* ffi.from_buffer() */ - } - else if (Py_TYPE(cd) == &CDataGCP_Type) { - return 2; /* ffi.gc() */ - } - PyErr_SetString(PyExc_ValueError, - "only 'cdata' object from ffi.new(), ffi.gc(), ffi.from_buffer() " - "or ffi.new_allocator()() can be used with the 'with' keyword or " - "ffi.release()"); - return -1; -} - -static PyObject *cdata_enter(PyObject *cd, PyObject *noarg) -{ - if (explicit_release_case(cd) < 0) /* only to check the ctype */ - return NULL; - Py_INCREF(cd); - return cd; -} - -static PyObject *cdata_exit(PyObject *cd, PyObject *args) -{ - /* 'args' ignored */ - CTypeDescrObject *ct; - Py_buffer *view; - switch (explicit_release_case(cd)) - { - case 0: /* ffi.new() */ - /* no effect on CPython: raw memory is allocated with the - same malloc() as the object itself, so it can't be - released independently. If we use a custom allocator, - then it's implemented with ffi.gc(). */ - ct = ((CDataObject *)cd)->c_type; - if (ct->ct_flags & CT_IS_PTR_TO_OWNED) { - PyObject *x = ((CDataObject_own_structptr *)cd)->structobj; - if (Py_TYPE(x) == &CDataGCP_Type) { - /* this is a special case for - ffi.new_allocator()("struct-or-union *") */ - cdatagcp_finalize((CDataObject_gcp *)x); - } - } - break; - - case 1: /* ffi.from_buffer() */ - view = ((CDataObject_frombuf *)cd)->bufferview; - PyBuffer_Release(view); - break; - - case 2: /* ffi.gc() or ffi.new_allocator()("not-struct-nor-union") */ - /* call the destructor immediately */ - cdatagcp_finalize((CDataObject_gcp *)cd); - break; - - default: - return NULL; - } - Py_INCREF(Py_None); - return Py_None; -} - +static PyObject *cdata_complex(PyObject *cd_, PyObject *noarg) +{ + CDataObject *cd = (CDataObject *)cd_; + + if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { + Py_complex value = read_raw_complex_data(cd->c_data, cd->c_type->ct_size); + PyObject *op = PyComplex_FromCComplex(value); + return op; + } + /* <cdata 'float'> or <cdata 'int'> cannot be directly converted by + calling complex(), just like <cdata 'int'> cannot be directly + converted by calling float() */ + + PyErr_Format(PyExc_TypeError, "complex() not supported on cdata '%s'", + cd->c_type->ct_name); + return NULL; +} + +static int explicit_release_case(PyObject *cd) +{ + CTypeDescrObject *ct = ((CDataObject *)cd)->c_type; + if (Py_TYPE(cd) == &CDataOwning_Type) { + if ((ct->ct_flags & (CT_POINTER | CT_ARRAY)) != 0) /* ffi.new() */ + return 0; + } + else if (Py_TYPE(cd) == &CDataFromBuf_Type) { + return 1; /* ffi.from_buffer() */ + } + else if (Py_TYPE(cd) == &CDataGCP_Type) { + return 2; /* ffi.gc() */ + } + PyErr_SetString(PyExc_ValueError, + "only 'cdata' object from ffi.new(), ffi.gc(), ffi.from_buffer() " + "or ffi.new_allocator()() can be used with the 'with' keyword or " + "ffi.release()"); + return -1; +} + +static PyObject *cdata_enter(PyObject *cd, PyObject *noarg) +{ + if (explicit_release_case(cd) < 0) /* only to check the ctype */ + return NULL; + Py_INCREF(cd); + return cd; +} + +static PyObject *cdata_exit(PyObject *cd, PyObject *args) +{ + /* 'args' ignored */ + CTypeDescrObject *ct; + Py_buffer *view; + switch (explicit_release_case(cd)) + { + case 0: /* ffi.new() */ + /* no effect on CPython: raw memory is allocated with the + same malloc() as the object itself, so it can't be + released independently. If we use a custom allocator, + then it's implemented with ffi.gc(). */ + ct = ((CDataObject *)cd)->c_type; + if (ct->ct_flags & CT_IS_PTR_TO_OWNED) { + PyObject *x = ((CDataObject_own_structptr *)cd)->structobj; + if (Py_TYPE(x) == &CDataGCP_Type) { + /* this is a special case for + ffi.new_allocator()("struct-or-union *") */ + cdatagcp_finalize((CDataObject_gcp *)x); + } + } + break; + + case 1: /* ffi.from_buffer() */ + view = ((CDataObject_frombuf *)cd)->bufferview; + PyBuffer_Release(view); + break; + + case 2: /* ffi.gc() or ffi.new_allocator()("not-struct-nor-union") */ + /* call the destructor immediately */ + cdatagcp_finalize((CDataObject_gcp *)cd); + break; + + default: + return NULL; + } + Py_INCREF(Py_None); + return Py_None; +} + static PyObject *cdata_iter(CDataObject *); static PyNumberMethods CData_as_number = { @@ -3382,16 +3382,16 @@ static PyMappingMethods CDataOwn_as_mapping = { }; static PyMethodDef cdata_methods[] = { - {"__dir__", cdata_dir, METH_NOARGS}, - {"__complex__", cdata_complex, METH_NOARGS}, - {"__enter__", cdata_enter, METH_NOARGS}, - {"__exit__", cdata_exit, METH_VARARGS}, - {NULL, NULL} /* sentinel */ + {"__dir__", cdata_dir, METH_NOARGS}, + {"__complex__", cdata_complex, METH_NOARGS}, + {"__enter__", cdata_enter, METH_NOARGS}, + {"__exit__", cdata_exit, METH_VARARGS}, + {NULL, NULL} /* sentinel */ }; static PyTypeObject CData_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend._CDataBase", + "_cffi_backend._CDataBase", sizeof(CDataObject), 0, (destructor)cdata_dealloc, /* tp_dealloc */ @@ -3403,16 +3403,16 @@ static PyTypeObject CData_Type = { &CData_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ &CData_as_mapping, /* tp_as_mapping */ - cdata_hash, /* tp_hash */ + cdata_hash, /* tp_hash */ (ternaryfunc)cdata_call, /* tp_call */ 0, /* tp_str */ (getattrofunc)cdata_getattro, /* tp_getattro */ (setattrofunc)cdata_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ - "The internal base type for CData objects. Use FFI.CData to access " - "it. Always check with isinstance(): subtypes are sometimes returned " - "on CPython, for performance reasons.", /* tp_doc */ + "The internal base type for CData objects. Use FFI.CData to access " + "it. Always check with isinstance(): subtypes are sometimes returned " + "on CPython, for performance reasons.", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ cdata_richcompare, /* tp_richcompare */ @@ -3420,22 +3420,22 @@ static PyTypeObject CData_Type = { (getiterfunc)cdata_iter, /* tp_iter */ 0, /* tp_iternext */ cdata_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - PyObject_Del, /* tp_free */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + PyObject_Del, /* tp_free */ }; static PyTypeObject CDataOwning_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.__CDataOwn", + "_cffi_backend.__CDataOwn", sizeof(CDataObject), 0, (destructor)cdataowning_dealloc, /* tp_dealloc */ @@ -3444,42 +3444,42 @@ static PyTypeObject CDataOwning_Type = { 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)cdataowning_repr, /* tp_repr */ - 0, /* inherited */ /* tp_as_number */ + 0, /* inherited */ /* tp_as_number */ 0, /* tp_as_sequence */ &CDataOwn_as_mapping, /* tp_as_mapping */ - 0, /* inherited */ /* tp_hash */ - 0, /* inherited */ /* tp_call */ + 0, /* inherited */ /* tp_hash */ + 0, /* inherited */ /* tp_call */ 0, /* tp_str */ - 0, /* inherited */ /* tp_getattro */ - 0, /* inherited */ /* tp_setattro */ + 0, /* inherited */ /* tp_getattro */ + 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ - "This is an internal subtype of _CDataBase for performance only on " - "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ + "This is an internal subtype of _CDataBase for performance only on " + "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - 0, /* inherited */ /* tp_richcompare */ - 0, /* inherited */ /* tp_weaklistoffset */ - 0, /* inherited */ /* tp_iter */ + 0, /* inherited */ /* tp_richcompare */ + 0, /* inherited */ /* tp_weaklistoffset */ + 0, /* inherited */ /* tp_iter */ 0, /* tp_iternext */ - 0, /* inherited */ /* tp_methods */ + 0, /* inherited */ /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &CData_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - free, /* tp_free */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + free, /* tp_free */ }; static PyTypeObject CDataOwningGC_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.__CDataOwnGC", - sizeof(CDataObject_own_structptr), + "_cffi_backend.__CDataOwnGC", + sizeof(CDataObject_own_structptr), 0, (destructor)cdataowninggc_dealloc, /* tp_dealloc */ 0, /* tp_print */ @@ -3487,86 +3487,86 @@ static PyTypeObject CDataOwningGC_Type = { 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)cdataowninggc_repr, /* tp_repr */ - 0, /* inherited */ /* tp_as_number */ + 0, /* inherited */ /* tp_as_number */ 0, /* tp_as_sequence */ - 0, /* inherited */ /* tp_as_mapping */ - 0, /* inherited */ /* tp_hash */ - 0, /* inherited */ /* tp_call */ + 0, /* inherited */ /* tp_as_mapping */ + 0, /* inherited */ /* tp_hash */ + 0, /* inherited */ /* tp_call */ 0, /* tp_str */ - 0, /* inherited */ /* tp_getattro */ - 0, /* inherited */ /* tp_setattro */ + 0, /* inherited */ /* tp_getattro */ + 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ | Py_TPFLAGS_HAVE_GC, - "This is an internal subtype of _CDataBase for performance only on " - "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ + "This is an internal subtype of _CDataBase for performance only on " + "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ (traverseproc)cdataowninggc_traverse, /* tp_traverse */ (inquiry)cdataowninggc_clear, /* tp_clear */ - 0, /* inherited */ /* tp_richcompare */ - 0, /* inherited */ /* tp_weaklistoffset */ - 0, /* inherited */ /* tp_iter */ + 0, /* inherited */ /* tp_richcompare */ + 0, /* inherited */ /* tp_weaklistoffset */ + 0, /* inherited */ /* tp_iter */ 0, /* tp_iternext */ - 0, /* inherited */ /* tp_methods */ + 0, /* inherited */ /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &CDataOwning_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - -static PyTypeObject CDataFromBuf_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.__CDataFromBuf", - sizeof(CDataObject_frombuf), - 0, - (destructor)cdatafrombuf_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc)cdatafrombuf_repr, /* tp_repr */ - 0, /* inherited */ /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* inherited */ /* tp_as_mapping */ - 0, /* inherited */ /* tp_hash */ - 0, /* inherited */ /* tp_call */ - 0, /* tp_str */ - 0, /* inherited */ /* tp_getattro */ - 0, /* inherited */ /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ - | Py_TPFLAGS_HAVE_GC, - "This is an internal subtype of _CDataBase for performance only on " - "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ - (traverseproc)cdatafrombuf_traverse, /* tp_traverse */ - (inquiry)cdatafrombuf_clear, /* tp_clear */ - 0, /* inherited */ /* tp_richcompare */ - 0, /* inherited */ /* tp_weaklistoffset */ - 0, /* inherited */ /* tp_iter */ - 0, /* tp_iternext */ - 0, /* inherited */ /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &CData_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; +static PyTypeObject CDataFromBuf_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_cffi_backend.__CDataFromBuf", + sizeof(CDataObject_frombuf), + 0, + (destructor)cdatafrombuf_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)cdatafrombuf_repr, /* tp_repr */ + 0, /* inherited */ /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* inherited */ /* tp_as_mapping */ + 0, /* inherited */ /* tp_hash */ + 0, /* inherited */ /* tp_call */ + 0, /* tp_str */ + 0, /* inherited */ /* tp_getattro */ + 0, /* inherited */ /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ + | Py_TPFLAGS_HAVE_GC, + "This is an internal subtype of _CDataBase for performance only on " + "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ + (traverseproc)cdatafrombuf_traverse, /* tp_traverse */ + (inquiry)cdatafrombuf_clear, /* tp_clear */ + 0, /* inherited */ /* tp_richcompare */ + 0, /* inherited */ /* tp_weaklistoffset */ + 0, /* inherited */ /* tp_iter */ + 0, /* tp_iternext */ + 0, /* inherited */ /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &CData_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + static PyTypeObject CDataGCP_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.__CDataGCP", + "_cffi_backend.__CDataGCP", sizeof(CDataObject_gcp), 0, (destructor)cdatagcp_dealloc, /* tp_dealloc */ @@ -3574,30 +3574,30 @@ static PyTypeObject CDataGCP_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ - 0, /* inherited */ /* tp_repr */ - 0, /* inherited */ /* tp_as_number */ + 0, /* inherited */ /* tp_repr */ + 0, /* inherited */ /* tp_as_number */ 0, /* tp_as_sequence */ - 0, /* inherited */ /* tp_as_mapping */ - 0, /* inherited */ /* tp_hash */ - 0, /* inherited */ /* tp_call */ + 0, /* inherited */ /* tp_as_mapping */ + 0, /* inherited */ /* tp_hash */ + 0, /* inherited */ /* tp_call */ 0, /* tp_str */ - 0, /* inherited */ /* tp_getattro */ - 0, /* inherited */ /* tp_setattro */ + 0, /* inherited */ /* tp_getattro */ + 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ #ifdef Py_TPFLAGS_HAVE_FINALIZE | Py_TPFLAGS_HAVE_FINALIZE #endif | Py_TPFLAGS_HAVE_GC, - "This is an internal subtype of _CDataBase for performance only on " - "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ + "This is an internal subtype of _CDataBase for performance only on " + "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ (traverseproc)cdatagcp_traverse, /* tp_traverse */ 0, /* tp_clear */ - 0, /* inherited */ /* tp_richcompare */ - 0, /* inherited */ /* tp_weaklistoffset */ - 0, /* inherited */ /* tp_iter */ + 0, /* inherited */ /* tp_richcompare */ + 0, /* inherited */ /* tp_weaklistoffset */ + 0, /* inherited */ /* tp_iter */ 0, /* tp_iternext */ - 0, /* inherited */ /* tp_methods */ + 0, /* inherited */ /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &CData_Type, /* tp_base */ @@ -3609,7 +3609,7 @@ static PyTypeObject CDataGCP_Type = { 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ - 0, /* inherited */ /* tp_free */ + 0, /* inherited */ /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ @@ -3651,7 +3651,7 @@ cdataiter_dealloc(CDataIterObject *it) static PyTypeObject CDataIter_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.__CData_iterator", /* tp_name */ + "_cffi_backend.__CData_iterator", /* tp_name */ sizeof(CDataIterObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -3706,16 +3706,16 @@ cdata_iter(CDataObject *cd) /************************************************************/ static CDataObject *allocate_owning_object(Py_ssize_t size, - CTypeDescrObject *ct, - int dont_clear) + CTypeDescrObject *ct, + int dont_clear) { - /* note: objects with &CDataOwning_Type are always allocated with - either a plain malloc() or calloc(), and freed with free(). */ + /* note: objects with &CDataOwning_Type are always allocated with + either a plain malloc() or calloc(), and freed with free(). */ CDataObject *cd; - if (dont_clear) - cd = malloc(size); - else - cd = calloc(size, 1); + if (dont_clear) + cd = malloc(size); + else + cd = calloc(size, 1); if (PyObject_Init((PyObject *)cd, &CDataOwning_Type) == NULL) return NULL; @@ -3741,9 +3741,9 @@ convert_struct_to_owning_object(char *data, CTypeDescrObject *ct) if (ct->ct_flags & CT_WITH_VAR_ARRAY) { PyErr_SetString(PyExc_TypeError, "return type is a struct/union with a varsize array member"); - return NULL; + return NULL; } - cd = allocate_owning_object(dataoffset + datasize, ct, /*dont_clear=*/1); + cd = allocate_owning_object(dataoffset + datasize, ct, /*dont_clear=*/1); if (cd == NULL) return NULL; cd->c_data = ((char *)cd) + dataoffset; @@ -3781,8 +3781,8 @@ static CDataObject *allocate_with_allocator(Py_ssize_t basesize, CDataObject *cd; if (allocator->ca_alloc == NULL) { - cd = allocate_owning_object(basesize + datasize, ct, - allocator->ca_dont_clear); + cd = allocate_owning_object(basesize + datasize, ct, + allocator->ca_dont_clear); if (cd == NULL) return NULL; cd->c_data = ((char *)cd) + basesize; @@ -3815,8 +3815,8 @@ static CDataObject *allocate_with_allocator(Py_ssize_t basesize, cd = allocate_gcp_object(cd, ct, allocator->ca_free); Py_DECREF(res); - if (!allocator->ca_dont_clear) - memset(cd->c_data, 0, datasize); + if (!allocator->ca_dont_clear) + memset(cd->c_data, 0, datasize); } return cd; } @@ -3864,7 +3864,7 @@ static PyObject *direct_newp(CTypeDescrObject *ct, PyObject *init, dataoffset = offsetof(CDataObject_own_nolength, alignment); datasize = ct->ct_size; if (datasize < 0) { - explicitlength = get_new_array_length(ct->ct_itemdescr, &init); + explicitlength = get_new_array_length(ct->ct_itemdescr, &init); if (explicitlength < 0) return NULL; ctitem = ct->ct_itemdescr; @@ -3897,8 +3897,8 @@ static PyObject *direct_newp(CTypeDescrObject *ct, PyObject *init, if (cds == NULL) return NULL; - cd = allocate_owning_object(sizeof(CDataObject_own_structptr), ct, - /*dont_clear=*/1); + cd = allocate_owning_object(sizeof(CDataObject_own_structptr), ct, + /*dont_clear=*/1); if (cd == NULL) { Py_DECREF(cds); return NULL; @@ -4035,22 +4035,22 @@ static CDataObject *cast_to_integer_or_char(CTypeDescrObject *ct, PyObject *ob) } #endif else if (PyUnicode_Check(ob)) { - char err_buf[80]; - cffi_char32_t ordinal; - if (_my_PyUnicode_AsSingleChar32(ob, &ordinal, err_buf) < 0) { + char err_buf[80]; + cffi_char32_t ordinal; + if (_my_PyUnicode_AsSingleChar32(ob, &ordinal, err_buf) < 0) { PyErr_Format(PyExc_TypeError, - "cannot cast %s to ctype '%s'", err_buf, ct->ct_name); + "cannot cast %s to ctype '%s'", err_buf, ct->ct_name); return NULL; } - /* the types char16_t and char32_t are both unsigned. However, - wchar_t might be signed. In theory it does not matter, - because 'ordinal' comes from a regular Python unicode. */ -#ifdef HAVE_WCHAR_H - if (ct->ct_flags & CT_IS_SIGNED_WCHAR) - value = (wchar_t)ordinal; - else -#endif - value = ordinal; + /* the types char16_t and char32_t are both unsigned. However, + wchar_t might be signed. In theory it does not matter, + because 'ordinal' comes from a regular Python unicode. */ +#ifdef HAVE_WCHAR_H + if (ct->ct_flags & CT_IS_SIGNED_WCHAR) + value = (wchar_t)ordinal; + else +#endif + value = ordinal; } else if (PyBytes_Check(ob)) { int res = _convert_to_char(ob); @@ -4077,35 +4077,35 @@ static CDataObject *cast_to_integer_or_char(CTypeDescrObject *ct, PyObject *ob) return cd; } -/* returns -1 if cannot cast, 0 if we don't get a value, 1 if we do */ -static int check_bytes_for_float_compatible(PyObject *io, double *out_value) -{ - if (PyBytes_Check(io)) { - if (PyBytes_GET_SIZE(io) != 1) - goto error; - *out_value = (unsigned char)PyBytes_AS_STRING(io)[0]; - return 1; - } - else if (PyUnicode_Check(io)) { - char ignored[80]; - cffi_char32_t ordinal; - if (_my_PyUnicode_AsSingleChar32(io, &ordinal, ignored) < 0) - goto error; - /* the signness of the 32-bit version of wide chars should not - * matter here, because 'ordinal' comes from a normal Python - * unicode string */ - *out_value = ordinal; - return 1; - } - *out_value = 0; /* silence a gcc warning if this function is inlined */ - return 0; - - error: - Py_DECREF(io); - *out_value = 0; /* silence a gcc warning if this function is inlined */ - return -1; -} - +/* returns -1 if cannot cast, 0 if we don't get a value, 1 if we do */ +static int check_bytes_for_float_compatible(PyObject *io, double *out_value) +{ + if (PyBytes_Check(io)) { + if (PyBytes_GET_SIZE(io) != 1) + goto error; + *out_value = (unsigned char)PyBytes_AS_STRING(io)[0]; + return 1; + } + else if (PyUnicode_Check(io)) { + char ignored[80]; + cffi_char32_t ordinal; + if (_my_PyUnicode_AsSingleChar32(io, &ordinal, ignored) < 0) + goto error; + /* the signness of the 32-bit version of wide chars should not + * matter here, because 'ordinal' comes from a normal Python + * unicode string */ + *out_value = ordinal; + return 1; + } + *out_value = 0; /* silence a gcc warning if this function is inlined */ + return 0; + + error: + Py_DECREF(io); + *out_value = 0; /* silence a gcc warning if this function is inlined */ + return -1; +} + static PyObject *do_cast(CTypeDescrObject *ct, PyObject *ob) { CDataObject *cd; @@ -4147,7 +4147,7 @@ static PyObject *do_cast(CTypeDescrObject *ct, PyObject *ob) /* cast to a float */ double value; PyObject *io; - int res; + int res; if (CData_Check(ob)) { CDataObject *cdsrc = (CDataObject *)ob; @@ -4163,22 +4163,22 @@ static PyObject *do_cast(CTypeDescrObject *ct, PyObject *ob) Py_INCREF(io); } - res = check_bytes_for_float_compatible(io, &value); - if (res == -1) - goto cannot_cast; - if (res == 0) { - if ((ct->ct_flags & CT_IS_LONGDOUBLE) && - CData_Check(io) && - (((CDataObject *)io)->c_type->ct_flags & CT_IS_LONGDOUBLE)) { - long double lvalue; - char *data = ((CDataObject *)io)->c_data; - /*READ(data, sizeof(long double)*/ - lvalue = read_raw_longdouble_data(data); + res = check_bytes_for_float_compatible(io, &value); + if (res == -1) + goto cannot_cast; + if (res == 0) { + if ((ct->ct_flags & CT_IS_LONGDOUBLE) && + CData_Check(io) && + (((CDataObject *)io)->c_type->ct_flags & CT_IS_LONGDOUBLE)) { + long double lvalue; + char *data = ((CDataObject *)io)->c_data; + /*READ(data, sizeof(long double)*/ + lvalue = read_raw_longdouble_data(data); Py_DECREF(io); - cd = _new_casted_primitive(ct); - if (cd != NULL) - write_raw_longdouble_data(cd->c_data, lvalue); - return (PyObject *)cd; + cd = _new_casted_primitive(ct); + if (cd != NULL) + write_raw_longdouble_data(cd->c_data, lvalue); + return (PyObject *)cd; } value = PyFloat_AsDouble(io); } @@ -4195,45 +4195,45 @@ static PyObject *do_cast(CTypeDescrObject *ct, PyObject *ob) } return (PyObject *)cd; } - else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { - /* cast to a complex */ - Py_complex value; - PyObject *io; - int res; - - if (CData_Check(ob)) { - CDataObject *cdsrc = (CDataObject *)ob; - - if (!(cdsrc->c_type->ct_flags & CT_PRIMITIVE_ANY)) - goto cannot_cast; - io = convert_to_object(cdsrc->c_data, cdsrc->c_type); - if (io == NULL) - return NULL; - } - else { - io = ob; - Py_INCREF(io); - } - - res = check_bytes_for_float_compatible(io, &value.real); - if (res == -1) - goto cannot_cast; - if (res == 1) { - // got it from string - value.imag = 0.0; - } else { - value = PyComplex_AsCComplex(io); - } - Py_DECREF(io); - if (PyErr_Occurred()) { - return NULL; - } - cd = _new_casted_primitive(ct); - if (cd != NULL) { - write_raw_complex_data(cd->c_data, value, ct->ct_size); - } - return (PyObject *)cd; - } + else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { + /* cast to a complex */ + Py_complex value; + PyObject *io; + int res; + + if (CData_Check(ob)) { + CDataObject *cdsrc = (CDataObject *)ob; + + if (!(cdsrc->c_type->ct_flags & CT_PRIMITIVE_ANY)) + goto cannot_cast; + io = convert_to_object(cdsrc->c_data, cdsrc->c_type); + if (io == NULL) + return NULL; + } + else { + io = ob; + Py_INCREF(io); + } + + res = check_bytes_for_float_compatible(io, &value.real); + if (res == -1) + goto cannot_cast; + if (res == 1) { + // got it from string + value.imag = 0.0; + } else { + value = PyComplex_AsCComplex(io); + } + Py_DECREF(io); + if (PyErr_Occurred()) { + return NULL; + } + cd = _new_casted_primitive(ct); + if (cd != NULL) { + write_raw_complex_data(cd->c_data, value, ct->ct_size); + } + return (PyObject *)cd; + } else { PyErr_Format(PyExc_TypeError, "cannot cast to ctype '%s'", ct->ct_name); @@ -4267,13 +4267,13 @@ typedef struct { PyObject_HEAD void *dl_handle; char *dl_name; - int dl_auto_close; + int dl_auto_close; } DynLibObject; static void dl_dealloc(DynLibObject *dlobj) { - if (dlobj->dl_handle != NULL && dlobj->dl_auto_close) - dlclose(dlobj->dl_handle); + if (dlobj->dl_handle != NULL && dlobj->dl_auto_close) + dlclose(dlobj->dl_handle); free(dlobj->dl_name); PyObject_Del(dlobj); } @@ -4283,17 +4283,17 @@ static PyObject *dl_repr(DynLibObject *dlobj) return PyText_FromFormat("<clibrary '%s'>", dlobj->dl_name); } -static int dl_check_closed(DynLibObject *dlobj) -{ - if (dlobj->dl_handle == NULL) - { - PyErr_Format(PyExc_ValueError, "library '%s' has already been closed", - dlobj->dl_name); - return -1; - } - return 0; -} - +static int dl_check_closed(DynLibObject *dlobj) +{ + if (dlobj->dl_handle == NULL) + { + PyErr_Format(PyExc_ValueError, "library '%s' has already been closed", + dlobj->dl_name); + return -1; + } + return 0; +} + static PyObject *dl_load_function(DynLibObject *dlobj, PyObject *args) { CTypeDescrObject *ct; @@ -4304,12 +4304,12 @@ static PyObject *dl_load_function(DynLibObject *dlobj, PyObject *args) &CTypeDescr_Type, &ct, &funcname)) return NULL; - if (dl_check_closed(dlobj) < 0) - return NULL; - - if (!(ct->ct_flags & (CT_FUNCTIONPTR | CT_POINTER | CT_ARRAY))) { - PyErr_Format(PyExc_TypeError, - "function or pointer or array cdata expected, got '%s'", + if (dl_check_closed(dlobj) < 0) + return NULL; + + if (!(ct->ct_flags & (CT_FUNCTIONPTR | CT_POINTER | CT_ARRAY))) { + PyErr_Format(PyExc_TypeError, + "function or pointer or array cdata expected, got '%s'", ct->ct_name); return NULL; } @@ -4317,15 +4317,15 @@ static PyObject *dl_load_function(DynLibObject *dlobj, PyObject *args) funcptr = dlsym(dlobj->dl_handle, funcname); if (funcptr == NULL) { const char *error = dlerror(); - PyErr_Format(PyExc_AttributeError, - "function/symbol '%s' not found in library '%s': %s", + PyErr_Format(PyExc_AttributeError, + "function/symbol '%s' not found in library '%s': %s", funcname, dlobj->dl_name, error); return NULL; } - if ((ct->ct_flags & CT_ARRAY) && ct->ct_length < 0) { - ct = (CTypeDescrObject *)ct->ct_stuff; - } + if ((ct->ct_flags & CT_ARRAY) && ct->ct_length < 0) { + ct = (CTypeDescrObject *)ct->ct_stuff; + } return new_simple_cdata(funcptr, ct); } @@ -4339,9 +4339,9 @@ static PyObject *dl_read_variable(DynLibObject *dlobj, PyObject *args) &CTypeDescr_Type, &ct, &varname)) return NULL; - if (dl_check_closed(dlobj) < 0) - return NULL; - + if (dl_check_closed(dlobj) < 0) + return NULL; + dlerror(); /* clear error condition */ data = dlsym(dlobj->dl_handle, varname); if (data == NULL) { @@ -4367,9 +4367,9 @@ static PyObject *dl_write_variable(DynLibObject *dlobj, PyObject *args) &CTypeDescr_Type, &ct, &varname, &value)) return NULL; - if (dl_check_closed(dlobj) < 0) - return NULL; - + if (dl_check_closed(dlobj) < 0) + return NULL; + dlerror(); /* clear error condition */ data = dlsym(dlobj->dl_handle, varname); if (data == NULL) { @@ -4385,28 +4385,28 @@ static PyObject *dl_write_variable(DynLibObject *dlobj, PyObject *args) return Py_None; } -static PyObject *dl_close_lib(DynLibObject *dlobj, PyObject *no_args) -{ - if (dlobj->dl_handle != NULL) - { - dlclose(dlobj->dl_handle); - dlobj->dl_handle = NULL; - } - Py_INCREF(Py_None); - return Py_None; -} - +static PyObject *dl_close_lib(DynLibObject *dlobj, PyObject *no_args) +{ + if (dlobj->dl_handle != NULL) + { + dlclose(dlobj->dl_handle); + dlobj->dl_handle = NULL; + } + Py_INCREF(Py_None); + return Py_None; +} + static PyMethodDef dl_methods[] = { {"load_function", (PyCFunction)dl_load_function, METH_VARARGS}, {"read_variable", (PyCFunction)dl_read_variable, METH_VARARGS}, {"write_variable", (PyCFunction)dl_write_variable, METH_VARARGS}, - {"close_lib", (PyCFunction)dl_close_lib, METH_NOARGS}, + {"close_lib", (PyCFunction)dl_close_lib, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; static PyTypeObject dl_type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.CLibrary", /* tp_name */ + "_cffi_backend.CLibrary", /* tp_name */ sizeof(DynLibObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -4436,150 +4436,150 @@ static PyTypeObject dl_type = { dl_methods, /* tp_methods */ }; -static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, - PyObject **p_temp, int *auto_close) +static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, + PyObject **p_temp, int *auto_close) { - /* Logic to call the correct version of dlopen(). Returns NULL in case of error. - Otherwise, '*p_printable_filename' will point to a printable char version of - the filename (maybe utf-8-encoded). '*p_temp' will be set either to NULL or - to a temporary object that must be freed after looking at printable_filename. - */ + /* Logic to call the correct version of dlopen(). Returns NULL in case of error. + Otherwise, '*p_printable_filename' will point to a printable char version of + the filename (maybe utf-8-encoded). '*p_temp' will be set either to NULL or + to a temporary object that must be freed after looking at printable_filename. + */ void *handle; - char *filename_or_null; + char *filename_or_null; int flags = 0; - *p_temp = NULL; - *auto_close = 1; - + *p_temp = NULL; + *auto_close = 1; + if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) { PyObject *dummy; if (!PyArg_ParseTuple(args, "|Oi:load_library", &dummy, &flags)) return NULL; filename_or_null = NULL; - *p_printable_filename = "<None>"; - } - else if (CData_Check(PyTuple_GET_ITEM(args, 0))) - { - CDataObject *cd; - if (!PyArg_ParseTuple(args, "O|i:load_library", &cd, &flags)) - return NULL; - /* 'flags' is accepted but ignored in this case */ - if ((cd->c_type->ct_flags & CT_IS_VOID_PTR) == 0) { - PyErr_Format(PyExc_TypeError, - "dlopen() takes a file name or 'void *' handle, not '%s'", - cd->c_type->ct_name); - return NULL; - } - handle = cd->c_data; - if (handle == NULL) { - PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)"); - return NULL; - } - *p_temp = PyText_FromFormat("%p", handle); - *p_printable_filename = PyText_AsUTF8(*p_temp); - *auto_close = 0; - return handle; - } - else - { - PyObject *s = PyTuple_GET_ITEM(args, 0); -#ifdef MS_WIN32 - PyObject *filename_unicode; - if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) - { - Py_ssize_t sz1; - wchar_t *w1; -#if PY_MAJOR_VERSION < 3 - s = PyUnicode_AsUTF8String(s); - if (s == NULL) - return NULL; - *p_temp = s; -#endif - *p_printable_filename = PyText_AsUTF8(s); - if (*p_printable_filename == NULL) - return NULL; - - sz1 = PyUnicode_GetSize(filename_unicode) + 1; - sz1 *= 2; /* should not be needed, but you never know */ - w1 = alloca(sizeof(wchar_t) * sz1); - sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode, - w1, sz1 - 1); - if (sz1 < 0) - return NULL; - w1[sz1] = 0; - handle = dlopenW(w1); - goto got_handle; - } - PyErr_Clear(); -#endif - if (!PyArg_ParseTuple(args, "et|i:load_library", - Py_FileSystemDefaultEncoding, &filename_or_null, &flags)) - return NULL; -#if PY_MAJOR_VERSION < 3 - if (PyUnicode_Check(s)) - { - s = PyUnicode_AsUTF8String(s); - if (s == NULL) { - PyMem_Free(filename_or_null); - return NULL; - } - *p_temp = s; - } -#endif - *p_printable_filename = PyText_AsUTF8(s); - if (*p_printable_filename == NULL) { - PyMem_Free(filename_or_null); - return NULL; - } - } + *p_printable_filename = "<None>"; + } + else if (CData_Check(PyTuple_GET_ITEM(args, 0))) + { + CDataObject *cd; + if (!PyArg_ParseTuple(args, "O|i:load_library", &cd, &flags)) + return NULL; + /* 'flags' is accepted but ignored in this case */ + if ((cd->c_type->ct_flags & CT_IS_VOID_PTR) == 0) { + PyErr_Format(PyExc_TypeError, + "dlopen() takes a file name or 'void *' handle, not '%s'", + cd->c_type->ct_name); + return NULL; + } + handle = cd->c_data; + if (handle == NULL) { + PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)"); + return NULL; + } + *p_temp = PyText_FromFormat("%p", handle); + *p_printable_filename = PyText_AsUTF8(*p_temp); + *auto_close = 0; + return handle; + } + else + { + PyObject *s = PyTuple_GET_ITEM(args, 0); +#ifdef MS_WIN32 + PyObject *filename_unicode; + if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) + { + Py_ssize_t sz1; + wchar_t *w1; +#if PY_MAJOR_VERSION < 3 + s = PyUnicode_AsUTF8String(s); + if (s == NULL) + return NULL; + *p_temp = s; +#endif + *p_printable_filename = PyText_AsUTF8(s); + if (*p_printable_filename == NULL) + return NULL; + + sz1 = PyUnicode_GetSize(filename_unicode) + 1; + sz1 *= 2; /* should not be needed, but you never know */ + w1 = alloca(sizeof(wchar_t) * sz1); + sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode, + w1, sz1 - 1); + if (sz1 < 0) + return NULL; + w1[sz1] = 0; + handle = dlopenW(w1); + goto got_handle; + } + PyErr_Clear(); +#endif + if (!PyArg_ParseTuple(args, "et|i:load_library", + Py_FileSystemDefaultEncoding, &filename_or_null, &flags)) + return NULL; +#if PY_MAJOR_VERSION < 3 + if (PyUnicode_Check(s)) + { + s = PyUnicode_AsUTF8String(s); + if (s == NULL) { + PyMem_Free(filename_or_null); + return NULL; + } + *p_temp = s; + } +#endif + *p_printable_filename = PyText_AsUTF8(s); + if (*p_printable_filename == NULL) { + PyMem_Free(filename_or_null); + return NULL; + } + } if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) flags |= RTLD_NOW; -#ifdef MS_WIN32 - if (filename_or_null == NULL) { - PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows"); - return NULL; - } -#endif - +#ifdef MS_WIN32 + if (filename_or_null == NULL) { + PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows"); + return NULL; + } +#endif + handle = dlopen(filename_or_null, flags); - PyMem_Free(filename_or_null); - -#ifdef MS_WIN32 - got_handle: -#endif + PyMem_Free(filename_or_null); + +#ifdef MS_WIN32 + got_handle: +#endif if (handle == NULL) { const char *error = dlerror(); - PyErr_Format(PyExc_OSError, "cannot load library '%s': %s", - *p_printable_filename, error); + PyErr_Format(PyExc_OSError, "cannot load library '%s': %s", + *p_printable_filename, error); return NULL; } - return handle; -} - -static PyObject *b_load_library(PyObject *self, PyObject *args) -{ - const char *printable_filename; - PyObject *temp; - void *handle; - DynLibObject *dlobj = NULL; - int auto_close; - - handle = b_do_dlopen(args, &printable_filename, &temp, &auto_close); - if (handle == NULL) - goto error; + return handle; +} +static PyObject *b_load_library(PyObject *self, PyObject *args) +{ + const char *printable_filename; + PyObject *temp; + void *handle; + DynLibObject *dlobj = NULL; + int auto_close; + + handle = b_do_dlopen(args, &printable_filename, &temp, &auto_close); + if (handle == NULL) + goto error; + dlobj = PyObject_New(DynLibObject, &dl_type); if (dlobj == NULL) { dlclose(handle); - goto error; + goto error; } dlobj->dl_handle = handle; dlobj->dl_name = strdup(printable_filename); - dlobj->dl_auto_close = auto_close; - - error: - Py_XDECREF(temp); + dlobj->dl_auto_close = auto_close; + + error: + Py_XDECREF(temp); return (PyObject *)dlobj; } @@ -4631,10 +4631,10 @@ static PyObject *get_unique_type(CTypeDescrObject *x, assert(x->ct_unique_key == NULL); x->ct_unique_key = key; /* the key will be freed in ctypedescr_dealloc() */ - /* the 'value' in unique_cache doesn't count as 1, but don't use - Py_DECREF(x) here because it will confuse debug builds into thinking - there was an extra DECREF in total. */ - ((PyObject *)x)->ob_refcnt--; + /* the 'value' in unique_cache doesn't count as 1, but don't use + Py_DECREF(x) here because it will confuse debug builds into thinking + there was an extra DECREF in total. */ + ((PyObject *)x)->ob_refcnt--; return (PyObject *)x; error: @@ -4642,11 +4642,11 @@ static PyObject *get_unique_type(CTypeDescrObject *x, return NULL; } -/* according to the C standard, these types should be equivalent to the - _Complex types for the purposes of storage (not arguments in calls!) */ -typedef float cffi_float_complex_t[2]; -typedef double cffi_double_complex_t[2]; - +/* according to the C standard, these types should be equivalent to the + _Complex types for the purposes of storage (not arguments in calls!) */ +typedef float cffi_float_complex_t[2]; +typedef double cffi_double_complex_t[2]; + static PyObject *new_primitive_type(const char *name) { #define ENUM_PRIMITIVE_TYPES \ @@ -4664,11 +4664,11 @@ static PyObject *new_primitive_type(const char *name) EPTYPE(f, float, CT_PRIMITIVE_FLOAT ) \ EPTYPE(d, double, CT_PRIMITIVE_FLOAT ) \ EPTYPE(ld, long double, CT_PRIMITIVE_FLOAT | CT_IS_LONGDOUBLE ) \ - EPTYPE2(fc, "float _Complex", cffi_float_complex_t, CT_PRIMITIVE_COMPLEX ) \ - EPTYPE2(dc, "double _Complex", cffi_double_complex_t, CT_PRIMITIVE_COMPLEX ) \ + EPTYPE2(fc, "float _Complex", cffi_float_complex_t, CT_PRIMITIVE_COMPLEX ) \ + EPTYPE2(dc, "double _Complex", cffi_double_complex_t, CT_PRIMITIVE_COMPLEX ) \ ENUM_PRIMITIVE_TYPES_WCHAR \ - EPTYPE2(c16, "char16_t", cffi_char16_t, CT_PRIMITIVE_CHAR ) \ - EPTYPE2(c32, "char32_t", cffi_char32_t, CT_PRIMITIVE_CHAR ) \ + EPTYPE2(c16, "char16_t", cffi_char16_t, CT_PRIMITIVE_CHAR ) \ + EPTYPE2(c32, "char32_t", cffi_char32_t, CT_PRIMITIVE_CHAR ) \ EPTYPE(b, _Bool, CT_PRIMITIVE_UNSIGNED | CT_IS_BOOL ) \ /* the following types are not primitive in the C sense */ \ EPTYPE(i8, int8_t, CT_PRIMITIVE_SIGNED) \ @@ -4705,8 +4705,8 @@ static PyObject *new_primitive_type(const char *name) #ifdef HAVE_WCHAR_H # define ENUM_PRIMITIVE_TYPES_WCHAR \ - EPTYPE(wc, wchar_t, CT_PRIMITIVE_CHAR | \ - (((wchar_t)-1) > 0 ? 0 : CT_IS_SIGNED_WCHAR)) + EPTYPE(wc, wchar_t, CT_PRIMITIVE_CHAR | \ + (((wchar_t)-1) > 0 ? 0 : CT_IS_SIGNED_WCHAR)) #else # define ENUM_PRIMITIVE_TYPES_WCHAR /* nothing */ #endif @@ -4779,13 +4779,13 @@ static PyObject *new_primitive_type(const char *name) else goto bad_ffi_type; } - else if (ptypes->flags & CT_PRIMITIVE_COMPLEX) { - /* As of March 2017, still no libffi support for complex. - It fails silently if we try to use ffi_type_complex_float - or ffi_type_complex_double. Better not use it at all. - */ - ffitype = NULL; - } + else if (ptypes->flags & CT_PRIMITIVE_COMPLEX) { + /* As of March 2017, still no libffi support for complex. + It fails silently if we try to use ffi_type_complex_float + or ffi_type_complex_double. Better not use it at all. + */ + ffitype = NULL; + } else { switch (ptypes->size) { case 1: ffitype = &ffi_type_uint8; break; @@ -5046,12 +5046,12 @@ _add_field(PyObject *interned_fields, PyObject *fname, CTypeDescrObject *ftype, #define SF_PACKED 0x08 #define SF_STD_FIELD_POS 0x80 -#ifdef MS_WIN32 -# define SF_DEFAULT_PACKING 8 -#else -# define SF_DEFAULT_PACKING 0x40000000 /* a huge power of two */ -#endif - +#ifdef MS_WIN32 +# define SF_DEFAULT_PACKING 8 +#else +# define SF_DEFAULT_PACKING 0x40000000 /* a huge power of two */ +#endif + static int complete_sflags(int sflags) { /* add one of the SF_xxx_BITFIELDS flags if none is specified */ @@ -5060,9 +5060,9 @@ static int complete_sflags(int sflags) #ifdef MS_WIN32 sflags |= SF_MSVC_BITFIELDS; #else -# if defined(__APPLE__) && defined(__arm64__) - sflags |= SF_GCC_X86_BITFIELDS; -# elif defined(__arm__) || defined(__aarch64__) +# if defined(__APPLE__) && defined(__arm64__) + sflags |= SF_GCC_X86_BITFIELDS; +# elif defined(__arm__) || defined(__aarch64__) sflags |= SF_GCC_ARM_BITFIELDS; # else sflags |= SF_GCC_X86_BITFIELDS; @@ -5090,8 +5090,8 @@ static int detect_custom_layout(CTypeDescrObject *ct, int sflags, if (sflags & SF_STD_FIELD_POS) { PyErr_Format(FFIError, "%s: %s%s%s (cdef says %zd, but C compiler says %zd)." - " fix it or use \"...;\" as the last field in the " - "cdef for %s to make it flexible", + " fix it or use \"...;\" as the last field in the " + "cdef for %s to make it flexible", ct->ct_name, msg1, txt, msg2, cdef_value, compiler_value, ct->ct_name); @@ -5102,37 +5102,37 @@ static int detect_custom_layout(CTypeDescrObject *ct, int sflags, return 0; } -#define ROUNDUP_BYTES(bytes, bits) ((bytes) + ((bits) > 0)) - +#define ROUNDUP_BYTES(bytes, bits) ((bytes) + ((bits) > 0)) + static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) { CTypeDescrObject *ct; PyObject *fields, *interned_fields, *ignored; int is_union, alignment; - Py_ssize_t byteoffset, i, nb_fields, byteoffsetmax, alignedsize; - int bitoffset; - Py_ssize_t byteoffsetorg; + Py_ssize_t byteoffset, i, nb_fields, byteoffsetmax, alignedsize; + int bitoffset; + Py_ssize_t byteoffsetorg; Py_ssize_t totalsize = -1; int totalalignment = -1; CFieldObject **previous; int prev_bitfield_size, prev_bitfield_free; int sflags = 0, fflags; - int pack = 0; + int pack = 0; - if (!PyArg_ParseTuple(args, "O!O!|Oniii:complete_struct_or_union", + if (!PyArg_ParseTuple(args, "O!O!|Oniii:complete_struct_or_union", &CTypeDescr_Type, &ct, &PyList_Type, &fields, - &ignored, &totalsize, &totalalignment, &sflags, - &pack)) + &ignored, &totalsize, &totalalignment, &sflags, + &pack)) return NULL; sflags = complete_sflags(sflags); - if (sflags & SF_PACKED) - pack = 1; - else if (pack <= 0) - pack = SF_DEFAULT_PACKING; - else - sflags |= SF_PACKED; + if (sflags & SF_PACKED) + pack = 1; + else if (pack <= 0) + pack = SF_DEFAULT_PACKING; + else + sflags |= SF_PACKED; if ((ct->ct_flags & (CT_STRUCT|CT_IS_OPAQUE)) == (CT_STRUCT|CT_IS_OPAQUE)) { @@ -5147,12 +5147,12 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) "first arg must be a non-initialized struct or union ctype"); return NULL; } - ct->ct_flags &= ~(CT_CUSTOM_FIELD_POS | CT_WITH_PACKED_CHANGE); + ct->ct_flags &= ~(CT_CUSTOM_FIELD_POS | CT_WITH_PACKED_CHANGE); alignment = 1; - byteoffset = 0; /* the real value is 'byteoffset+bitoffset*8', which */ - bitoffset = 0; /* counts the offset in bits */ - byteoffsetmax = 0; /* the maximum value of byteoffset-rounded-up-to-byte */ + byteoffset = 0; /* the real value is 'byteoffset+bitoffset*8', which */ + bitoffset = 0; /* counts the offset in bits */ + byteoffsetmax = 0; /* the maximum value of byteoffset-rounded-up-to-byte */ prev_bitfield_size = 0; prev_bitfield_free = 0; nb_fields = PyList_GET_SIZE(fields); @@ -5165,7 +5165,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) for (i=0; i<nb_fields; i++) { PyObject *fname; CTypeDescrObject *ftype; - int fbitsize = -1, falign, falignorg, do_align; + int fbitsize = -1, falign, falignorg, do_align; Py_ssize_t foffset = -1; if (!PyArg_ParseTuple(PyList_GET_ITEM(fields, i), "O!O!|in:list item", @@ -5187,29 +5187,29 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) goto error; } } - else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) { - if (force_lazy_struct(ftype) < 0) /* for CT_WITH_VAR_ARRAY */ - return NULL; - - /* GCC (or maybe C99) accepts var-sized struct fields that are not - the last field of a larger struct. That's why there is no - check here for "last field": we propagate the flag - CT_WITH_VAR_ARRAY to any struct that contains either an open- - ended array or another struct that recursively contains an - open-ended array. */ - if (ftype->ct_flags & CT_WITH_VAR_ARRAY) - ct->ct_flags |= CT_WITH_VAR_ARRAY; - } - + else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) { + if (force_lazy_struct(ftype) < 0) /* for CT_WITH_VAR_ARRAY */ + return NULL; + + /* GCC (or maybe C99) accepts var-sized struct fields that are not + the last field of a larger struct. That's why there is no + check here for "last field": we propagate the flag + CT_WITH_VAR_ARRAY to any struct that contains either an open- + ended array or another struct that recursively contains an + open-ended array. */ + if (ftype->ct_flags & CT_WITH_VAR_ARRAY) + ct->ct_flags |= CT_WITH_VAR_ARRAY; + } + if (is_union) - byteoffset = bitoffset = 0; /* reset each field at offset 0 */ + byteoffset = bitoffset = 0; /* reset each field at offset 0 */ /* update the total alignment requirement, but skip it if the field is an anonymous bitfield or if SF_PACKED */ - falignorg = get_alignment(ftype); - if (falignorg < 0) + falignorg = get_alignment(ftype); + if (falignorg < 0) goto error; - falign = (pack < falignorg) ? pack : falignorg; + falign = (pack < falignorg) ? pack : falignorg; do_align = 1; if (!(sflags & SF_GCC_ARM_BITFIELDS) && fbitsize >= 0) { @@ -5238,25 +5238,25 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) /* align this field to its own 'falign' by inserting padding */ - /* first, pad to the next byte, - * then pad to 'falign' or 'falignorg' bytes */ - byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset); - bitoffset = 0; - byteoffsetorg = (byteoffset + falignorg-1) & ~(falignorg-1); - byteoffset = (byteoffset + falign-1) & ~(falign-1); - - if (byteoffsetorg != byteoffset) { - ct->ct_flags |= CT_WITH_PACKED_CHANGE; - } - + /* first, pad to the next byte, + * then pad to 'falign' or 'falignorg' bytes */ + byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset); + bitoffset = 0; + byteoffsetorg = (byteoffset + falignorg-1) & ~(falignorg-1); + byteoffset = (byteoffset + falign-1) & ~(falign-1); + + if (byteoffsetorg != byteoffset) { + ct->ct_flags |= CT_WITH_PACKED_CHANGE; + } + if (foffset >= 0) { /* a forced field position: ignore the offset just computed, except to know if we must set CT_CUSTOM_FIELD_POS */ - if (detect_custom_layout(ct, sflags, byteoffset, foffset, + if (detect_custom_layout(ct, sflags, byteoffset, foffset, "wrong offset for field '", PyText_AS_UTF8(fname), "'") < 0) goto error; - byteoffset = foffset; + byteoffset = foffset; } if (PyText_GetSize(fname) == 0 && @@ -5270,7 +5270,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) *previous = _add_field(interned_fields, get_field_name(ftype, cfsrc), cfsrc->cf_type, - byteoffset + cfsrc->cf_offset, + byteoffset + cfsrc->cf_offset, cfsrc->cf_bitshift, cfsrc->cf_bitsize, cfsrc->cf_flags | fflags); @@ -5283,13 +5283,13 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) } else { *previous = _add_field(interned_fields, fname, ftype, - byteoffset, bs_flag, -1, fflags); + byteoffset, bs_flag, -1, fflags); if (*previous == NULL) goto error; previous = &(*previous)->cf_next; } if (ftype->ct_size >= 0) - byteoffset += ftype->ct_size; + byteoffset += ftype->ct_size; prev_bitfield_size = 0; } else { @@ -5326,7 +5326,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) /* compute the starting position of the theoretical field that covers a complete 'ftype', inside of which we will locate the real bitfield */ - field_offset_bytes = byteoffset; + field_offset_bytes = byteoffset; field_offset_bytes &= ~(falign - 1); if (fbitsize == 0) { @@ -5339,13 +5339,13 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) if (!(sflags & SF_MSVC_BITFIELDS)) { /* GCC's notion of "ftype :0;" */ - /* pad byteoffset to a value aligned for "ftype" */ - if (ROUNDUP_BYTES(byteoffset, bitoffset) > field_offset_bytes) { + /* pad byteoffset to a value aligned for "ftype" */ + if (ROUNDUP_BYTES(byteoffset, bitoffset) > field_offset_bytes) { field_offset_bytes += falign; - assert(byteoffset < field_offset_bytes); + assert(byteoffset < field_offset_bytes); } - byteoffset = field_offset_bytes; - bitoffset = 0; + byteoffset = field_offset_bytes; + bitoffset = 0; } else { /* MSVC's notion of "ftype :0;" */ @@ -5362,8 +5362,8 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) /* Can the field start at the offset given by 'boffset'? It can if it would entirely fit into an aligned ftype field. */ - bits_already_occupied = (byteoffset-field_offset_bytes) * 8 - + bitoffset; + bits_already_occupied = (byteoffset-field_offset_bytes) * 8 + + bitoffset; if (bits_already_occupied + fbitsize > 8 * ftype->ct_size) { /* it would not fit, we need to start at the next @@ -5377,18 +5377,18 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) goto error; } field_offset_bytes += falign; - assert(byteoffset < field_offset_bytes); - byteoffset = field_offset_bytes; - bitoffset = 0; + assert(byteoffset < field_offset_bytes); + byteoffset = field_offset_bytes; + bitoffset = 0; bitshift = 0; } else { bitshift = bits_already_occupied; assert(bitshift >= 0); } - bitoffset += fbitsize; - byteoffset += (bitoffset >> 3); - bitoffset &= 7; + bitoffset += fbitsize; + byteoffset += (bitoffset >> 3); + bitoffset &= 7; } else { /* MSVC's algorithm */ @@ -5404,43 +5404,43 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) } else { /* no: start a new full field */ - byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset); - bitoffset = 0; - /* align */ - byteoffset = (byteoffset + falign-1) & ~(falign-1); - byteoffset += ftype->ct_size; + byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset); + bitoffset = 0; + /* align */ + byteoffset = (byteoffset + falign-1) & ~(falign-1); + byteoffset += ftype->ct_size; bitshift = 0; prev_bitfield_size = ftype->ct_size; prev_bitfield_free = 8 * prev_bitfield_size; } prev_bitfield_free -= fbitsize; - field_offset_bytes = byteoffset - ftype->ct_size; + field_offset_bytes = byteoffset - ftype->ct_size; } if (sflags & SF_GCC_BIG_ENDIAN) bitshift = 8 * ftype->ct_size - fbitsize - bitshift; - if (PyText_GetSize(fname) > 0) { - - *previous = _add_field(interned_fields, fname, ftype, + if (PyText_GetSize(fname) > 0) { + + *previous = _add_field(interned_fields, fname, ftype, field_offset_bytes, bitshift, fbitsize, fflags); - if (*previous == NULL) - goto error; - previous = &(*previous)->cf_next; - } + if (*previous == NULL) + goto error; + previous = &(*previous)->cf_next; + } } } - assert(bitoffset == (bitoffset & 7)); - if (ROUNDUP_BYTES(byteoffset, bitoffset) > byteoffsetmax) - byteoffsetmax = ROUNDUP_BYTES(byteoffset, bitoffset); + assert(bitoffset == (bitoffset & 7)); + if (ROUNDUP_BYTES(byteoffset, bitoffset) > byteoffsetmax) + byteoffsetmax = ROUNDUP_BYTES(byteoffset, bitoffset); } *previous = NULL; /* Like C, if the size of this structure would be zero, we compute it as 1 instead. But for ctypes support, we allow the manually- specified totalsize to be zero in this case. */ - alignedsize = (byteoffsetmax + alignment - 1) & ~(alignment-1); + alignedsize = (byteoffsetmax + alignment - 1) & ~(alignment-1); if (alignedsize == 0) alignedsize = 1; @@ -5451,10 +5451,10 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) if (detect_custom_layout(ct, sflags, alignedsize, totalsize, "wrong total size", "", "") < 0) goto error; - if (totalsize < byteoffsetmax) { + if (totalsize < byteoffsetmax) { PyErr_Format(PyExc_TypeError, "%s cannot be of size %zd: there are fields at least " - "up to %zd", ct->ct_name, totalsize, byteoffsetmax); + "up to %zd", ct->ct_name, totalsize, byteoffsetmax); goto error; } } @@ -5503,28 +5503,28 @@ static void *fb_alloc(struct funcbuilder_s *fb, Py_ssize_t size) } } -#define SUPPORTED_IN_API_MODE \ - " are only supported as %s if the function is " \ - "'API mode' and non-variadic (i.e. declared inside ffibuilder" \ - ".cdef()+ffibuilder.set_source() and not taking a final '...' " \ - "argument)" - -static ffi_type *fb_unsupported(CTypeDescrObject *ct, const char *place, - const char *detail) -{ - PyErr_Format(PyExc_NotImplementedError, - "ctype '%s' not supported as %s. %s. " - "Such structs" SUPPORTED_IN_API_MODE, - ct->ct_name, place, detail, place); - return NULL; -} - +#define SUPPORTED_IN_API_MODE \ + " are only supported as %s if the function is " \ + "'API mode' and non-variadic (i.e. declared inside ffibuilder" \ + ".cdef()+ffibuilder.set_source() and not taking a final '...' " \ + "argument)" + +static ffi_type *fb_unsupported(CTypeDescrObject *ct, const char *place, + const char *detail) +{ + PyErr_Format(PyExc_NotImplementedError, + "ctype '%s' not supported as %s. %s. " + "Such structs" SUPPORTED_IN_API_MODE, + ct->ct_name, place, detail, place); + return NULL; +} + static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct, int is_result_type) { const char *place = is_result_type ? "return value" : "argument"; - if (ct->ct_flags & (CT_PRIMITIVE_ANY & ~CT_PRIMITIVE_COMPLEX)) { + if (ct->ct_flags & (CT_PRIMITIVE_ANY & ~CT_PRIMITIVE_COMPLEX)) { return (ffi_type *)ct->ct_extra; } else if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) { @@ -5558,26 +5558,26 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct, Another reason for CT_CUSTOM_FIELD_POS would be anonymous nested structures: we lost the information about having it here, so better safe (and forbid it) than sorry (and maybe - crash). Note: it seems we only get in this case with - ffi.verify(). + crash). Note: it seems we only get in this case with + ffi.verify(). */ if (force_lazy_struct(ct) < 0) return NULL; if (ct->ct_flags & CT_CUSTOM_FIELD_POS) { /* these NotImplementedErrors may be caught and ignored until a real call is made to a function of this type */ - return fb_unsupported(ct, place, - "It is a struct declared with \"...;\", but the C " - "calling convention may depend on the missing fields; " - "or, it contains anonymous struct/unions"); - } - /* Another reason: __attribute__((packed)) is not supported by libffi. - */ - if (ct->ct_flags & CT_WITH_PACKED_CHANGE) { - return fb_unsupported(ct, place, - "It is a 'packed' structure, with a different layout than " - "expected by libffi"); - } + return fb_unsupported(ct, place, + "It is a struct declared with \"...;\", but the C " + "calling convention may depend on the missing fields; " + "or, it contains anonymous struct/unions"); + } + /* Another reason: __attribute__((packed)) is not supported by libffi. + */ + if (ct->ct_flags & CT_WITH_PACKED_CHANGE) { + return fb_unsupported(ct, place, + "It is a 'packed' structure, with a different layout than " + "expected by libffi"); + } n = PyDict_Size(ct->ct_stuff); nflat = 0; @@ -5590,9 +5590,9 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct, CTypeDescrObject *ct1; assert(cf != NULL); if (cf->cf_bitshift >= 0) { - return fb_unsupported(ct, place, - "It is a struct with bit fields, which libffi does not " - "support"); + return fb_unsupported(ct, place, + "It is a struct with bit fields, which libffi does not " + "support"); } flat = 1; ct1 = cf->cf_type; @@ -5601,9 +5601,9 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct, ct1 = ct1->ct_itemdescr; } if (flat <= 0) { - return fb_unsupported(ct, place, - "It is a struct with a zero-length array, which libffi " - "does not support"); + return fb_unsupported(ct, place, + "It is a struct with a zero-length array, which libffi " + "does not support"); } nflat += flat; cf = cf->cf_next; @@ -5642,24 +5642,24 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct, } return ffistruct; } - else if (ct->ct_flags & CT_UNION) { - PyErr_Format(PyExc_NotImplementedError, - "ctype '%s' not supported as %s by libffi. " - "Unions" SUPPORTED_IN_API_MODE, - ct->ct_name, place, place); - return NULL; - } + else if (ct->ct_flags & CT_UNION) { + PyErr_Format(PyExc_NotImplementedError, + "ctype '%s' not supported as %s by libffi. " + "Unions" SUPPORTED_IN_API_MODE, + ct->ct_name, place, place); + return NULL; + } else { - char *extra = ""; - if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) - extra = " (the support for complex types inside libffi " - "is mostly missing at this point, so CFFI only " - "supports complex types as arguments or return " - "value in API-mode functions)"; - + char *extra = ""; + if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) + extra = " (the support for complex types inside libffi " + "is mostly missing at this point, so CFFI only " + "supports complex types as arguments or return " + "value in API-mode functions)"; + PyErr_Format(PyExc_NotImplementedError, - "ctype '%s' (size %zd) not supported as %s%s", - ct->ct_name, ct->ct_size, place, extra); + "ctype '%s' (size %zd) not supported as %s%s", + ct->ct_name, ct->ct_size, place, extra); return NULL; } } @@ -5850,14 +5850,14 @@ static CTypeDescrObject *fb_prepare_ctype(struct funcbuilder_s *fb, static cif_description_t *fb_prepare_cif(PyObject *fargs, CTypeDescrObject *fresult, - Py_ssize_t variadic_nargs_declared, + Py_ssize_t variadic_nargs_declared, ffi_abi fabi) - + { char *buffer; cif_description_t *cif_descr; struct funcbuilder_s funcbuffer; - ffi_status status = (ffi_status)-1; + ffi_status status = (ffi_status)-1; funcbuffer.nb_bytes = 0; funcbuffer.bufferp = NULL; @@ -5880,24 +5880,24 @@ static cif_description_t *fb_prepare_cif(PyObject *fargs, assert(funcbuffer.bufferp == buffer + funcbuffer.nb_bytes); cif_descr = (cif_description_t *)buffer; - - /* use `ffi_prep_cif_var` if necessary and available */ -#if CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE - if (variadic_nargs_declared >= 0) { - if (CFFI_CHECK_FFI_PREP_CIF_VAR) { - status = ffi_prep_cif_var(&cif_descr->cif, fabi, - variadic_nargs_declared, funcbuffer.nargs, - funcbuffer.rtype, funcbuffer.atypes); - } - } -#endif - - if (status == (ffi_status)-1) { - status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs, - funcbuffer.rtype, funcbuffer.atypes); - } - - if (status != FFI_OK) { + + /* use `ffi_prep_cif_var` if necessary and available */ +#if CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE + if (variadic_nargs_declared >= 0) { + if (CFFI_CHECK_FFI_PREP_CIF_VAR) { + status = ffi_prep_cif_var(&cif_descr->cif, fabi, + variadic_nargs_declared, funcbuffer.nargs, + funcbuffer.rtype, funcbuffer.atypes); + } + } +#endif + + if (status == (ffi_status)-1) { + status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs, + funcbuffer.rtype, funcbuffer.atypes); + } + + if (status != FFI_OK) { PyErr_SetString(PyExc_SystemError, "libffi failed to build this function type"); goto error; @@ -5941,7 +5941,7 @@ static PyObject *new_function_type(PyObject *fargs, /* tuple */ is computed here. */ cif_description_t *cif_descr; - cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi); + cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi); if (cif_descr == NULL) { if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { PyErr_Clear(); /* will get the exception if we see an @@ -6046,14 +6046,14 @@ static int convert_from_object_fficallback(char *result, return 0; } else if (ctype->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED | - CT_PRIMITIVE_UNSIGNED | - CT_POINTER | CT_FUNCTIONPTR)) { + CT_PRIMITIVE_UNSIGNED | + CT_POINTER | CT_FUNCTIONPTR)) { /* zero extension: fill the '*result' with zeros, and (on big- - endian machines) correct the 'result' pointer to write to. - We also do that for pointers, even though we're normally not - in this branch because ctype->ct_size == sizeof(ffi_arg) for - pointers---except on some architectures like x32 (issue #372). - */ + endian machines) correct the 'result' pointer to write to. + We also do that for pointers, even though we're normally not + in this branch because ctype->ct_size == sizeof(ffi_arg) for + pointers---except on some architectures like x32 (issue #372). + */ memset(result, 0, sizeof(ffi_arg)); #ifdef WORDS_BIGENDIAN result += (sizeof(ffi_arg) - ctype->ct_size); @@ -6064,49 +6064,49 @@ static int convert_from_object_fficallback(char *result, return convert_from_object(result, ctype, pyobj); } -static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, - char *objdescr, PyObject *obj, +static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, + char *objdescr, PyObject *obj, char *extra_error_line) { /* like PyErr_WriteUnraisable(), but write a full traceback */ -#ifdef USE_WRITEUNRAISABLEMSG - - /* PyErr_WriteUnraisable actually writes the full traceback anyway - from Python 3.4, but we can't really get the formatting of the - custom text to be what we want. We can do better from Python - 3.8 by calling the new _PyErr_WriteUnraisableMsg(). - Luckily it's also Python 3.8 that adds new functionality that - people might want: the new sys.unraisablehook(). - */ - PyObject *s; - int first_char; - assert(objdescr != NULL && objdescr[0] != 0); /* non-empty */ - first_char = objdescr[0]; - if (first_char >= 'A' && first_char <= 'Z') - first_char += 'a' - 'A'; /* lower() the very first character */ - if (extra_error_line == NULL) - extra_error_line = ""; - - if (obj != NULL) - s = PyUnicode_FromFormat("%c%s%R%s", - first_char, objdescr + 1, obj, extra_error_line); - else - s = PyUnicode_FromFormat("%c%s%s", - first_char, objdescr + 1, extra_error_line); - - PyErr_Restore(t, v, tb); - if (s != NULL) { - _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL); - Py_DECREF(s); - } - else - PyErr_WriteUnraisable(obj); /* best effort */ - PyErr_Clear(); - -#else - - /* version for Python 2.7 and < 3.8 */ - PyObject *f; +#ifdef USE_WRITEUNRAISABLEMSG + + /* PyErr_WriteUnraisable actually writes the full traceback anyway + from Python 3.4, but we can't really get the formatting of the + custom text to be what we want. We can do better from Python + 3.8 by calling the new _PyErr_WriteUnraisableMsg(). + Luckily it's also Python 3.8 that adds new functionality that + people might want: the new sys.unraisablehook(). + */ + PyObject *s; + int first_char; + assert(objdescr != NULL && objdescr[0] != 0); /* non-empty */ + first_char = objdescr[0]; + if (first_char >= 'A' && first_char <= 'Z') + first_char += 'a' - 'A'; /* lower() the very first character */ + if (extra_error_line == NULL) + extra_error_line = ""; + + if (obj != NULL) + s = PyUnicode_FromFormat("%c%s%R%s", + first_char, objdescr + 1, obj, extra_error_line); + else + s = PyUnicode_FromFormat("%c%s%s", + first_char, objdescr + 1, extra_error_line); + + PyErr_Restore(t, v, tb); + if (s != NULL) { + _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL); + Py_DECREF(s); + } + else + PyErr_WriteUnraisable(obj); /* best effort */ + PyErr_Clear(); + +#else + + /* version for Python 2.7 and < 3.8 */ + PyObject *f; #if PY_MAJOR_VERSION >= 3 /* jump through hoops to ensure the tb is attached to v, on Python 3 */ PyErr_NormalizeException(&t, &v, &tb); @@ -6130,8 +6130,8 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, Py_XDECREF(t); Py_XDECREF(v); Py_XDECREF(tb); - -#endif + +#endif } static void general_invoke_callback(int decode_args_from_libffi, @@ -6181,11 +6181,11 @@ static void general_invoke_callback(int decode_args_from_libffi, goto error; if (convert_from_object_fficallback(result, SIGNATURE(1), py_res, decode_args_from_libffi) < 0) { -#ifdef USE_WRITEUNRAISABLEMSG - extra_error_line = ", trying to convert the result back to C"; -#else +#ifdef USE_WRITEUNRAISABLEMSG + extra_error_line = ", trying to convert the result back to C"; +#else extra_error_line = "Trying to convert the result back to C:\n"; -#endif +#endif goto error; } done: @@ -6202,12 +6202,12 @@ static void general_invoke_callback(int decode_args_from_libffi, } onerror_cb = PyTuple_GET_ITEM(cb_args, 3); if (onerror_cb == Py_None) { - PyObject *ecap, *t, *v, *tb; - PyErr_Fetch(&t, &v, &tb); - ecap = _cffi_start_error_capture(); - _my_PyErr_WriteUnraisable(t, v, tb, "From cffi callback ", py_ob, + PyObject *ecap, *t, *v, *tb; + PyErr_Fetch(&t, &v, &tb); + ecap = _cffi_start_error_capture(); + _my_PyErr_WriteUnraisable(t, v, tb, "From cffi callback ", py_ob, extra_error_line); - _cffi_stop_error_capture(ecap); + _cffi_stop_error_capture(ecap); } else { PyObject *exc1, *val1, *tb1, *res1, *exc2, *val2, *tb2; @@ -6231,23 +6231,23 @@ static void general_invoke_callback(int decode_args_from_libffi, } else { /* double exception! print a double-traceback... */ - PyObject *ecap; + PyObject *ecap; PyErr_Fetch(&exc2, &val2, &tb2); - ecap = _cffi_start_error_capture(); - _my_PyErr_WriteUnraisable(exc1, val1, tb1, - "From cffi callback ", py_ob, + ecap = _cffi_start_error_capture(); + _my_PyErr_WriteUnraisable(exc1, val1, tb1, + "From cffi callback ", py_ob, extra_error_line); -#ifdef USE_WRITEUNRAISABLEMSG - _my_PyErr_WriteUnraisable(exc2, val2, tb2, - "during handling of the above exception by 'onerror'", - NULL, NULL); -#else +#ifdef USE_WRITEUNRAISABLEMSG + _my_PyErr_WriteUnraisable(exc2, val2, tb2, + "during handling of the above exception by 'onerror'", + NULL, NULL); +#else extra_error_line = ("\nDuring the call to 'onerror', " "another exception occurred:\n\n"); - _my_PyErr_WriteUnraisable(exc2, val2, tb2, - NULL, NULL, extra_error_line); -#endif - _cffi_stop_error_capture(ecap); + _my_PyErr_WriteUnraisable(exc2, val2, tb2, + NULL, NULL, extra_error_line); +#endif + _cffi_stop_error_capture(ecap); } } goto done; @@ -6314,38 +6314,38 @@ static PyObject *prepare_callback_info_tuple(CTypeDescrObject *ct, infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob); Py_DECREF(py_rawerr); -#if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000 +#if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000 /* We must setup the GIL here, in case the callback is invoked in - some other non-Pythonic thread. This is the same as ctypes. - But PyEval_InitThreads() is always a no-op from CPython 3.7 - (the call from ctypes was removed some time later I think). */ + some other non-Pythonic thread. This is the same as ctypes. + But PyEval_InitThreads() is always a no-op from CPython 3.7 + (the call from ctypes was removed some time later I think). */ PyEval_InitThreads(); #endif return infotuple; } -/* messily try to silence a gcc/clang deprecation warning for - ffi_prep_closure. Don't miss the "pragma pop" after the function. - This is done around the whole function because very old GCCs don't - support it inside a function. */ -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +/* messily try to silence a gcc/clang deprecation warning for + ffi_prep_closure. Don't miss the "pragma pop" after the function. + This is done around the whole function because very old GCCs don't + support it inside a function. */ +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif static PyObject *b_callback(PyObject *self, PyObject *args) { CTypeDescrObject *ct; - CDataObject_closure *cd; + CDataObject_closure *cd; PyObject *ob, *error_ob = Py_None, *onerror_ob = Py_None; PyObject *infotuple; cif_description_t *cif_descr; ffi_closure *closure; - ffi_status status; - void *closure_exec; + ffi_status status; + void *closure_exec; if (!PyArg_ParseTuple(args, "O!O|OO:callback", &CTypeDescr_Type, &ct, &ob, &error_ob, &onerror_ob)) @@ -6355,34 +6355,34 @@ static PyObject *b_callback(PyObject *self, PyObject *args) if (infotuple == NULL) return NULL; -#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE - if (CFFI_CHECK_FFI_CLOSURE_ALLOC) { - closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec); - } else -#endif - { - closure = cffi_closure_alloc(); - closure_exec = closure; - } - - if (closure == NULL) { - Py_DECREF(infotuple); - PyErr_SetString(PyExc_MemoryError, - "Cannot allocate write+execute memory for ffi.callback(). " - "You might be running on a system that prevents this. " - "For more information, see " - "https://cffi.readthedocs.io/en/latest/using.html#callbacks"); - return NULL; - } - cd = PyObject_GC_New(CDataObject_closure, &CDataOwningGC_Type); +#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE + if (CFFI_CHECK_FFI_CLOSURE_ALLOC) { + closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec); + } else +#endif + { + closure = cffi_closure_alloc(); + closure_exec = closure; + } + + if (closure == NULL) { + Py_DECREF(infotuple); + PyErr_SetString(PyExc_MemoryError, + "Cannot allocate write+execute memory for ffi.callback(). " + "You might be running on a system that prevents this. " + "For more information, see " + "https://cffi.readthedocs.io/en/latest/using.html#callbacks"); + return NULL; + } + cd = PyObject_GC_New(CDataObject_closure, &CDataOwningGC_Type); if (cd == NULL) goto error; Py_INCREF(ct); - cd->head.c_type = ct; - cd->head.c_data = (char *)closure_exec; - cd->head.c_weakreflist = NULL; - closure->user_data = NULL; - cd->closure = closure; + cd->head.c_type = ct; + cd->head.c_data = (char *)closure_exec; + cd->head.c_weakreflist = NULL; + closure->user_data = NULL; + cd->closure = closure; cif_descr = (cif_description_t *)ct->ct_extra; if (cif_descr == NULL) { @@ -6391,30 +6391,30 @@ static PyObject *b_callback(PyObject *self, PyObject *args) "return type or with '...'", ct->ct_name); goto error; } - -#if CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE - if (CFFI_CHECK_FFI_PREP_CLOSURE_LOC) { - status = ffi_prep_closure_loc(closure, &cif_descr->cif, - invoke_callback, infotuple, closure_exec); - } - else -#endif - { -#if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API - PyErr_Format(PyExc_SystemError, "ffi_prep_closure_loc() is missing"); - goto error; -#else - status = ffi_prep_closure(closure, &cif_descr->cif, - invoke_callback, infotuple); -#endif - } - - if (status != FFI_OK) { + +#if CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE + if (CFFI_CHECK_FFI_PREP_CLOSURE_LOC) { + status = ffi_prep_closure_loc(closure, &cif_descr->cif, + invoke_callback, infotuple, closure_exec); + } + else +#endif + { +#if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API + PyErr_Format(PyExc_SystemError, "ffi_prep_closure_loc() is missing"); + goto error; +#else + status = ffi_prep_closure(closure, &cif_descr->cif, + invoke_callback, infotuple); +#endif + } + + if (status != FFI_OK) { PyErr_SetString(PyExc_SystemError, "libffi failed to build this callback"); goto error; } - + if (closure->user_data != infotuple) { /* Issue #266. Should not occur, but could, if we are using at runtime a version of libffi compiled with a different @@ -6429,30 +6429,30 @@ static PyObject *b_callback(PyObject *self, PyObject *args) "different from the 'ffi.h' file seen at compile-time)"); goto error; } - PyObject_GC_Track(cd); + PyObject_GC_Track(cd); return (PyObject *)cd; error: closure->user_data = NULL; - if (cd == NULL) { -#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE - if (CFFI_CHECK_FFI_CLOSURE_ALLOC) { - ffi_closure_free(closure); - } - else -#endif - cffi_closure_free(closure); - } + if (cd == NULL) { +#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE + if (CFFI_CHECK_FFI_CLOSURE_ALLOC) { + ffi_closure_free(closure); + } + else +#endif + cffi_closure_free(closure); + } else Py_DECREF(cd); Py_XDECREF(infotuple); return NULL; } -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif static PyObject *b_new_enum_type(PyObject *self, PyObject *args) { @@ -6498,7 +6498,7 @@ static PyObject *b_new_enum_type(PyObject *self, PyObject *args) if (!PyText_Check(tmpkey)) { #if PY_MAJOR_VERSION < 3 if (PyUnicode_Check(tmpkey)) { - const char *text = PyText_AsUTF8(tmpkey); + const char *text = PyText_AsUTF8(tmpkey); if (text == NULL) goto error; Py_DECREF(tmpkey); @@ -6758,8 +6758,8 @@ static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds) if (cd->c_type->ct_itemdescr != NULL && cd->c_type->ct_itemdescr->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED | - CT_PRIMITIVE_UNSIGNED) && - !(cd->c_type->ct_itemdescr->ct_flags & CT_IS_BOOL)) { + CT_PRIMITIVE_UNSIGNED) && + !(cd->c_type->ct_itemdescr->ct_flags & CT_IS_BOOL)) { Py_ssize_t length = maxlen; if (cd->c_data == NULL) { PyObject *s = cdata_repr(cd); @@ -6791,44 +6791,44 @@ static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds) return PyBytes_FromStringAndSize(start, length); } else if (cd->c_type->ct_itemdescr->ct_flags & CT_PRIMITIVE_CHAR) { - switch (cd->c_type->ct_itemdescr->ct_size) { - case 2: { - const cffi_char16_t *start = (cffi_char16_t *)cd->c_data; - if (length < 0) { - /*READ(start, 2)*/ - length = 0; - while (start[length]) - length++; - /*READ(start, 2 * length)*/ - } - else { - /*READ(start, 2 * length)*/ - maxlen = length; - length = 0; - while (length < maxlen && start[length]) - length++; - } - return _my_PyUnicode_FromChar16(start, length); - } - case 4: { - const cffi_char32_t *start = (cffi_char32_t *)cd->c_data; - if (length < 0) { - /*READ(start, 4)*/ - length = 0; - while (start[length]) - length++; - /*READ(start, 4 * length)*/ - } - else { - /*READ(start, 4 * length)*/ - maxlen = length; - length = 0; - while (length < maxlen && start[length]) - length++; - } - return _my_PyUnicode_FromChar32(start, length); + switch (cd->c_type->ct_itemdescr->ct_size) { + case 2: { + const cffi_char16_t *start = (cffi_char16_t *)cd->c_data; + if (length < 0) { + /*READ(start, 2)*/ + length = 0; + while (start[length]) + length++; + /*READ(start, 2 * length)*/ + } + else { + /*READ(start, 2 * length)*/ + maxlen = length; + length = 0; + while (length < maxlen && start[length]) + length++; + } + return _my_PyUnicode_FromChar16(start, length); } + case 4: { + const cffi_char32_t *start = (cffi_char32_t *)cd->c_data; + if (length < 0) { + /*READ(start, 4)*/ + length = 0; + while (start[length]) + length++; + /*READ(start, 4 * length)*/ + } + else { + /*READ(start, 4 * length)*/ + maxlen = length; + length = 0; + while (length < maxlen && start[length]) + length++; + } + return _my_PyUnicode_FromChar32(start, length); } + } } } else if (cd->c_type->ct_flags & CT_IS_ENUM) { @@ -6844,12 +6844,12 @@ static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds) if (cd->c_type->ct_size == sizeof(char)) return PyBytes_FromStringAndSize(cd->c_data, 1); else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) { - switch (cd->c_type->ct_size) { - case 2: - return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data, 1); - case 4: - return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data, 1); - } + switch (cd->c_type->ct_size) { + case 2: + return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data, 1); + case 4: + return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data, 1); + } } } PyErr_Format(PyExc_TypeError, "string(): unexpected cdata '%s' argument", @@ -6895,14 +6895,14 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) /* byte- and unicode strings */ ctitem = cd->c_type->ct_itemdescr; if (ctitem->ct_flags & CT_PRIMITIVE_CHAR) { - switch (ctitem->ct_size) { - case sizeof(char): + switch (ctitem->ct_size) { + case sizeof(char): return PyBytes_FromStringAndSize(cd->c_data, length); - case 2: - return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data,length); - case 4: - return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data,length); - } + case 2: + return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data,length); + case 4: + return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data,length); + } } /* else, the result is a list. This implementation should be @@ -6918,7 +6918,7 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) src = cd->c_data; itemsize = ctitem->ct_size; if (itemsize < 0) { - Py_DECREF(result); + Py_DECREF(result); PyErr_Format(PyExc_ValueError, "'%s' points to items of unknown size", cd->c_type->ct_name); return NULL; @@ -6951,8 +6951,8 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) /* Note: we never pick case 6 if sizeof(int) == sizeof(long), so that case 6 below can assume that the 'unsigned int' result would always fit in a 'signed long'. */ - if (ctitem->ct_flags & CT_IS_BOOL) casenum = 11; - else if (itemsize == sizeof(unsigned long)) casenum = 7; + if (ctitem->ct_flags & CT_IS_BOOL) casenum = 11; + else if (itemsize == sizeof(unsigned long)) casenum = 7; else if (itemsize == sizeof(unsigned int)) casenum = 6; else if (itemsize == sizeof(unsigned short)) casenum = 5; else if (itemsize == sizeof(unsigned char)) casenum = 4; @@ -6985,13 +6985,13 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) case 8: x = PyFloat_FromDouble(*(float *)src); break; case 9: x = PyFloat_FromDouble(*(double *)src); break; case 10: x = new_simple_cdata(*(char **)src, ctitem); break; - case 11: - switch (*(unsigned char *)src) { - case 0: x = Py_False; Py_INCREF(x); break; - case 1: x = Py_True; Py_INCREF(x); break; - default: x = convert_to_object(src, ctitem); /* error */ - } - break; + case 11: + switch (*(unsigned char *)src) { + case 0: x = Py_False; Py_INCREF(x); break; + case 1: x = Py_True; Py_INCREF(x); break; + default: x = convert_to_object(src, ctitem); /* error */ + } + break; } if (x == NULL) { Py_DECREF(result); @@ -7003,10 +7003,10 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) return result; } -static PyObject * -b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject * +b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - /* this is the constructor of the type implemented in minibuffer.h */ + /* this is the constructor of the type implemented in minibuffer.h */ CDataObject *cd; Py_ssize_t size = -1; static char *keywords[] = {"cdata", "size", NULL}; @@ -7074,7 +7074,7 @@ static PyObject *newp_handle(CTypeDescrObject *ct_voidp, PyObject *x) &CDataOwningGC_Type); if (cd == NULL) return NULL; - Py_INCREF(ct_voidp); /* must be "void *" */ + Py_INCREF(ct_voidp); /* must be "void *" */ cd->head.c_type = ct_voidp; cd->head.c_data = (char *)cd; cd->head.c_weakreflist = NULL; @@ -7187,27 +7187,27 @@ static int _my_PyObject_GetContiguousBuffer(PyObject *x, Py_buffer *view, return 0; } -static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x, - int require_writable) +static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x, + int require_writable) { - CDataObject *cd; - Py_buffer *view; - Py_ssize_t arraylength, minimumlength = 0; + CDataObject *cd; + Py_buffer *view; + Py_ssize_t arraylength, minimumlength = 0; - if (!(ct->ct_flags & (CT_ARRAY | CT_POINTER))) { - PyErr_Format(PyExc_TypeError, - "expected a pointer or array ctype, got '%s'", - ct->ct_name); - return NULL; + if (!(ct->ct_flags & (CT_ARRAY | CT_POINTER))) { + PyErr_Format(PyExc_TypeError, + "expected a pointer or array ctype, got '%s'", + ct->ct_name); + return NULL; } - /* PyPy 5.7 can obtain buffers for string (python 2) - or bytes (python 3). from_buffer(u"foo") is disallowed. - */ - if (PyUnicode_Check(x)) { + /* PyPy 5.7 can obtain buffers for string (python 2) + or bytes (python 3). from_buffer(u"foo") is disallowed. + */ + if (PyUnicode_Check(x)) { PyErr_SetString(PyExc_TypeError, - "from_buffer() cannot return the address " - "of a unicode object"); + "from_buffer() cannot return the address " + "of a unicode object"); return NULL; } @@ -7216,54 +7216,54 @@ static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x, PyErr_NoMemory(); return NULL; } - if (_my_PyObject_GetContiguousBuffer(x, view, require_writable) < 0) + if (_my_PyObject_GetContiguousBuffer(x, view, require_writable) < 0) goto error1; - if (ct->ct_flags & CT_POINTER) - { - arraylength = view->len; /* number of bytes, not used so far */ - } - else { - /* ct->ct_flags & CT_ARRAY */ - if (ct->ct_length >= 0) { - /* it's an array with a fixed length; make sure that the - buffer contains enough bytes. */ - minimumlength = ct->ct_size; - arraylength = ct->ct_length; - } - else { - /* it's an open 'array[]' */ - if (ct->ct_itemdescr->ct_size == 1) { - /* fast path, performance only */ - arraylength = view->len; - } - else if (ct->ct_itemdescr->ct_size > 0) { - /* give it as many items as fit the buffer. Ignore a - partial last element. */ - arraylength = view->len / ct->ct_itemdescr->ct_size; - } - else { - /* it's an array 'empty[]'. Unsupported obscure case: - the problem is that setting the length of the result - to anything large (like SSIZE_T_MAX) is dangerous, - because if someone tries to loop over it, it will - turn effectively into an infinite loop. */ - PyErr_Format(PyExc_ZeroDivisionError, - "from_buffer('%s', ..): the actual length of the array " - "cannot be computed", ct->ct_name); - goto error2; - } - } - } - if (view->len < minimumlength) { - PyErr_Format(PyExc_ValueError, - "buffer is too small (%zd bytes) for '%s' (%zd bytes)", - view->len, ct->ct_name, minimumlength); - goto error2; - } - - cd = (CDataObject *)PyObject_GC_New(CDataObject_frombuf, - &CDataFromBuf_Type); + if (ct->ct_flags & CT_POINTER) + { + arraylength = view->len; /* number of bytes, not used so far */ + } + else { + /* ct->ct_flags & CT_ARRAY */ + if (ct->ct_length >= 0) { + /* it's an array with a fixed length; make sure that the + buffer contains enough bytes. */ + minimumlength = ct->ct_size; + arraylength = ct->ct_length; + } + else { + /* it's an open 'array[]' */ + if (ct->ct_itemdescr->ct_size == 1) { + /* fast path, performance only */ + arraylength = view->len; + } + else if (ct->ct_itemdescr->ct_size > 0) { + /* give it as many items as fit the buffer. Ignore a + partial last element. */ + arraylength = view->len / ct->ct_itemdescr->ct_size; + } + else { + /* it's an array 'empty[]'. Unsupported obscure case: + the problem is that setting the length of the result + to anything large (like SSIZE_T_MAX) is dangerous, + because if someone tries to loop over it, it will + turn effectively into an infinite loop. */ + PyErr_Format(PyExc_ZeroDivisionError, + "from_buffer('%s', ..): the actual length of the array " + "cannot be computed", ct->ct_name); + goto error2; + } + } + } + if (view->len < minimumlength) { + PyErr_Format(PyExc_ValueError, + "buffer is too small (%zd bytes) for '%s' (%zd bytes)", + view->len, ct->ct_name, minimumlength); + goto error2; + } + + cd = (CDataObject *)PyObject_GC_New(CDataObject_frombuf, + &CDataFromBuf_Type); if (cd == NULL) goto error2; @@ -7271,8 +7271,8 @@ static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x, cd->c_type = ct; cd->c_data = view->buf; cd->c_weakreflist = NULL; - ((CDataObject_frombuf *)cd)->length = arraylength; - ((CDataObject_frombuf *)cd)->bufferview = view; + ((CDataObject_frombuf *)cd)->length = arraylength; + ((CDataObject_frombuf *)cd)->bufferview = view; PyObject_GC_Track(cd); return (PyObject *)cd; @@ -7287,13 +7287,13 @@ static PyObject *b_from_buffer(PyObject *self, PyObject *args) { CTypeDescrObject *ct; PyObject *x; - int require_writable = 0; + int require_writable = 0; - if (!PyArg_ParseTuple(args, "O!O|i", &CTypeDescr_Type, &ct, &x, - &require_writable)) + if (!PyArg_ParseTuple(args, "O!O|i", &CTypeDescr_Type, &ct, &x, + &require_writable)) return NULL; - return direct_from_buffer(ct, x, require_writable); + return direct_from_buffer(ct, x, require_writable); } static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only) @@ -7360,12 +7360,12 @@ static PyObject *b_gcp(PyObject *self, PyObject *args, PyObject *kwds) CDataObject *cd; CDataObject *origobj; PyObject *destructor; - Py_ssize_t ignored; /* for pypy */ - static char *keywords[] = {"cdata", "destructor", "size", NULL}; + Py_ssize_t ignored; /* for pypy */ + static char *keywords[] = {"cdata", "destructor", "size", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|n:gc", keywords, - &CData_Type, &origobj, &destructor, - &ignored)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|n:gc", keywords, + &CData_Type, &origobj, &destructor, + &ignored)) return NULL; if (destructor == Py_None) { @@ -7383,15 +7383,15 @@ static PyObject *b_gcp(PyObject *self, PyObject *args, PyObject *kwds) return (PyObject *)cd; } -static PyObject *b_release(PyObject *self, PyObject *arg) -{ - if (!CData_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object"); - return NULL; - } - return cdata_exit(arg, NULL); -} - +static PyObject *b_release(PyObject *self, PyObject *arg) +{ + if (!CData_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object"); + return NULL; + } + return cdata_exit(arg, NULL); +} + /************************************************************/ static char _testfunc0(char a, char b) @@ -7566,20 +7566,20 @@ static int _testfunc23(char *p) return -42; } -#if 0 /* libffi doesn't properly support complexes currently */ - /* also, MSVC might not support _Complex... */ - /* if this is enabled one day, remember to also add _Complex - * arguments in addition to return values. */ -static float _Complex _testfunc24(float a, float b) -{ - return a + I*2.0*b; -} -static double _Complex _testfunc25(double a, double b) -{ - return a + I*2.0*b; -} -#endif - +#if 0 /* libffi doesn't properly support complexes currently */ + /* also, MSVC might not support _Complex... */ + /* if this is enabled one day, remember to also add _Complex + * arguments in addition to return values. */ +static float _Complex _testfunc24(float a, float b) +{ + return a + I*2.0*b; +} +static double _Complex _testfunc25(double a, double b) +{ + return a + I*2.0*b; +} +#endif + static PyObject *b__testfunc(PyObject *self, PyObject *args) { /* for testing only */ @@ -7612,10 +7612,10 @@ static PyObject *b__testfunc(PyObject *self, PyObject *args) case 21: f = &_testfunc21; break; case 22: f = &_testfunc22; break; case 23: f = &_testfunc23; break; -#if 0 - case 24: f = &_testfunc24; break; - case 25: f = &_testfunc25; break; -#endif +#if 0 + case 24: f = &_testfunc24; break; + case 25: f = &_testfunc25; break; +#endif default: PyErr_SetNone(PyExc_ValueError); return NULL; @@ -7717,7 +7717,7 @@ static PyMethodDef FFIBackendMethods[] = { {"from_buffer", b_from_buffer, METH_VARARGS}, {"memmove", (PyCFunction)b_memmove, METH_VARARGS | METH_KEYWORDS}, {"gcp", (PyCFunction)b_gcp, METH_VARARGS | METH_KEYWORDS}, - {"release", b_release, METH_O}, + {"release", b_release, METH_O}, #ifdef MS_WIN32 {"getwinerror", (PyCFunction)b_getwinerror, METH_VARARGS | METH_KEYWORDS}, #endif @@ -7832,51 +7832,51 @@ static PyObject *_cffi_from_c_char(char x) { return PyBytes_FromStringAndSize(&x, 1); } -/* backward-compatibility hack: instead of _cffi_to_c_char16_t() and - * _cffi_to_c_char32_t(), we have _cffi_to_c_wchar_t() handling whatever - * size is wchar_t, and _cffi_to_c_wchar3216_t() handling the opposite. - */ +/* backward-compatibility hack: instead of _cffi_to_c_char16_t() and + * _cffi_to_c_char32_t(), we have _cffi_to_c_wchar_t() handling whatever + * size is wchar_t, and _cffi_to_c_wchar3216_t() handling the opposite. + */ #ifdef HAVE_WCHAR_H -typedef wchar_t cffi_wchar_t; -#else -typedef uint16_t cffi_wchar_t; /* random pick... */ +typedef wchar_t cffi_wchar_t; +#else +typedef uint16_t cffi_wchar_t; /* random pick... */ #endif -static cffi_wchar_t _cffi_to_c_wchar_t(PyObject *init) -{ - if (sizeof(cffi_wchar_t) == 2) - return (cffi_wchar_t)_convert_to_char16_t(init); - else - return (cffi_wchar_t)_convert_to_char32_t(init); -} -static PyObject *_cffi_from_c_wchar_t(cffi_wchar_t x) { - if (sizeof(cffi_wchar_t) == 2) { - cffi_char16_t input = x; - return _my_PyUnicode_FromChar16(&input, 1); - } - else { - cffi_char32_t input = x; - return _my_PyUnicode_FromChar32(&input, 1); - } -} -static int _cffi_to_c_wchar3216_t(PyObject *init) -{ - if (sizeof(cffi_wchar_t) == 4) - return (int)_convert_to_char16_t(init); - else - return (int)_convert_to_char32_t(init); -} -static PyObject *_cffi_from_c_wchar3216_t(int x) { - if (sizeof(cffi_wchar_t) == 4) { - cffi_char16_t input = x; - return _my_PyUnicode_FromChar16(&input, 1); - } - else { - cffi_char32_t input = x; - return _my_PyUnicode_FromChar32(&input, 1); - } -} - +static cffi_wchar_t _cffi_to_c_wchar_t(PyObject *init) +{ + if (sizeof(cffi_wchar_t) == 2) + return (cffi_wchar_t)_convert_to_char16_t(init); + else + return (cffi_wchar_t)_convert_to_char32_t(init); +} +static PyObject *_cffi_from_c_wchar_t(cffi_wchar_t x) { + if (sizeof(cffi_wchar_t) == 2) { + cffi_char16_t input = x; + return _my_PyUnicode_FromChar16(&input, 1); + } + else { + cffi_char32_t input = x; + return _my_PyUnicode_FromChar32(&input, 1); + } +} +static int _cffi_to_c_wchar3216_t(PyObject *init) +{ + if (sizeof(cffi_wchar_t) == 4) + return (int)_convert_to_char16_t(init); + else + return (int)_convert_to_char32_t(init); +} +static PyObject *_cffi_from_c_wchar3216_t(int x) { + if (sizeof(cffi_wchar_t) == 4) { + cffi_char16_t input = x; + return _my_PyUnicode_FromChar16(&input, 1); + } + else { + cffi_char32_t input = x; + return _my_PyUnicode_FromChar32(&input, 1); + } +} + struct _cffi_externpy_s; /* forward declaration */ static void cffi_call_python(struct _cffi_externpy_s *, char *args); @@ -7900,15 +7900,15 @@ static void *cffi_exports[] = { convert_to_object, convert_from_object, convert_struct_to_owning_object, - _cffi_to_c_wchar_t, + _cffi_to_c_wchar_t, _cffi_from_c_wchar_t, _cffi_to_c_long_double, _cffi_to_c__Bool, _prepare_pointer_call_argument, convert_array_from_object, cffi_call_python, - _cffi_to_c_wchar3216_t, - _cffi_from_c_wchar3216_t, + _cffi_to_c_wchar3216_t, + _cffi_from_c_wchar3216_t, }; static struct { const char *name; int value; } all_dlopen_flags[] = { @@ -7962,22 +7962,22 @@ init_cffi_backend(void) PyObject *m, *v; int i; static char init_done = 0; - static PyTypeObject *all_types[] = { - &dl_type, - &CTypeDescr_Type, - &CField_Type, - &CData_Type, - &CDataOwning_Type, - &CDataOwningGC_Type, - &CDataFromBuf_Type, - &CDataGCP_Type, - &CDataIter_Type, - &MiniBuffer_Type, - &FFI_Type, - &Lib_Type, - &GlobSupport_Type, - NULL - }; + static PyTypeObject *all_types[] = { + &dl_type, + &CTypeDescr_Type, + &CField_Type, + &CData_Type, + &CDataOwning_Type, + &CDataOwningGC_Type, + &CDataFromBuf_Type, + &CDataGCP_Type, + &CDataIter_Type, + &MiniBuffer_Type, + &FFI_Type, + &Lib_Type, + &GlobSupport_Type, + NULL + }; v = PySys_GetObject("version"); if (v == NULL || !PyText_Check(v) || @@ -8003,23 +8003,23 @@ init_cffi_backend(void) INITERROR; } - /* readify all types and add them to the module */ - for (i = 0; all_types[i] != NULL; i++) { - PyTypeObject *tp = all_types[i]; - PyObject *tpo = (PyObject *)tp; - if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) { - PyErr_Format(PyExc_ImportError, - "'%s' is an ill-formed type name", tp->tp_name); - INITERROR; - } - if (PyType_Ready(tp) < 0) - INITERROR; - - Py_INCREF(tpo); - if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0) - INITERROR; - } - + /* readify all types and add them to the module */ + for (i = 0; all_types[i] != NULL; i++) { + PyTypeObject *tp = all_types[i]; + PyObject *tpo = (PyObject *)tp; + if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) { + PyErr_Format(PyExc_ImportError, + "'%s' is an ill-formed type name", tp->tp_name); + INITERROR; + } + if (PyType_Ready(tp) < 0) + INITERROR; + + Py_INCREF(tpo); + if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0) + INITERROR; + } + if (!init_done) { v = PyText_FromString("_cffi_backend"); if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict, @@ -8067,9 +8067,9 @@ init_cffi_backend(void) init_cffi_tls(); if (PyErr_Occurred()) INITERROR; - init_cffi_tls_zombie(); - if (PyErr_Occurred()) - INITERROR; + init_cffi_tls_zombie(); + if (PyErr_Occurred()) + INITERROR; if (init_ffi_lib(m) < 0) INITERROR; diff --git a/contrib/python/cffi/c/call_python.c b/contrib/python/cffi/c/call_python.c index d3d2e178104..520e026cbf5 100644 --- a/contrib/python/cffi/c/call_python.c +++ b/contrib/python/cffi/c/call_python.c @@ -1,18 +1,18 @@ -#if PY_VERSION_HEX >= 0x03080000 -# define HAVE_PYINTERPSTATE_GETDICT -#endif - - -static PyObject *_current_interp_key(void) -{ - PyInterpreterState *interp = PyThreadState_GET()->interp; -#ifdef HAVE_PYINTERPSTATE_GETDICT - return PyInterpreterState_GetDict(interp); /* shared reference */ -#else - return interp->modules; -#endif -} - +#if PY_VERSION_HEX >= 0x03080000 +# define HAVE_PYINTERPSTATE_GETDICT +#endif + + +static PyObject *_current_interp_key(void) +{ + PyInterpreterState *interp = PyThreadState_GET()->interp; +#ifdef HAVE_PYINTERPSTATE_GETDICT + return PyInterpreterState_GetDict(interp); /* shared reference */ +#else + return interp->modules; +#endif +} + static PyObject *_get_interpstate_dict(void) { /* Hack around to return a dict that is subinterpreter-local. @@ -22,9 +22,9 @@ static PyObject *_get_interpstate_dict(void) */ static PyObject *attr_name = NULL; PyThreadState *tstate; - PyObject *d, *interpdict; + PyObject *d, *interpdict; int err; - PyInterpreterState *interp; + PyInterpreterState *interp; tstate = PyThreadState_GET(); if (tstate == NULL) { @@ -32,13 +32,13 @@ static PyObject *_get_interpstate_dict(void) return NULL; } - interp = tstate->interp; -#ifdef HAVE_PYINTERPSTATE_GETDICT - interpdict = PyInterpreterState_GetDict(interp); /* shared reference */ -#else - interpdict = interp->builtins; -#endif - if (interpdict == NULL) { + interp = tstate->interp; +#ifdef HAVE_PYINTERPSTATE_GETDICT + interpdict = PyInterpreterState_GetDict(interp); /* shared reference */ +#else + interpdict = interp->builtins; +#endif + if (interpdict == NULL) { /* subinterpreter was cleared already, or is being cleared right now, to a point that is too much for us to continue */ return NULL; @@ -52,13 +52,13 @@ static PyObject *_get_interpstate_dict(void) goto error; } - d = PyDict_GetItem(interpdict, attr_name); + d = PyDict_GetItem(interpdict, attr_name); if (d == NULL) { d = PyDict_New(); if (d == NULL) goto error; - err = PyDict_SetItem(interpdict, attr_name, d); - Py_DECREF(d); /* if successful, there is one ref left in interpdict */ + err = PyDict_SetItem(interpdict, attr_name, d); + Py_DECREF(d); /* if successful, there is one ref left in interpdict */ if (err < 0) goto error; } @@ -71,7 +71,7 @@ static PyObject *_get_interpstate_dict(void) static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn) { - const char *s; + const char *s; PyObject *error, *onerror, *infotuple, *old1; int index, err; const struct _cffi_global_s *g; @@ -177,7 +177,7 @@ static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy) if (infotuple == NULL) return 3; /* no ffi.def_extern() from this subinterpreter */ - new1 = _current_interp_key(); + new1 = _current_interp_key(); Py_INCREF(new1); Py_INCREF(infotuple); old1 = (PyObject *)externpy->reserved1; @@ -197,20 +197,20 @@ static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy) #if (defined(WITH_THREAD) && !defined(_MSC_VER) && \ !defined(__amd64__) && !defined(__x86_64__) && \ !defined(__i386__) && !defined(__i386)) -# if defined(HAVE_SYNC_SYNCHRONIZE) -# define read_barrier() __sync_synchronize() -# elif defined(_AIX) -# define read_barrier() __lwsync() -# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) -# include <mbarrier.h> -# define read_barrier() __compiler_barrier() -# elif defined(__hpux) -# define read_barrier() _Asm_mf() -# else -# define read_barrier() /* missing */ -# warning "no definition for read_barrier(), missing synchronization for\ - multi-thread initialization in embedded mode" -# endif +# if defined(HAVE_SYNC_SYNCHRONIZE) +# define read_barrier() __sync_synchronize() +# elif defined(_AIX) +# define read_barrier() __lwsync() +# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# include <mbarrier.h> +# define read_barrier() __compiler_barrier() +# elif defined(__hpux) +# define read_barrier() _Asm_mf() +# else +# define read_barrier() /* missing */ +# warning "no definition for read_barrier(), missing synchronization for\ + multi-thread initialization in embedded mode" +# endif #else # define read_barrier() (void)0 #endif @@ -254,10 +254,10 @@ static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args) save_errno(); /* We need the infotuple here. We could always go through - _update_cache_to_call_python(), but to avoid the extra dict + _update_cache_to_call_python(), but to avoid the extra dict lookups, we cache in (reserved1, reserved2) the last seen pair - (interp->modules, infotuple). The first item in this tuple is - a random PyObject that identifies the subinterpreter. + (interp->modules, infotuple). The first item in this tuple is + a random PyObject that identifies the subinterpreter. */ if (externpy->reserved1 == NULL) { /* Not initialized! We didn't call @ffi.def_extern() on this @@ -266,7 +266,7 @@ static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args) } else { PyGILState_STATE state = gil_ensure(); - if (externpy->reserved1 != _current_interp_key()) { + if (externpy->reserved1 != _current_interp_key()) { /* Update the (reserved1, reserved2) cache. This will fail if we didn't call @ffi.def_extern() in this particular subinterpreter. */ diff --git a/contrib/python/cffi/c/cdlopen.c b/contrib/python/cffi/c/cdlopen.c index 0ed319b8b59..9dc542590f7 100644 --- a/contrib/python/cffi/c/cdlopen.c +++ b/contrib/python/cffi/c/cdlopen.c @@ -1,7 +1,7 @@ /* ffi.dlopen() interface with dlopen()/dlsym()/dlclose() */ -static void *cdlopen_fetch(PyObject *libname, void *libhandle, - const char *symbol) +static void *cdlopen_fetch(PyObject *libname, void *libhandle, + const char *symbol) { void *address; @@ -40,19 +40,19 @@ static int cdlopen_close(PyObject *libname, void *libhandle) static PyObject *ffi_dlopen(PyObject *self, PyObject *args) { - const char *modname; - PyObject *temp, *result = NULL; + const char *modname; + PyObject *temp, *result = NULL; void *handle; - int auto_close; + int auto_close; - handle = b_do_dlopen(args, &modname, &temp, &auto_close); - if (handle != NULL) - { - result = (PyObject *)lib_internal_new((FFIObject *)self, - modname, handle, auto_close); + handle = b_do_dlopen(args, &modname, &temp, &auto_close); + if (handle != NULL) + { + result = (PyObject *)lib_internal_new((FFIObject *)self, + modname, handle, auto_close); } - Py_XDECREF(temp); - return result; + Py_XDECREF(temp); + return result; } static PyObject *ffi_dlclose(PyObject *self, PyObject *args) @@ -63,16 +63,16 @@ static PyObject *ffi_dlclose(PyObject *self, PyObject *args) return NULL; libhandle = lib->l_libhandle; - if (libhandle != NULL) - { - lib->l_libhandle = NULL; - - /* Clear the dict to force further accesses to do cdlopen_fetch() - again, and fail because the library was closed. */ - PyDict_Clear(lib->l_dict); - - if (cdlopen_close(lib->l_libname, libhandle) < 0) - return NULL; + if (libhandle != NULL) + { + lib->l_libhandle = NULL; + + /* Clear the dict to force further accesses to do cdlopen_fetch() + again, and fail because the library was closed. */ + PyDict_Clear(lib->l_dict); + + if (cdlopen_close(lib->l_libname, libhandle) < 0) + return NULL; } Py_INCREF(Py_None); return Py_None; diff --git a/contrib/python/cffi/c/cffi1_module.c b/contrib/python/cffi/c/cffi1_module.c index 06a84fea37c..2c00c5f57ac 100644 --- a/contrib/python/cffi/c/cffi1_module.c +++ b/contrib/python/cffi/c/cffi1_module.c @@ -2,9 +2,9 @@ #include "parse_c_type.c" #include "realize_c_type.c" -#define CFFI_VERSION_MIN 0x2601 -#define CFFI_VERSION_CHAR16CHAR32 0x2801 -#define CFFI_VERSION_MAX 0x28FF +#define CFFI_VERSION_MIN 0x2601 +#define CFFI_VERSION_CHAR16CHAR32 0x2801 +#define CFFI_VERSION_MAX 0x28FF typedef struct FFIObject_s FFIObject; typedef struct LibObject_s LibObject; @@ -41,9 +41,9 @@ static int init_ffi_lib(PyObject *m) if (PyDict_SetItemString(FFI_Type.tp_dict, "CData", (PyObject *)&CData_Type) < 0) return -1; - if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer", - (PyObject *)&MiniBuffer_Type) < 0) - return -1; + if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer", + (PyObject *)&MiniBuffer_Type) < 0) + return -1; for (i = 0; all_dlopen_flags[i].name != NULL; i++) { x = PyInt_FromLong(all_dlopen_flags[i].value); @@ -169,8 +169,8 @@ static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) num_exports = 25; if (ctx->flags & 1) /* set to mean that 'extern "Python"' is used */ num_exports = 26; - if (version >= CFFI_VERSION_CHAR16CHAR32) - num_exports = 28; + if (version >= CFFI_VERSION_CHAR16CHAR32) + num_exports = 28; memcpy(exports, (char *)cffi_exports, num_exports * sizeof(void *)); /* make the module object */ @@ -184,7 +184,7 @@ static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0) return NULL; - lib = lib_internal_new(ffi, module_name, NULL, 0); + lib = lib_internal_new(ffi, module_name, NULL, 0); if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0) return NULL; diff --git a/contrib/python/cffi/c/cglob.c b/contrib/python/cffi/c/cglob.c index e97767c9d75..0d708b8aa3b 100644 --- a/contrib/python/cffi/c/cglob.c +++ b/contrib/python/cffi/c/cglob.c @@ -20,7 +20,7 @@ static void glob_support_dealloc(GlobSupportObject *gs) static PyTypeObject GlobSupport_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.__FFIGlobSupport", + "_cffi_backend.__FFIGlobSupport", sizeof(GlobSupportObject), 0, (destructor)glob_support_dealloc, /* tp_dealloc */ diff --git a/contrib/python/cffi/c/ffi_obj.c b/contrib/python/cffi/c/ffi_obj.c index f154146621e..cb5f3355a1f 100644 --- a/contrib/python/cffi/c/ffi_obj.c +++ b/contrib/python/cffi/c/ffi_obj.c @@ -92,7 +92,7 @@ static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* forward, declared in cdlopen.c because it's mostly useful for this case */ static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds); -static PyObject *ffi_fetch_int_constant(FFIObject *ffi, const char *name, +static PyObject *ffi_fetch_int_constant(FFIObject *ffi, const char *name, int recursion) { int index; @@ -145,7 +145,7 @@ static PyObject *ffi_fetch_int_constant(FFIObject *ffi, const char *name, #define ACCEPT_ALL (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA) #define CONSIDER_FN_AS_FNPTR 8 -static CTypeDescrObject *_ffi_bad_type(FFIObject *ffi, const char *input_text) +static CTypeDescrObject *_ffi_bad_type(FFIObject *ffi, const char *input_text) { size_t length = strlen(input_text); char *extra; @@ -188,7 +188,7 @@ static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, PyObject *x = PyDict_GetItem(types_dict, arg); if (x == NULL) { - const char *input_text = PyText_AS_UTF8(arg); + const char *input_text = PyText_AS_UTF8(arg); int err, index = parse_c_type(&ffi->info, input_text); if (index < 0) return _ffi_bad_type(ffi, input_text); @@ -697,40 +697,40 @@ PyDoc_STRVAR(ffi_from_buffer_doc, "containing large quantities of raw data in some other format, like\n" "'array.array' or numpy arrays."); -static PyObject *ffi_from_buffer(FFIObject *self, PyObject *args, - PyObject *kwds) +static PyObject *ffi_from_buffer(FFIObject *self, PyObject *args, + PyObject *kwds) { - PyObject *cdecl1, *python_buf = NULL; - CTypeDescrObject *ct; - int require_writable = 0; - static char *keywords[] = {"cdecl", "python_buffer", - "require_writable", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:from_buffer", keywords, - &cdecl1, &python_buf, &require_writable)) - return NULL; - - if (python_buf == NULL) { - python_buf = cdecl1; - ct = g_ct_chararray; - } - else { - ct = _ffi_type(self, cdecl1, ACCEPT_STRING|ACCEPT_CTYPE); - if (ct == NULL) - return NULL; - } - return direct_from_buffer(ct, python_buf, require_writable); + PyObject *cdecl1, *python_buf = NULL; + CTypeDescrObject *ct; + int require_writable = 0; + static char *keywords[] = {"cdecl", "python_buffer", + "require_writable", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:from_buffer", keywords, + &cdecl1, &python_buf, &require_writable)) + return NULL; + + if (python_buf == NULL) { + python_buf = cdecl1; + ct = g_ct_chararray; + } + else { + ct = _ffi_type(self, cdecl1, ACCEPT_STRING|ACCEPT_CTYPE); + if (ct == NULL) + return NULL; + } + return direct_from_buffer(ct, python_buf, require_writable); } PyDoc_STRVAR(ffi_gc_doc, "Return a new cdata object that points to the same data.\n" "Later, when this new cdata object is garbage-collected,\n" -"'destructor(old_cdata_object)' will be called.\n" -"\n" -"The optional 'size' gives an estimate of the size, used to\n" -"trigger the garbage collection more eagerly. So far only used\n" -"on PyPy. It tells the GC that the returned object keeps alive\n" -"roughly 'size' bytes of external memory."); +"'destructor(old_cdata_object)' will be called.\n" +"\n" +"The optional 'size' gives an estimate of the size, used to\n" +"trigger the garbage collection more eagerly. So far only used\n" +"on PyPy. It tells the GC that the returned object keeps alive\n" +"roughly 'size' bytes of external memory."); #define ffi_gc b_gcp /* ffi_gc() => b_gcp() from _cffi_backend.c */ @@ -1073,7 +1073,7 @@ static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds) Py_DECREF(res); res = NULL; } - Py_XDECREF(tup); + Py_XDECREF(tup); } } @@ -1082,22 +1082,22 @@ static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds) return res; } -PyDoc_STRVAR(ffi_release_doc, -"Release now the resources held by a 'cdata' object from ffi.new(),\n" -"ffi.gc() or ffi.from_buffer(). The cdata object must not be used\n" -"afterwards.\n" -"\n" -"'ffi.release(cdata)' is equivalent to 'cdata.__exit__()'.\n" -"\n" -"Note that on CPython this method has no effect (so far) on objects\n" -"returned by ffi.new(), because the memory is allocated inline with the\n" -"cdata object and cannot be freed independently. It might be fixed in\n" -"future releases of cffi."); - -#define ffi_release b_release /* ffi_release() => b_release() - from _cffi_backend.c */ - - +PyDoc_STRVAR(ffi_release_doc, +"Release now the resources held by a 'cdata' object from ffi.new(),\n" +"ffi.gc() or ffi.from_buffer(). The cdata object must not be used\n" +"afterwards.\n" +"\n" +"'ffi.release(cdata)' is equivalent to 'cdata.__exit__()'.\n" +"\n" +"Note that on CPython this method has no effect (so far) on objects\n" +"returned by ffi.new(), because the memory is allocated inline with the\n" +"cdata object and cannot be freed independently. It might be fixed in\n" +"future releases of cffi."); + +#define ffi_release b_release /* ffi_release() => b_release() + from _cffi_backend.c */ + + #define METH_VKW (METH_VARARGS | METH_KEYWORDS) static PyMethodDef ffi_methods[] = { {"addressof", (PyCFunction)ffi_addressof, METH_VARARGS, ffi_addressof_doc}, @@ -1107,7 +1107,7 @@ static PyMethodDef ffi_methods[] = { {"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc}, {"dlclose", (PyCFunction)ffi_dlclose, METH_VARARGS, ffi_dlclose_doc}, {"dlopen", (PyCFunction)ffi_dlopen, METH_VARARGS, ffi_dlopen_doc}, - {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW, ffi_from_buffer_doc}, + {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW, ffi_from_buffer_doc}, {"from_handle",(PyCFunction)ffi_from_handle,METH_O, ffi_from_handle_doc}, {"gc", (PyCFunction)ffi_gc, METH_VKW, ffi_gc_doc}, {"getctype", (PyCFunction)ffi_getctype, METH_VKW, ffi_getctype_doc}, @@ -1122,7 +1122,7 @@ static PyMethodDef ffi_methods[] = { {"new_allocator",(PyCFunction)ffi_new_allocator,METH_VKW,ffi_new_allocator_doc}, {"new_handle", (PyCFunction)ffi_new_handle, METH_O, ffi_new_handle_doc}, {"offsetof", (PyCFunction)ffi_offsetof, METH_VARARGS, ffi_offsetof_doc}, - {"release", (PyCFunction)ffi_release, METH_O, ffi_release_doc}, + {"release", (PyCFunction)ffi_release, METH_O, ffi_release_doc}, {"sizeof", (PyCFunction)ffi_sizeof, METH_O, ffi_sizeof_doc}, {"string", (PyCFunction)ffi_string, METH_VKW, ffi_string_doc}, {"typeof", (PyCFunction)ffi_typeof, METH_O, ffi_typeof_doc}, @@ -1137,7 +1137,7 @@ static PyGetSetDef ffi_getsets[] = { static PyTypeObject FFI_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.FFI", + "_cffi_backend.FFI", sizeof(FFIObject), 0, (destructor)ffi_dealloc, /* tp_dealloc */ diff --git a/contrib/python/cffi/c/file_emulator.h b/contrib/python/cffi/c/file_emulator.h index 82a34c0c72f..93b9d82ac01 100644 --- a/contrib/python/cffi/c/file_emulator.h +++ b/contrib/python/cffi/c/file_emulator.h @@ -33,7 +33,7 @@ static FILE *PyFile_AsFile(PyObject *ob_file) PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL; FILE *f; int fd; - const char *mode; + const char *mode; ob = PyObject_CallMethod(ob_file, "flush", NULL); if (ob == NULL) diff --git a/contrib/python/cffi/c/lib_obj.c b/contrib/python/cffi/c/lib_obj.c index 38bf3d55104..4f37f5811fb 100644 --- a/contrib/python/cffi/c/lib_obj.c +++ b/contrib/python/cffi/c/lib_obj.c @@ -29,7 +29,7 @@ struct LibObject_s { PyObject *l_libname; /* some string that gives the name of the lib */ FFIObject *l_ffi; /* reference back to the ffi object */ void *l_libhandle; /* the dlopen()ed handle, if any */ - int l_auto_close; /* if we must dlclose() this handle */ + int l_auto_close; /* if we must dlclose() this handle */ }; static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x) @@ -86,14 +86,14 @@ static PyObject *_cpyextfunc_type_index(PyObject *x) } static void cdlopen_close_ignore_errors(void *libhandle); /* forward */ -static void *cdlopen_fetch(PyObject *libname, void *libhandle, - const char *symbol); +static void *cdlopen_fetch(PyObject *libname, void *libhandle, + const char *symbol); static void lib_dealloc(LibObject *lib) { - PyObject_GC_UnTrack(lib); - if (lib->l_auto_close) - cdlopen_close_ignore_errors(lib->l_libhandle); + PyObject_GC_UnTrack(lib); + if (lib->l_auto_close) + cdlopen_close_ignore_errors(lib->l_libhandle); Py_DECREF(lib->l_dict); Py_DECREF(lib->l_libname); Py_DECREF(lib->l_ffi); @@ -130,7 +130,7 @@ static PyObject *lib_build_cpython_func(LibObject *lib, int i, type_index = _CFFI_GETARG(g->type_op); _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types; static const char *const format = ";\n\nCFFI C function from %s.lib"; - const char *libname = PyText_AS_UTF8(lib->l_libname); + const char *libname = PyText_AS_UTF8(lib->l_libname); struct funcbuilder_s funcbuilder; /* return type: */ @@ -161,14 +161,14 @@ static PyObject *lib_build_cpython_func(LibObject *lib, if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0) goto error; - /* The few bytes of memory we allocate here appear to leak, but - this is not a real leak. Indeed, CPython never unloads its C - extension modules. There is only one PyMem_Malloc() per real - C function in a CFFI C extension module. That means that this - PyMem_Malloc() could also have been written with a static - global variable generated for each CPYTHON_BLTN defined in the - C extension, and the effect would be the same (but a bit more - complicated). + /* The few bytes of memory we allocate here appear to leak, but + this is not a real leak. Indeed, CPython never unloads its C + extension modules. There is only one PyMem_Malloc() per real + C function in a CFFI C extension module. That means that this + PyMem_Malloc() could also have been written with a static + global variable generated for each CPYTHON_BLTN defined in the + C extension, and the effect would be the same (but a bit more + complicated). */ xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s) + funcbuilder.nb_bytes + @@ -213,7 +213,7 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name, const struct _cffi_global_s *g; CTypeDescrObject *ct; builder_c_t *types_builder = lib->l_types_builder; - const char *s = PyText_AsUTF8(name); + const char *s = PyText_AsUTF8(name); if (s == NULL) return NULL; @@ -320,20 +320,20 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name, return NULL; } else { - /* The few bytes of memory we allocate here appear to leak, but - this is not a real leak. Indeed, CPython never unloads its C - extension modules. There is only one PyMem_Malloc() per real - non-integer C constant in a CFFI C extension module. That - means that this PyMem_Malloc() could also have been written - with a static global variable generated for each OP_CONSTANT - defined in the C extension, and the effect would be the same - (but a bit more complicated). - - Note that we used to do alloca(), but see issue #198. We - could still do alloca(), or explicit PyMem_Free(), in some - cases; but there is no point and it only makes the remaining - less-common cases more suspicious. - */ + /* The few bytes of memory we allocate here appear to leak, but + this is not a real leak. Indeed, CPython never unloads its C + extension modules. There is only one PyMem_Malloc() per real + non-integer C constant in a CFFI C extension module. That + means that this PyMem_Malloc() could also have been written + with a static global variable generated for each OP_CONSTANT + defined in the C extension, and the effect would be the same + (but a bit more complicated). + + Note that we used to do alloca(), but see issue #198. We + could still do alloca(), or explicit PyMem_Free(), in some + cases; but there is no point and it only makes the remaining + less-common cases more suspicious. + */ assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT); data = PyMem_Malloc(ct->ct_size); if (data == NULL) { @@ -508,7 +508,7 @@ static PyObject *_lib_dict(LibObject *lib) static PyObject *lib_getattr(LibObject *lib, PyObject *name) { - const char *p; + const char *p; PyObject *x; LIB_GET_OR_CACHE_ADDR(x, lib, name, goto missing); @@ -519,7 +519,7 @@ static PyObject *lib_getattr(LibObject *lib, PyObject *name) return x; missing: - /*** ATTRIBUTEERROR IS SET HERE ***/ + /*** ATTRIBUTEERROR IS SET HERE ***/ p = PyText_AsUTF8(name); if (p == NULL) return NULL; @@ -546,14 +546,14 @@ static PyObject *lib_getattr(LibObject *lib, PyObject *name) PyErr_Clear(); return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname)); } -#if PY_MAJOR_VERSION >= 3 - if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) { - /* some more module-like behavior hacks */ - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } -#endif +#if PY_MAJOR_VERSION >= 3 + if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) { + /* some more module-like behavior hacks */ + PyErr_Clear(); + Py_INCREF(Py_None); + return Py_None; + } +#endif return NULL; } @@ -589,7 +589,7 @@ static PyMethodDef lib_methods[] = { static PyTypeObject Lib_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.Lib", + "_cffi_backend.Lib", sizeof(LibObject), 0, (destructor)lib_dealloc, /* tp_dealloc */ @@ -625,8 +625,8 @@ static PyTypeObject Lib_Type = { offsetof(LibObject, l_dict), /* tp_dictoffset */ }; -static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name, - void *dlopen_libhandle, int auto_close) +static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name, + void *dlopen_libhandle, int auto_close) { LibObject *lib; PyObject *libname, *dict; @@ -649,7 +649,7 @@ static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name, Py_INCREF(ffi); lib->l_ffi = ffi; lib->l_libhandle = dlopen_libhandle; - lib->l_auto_close = auto_close; + lib->l_auto_close = auto_close; return lib; err3: @@ -657,8 +657,8 @@ static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name, err2: Py_DECREF(libname); err1: - if (auto_close) - cdlopen_close_ignore_errors(dlopen_libhandle); + if (auto_close) + cdlopen_close_ignore_errors(dlopen_libhandle); return NULL; } diff --git a/contrib/python/cffi/c/libffi_msvc/ffi.c b/contrib/python/cffi/c/libffi_msvc/ffi.c index 581d6599826..4fe84f16b3c 100644 --- a/contrib/python/cffi/c/libffi_msvc/ffi.c +++ b/contrib/python/cffi/c/libffi_msvc/ffi.c @@ -103,7 +103,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif) } } #ifdef _WIN64 - else if (z != 1 && z != 2 && z != 4 && z != 8) + else if (z != 1 && z != 2 && z != 4 && z != 8) { /* On Win64, if a single argument takes more than 8 bytes, then it is always passed by reference. */ @@ -144,11 +144,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* MSVC returns small structures in registers. Put in cif->flags the value FFI_TYPE_STRUCT only if the structure is big enough; otherwise, put the 4- or 8-bytes integer type. */ - if (cif->rtype->size == 1 || - cif->rtype->size == 2 || - cif->rtype->size == 4) + if (cif->rtype->size == 1 || + cif->rtype->size == 2 || + cif->rtype->size == 4) cif->flags = FFI_TYPE_INT; - else if (cif->rtype->size == 8) + else if (cif->rtype->size == 8) cif->flags = FFI_TYPE_SINT64; else cif->flags = FFI_TYPE_STRUCT; @@ -289,7 +289,7 @@ ffi_closure_SYSV (ffi_closure *closure, char *argp) _asm fld DWORD PTR [eax] ; // asm ("flds (%0)" : : "r" (resp) : "st" ); } - else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE) + else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE) { _asm mov eax, resp ; _asm fld QWORD PTR [eax] ; @@ -305,10 +305,10 @@ ffi_closure_SYSV (ffi_closure *closure, char *argp) // : : "r"(resp) // : "eax", "edx"); } - else if (rtype == FFI_TYPE_STRUCT) - { - _asm mov eax, resp ; - } + else if (rtype == FFI_TYPE_STRUCT) + { + _asm mov eax, resp ; + } #else /* now, do a generic return based on the value of rtype */ if (rtype == FFI_TYPE_INT) @@ -319,7 +319,7 @@ ffi_closure_SYSV (ffi_closure *closure, char *argp) { asm ("flds (%0)" : : "r" (resp) : "st" ); } - else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE) + else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE) { asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); } @@ -330,10 +330,10 @@ ffi_closure_SYSV (ffi_closure *closure, char *argp) : : "r"(resp) : "eax", "edx"); } - else if (rtype == FFI_TYPE_STRUCT) - { - asm ("movl %0,%%eax" : : "r" (resp) : "eax"); - } + else if (rtype == FFI_TYPE_STRUCT) + { + asm ("movl %0,%%eax" : : "r" (resp) : "eax"); + } #endif #endif @@ -342,8 +342,8 @@ ffi_closure_SYSV (ffi_closure *closure, char *argp) result types except for floats; we have to 'mov xmm0, rax' in the caller to correct this. */ - if (rtype == FFI_TYPE_STRUCT) - return resp; + if (rtype == FFI_TYPE_STRUCT) + return resp; return *(void **)resp; #endif } @@ -382,7 +382,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, /* because we're little endian, this is what it turns into. */ #ifdef _WIN64 - if (z != 1 && z != 2 && z != 4 && z != 8) + if (z != 1 && z != 2 && z != 4 && z != 8) { /* On Win64, if a single argument takes more than 8 bytes, then it is always passed by reference. */ @@ -451,11 +451,11 @@ ffi_prep_closure_loc (ffi_closure* closure, || cif->arg_types[3]->type == FFI_TYPE_DOUBLE)) mask |= 8; - /* if we return a non-small struct, then the first argument is a pointer - * to the return area, and all real arguments are shifted by one */ - if (cif->flags == FFI_TYPE_STRUCT) - mask = (mask & ~8) << 1; - + /* if we return a non-small struct, then the first argument is a pointer + * to the return area, and all real arguments are shifted by one */ + if (cif->flags == FFI_TYPE_STRUCT) + mask = (mask & ~8) << 1; + /* 41 BB ---- mov r11d,mask */ BYTES("\x41\xBB"); INT(mask); diff --git a/contrib/python/cffi/c/libffi_msvc/prep_cif.c b/contrib/python/cffi/c/libffi_msvc/prep_cif.c index df94a988758..5ee83a9f0d1 100644 --- a/contrib/python/cffi/c/libffi_msvc/prep_cif.c +++ b/contrib/python/cffi/c/libffi_msvc/prep_cif.c @@ -117,10 +117,10 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, /* Make space for the return structure pointer */ if (cif->rtype->type == FFI_TYPE_STRUCT #ifdef _WIN32 - && (cif->rtype->size != 1) /* MSVC returns small structs in registers */ - && (cif->rtype->size != 2) - && (cif->rtype->size != 4) - && (cif->rtype->size != 8) + && (cif->rtype->size != 1) /* MSVC returns small structs in registers */ + && (cif->rtype->size != 2) + && (cif->rtype->size != 4) + && (cif->rtype->size != 8) #endif #ifdef SPARC && (cif->abi != FFI_V9 || cif->rtype->size > 32) diff --git a/contrib/python/cffi/c/minibuffer.h b/contrib/python/cffi/c/minibuffer.h index f3f5ca15c43..e92141fa167 100644 --- a/contrib/python/cffi/c/minibuffer.h +++ b/contrib/python/cffi/c/minibuffer.h @@ -56,17 +56,17 @@ static int mb_ass_item(MiniBufferObj *self, Py_ssize_t idx, PyObject *other) } } -/* forward: from _cffi_backend.c */ -static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only); - +/* forward: from _cffi_backend.c */ +static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only); + static int mb_ass_slice(MiniBufferObj *self, Py_ssize_t left, Py_ssize_t right, PyObject *other) { - Py_ssize_t count; + Py_ssize_t count; Py_ssize_t size = self->mb_size; - Py_buffer src_view; + Py_buffer src_view; - if (_fetch_as_buffer(other, &src_view, 0) < 0) + if (_fetch_as_buffer(other, &src_view, 0) < 0) return -1; if (left < 0) left = 0; @@ -74,14 +74,14 @@ static int mb_ass_slice(MiniBufferObj *self, if (left > right) left = right; count = right - left; - if (count != src_view.len) { - PyBuffer_Release(&src_view); + if (count != src_view.len) { + PyBuffer_Release(&src_view); PyErr_SetString(PyExc_ValueError, "right operand length must match slice length"); return -1; } - memcpy(self->mb_data + left, src_view.buf, count); - PyBuffer_Release(&src_view); + memcpy(self->mb_data + left, src_view.buf, count); + PyBuffer_Release(&src_view); return 0; } @@ -160,91 +160,91 @@ mb_clear(MiniBufferObj *ob) return 0; } -static PyObject * -mb_richcompare(PyObject *self, PyObject *other, int op) -{ - Py_ssize_t self_size, other_size; - Py_buffer self_bytes, other_bytes; - PyObject *res; - Py_ssize_t minsize; - int cmp, rc; - - /* Bytes can be compared to anything that supports the (binary) - buffer API. Except that a comparison with Unicode is always an - error, even if the comparison is for equality. */ - rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); - if (!rc) - rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); - if (rc < 0) - return NULL; - if (rc) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) { - PyErr_Clear(); - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - - } - self_size = self_bytes.len; - - if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) { - PyErr_Clear(); - PyBuffer_Release(&self_bytes); - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - - } - other_size = other_bytes.len; - - if (self_size != other_size && (op == Py_EQ || op == Py_NE)) { - /* Shortcut: if the lengths differ, the objects differ */ - cmp = (op == Py_NE); - } - else { - minsize = self_size; - if (other_size < minsize) - minsize = other_size; - - cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize); - /* In ISO C, memcmp() guarantees to use unsigned bytes! */ - - if (cmp == 0) { - if (self_size < other_size) - cmp = -1; - else if (self_size > other_size) - cmp = 1; - } - - switch (op) { - case Py_LT: cmp = cmp < 0; break; - case Py_LE: cmp = cmp <= 0; break; - case Py_EQ: cmp = cmp == 0; break; - case Py_NE: cmp = cmp != 0; break; - case Py_GT: cmp = cmp > 0; break; - case Py_GE: cmp = cmp >= 0; break; - } - } - - res = cmp ? Py_True : Py_False; - PyBuffer_Release(&self_bytes); - PyBuffer_Release(&other_bytes); - Py_INCREF(res); - return res; -} - +static PyObject * +mb_richcompare(PyObject *self, PyObject *other, int op) +{ + Py_ssize_t self_size, other_size; + Py_buffer self_bytes, other_bytes; + PyObject *res; + Py_ssize_t minsize; + int cmp, rc; + + /* Bytes can be compared to anything that supports the (binary) + buffer API. Except that a comparison with Unicode is always an + error, even if the comparison is for equality. */ + rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) { + PyErr_Clear(); + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + + } + self_size = self_bytes.len; + + if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) { + PyErr_Clear(); + PyBuffer_Release(&self_bytes); + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + + } + other_size = other_bytes.len; + + if (self_size != other_size && (op == Py_EQ || op == Py_NE)) { + /* Shortcut: if the lengths differ, the objects differ */ + cmp = (op == Py_NE); + } + else { + minsize = self_size; + if (other_size < minsize) + minsize = other_size; + + cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize); + /* In ISO C, memcmp() guarantees to use unsigned bytes! */ + + if (cmp == 0) { + if (self_size < other_size) + cmp = -1; + else if (self_size > other_size) + cmp = 1; + } + + switch (op) { + case Py_LT: cmp = cmp < 0; break; + case Py_LE: cmp = cmp <= 0; break; + case Py_EQ: cmp = cmp == 0; break; + case Py_NE: cmp = cmp != 0; break; + case Py_GT: cmp = cmp > 0; break; + case Py_GE: cmp = cmp >= 0; break; + } + } + + res = cmp ? Py_True : Py_False; + PyBuffer_Release(&self_bytes); + PyBuffer_Release(&other_bytes); + Py_INCREF(res); + return res; +} + #if PY_MAJOR_VERSION >= 3 /* pfffffffffffff pages of copy-paste from listobject.c */ - -/* pfffffffffffff#2: the PySlice_GetIndicesEx() *macro* should not - be called, because C extension modules compiled with it differ - on ABI between 3.6.0, 3.6.1 and 3.6.2. */ -#if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && !defined(PYPY_VERSION) -#undef PySlice_GetIndicesEx -#endif - + +/* pfffffffffffff#2: the PySlice_GetIndicesEx() *macro* should not + be called, because C extension modules compiled with it differ + on ABI between 3.6.0, 3.6.1 and 3.6.2. */ +#if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && !defined(PYPY_VERSION) +#undef PySlice_GetIndicesEx +#endif + static PyObject *mb_subscript(MiniBufferObj *self, PyObject *item) { if (PyIndex_Check(item)) { @@ -326,22 +326,22 @@ static PyMappingMethods mb_as_mapping = { # define MINIBUF_TPFLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER) #endif -PyDoc_STRVAR(ffi_buffer_doc, -"ffi.buffer(cdata[, byte_size]):\n" -"Return a read-write buffer object that references the raw C data\n" -"pointed to by the given 'cdata'. The 'cdata' must be a pointer or an\n" -"array. Can be passed to functions expecting a buffer, or directly\n" -"manipulated with:\n" -"\n" -" buf[:] get a copy of it in a regular string, or\n" -" buf[idx] as a single character\n" -" buf[:] = ...\n" -" buf[idx] = ... change the content"); - -static PyObject * /* forward, implemented in _cffi_backend.c */ -b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds); - - +PyDoc_STRVAR(ffi_buffer_doc, +"ffi.buffer(cdata[, byte_size]):\n" +"Return a read-write buffer object that references the raw C data\n" +"pointed to by the given 'cdata'. The 'cdata' must be a pointer or an\n" +"array. Can be passed to functions expecting a buffer, or directly\n" +"manipulated with:\n" +"\n" +" buf[:] get a copy of it in a regular string, or\n" +" buf[idx] as a single character\n" +" buf[:] = ...\n" +" buf[idx] = ... change the content"); + +static PyObject * /* forward, implemented in _cffi_backend.c */ +b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds); + + static PyTypeObject MiniBuffer_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_cffi_backend.buffer", @@ -372,25 +372,25 @@ static PyTypeObject MiniBuffer_Type = { &mb_as_buffer, /* tp_as_buffer */ (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | MINIBUF_TPFLAGS), /* tp_flags */ - ffi_buffer_doc, /* tp_doc */ + ffi_buffer_doc, /* tp_doc */ (traverseproc)mb_traverse, /* tp_traverse */ (inquiry)mb_clear, /* tp_clear */ - (richcmpfunc)mb_richcompare, /* tp_richcompare */ + (richcmpfunc)mb_richcompare, /* tp_richcompare */ offsetof(MiniBufferObj, mb_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - b_buffer_new, /* tp_new */ - 0, /* tp_free */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + b_buffer_new, /* tp_new */ + 0, /* tp_free */ }; static PyObject *minibuffer_new(char *data, Py_ssize_t size, diff --git a/contrib/python/cffi/c/misc_thread_common.h b/contrib/python/cffi/c/misc_thread_common.h index 66e283545b7..7c8a543f26c 100644 --- a/contrib/python/cffi/c/misc_thread_common.h +++ b/contrib/python/cffi/c/misc_thread_common.h @@ -1,14 +1,14 @@ #ifndef WITH_THREAD # error "xxx no-thread configuration not tested, please report if you need that" #endif -#include "pythread.h" +#include "pythread.h" struct cffi_tls_s { - /* The current thread's ThreadCanaryObj. This is only non-null in - case cffi builds the thread state here. It remains null if this - thread had already a thread state provided by CPython. */ - struct thread_canary_s *local_thread_canary; + /* The current thread's ThreadCanaryObj. This is only non-null in + case cffi builds the thread state here. It remains null if this + thread had already a thread state provided by CPython. */ + struct thread_canary_s *local_thread_canary; #ifndef USE__THREAD /* The saved errno. If the C compiler supports '__thread', then @@ -25,247 +25,247 @@ struct cffi_tls_s { static struct cffi_tls_s *get_cffi_tls(void); /* in misc_thread_posix.h or misc_win32.h */ - -/* We try to keep the PyThreadState around in a thread not started by - * Python but where cffi callbacks occur. If we didn't do that, then - * the standard logic in PyGILState_Ensure() and PyGILState_Release() - * would create a new PyThreadState and completely free it for every - * single call. For some applications, this is a huge slow-down. - * - * As shown by issue #362, it is quite messy to do. The current - * solution is to keep the PyThreadState alive by incrementing its - * 'gilstate_counter'. We detect thread shut-down, and we put the - * PyThreadState inside a list of zombies (we can't free it - * immediately because we don't have the GIL at that point in time). - * We also detect other pieces of code (notably Py_Finalize()) which - * clear and free PyThreadStates under our feet, using ThreadCanaryObj. - */ - -#define TLS_ZOM_LOCK() PyThread_acquire_lock(cffi_zombie_lock, WAIT_LOCK) -#define TLS_ZOM_UNLOCK() PyThread_release_lock(cffi_zombie_lock) -static PyThread_type_lock cffi_zombie_lock = NULL; - - -/* A 'canary' object is created in a thread when there is a callback - invoked, and that thread has no PyThreadState so far. It is an - object of reference count equal to 1, which is stored in the - PyThreadState->dict. Two things can occur then: - - 1. The PyThreadState can be forcefully cleared by Py_Finalize(). - Then thread_canary_dealloc() is called, and we have to cancel - the hacks we did to keep the PyThreadState alive. - - 2. The thread finishes. In that case, we put the canary in a list - of zombies, and at some convenient time later when we have the - GIL, we free all PyThreadStates in the zombie list. - - Some more fun comes from the fact that thread_canary_dealloc() can - be called at a point where the canary is in the zombie list already. - Also, the various pieces are freed at specific points in time, and - we must make sure not to access already-freed structures: - - - the struct cffi_tls_s is valid until the thread shuts down, and - then it is freed by cffi_thread_shutdown(). - - - the canary is a normal Python object, but we have a borrowed - reference to it from cffi_tls_s.local_thread_canary. - */ - -typedef struct thread_canary_s { - PyObject_HEAD - struct thread_canary_s *zombie_prev, *zombie_next; - PyThreadState *tstate; - struct cffi_tls_s *tls; -} ThreadCanaryObj; - -static PyTypeObject ThreadCanary_Type; /* forward */ -static ThreadCanaryObj cffi_zombie_head; - -static void -_thread_canary_detach_with_lock(ThreadCanaryObj *ob) -{ - /* must be called with both the GIL and TLS_ZOM_LOCK. */ - ThreadCanaryObj *p, *n; - p = ob->zombie_prev; - n = ob->zombie_next; - p->zombie_next = n; - n->zombie_prev = p; - ob->zombie_prev = NULL; - ob->zombie_next = NULL; -} - -static void -thread_canary_dealloc(ThreadCanaryObj *ob) -{ - /* this ThreadCanaryObj is being freed: if it is in the zombie - chained list, remove it. Thread-safety: 'zombie_next' amd - 'local_thread_canary' accesses need to be protected with - the TLS_ZOM_LOCK. - */ - TLS_ZOM_LOCK(); - if (ob->zombie_next != NULL) { - //fprintf(stderr, "thread_canary_dealloc(%p): ZOMBIE\n", ob); - _thread_canary_detach_with_lock(ob); - } - else { - //fprintf(stderr, "thread_canary_dealloc(%p): not a zombie\n", ob); - } - - if (ob->tls != NULL) { - //fprintf(stderr, "thread_canary_dealloc(%p): was local_thread_canary\n", ob); - assert(ob->tls->local_thread_canary == ob); - ob->tls->local_thread_canary = NULL; - } - TLS_ZOM_UNLOCK(); - - PyObject_Del((PyObject *)ob); -} - -static void -thread_canary_make_zombie(ThreadCanaryObj *ob) -{ - /* This must be called without the GIL, but with the TLS_ZOM_LOCK. - It must be called at most once for a given ThreadCanaryObj. */ - ThreadCanaryObj *last; - - //fprintf(stderr, "thread_canary_make_zombie(%p)\n", ob); - if (ob->zombie_next) - Py_FatalError("cffi: ThreadCanaryObj is already a zombie"); - last = cffi_zombie_head.zombie_prev; - ob->zombie_next = &cffi_zombie_head; - ob->zombie_prev = last; - last->zombie_next = ob; - cffi_zombie_head.zombie_prev = ob; -} - -static void -thread_canary_free_zombies(void) -{ - /* This must be called with the GIL. */ - if (cffi_zombie_head.zombie_next == &cffi_zombie_head) - return; /* fast path */ - - while (1) { - ThreadCanaryObj *ob; - PyThreadState *tstate = NULL; - - TLS_ZOM_LOCK(); - ob = cffi_zombie_head.zombie_next; - if (ob != &cffi_zombie_head) { - tstate = ob->tstate; - //fprintf(stderr, "thread_canary_free_zombie(%p) tstate=%p\n", ob, tstate); - _thread_canary_detach_with_lock(ob); - if (tstate == NULL) - Py_FatalError("cffi: invalid ThreadCanaryObj->tstate"); - } - TLS_ZOM_UNLOCK(); - - if (tstate == NULL) - break; - PyThreadState_Clear(tstate); /* calls thread_canary_dealloc on 'ob', - but now ob->zombie_next == NULL. */ - PyThreadState_Delete(tstate); - //fprintf(stderr, "thread_canary_free_zombie: cleared and deleted tstate=%p\n", tstate); - } - //fprintf(stderr, "thread_canary_free_zombie: end\n"); -} - -static void -thread_canary_register(PyThreadState *tstate) -{ - /* called with the GIL; 'tstate' is the current PyThreadState. */ - ThreadCanaryObj *canary; - PyObject *tdict; - struct cffi_tls_s *tls; - int err; - - /* first free the zombies, if any */ - thread_canary_free_zombies(); - - tls = get_cffi_tls(); - if (tls == NULL) - goto ignore_error; - - tdict = PyThreadState_GetDict(); - if (tdict == NULL) - goto ignore_error; - - canary = PyObject_New(ThreadCanaryObj, &ThreadCanary_Type); - //fprintf(stderr, "thread_canary_register(%p): tstate=%p tls=%p\n", canary, tstate, tls); - if (canary == NULL) - goto ignore_error; - canary->zombie_prev = NULL; - canary->zombie_next = NULL; - canary->tstate = tstate; - canary->tls = tls; - - err = PyDict_SetItemString(tdict, "cffi.thread.canary", (PyObject *)canary); - Py_DECREF(canary); - if (err < 0) - goto ignore_error; - - /* thread-safety: we have the GIL here, and 'tstate' is the one that - corresponds to our own thread. We are allocating a new 'canary' - and setting it up for our own thread, both in 'tdict' (which owns - the reference) and in 'tls->local_thread_canary' (which doesn't). */ - assert(Py_REFCNT(canary) == 1); - tls->local_thread_canary = canary; - tstate->gilstate_counter++; - /* ^^^ this means 'tstate' will never be automatically freed by - PyGILState_Release() */ - return; - - ignore_error: - PyErr_Clear(); -} - -static PyTypeObject ThreadCanary_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_cffi_backend.thread_canary", - sizeof(ThreadCanaryObj), - 0, - (destructor)thread_canary_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ -}; - -static void init_cffi_tls_zombie(void) -{ - cffi_zombie_head.zombie_next = &cffi_zombie_head; - cffi_zombie_head.zombie_prev = &cffi_zombie_head; - cffi_zombie_lock = PyThread_allocate_lock(); - if (cffi_zombie_lock == NULL) - PyErr_SetString(PyExc_SystemError, "can't allocate cffi_zombie_lock"); -} - + +/* We try to keep the PyThreadState around in a thread not started by + * Python but where cffi callbacks occur. If we didn't do that, then + * the standard logic in PyGILState_Ensure() and PyGILState_Release() + * would create a new PyThreadState and completely free it for every + * single call. For some applications, this is a huge slow-down. + * + * As shown by issue #362, it is quite messy to do. The current + * solution is to keep the PyThreadState alive by incrementing its + * 'gilstate_counter'. We detect thread shut-down, and we put the + * PyThreadState inside a list of zombies (we can't free it + * immediately because we don't have the GIL at that point in time). + * We also detect other pieces of code (notably Py_Finalize()) which + * clear and free PyThreadStates under our feet, using ThreadCanaryObj. + */ + +#define TLS_ZOM_LOCK() PyThread_acquire_lock(cffi_zombie_lock, WAIT_LOCK) +#define TLS_ZOM_UNLOCK() PyThread_release_lock(cffi_zombie_lock) +static PyThread_type_lock cffi_zombie_lock = NULL; + + +/* A 'canary' object is created in a thread when there is a callback + invoked, and that thread has no PyThreadState so far. It is an + object of reference count equal to 1, which is stored in the + PyThreadState->dict. Two things can occur then: + + 1. The PyThreadState can be forcefully cleared by Py_Finalize(). + Then thread_canary_dealloc() is called, and we have to cancel + the hacks we did to keep the PyThreadState alive. + + 2. The thread finishes. In that case, we put the canary in a list + of zombies, and at some convenient time later when we have the + GIL, we free all PyThreadStates in the zombie list. + + Some more fun comes from the fact that thread_canary_dealloc() can + be called at a point where the canary is in the zombie list already. + Also, the various pieces are freed at specific points in time, and + we must make sure not to access already-freed structures: + + - the struct cffi_tls_s is valid until the thread shuts down, and + then it is freed by cffi_thread_shutdown(). + + - the canary is a normal Python object, but we have a borrowed + reference to it from cffi_tls_s.local_thread_canary. + */ + +typedef struct thread_canary_s { + PyObject_HEAD + struct thread_canary_s *zombie_prev, *zombie_next; + PyThreadState *tstate; + struct cffi_tls_s *tls; +} ThreadCanaryObj; + +static PyTypeObject ThreadCanary_Type; /* forward */ +static ThreadCanaryObj cffi_zombie_head; + +static void +_thread_canary_detach_with_lock(ThreadCanaryObj *ob) +{ + /* must be called with both the GIL and TLS_ZOM_LOCK. */ + ThreadCanaryObj *p, *n; + p = ob->zombie_prev; + n = ob->zombie_next; + p->zombie_next = n; + n->zombie_prev = p; + ob->zombie_prev = NULL; + ob->zombie_next = NULL; +} + +static void +thread_canary_dealloc(ThreadCanaryObj *ob) +{ + /* this ThreadCanaryObj is being freed: if it is in the zombie + chained list, remove it. Thread-safety: 'zombie_next' amd + 'local_thread_canary' accesses need to be protected with + the TLS_ZOM_LOCK. + */ + TLS_ZOM_LOCK(); + if (ob->zombie_next != NULL) { + //fprintf(stderr, "thread_canary_dealloc(%p): ZOMBIE\n", ob); + _thread_canary_detach_with_lock(ob); + } + else { + //fprintf(stderr, "thread_canary_dealloc(%p): not a zombie\n", ob); + } + + if (ob->tls != NULL) { + //fprintf(stderr, "thread_canary_dealloc(%p): was local_thread_canary\n", ob); + assert(ob->tls->local_thread_canary == ob); + ob->tls->local_thread_canary = NULL; + } + TLS_ZOM_UNLOCK(); + + PyObject_Del((PyObject *)ob); +} + +static void +thread_canary_make_zombie(ThreadCanaryObj *ob) +{ + /* This must be called without the GIL, but with the TLS_ZOM_LOCK. + It must be called at most once for a given ThreadCanaryObj. */ + ThreadCanaryObj *last; + + //fprintf(stderr, "thread_canary_make_zombie(%p)\n", ob); + if (ob->zombie_next) + Py_FatalError("cffi: ThreadCanaryObj is already a zombie"); + last = cffi_zombie_head.zombie_prev; + ob->zombie_next = &cffi_zombie_head; + ob->zombie_prev = last; + last->zombie_next = ob; + cffi_zombie_head.zombie_prev = ob; +} + +static void +thread_canary_free_zombies(void) +{ + /* This must be called with the GIL. */ + if (cffi_zombie_head.zombie_next == &cffi_zombie_head) + return; /* fast path */ + + while (1) { + ThreadCanaryObj *ob; + PyThreadState *tstate = NULL; + + TLS_ZOM_LOCK(); + ob = cffi_zombie_head.zombie_next; + if (ob != &cffi_zombie_head) { + tstate = ob->tstate; + //fprintf(stderr, "thread_canary_free_zombie(%p) tstate=%p\n", ob, tstate); + _thread_canary_detach_with_lock(ob); + if (tstate == NULL) + Py_FatalError("cffi: invalid ThreadCanaryObj->tstate"); + } + TLS_ZOM_UNLOCK(); + + if (tstate == NULL) + break; + PyThreadState_Clear(tstate); /* calls thread_canary_dealloc on 'ob', + but now ob->zombie_next == NULL. */ + PyThreadState_Delete(tstate); + //fprintf(stderr, "thread_canary_free_zombie: cleared and deleted tstate=%p\n", tstate); + } + //fprintf(stderr, "thread_canary_free_zombie: end\n"); +} + +static void +thread_canary_register(PyThreadState *tstate) +{ + /* called with the GIL; 'tstate' is the current PyThreadState. */ + ThreadCanaryObj *canary; + PyObject *tdict; + struct cffi_tls_s *tls; + int err; + + /* first free the zombies, if any */ + thread_canary_free_zombies(); + + tls = get_cffi_tls(); + if (tls == NULL) + goto ignore_error; + + tdict = PyThreadState_GetDict(); + if (tdict == NULL) + goto ignore_error; + + canary = PyObject_New(ThreadCanaryObj, &ThreadCanary_Type); + //fprintf(stderr, "thread_canary_register(%p): tstate=%p tls=%p\n", canary, tstate, tls); + if (canary == NULL) + goto ignore_error; + canary->zombie_prev = NULL; + canary->zombie_next = NULL; + canary->tstate = tstate; + canary->tls = tls; + + err = PyDict_SetItemString(tdict, "cffi.thread.canary", (PyObject *)canary); + Py_DECREF(canary); + if (err < 0) + goto ignore_error; + + /* thread-safety: we have the GIL here, and 'tstate' is the one that + corresponds to our own thread. We are allocating a new 'canary' + and setting it up for our own thread, both in 'tdict' (which owns + the reference) and in 'tls->local_thread_canary' (which doesn't). */ + assert(Py_REFCNT(canary) == 1); + tls->local_thread_canary = canary; + tstate->gilstate_counter++; + /* ^^^ this means 'tstate' will never be automatically freed by + PyGILState_Release() */ + return; + + ignore_error: + PyErr_Clear(); +} + +static PyTypeObject ThreadCanary_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_cffi_backend.thread_canary", + sizeof(ThreadCanaryObj), + 0, + (destructor)thread_canary_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ +}; + +static void init_cffi_tls_zombie(void) +{ + cffi_zombie_head.zombie_next = &cffi_zombie_head; + cffi_zombie_head.zombie_prev = &cffi_zombie_head; + cffi_zombie_lock = PyThread_allocate_lock(); + if (cffi_zombie_lock == NULL) + PyErr_SetString(PyExc_SystemError, "can't allocate cffi_zombie_lock"); +} + static void cffi_thread_shutdown(void *p) { - /* this function is called from misc_thread_posix or misc_win32 - when a thread is about to end. */ + /* this function is called from misc_thread_posix or misc_win32 + when a thread is about to end. */ struct cffi_tls_s *tls = (struct cffi_tls_s *)p; - /* thread-safety: this field 'local_thread_canary' can be reset - to NULL in parallel, protected by TLS_ZOM_LOCK. */ - TLS_ZOM_LOCK(); - if (tls->local_thread_canary != NULL) { - tls->local_thread_canary->tls = NULL; - thread_canary_make_zombie(tls->local_thread_canary); + /* thread-safety: this field 'local_thread_canary' can be reset + to NULL in parallel, protected by TLS_ZOM_LOCK. */ + TLS_ZOM_LOCK(); + if (tls->local_thread_canary != NULL) { + tls->local_thread_canary->tls = NULL; + thread_canary_make_zombie(tls->local_thread_canary); } - TLS_ZOM_UNLOCK(); - //fprintf(stderr, "thread_shutdown(%p)\n", tls); + TLS_ZOM_UNLOCK(); + //fprintf(stderr, "thread_shutdown(%p)\n", tls); free(tls); } @@ -297,33 +297,33 @@ static void restore_errno_only(void) #endif -/* MESS. We can't use PyThreadState_GET(), because that calls - PyThreadState_Get() which fails an assert if the result is NULL. - - * in Python 2.7 and <= 3.4, the variable _PyThreadState_Current - is directly available, so use that. - - * in Python 3.5, the variable is available too, but it might be - the case that the headers don't define it (this changed in 3.5.1). - In case we're compiling with 3.5.x with x >= 1, we need to - manually define this variable. - - * in Python >= 3.6 there is _PyThreadState_UncheckedGet(). - It was added in 3.5.2 but should never be used in 3.5.x - because it is not available in 3.5.0 or 3.5.1. -*/ -#if PY_VERSION_HEX >= 0x03050100 && PY_VERSION_HEX < 0x03060000 -PyAPI_DATA(void *volatile) _PyThreadState_Current; +/* MESS. We can't use PyThreadState_GET(), because that calls + PyThreadState_Get() which fails an assert if the result is NULL. + + * in Python 2.7 and <= 3.4, the variable _PyThreadState_Current + is directly available, so use that. + + * in Python 3.5, the variable is available too, but it might be + the case that the headers don't define it (this changed in 3.5.1). + In case we're compiling with 3.5.x with x >= 1, we need to + manually define this variable. + + * in Python >= 3.6 there is _PyThreadState_UncheckedGet(). + It was added in 3.5.2 but should never be used in 3.5.x + because it is not available in 3.5.0 or 3.5.1. +*/ +#if PY_VERSION_HEX >= 0x03050100 && PY_VERSION_HEX < 0x03060000 +PyAPI_DATA(void *volatile) _PyThreadState_Current; #endif static PyThreadState *get_current_ts(void) { -#if PY_VERSION_HEX >= 0x03060000 - return _PyThreadState_UncheckedGet(); -#elif defined(_Py_atomic_load_relaxed) +#if PY_VERSION_HEX >= 0x03060000 + return _PyThreadState_UncheckedGet(); +#elif defined(_Py_atomic_load_relaxed) return (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current); #else - return (PyThreadState*)_PyThreadState_Current; /* assume atomic read */ + return (PyThreadState*)_PyThreadState_Current; /* assume atomic read */ #endif } @@ -357,9 +357,9 @@ static PyGILState_STATE gil_ensure(void) assert(ts == get_current_ts()); assert(ts->gilstate_counter >= 1); - /* Use the ThreadCanary mechanism to keep 'ts' alive until the - thread really shuts down */ - thread_canary_register(ts); + /* Use the ThreadCanary mechanism to keep 'ts' alive until the + thread really shuts down */ + thread_canary_register(ts); return result; } diff --git a/contrib/python/cffi/c/misc_win32.h b/contrib/python/cffi/c/misc_win32.h index 2946721801d..f1848850800 100644 --- a/contrib/python/cffi/c/misc_win32.h +++ b/contrib/python/cffi/c/misc_win32.h @@ -100,10 +100,10 @@ static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds) s_buf[--len] = L'\0'; message = PyUnicode_FromWideChar(s_buf, len); } - if (message != NULL) { + if (message != NULL) { v = Py_BuildValue("(iO)", err, message); - Py_DECREF(message); - } + Py_DECREF(message); + } else v = NULL; LocalFree(s_buf); @@ -169,14 +169,14 @@ static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds) static void *dlopen(const char *filename, int flag) { - return (void *)LoadLibraryA(filename); -} - -static void *dlopenW(const wchar_t *filename) -{ - return (void *)LoadLibraryW(filename); + return (void *)LoadLibraryA(filename); } +static void *dlopenW(const wchar_t *filename) +{ + return (void *)LoadLibraryW(filename); +} + static void *dlsym(void *handle, const char *symbol) { void *address = GetProcAddress((HMODULE)handle, symbol); diff --git a/contrib/python/cffi/c/parse_c_type.c b/contrib/python/cffi/c/parse_c_type.c index 698ef6451ec..c2bff61e772 100644 --- a/contrib/python/cffi/c/parse_c_type.c +++ b/contrib/python/cffi/c/parse_c_type.c @@ -25,7 +25,7 @@ enum token_e { /* keywords */ TOK__BOOL, TOK_CHAR, - TOK__COMPLEX, + TOK__COMPLEX, TOK_CONST, TOK_DOUBLE, TOK_ENUM, @@ -159,7 +159,7 @@ static void next_token(token_t *tok) if (tok->size == 5 && !memcmp(p, "_Bool", 5)) tok->kind = TOK__BOOL; if (tok->size == 7 && !memcmp(p,"__cdecl",7)) tok->kind = TOK_CDECL; if (tok->size == 9 && !memcmp(p,"__stdcall",9))tok->kind = TOK_STDCALL; - if (tok->size == 8 && !memcmp(p,"_Complex",8)) tok->kind = TOK__COMPLEX; + if (tok->size == 8 && !memcmp(p,"_Complex",8)) tok->kind = TOK__COMPLEX; break; case 'c': if (tok->size == 4 && !memcmp(p, "char", 4)) tok->kind = TOK_CHAR; @@ -493,7 +493,7 @@ int search_standard_typename(const char *p, size_t size) case '1': if (size == 8 && !memcmp(p, "uint16", 6)) return _CFFI_PRIM_UINT16; - if (size == 8 && !memcmp(p, "char16", 6)) return _CFFI_PRIM_CHAR16; + if (size == 8 && !memcmp(p, "char16", 6)) return _CFFI_PRIM_CHAR16; break; case '2': @@ -502,7 +502,7 @@ int search_standard_typename(const char *p, size_t size) case '3': if (size == 8 && !memcmp(p, "uint32", 6)) return _CFFI_PRIM_UINT32; - if (size == 8 && !memcmp(p, "char32", 6)) return _CFFI_PRIM_CHAR32; + if (size == 8 && !memcmp(p, "char32", 6)) return _CFFI_PRIM_CHAR32; break; case '4': @@ -604,7 +604,7 @@ static int parse_complete(token_t *tok) { unsigned int t0; _cffi_opcode_t t1; - _cffi_opcode_t t1complex; + _cffi_opcode_t t1complex; int modifiers_length, modifiers_sign; qualifiers: @@ -660,8 +660,8 @@ static int parse_complete(token_t *tok) break; } - t1complex = 0; - + t1complex = 0; + if (modifiers_length || modifiers_sign) { switch (tok->kind) { @@ -672,7 +672,7 @@ static int parse_complete(token_t *tok) case TOK_STRUCT: case TOK_UNION: case TOK_ENUM: - case TOK__COMPLEX: + case TOK__COMPLEX: return parse_error(tok, "invalid combination of types"); case TOK_DOUBLE: @@ -726,11 +726,11 @@ static int parse_complete(token_t *tok) break; case TOK_FLOAT: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOAT); - t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOATCOMPLEX); + t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOATCOMPLEX); break; case TOK_DOUBLE: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLE); - t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLECOMPLEX); + t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLECOMPLEX); break; case TOK_IDENTIFIER: { @@ -797,13 +797,13 @@ static int parse_complete(token_t *tok) } next_token(tok); } - if (tok->kind == TOK__COMPLEX) - { - if (t1complex == 0) - return parse_error(tok, "_Complex type combination unsupported"); - t1 = t1complex; - next_token(tok); - } + if (tok->kind == TOK__COMPLEX) + { + if (t1complex == 0) + return parse_error(tok, "_Complex type combination unsupported"); + t1 = t1complex; + next_token(tok); + } return parse_sequel(tok, write_ds(tok, t1)); } diff --git a/contrib/python/cffi/c/realize_c_type.c b/contrib/python/cffi/c/realize_c_type.c index 82629b7ef16..6c70c14cf3a 100644 --- a/contrib/python/cffi/c/realize_c_type.c +++ b/contrib/python/cffi/c/realize_c_type.c @@ -151,10 +151,10 @@ static PyObject *build_primitive_type(int num) "uint_fast64_t", "intmax_t", "uintmax_t", - "float _Complex", - "double _Complex", - "char16_t", - "char32_t", + "float _Complex", + "double _Complex", + "char16_t", + "char32_t", }; PyObject *x; @@ -269,11 +269,11 @@ realize_c_type(builder_c_t *builder, _cffi_opcode_t opcodes[], int index) PyObject *x = realize_c_type_or_func(builder, opcodes, index); if (x == NULL || CTypeDescr_Check(x)) return (CTypeDescrObject *)x; - else { - unexpected_fn_type(x); - Py_DECREF(x); - return NULL; - } + else { + unexpected_fn_type(x); + Py_DECREF(x); + return NULL; + } } static void _realize_name(char *target, const char *prefix, const char *srcname) @@ -413,8 +413,8 @@ _realize_c_struct_or_union(builder_c_t *builder, int sindex) } static PyObject * -realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op, - _cffi_opcode_t opcodes[], int index) +realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op, + _cffi_opcode_t opcodes[], int index) { PyObject *x, *y, *z; Py_ssize_t length = -1; @@ -636,36 +636,36 @@ realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op, return NULL; } - return x; -} - -static int _realize_recursion_level; - -static PyObject * -realize_c_type_or_func(builder_c_t *builder, - _cffi_opcode_t opcodes[], int index) -{ - PyObject *x; - _cffi_opcode_t op = opcodes[index]; - - if ((((uintptr_t)op) & 1) == 0) { - x = (PyObject *)op; - Py_INCREF(x); - return x; - } - - if (_realize_recursion_level >= 1000) { - PyErr_Format(PyExc_RuntimeError, - "type-building recursion too deep or infinite. " - "This is known to occur e.g. in ``struct s { void(*callable)" - "(struct s); }''. Please report if you get this error and " - "really need support for your case."); - return NULL; - } - _realize_recursion_level++; - x = realize_c_type_or_func_now(builder, op, opcodes, index); - _realize_recursion_level--; - + return x; +} + +static int _realize_recursion_level; + +static PyObject * +realize_c_type_or_func(builder_c_t *builder, + _cffi_opcode_t opcodes[], int index) +{ + PyObject *x; + _cffi_opcode_t op = opcodes[index]; + + if ((((uintptr_t)op) & 1) == 0) { + x = (PyObject *)op; + Py_INCREF(x); + return x; + } + + if (_realize_recursion_level >= 1000) { + PyErr_Format(PyExc_RuntimeError, + "type-building recursion too deep or infinite. " + "This is known to occur e.g. in ``struct s { void(*callable)" + "(struct s); }''. Please report if you get this error and " + "really need support for your case."); + return NULL; + } + _realize_recursion_level++; + x = realize_c_type_or_func_now(builder, op, opcodes, index); + _realize_recursion_level--; + if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) { assert((((uintptr_t)x) & 1) == 0); assert((((uintptr_t)opcodes[index]) & 1) == 1); @@ -673,7 +673,7 @@ realize_c_type_or_func(builder_c_t *builder, opcodes[index] = x; } return x; -} +} static CTypeDescrObject * realize_c_func_return_type(builder_c_t *builder, @@ -760,13 +760,13 @@ static int do_realize_lazy_struct(CTypeDescrObject *ct) return -1; } - if (ctf != NULL && fld->field_offset == (size_t)-1) { + if (ctf != NULL && fld->field_offset == (size_t)-1) { /* unnamed struct, with field positions and sizes entirely determined by complete_struct_or_union() and not checked. Or, bitfields (field_size >= 0), similarly not checked. */ assert(fld->field_size == (size_t)-1 || fbitsize >= 0); } - else if (ctf == NULL || detect_custom_layout(ct, SF_STD_FIELD_POS, + else if (ctf == NULL || detect_custom_layout(ct, SF_STD_FIELD_POS, ctf->ct_size, fld->field_size, "wrong size for field '", fld->name, "'") < 0) { diff --git a/contrib/python/cffi/c/test_c.py b/contrib/python/cffi/c/test_c.py index 654584d9244..ba577e28b9b 100644 --- a/contrib/python/cffi/c/test_c.py +++ b/contrib/python/cffi/c/test_c.py @@ -1,25 +1,25 @@ import py -import pytest - +import pytest + def _setup_path(): import os, sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) _setup_path() from _cffi_backend import * -from _cffi_backend import _get_types, _get_common_types -try: - from _cffi_backend import _testfunc -except ImportError: - def _testfunc(num): - pytest.skip("_testunc() not available") -from _cffi_backend import __version__ +from _cffi_backend import _get_types, _get_common_types +try: + from _cffi_backend import _testfunc +except ImportError: + def _testfunc(num): + pytest.skip("_testunc() not available") +from _cffi_backend import __version__ # ____________________________________________________________ import sys -assert __version__ == "1.15.0", ("This test_c.py file is for testing a version" - " of cffi that differs from the one that we" - " get from 'import _cffi_backend'") +assert __version__ == "1.15.0", ("This test_c.py file is for testing a version" + " of cffi that differs from the one that we" + " get from 'import _cffi_backend'") if sys.version_info < (3,): type_or_class = "type" mandatory_b_prefix = '' @@ -32,7 +32,7 @@ if sys.version_info < (3,): .replace(r'\\U', r'\U')) u = U() str2bytes = str - strict_compare = False + strict_compare = False else: type_or_class = "class" long = int @@ -44,7 +44,7 @@ else: bitem2bchr = bytechr u = "" str2bytes = lambda s: bytes(s, "ascii") - strict_compare = True + strict_compare = True def size_of_int(): BInt = new_primitive_type("int") @@ -66,12 +66,12 @@ def find_and_load_library(name, flags=RTLD_NOW): path = None else: path = ctypes.util.find_library(name) - if path is None and name == 'c': - assert sys.platform == 'win32' - assert (sys.version_info >= (3,) or - '__pypy__' in sys.builtin_module_names) - py.test.skip("dlopen(None) cannot work on Windows " - "with PyPy or Python 3") + if path is None and name == 'c': + assert sys.platform == 'win32' + assert (sys.version_info >= (3,) or + '__pypy__' in sys.builtin_module_names) + py.test.skip("dlopen(None) cannot work on Windows " + "with PyPy or Python 3") return load_library(path, flags) def test_load_library(): @@ -114,16 +114,16 @@ def test_cast_to_signed_char(): p = new_primitive_type("signed char") x = cast(p, -65 + 17*256) assert repr(x) == "<cdata 'signed char' -65>" - assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class + assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class assert int(x) == -65 x = cast(p, -66 + (1<<199)*256) assert repr(x) == "<cdata 'signed char' -66>" assert int(x) == -66 - assert (x == cast(p, -66)) is True - assert (x != cast(p, -66)) is False + assert (x == cast(p, -66)) is True + assert (x != cast(p, -66)) is False q = new_primitive_type("short") - assert (x == cast(q, -66)) is True - assert (x != cast(q, -66)) is False + assert (x == cast(q, -66)) is True + assert (x != cast(q, -66)) is False def test_sizeof_type(): py.test.raises(TypeError, sizeof, 42.5) @@ -188,7 +188,7 @@ def test_float_types(): assert float(cast(p, 1.1)) != 1.1 # rounding error assert float(cast(p, 1E200)) == INF # limited range - assert cast(p, -1.1) == cast(p, -1.1) + assert cast(p, -1.1) == cast(p, -1.1) assert repr(float(cast(p, -0.0))) == '-0.0' assert float(cast(p, b'\x09')) == 9.0 assert float(cast(p, u+'\x09')) == 9.0 @@ -198,60 +198,60 @@ def test_float_types(): def test_complex_types(): INF = 1E200 * 1E200 for name in ["float", "double"]: - p = new_primitive_type(name + " _Complex") - assert bool(cast(p, 0)) is False + p = new_primitive_type(name + " _Complex") + assert bool(cast(p, 0)) is False assert bool(cast(p, INF)) assert bool(cast(p, -INF)) - assert bool(cast(p, 0j)) is False + assert bool(cast(p, 0j)) is False assert bool(cast(p, INF*1j)) assert bool(cast(p, -INF*1j)) - # "can't convert complex to float", like CPython's "float(0j)" + # "can't convert complex to float", like CPython's "float(0j)" py.test.raises(TypeError, int, cast(p, -150)) py.test.raises(TypeError, long, cast(p, -150)) py.test.raises(TypeError, float, cast(p, -150)) assert complex(cast(p, 1.25)) == 1.25 assert complex(cast(p, 1.25j)) == 1.25j - assert complex(cast(p, complex(0,INF))) == complex(0,INF) - assert complex(cast(p, -INF)) == -INF + assert complex(cast(p, complex(0,INF))) == complex(0,INF) + assert complex(cast(p, -INF)) == -INF if name == "float": assert complex(cast(p, 1.1j)) != 1.1j # rounding error assert complex(cast(p, 1E200+3j)) == INF+3j # limited range - assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range + assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range - assert cast(p, -1.1j) == cast(p, -1.1j) + assert cast(p, -1.1j) == cast(p, -1.1j) assert repr(complex(cast(p, -0.0)).real) == '-0.0' - #assert repr(complex(cast(p, -0j))) == '-0j' # http://bugs.python.org/issue29602 - assert complex(cast(p, b'\x09')) == 9.0 + 0j - assert complex(cast(p, u+'\x09')) == 9.0 + 0j - assert complex(cast(p, True)) == 1.0 + 0j + #assert repr(complex(cast(p, -0j))) == '-0j' # http://bugs.python.org/issue29602 + assert complex(cast(p, b'\x09')) == 9.0 + 0j + assert complex(cast(p, u+'\x09')) == 9.0 + 0j + assert complex(cast(p, True)) == 1.0 + 0j py.test.raises(TypeError, cast, p, None) # - py.test.raises(TypeError, cast, new_primitive_type(name), 1+0j) - # - for basetype in ["char", "int", "uint64_t", "float", - "double", "long double"]: - baseobj = cast(new_primitive_type(basetype), 65) - py.test.raises(TypeError, complex, baseobj) - # - BArray = new_array_type(new_pointer_type(p), 10) - x = newp(BArray, None) - x[5] = 12.34 + 56.78j - assert type(x[5]) is complex - assert abs(x[5] - (12.34 + 56.78j)) < 1e-5 - assert (x[5] == 12.34 + 56.78j) == (name == "double") # rounding error - # - class Foo: - def __complex__(self): - return 2 + 3j - assert complex(Foo()) == 2 + 3j - assert complex(cast(p, Foo())) == 2 + 3j - py.test.raises(TypeError, cast, new_primitive_type("int"), 1+0j) + py.test.raises(TypeError, cast, new_primitive_type(name), 1+0j) + # + for basetype in ["char", "int", "uint64_t", "float", + "double", "long double"]: + baseobj = cast(new_primitive_type(basetype), 65) + py.test.raises(TypeError, complex, baseobj) + # + BArray = new_array_type(new_pointer_type(p), 10) + x = newp(BArray, None) + x[5] = 12.34 + 56.78j + assert type(x[5]) is complex + assert abs(x[5] - (12.34 + 56.78j)) < 1e-5 + assert (x[5] == 12.34 + 56.78j) == (name == "double") # rounding error + # + class Foo: + def __complex__(self): + return 2 + 3j + assert complex(Foo()) == 2 + 3j + assert complex(cast(p, Foo())) == 2 + 3j + py.test.raises(TypeError, cast, new_primitive_type("int"), 1+0j) def test_character_type(): p = new_primitive_type("char") assert bool(cast(p, 'A')) is True assert bool(cast(p, '\x00')) is False # since 1.7 - assert cast(p, '\x00') == cast(p, -17*256) + assert cast(p, '\x00') == cast(p, -17*256) assert int(cast(p, 'A')) == 65 assert long(cast(p, 'A')) == 65 assert type(int(cast(p, 'A'))) is int @@ -296,9 +296,9 @@ def test_pointer_to_int(): assert repr(q).startswith("<cdata 'int *' 0x") assert p == q assert hash(p) == hash(q) - e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), None) - assert str(e.value) == ( - "expected new array length or list/tuple/str, not NoneType") + e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), None) + assert str(e.value) == ( + "expected new array length or list/tuple/str, not NoneType") def test_pointer_bool(): BInt = new_primitive_type("int") @@ -322,10 +322,10 @@ def test_reading_pointer_to_int(): assert p[0] == 0 p = newp(BPtr, 5000) assert p[0] == 5000 - with pytest.raises(IndexError): - p[1] - with pytest.raises(IndexError): - p[-1] + with pytest.raises(IndexError): + p[1] + with pytest.raises(IndexError): + p[-1] def test_reading_pointer_to_float(): BFloat = new_primitive_type("float") @@ -354,18 +354,18 @@ def test_newp_integer_types(): max = (1 << (8*size-1)) - 1 assert newp(pp, min)[0] == min assert newp(pp, max)[0] == max - py.test.raises(OverflowError, newp, pp, min - 2 ** 32) - py.test.raises(OverflowError, newp, pp, min - 2 ** 64) - py.test.raises(OverflowError, newp, pp, max + 2 ** 32) - py.test.raises(OverflowError, newp, pp, max + 2 ** 64) + py.test.raises(OverflowError, newp, pp, min - 2 ** 32) + py.test.raises(OverflowError, newp, pp, min - 2 ** 64) + py.test.raises(OverflowError, newp, pp, max + 2 ** 32) + py.test.raises(OverflowError, newp, pp, max + 2 ** 64) py.test.raises(OverflowError, newp, pp, min - 1) py.test.raises(OverflowError, newp, pp, max + 1) - py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32) - py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64) - py.test.raises(OverflowError, newp, pp, max + 1) - py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32) - py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64) - py.test.raises(TypeError, newp, pp, 1.0) + py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32) + py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64) + py.test.raises(OverflowError, newp, pp, max + 1) + py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32) + py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64) + py.test.raises(TypeError, newp, pp, 1.0) for name in ['char', 'short', 'int', 'long', 'long long']: p = new_primitive_type('unsigned ' + name) pp = new_pointer_type(p) @@ -392,9 +392,9 @@ def test_reading_pointer_to_char(): assert int(c) == ord(b'A') py.test.raises(TypeError, cast, BChar, b'foo') py.test.raises(TypeError, cast, BChar, u+'foo') - e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), 12.3) - assert str(e.value) == ( - "expected new array length or list/tuple/str, not float") + e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), 12.3) + assert str(e.value) == ( + "expected new array length or list/tuple/str, not float") def test_reading_pointer_to_pointer(): BVoidP = new_pointer_type(new_void_type()) @@ -426,15 +426,15 @@ def test_load_standard_library(): x = find_and_load_library(None) BVoidP = new_pointer_type(new_void_type()) assert x.load_function(BVoidP, 'strcpy') - py.test.raises(AttributeError, x.load_function, + py.test.raises(AttributeError, x.load_function, BVoidP, 'xxx_this_function_does_not_exist') # the next one is from 'libm', not 'libc', but we assume # that it is already loaded too, so it should work assert x.load_function(BVoidP, 'sqrt') - # - x.close_lib() - py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt') - x.close_lib() + # + x.close_lib() + py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt') + x.close_lib() def test_no_len_on_nonarray(): p = new_primitive_type("int") @@ -453,8 +453,8 @@ def test_cmp_none(): def test_invalid_indexing(): p = new_primitive_type("int") x = cast(p, 42) - with pytest.raises(TypeError): - x[0] + with pytest.raises(TypeError): + x[0] def test_default_str(): BChar = new_primitive_type("char") @@ -547,16 +547,16 @@ def test_array_instance(): assert len(a) == LENGTH for i in range(LENGTH): assert a[i] == 0 - with pytest.raises(IndexError): - a[LENGTH] - with pytest.raises(IndexError): - a[-1] + with pytest.raises(IndexError): + a[LENGTH] + with pytest.raises(IndexError): + a[-1] for i in range(LENGTH): a[i] = i * i + 1 for i in range(LENGTH): assert a[i] == i * i + 1 - with pytest.raises(IndexError) as e: - a[LENGTH+100] = 500 + with pytest.raises(IndexError) as e: + a[LENGTH+100] = 500 assert ('(expected %d < %d)' % (LENGTH+100, LENGTH)) in str(e.value) py.test.raises(TypeError, int, a) @@ -571,14 +571,14 @@ def test_array_of_unknown_length_instance(): a[i] -= i for i in range(42): assert a[i] == -i - with pytest.raises(IndexError): - a[42] - with pytest.raises(IndexError): - a[-1] - with pytest.raises(IndexError): - a[42] = 123 - with pytest.raises(IndexError): - a[-1] = 456 + with pytest.raises(IndexError): + a[42] + with pytest.raises(IndexError): + a[-1] + with pytest.raises(IndexError): + a[42] = 123 + with pytest.raises(IndexError): + a[-1] = 456 def test_array_of_unknown_length_instance_with_initializer(): p = new_primitive_type("int") @@ -626,14 +626,14 @@ def test_array_sub(): assert a == (p - 1) BPtr = new_pointer_type(new_primitive_type("short")) q = newp(BPtr, None) - with pytest.raises(TypeError): - p - q - with pytest.raises(TypeError): - q - p - with pytest.raises(TypeError): - a - q - with pytest.raises(TypeError) as e: - q - a + with pytest.raises(TypeError): + p - q + with pytest.raises(TypeError): + q - p + with pytest.raises(TypeError): + a - q + with pytest.raises(TypeError) as e: + q - a assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'" def test_ptr_sub_unaligned(): @@ -646,10 +646,10 @@ def test_ptr_sub_unaligned(): assert b - a == (bi - 1240) // size_of_int() assert a - b == (1240 - bi) // size_of_int() else: - with pytest.raises(ValueError): - b - a - with pytest.raises(ValueError): - a - b + with pytest.raises(ValueError): + b - a + with pytest.raises(ValueError): + a - b def test_cast_primitive_from_cdata(): p = new_primitive_type("int") @@ -799,16 +799,16 @@ def test_struct_instance(): BInt = new_primitive_type("int") BStruct = new_struct_type("struct foo") BStructPtr = new_pointer_type(BStruct) - p = cast(BStructPtr, 42) - with pytest.raises(AttributeError) as e: - p.a1 # opaque - assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: " - "cannot read fields") - with pytest.raises(AttributeError) as e: - p.a1 = 10 # opaque - assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: " - "cannot write fields") - + p = cast(BStructPtr, 42) + with pytest.raises(AttributeError) as e: + p.a1 # opaque + assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: " + "cannot read fields") + with pytest.raises(AttributeError) as e: + p.a1 = 10 # opaque + assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: " + "cannot write fields") + complete_struct_or_union(BStruct, [('a1', BInt, -1), ('a2', BInt, -1)]) p = newp(BStructPtr, None) @@ -817,42 +817,42 @@ def test_struct_instance(): s.a2 = 123 assert s.a1 == 0 assert s.a2 == 123 - with pytest.raises(OverflowError): - s.a1 = sys.maxsize+1 + with pytest.raises(OverflowError): + s.a1 = sys.maxsize+1 assert s.a1 == 0 - with pytest.raises(AttributeError) as e: - p.foobar - assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'" - with pytest.raises(AttributeError) as e: - p.foobar = 42 - assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'" - with pytest.raises(AttributeError) as e: - s.foobar - assert str(e.value) == "cdata 'struct foo' has no field 'foobar'" - with pytest.raises(AttributeError) as e: - s.foobar = 42 - assert str(e.value) == "cdata 'struct foo' has no field 'foobar'" - j = cast(BInt, 42) - with pytest.raises(AttributeError) as e: - j.foobar - assert str(e.value) == "cdata 'int' has no attribute 'foobar'" - with pytest.raises(AttributeError) as e: - j.foobar = 42 - assert str(e.value) == "cdata 'int' has no attribute 'foobar'" - j = cast(new_pointer_type(BInt), 42) - with pytest.raises(AttributeError) as e: - j.foobar - assert str(e.value) == "cdata 'int *' has no attribute 'foobar'" - with pytest.raises(AttributeError) as e: - j.foobar = 42 - assert str(e.value) == "cdata 'int *' has no attribute 'foobar'" - pp = newp(new_pointer_type(BStructPtr), p) - with pytest.raises(AttributeError) as e: - pp.a1 - assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'" - with pytest.raises(AttributeError) as e: - pp.a1 = 42 - assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'" + with pytest.raises(AttributeError) as e: + p.foobar + assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'" + with pytest.raises(AttributeError) as e: + p.foobar = 42 + assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'" + with pytest.raises(AttributeError) as e: + s.foobar + assert str(e.value) == "cdata 'struct foo' has no field 'foobar'" + with pytest.raises(AttributeError) as e: + s.foobar = 42 + assert str(e.value) == "cdata 'struct foo' has no field 'foobar'" + j = cast(BInt, 42) + with pytest.raises(AttributeError) as e: + j.foobar + assert str(e.value) == "cdata 'int' has no attribute 'foobar'" + with pytest.raises(AttributeError) as e: + j.foobar = 42 + assert str(e.value) == "cdata 'int' has no attribute 'foobar'" + j = cast(new_pointer_type(BInt), 42) + with pytest.raises(AttributeError) as e: + j.foobar + assert str(e.value) == "cdata 'int *' has no attribute 'foobar'" + with pytest.raises(AttributeError) as e: + j.foobar = 42 + assert str(e.value) == "cdata 'int *' has no attribute 'foobar'" + pp = newp(new_pointer_type(BStructPtr), p) + with pytest.raises(AttributeError) as e: + pp.a1 + assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'" + with pytest.raises(AttributeError) as e: + pp.a1 = 42 + assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'" def test_union_instance(): BInt = new_primitive_type("int") @@ -987,15 +987,15 @@ def test_call_function_0(): py.test.raises(OverflowError, f, 128, 0) py.test.raises(OverflowError, f, 0, 128) -def test_call_function_0_pretend_bool_result(): - BSignedChar = new_primitive_type("signed char") - BBool = new_primitive_type("_Bool") - BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False) - f = cast(BFunc0, _testfunc(0)) - assert f(40, -39) is True - assert f(40, -40) is False - py.test.raises(ValueError, f, 40, 2) - +def test_call_function_0_pretend_bool_result(): + BSignedChar = new_primitive_type("signed char") + BBool = new_primitive_type("_Bool") + BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False) + f = cast(BFunc0, _testfunc(0)) + assert f(40, -39) is True + assert f(40, -40) is False + py.test.raises(ValueError, f, 40, 2) + def test_call_function_1(): BInt = new_primitive_type("int") BLong = new_primitive_type("long") @@ -1158,17 +1158,17 @@ def test_call_function_23_bis(): res = f(b"foo") assert res == 1000 * ord(b'f') -def test_call_function_23_bool_array(): - # declaring the function as int(_Bool*) - BBool = new_primitive_type("_Bool") - BBoolP = new_pointer_type(BBool) - BInt = new_primitive_type("int") - BFunc23 = new_function_type((BBoolP,), BInt, False) - f = cast(BFunc23, _testfunc(23)) - res = f(b"\x01\x01") - assert res == 1000 - py.test.raises(ValueError, f, b"\x02\x02") - +def test_call_function_23_bool_array(): + # declaring the function as int(_Bool*) + BBool = new_primitive_type("_Bool") + BBoolP = new_pointer_type(BBool) + BInt = new_primitive_type("int") + BFunc23 = new_function_type((BBoolP,), BInt, False) + f = cast(BFunc23, _testfunc(23)) + res = f(b"\x01\x01") + assert res == 1000 + py.test.raises(ValueError, f, b"\x02\x02") + def test_cannot_pass_struct_with_array_of_length_0(): BInt = new_primitive_type("int") BArray0 = new_array_type(new_pointer_type(BInt), 0) @@ -1195,34 +1195,34 @@ def test_call_function_9(): BSShort = new_primitive_type("short") assert f(3, cast(BSChar, -3), cast(BUChar, 200), cast(BSShort, -5)) == 192 -def test_call_function_24(): - BFloat = new_primitive_type("float") - BFloatComplex = new_primitive_type("float _Complex") - BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False) - if 0: # libffi returning nonsense silently, so logic disabled for now - f = cast(BFunc3, _testfunc(24)) - result = f(1.25, 5.1) - assert type(result) == complex - assert result.real == 1.25 # exact - assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact - else: - f = cast(BFunc3, _testfunc(9)) - py.test.raises(NotImplementedError, f, 12.3, 34.5) - -def test_call_function_25(): - BDouble = new_primitive_type("double") - BDoubleComplex = new_primitive_type("double _Complex") - BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False) - if 0: # libffi returning nonsense silently, so logic disabled for now - f = cast(BFunc3, _testfunc(25)) - result = f(1.25, 5.1) - assert type(result) == complex - assert result.real == 1.25 # exact - assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact - else: - f = cast(BFunc3, _testfunc(9)) - py.test.raises(NotImplementedError, f, 12.3, 34.5) - +def test_call_function_24(): + BFloat = new_primitive_type("float") + BFloatComplex = new_primitive_type("float _Complex") + BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False) + if 0: # libffi returning nonsense silently, so logic disabled for now + f = cast(BFunc3, _testfunc(24)) + result = f(1.25, 5.1) + assert type(result) == complex + assert result.real == 1.25 # exact + assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact + else: + f = cast(BFunc3, _testfunc(9)) + py.test.raises(NotImplementedError, f, 12.3, 34.5) + +def test_call_function_25(): + BDouble = new_primitive_type("double") + BDoubleComplex = new_primitive_type("double _Complex") + BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False) + if 0: # libffi returning nonsense silently, so logic disabled for now + f = cast(BFunc3, _testfunc(25)) + result = f(1.25, 5.1) + assert type(result) == complex + assert result.real == 1.25 # exact + assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact + else: + f = cast(BFunc3, _testfunc(9)) + py.test.raises(NotImplementedError, f, 12.3, 34.5) + def test_cannot_call_with_a_autocompleted_struct(): BSChar = new_primitive_type("signed char") BDouble = new_primitive_type("double") @@ -1234,13 +1234,13 @@ def test_cannot_call_with_a_autocompleted_struct(): BFunc = new_function_type((BStruct,), BDouble) # internally not callable dummy_func = cast(BFunc, 42) e = py.test.raises(NotImplementedError, dummy_func, "?") - msg = ("ctype 'struct foo' not supported as argument. It is a struct " - 'declared with "...;", but the C calling convention may depend ' - "on the missing fields; or, it contains anonymous struct/unions. " - "Such structs are only supported as argument if the function is " - "'API mode' and non-variadic (i.e. declared inside ffibuilder." - "cdef()+ffibuilder.set_source() and not taking a final '...' " - "argument)") + msg = ("ctype 'struct foo' not supported as argument. It is a struct " + 'declared with "...;", but the C calling convention may depend ' + "on the missing fields; or, it contains anonymous struct/unions. " + "Such structs are only supported as argument if the function is " + "'API mode' and non-variadic (i.e. declared inside ffibuilder." + "cdef()+ffibuilder.set_source() and not taking a final '...' " + "argument)") assert str(e.value) == msg def test_new_charp(): @@ -1277,9 +1277,9 @@ def test_read_variable(): ll = find_and_load_library('c') stderr = ll.read_variable(BVoidP, "stderr") assert stderr == cast(BVoidP, _testfunc(8)) - # - ll.close_lib() - py.test.raises(ValueError, ll.read_variable, BVoidP, "stderr") + # + ll.close_lib() + py.test.raises(ValueError, ll.read_variable, BVoidP, "stderr") def test_read_variable_as_unknown_length_array(): ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard @@ -1306,9 +1306,9 @@ def test_write_variable(): assert not ll.read_variable(BVoidP, "stderr") ll.write_variable(BVoidP, "stderr", stderr) assert ll.read_variable(BVoidP, "stderr") == stderr - # - ll.close_lib() - py.test.raises(ValueError, ll.write_variable, BVoidP, "stderr", stderr) + # + ll.close_lib() + py.test.raises(ValueError, ll.write_variable, BVoidP, "stderr", stderr) def test_callback(): BInt = new_primitive_type("int") @@ -1331,9 +1331,9 @@ def test_callback_exception(): except ImportError: import io as cStringIO # Python 3 import linecache - def matches(istr, ipattern, ipattern38): - if sys.version_info >= (3, 8): - ipattern = ipattern38 + def matches(istr, ipattern, ipattern38): + if sys.version_info >= (3, 8): + ipattern = ipattern38 str, pattern = istr, ipattern while '$' in pattern: i = pattern.index('$') @@ -1366,8 +1366,8 @@ def test_callback_exception(): try: linecache.getline = lambda *args: 'LINE' # hack: speed up PyPy tests sys.stderr = cStringIO.StringIO() - if hasattr(sys, '__unraisablehook__'): # work around pytest - sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons + if hasattr(sys, '__unraisablehook__'): # work around pytest + sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons assert f(100) == 300 assert sys.stderr.getvalue() == '' assert f(10000) == -42 @@ -1379,14 +1379,14 @@ Traceback (most recent call last): File "$", line $, in check_value $ ValueError: 42 -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>: -Traceback (most recent call last): - File "$", line $, in Zcb1 - $ - File "$", line $, in check_value - $ -ValueError: 42 +""", """\ +Exception ignored from cffi callback <function$Zcb1 at 0x$>: +Traceback (most recent call last): + File "$", line $, in Zcb1 + $ + File "$", line $, in check_value + $ +ValueError: 42 """) sys.stderr = cStringIO.StringIO() bigvalue = 20000 @@ -1395,12 +1395,12 @@ ValueError: 42 From cffi callback <function$Zcb1 at 0x$>: Trying to convert the result back to C: OverflowError: integer 60000 does not fit 'short' -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -OverflowError: integer 60000 does not fit 'short' +""", """\ +Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: +Traceback (most recent call last): + File "$", line $, in test_callback_exception + $ +OverflowError: integer 60000 does not fit 'short' """) sys.stderr = cStringIO.StringIO() bigvalue = 20000 @@ -1438,24 +1438,24 @@ OverflowError: integer 60000 does not fit 'short' During the call to 'onerror', another exception occurred: TypeError: $integer$ -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -OverflowError: integer 60000 does not fit 'short' -Exception ignored during handling of the above exception by 'onerror': -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -TypeError: $integer$ +""", """\ +Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: +Traceback (most recent call last): + File "$", line $, in test_callback_exception + $ +OverflowError: integer 60000 does not fit 'short' +Exception ignored during handling of the above exception by 'onerror': +Traceback (most recent call last): + File "$", line $, in test_callback_exception + $ +TypeError: $integer$ """) # sys.stderr = cStringIO.StringIO() seen = "not a list" # this makes the oops() function crash assert ff(bigvalue) == -42 - # the $ after the AttributeError message are for the suggestions that - # will be added in Python 3.10 + # the $ after the AttributeError message are for the suggestions that + # will be added in Python 3.10 assert matches(sys.stderr.getvalue(), """\ From cffi callback <function$Zcb1 at 0x$>: Trying to convert the result back to C: @@ -1466,18 +1466,18 @@ During the call to 'onerror', another exception occurred: Traceback (most recent call last): File "$", line $, in oops $ -AttributeError: 'str' object has no attribute 'append$ -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -OverflowError: integer 60000 does not fit 'short' -Exception ignored during handling of the above exception by 'onerror': -Traceback (most recent call last): - File "$", line $, in oops - $ -AttributeError: 'str' object has no attribute 'append$ +AttributeError: 'str' object has no attribute 'append$ +""", """\ +Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: +Traceback (most recent call last): + File "$", line $, in test_callback_exception + $ +OverflowError: integer 60000 does not fit 'short' +Exception ignored during handling of the above exception by 'onerror': +Traceback (most recent call last): + File "$", line $, in oops + $ +AttributeError: 'str' object has no attribute 'append$ """) finally: sys.stderr = orig_stderr @@ -1512,7 +1512,7 @@ def test_a_lot_of_callbacks(): def make_callback(m): def cb(n): return n + m - return callback(BFunc, cb, 42) # 'cb' goes out of scope + return callback(BFunc, cb, 42) # 'cb' goes out of scope # flist = [make_callback(i) for i in range(BIGNUM)] for i, f in enumerate(flist): @@ -1714,8 +1714,8 @@ def test_enum_in_struct(): assert ("an integer is required" in msg or # CPython "unsupported operand type for int(): 'NoneType'" in msg or # old PyPys "expected integer, got NoneType object" in msg) # newer PyPys - with pytest.raises(TypeError): - p.a1 = "def" + with pytest.raises(TypeError): + p.a1 = "def" if sys.version_info < (3,): BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt) assert string(cast(BEnum2, 5)) == 'abc' @@ -1845,17 +1845,17 @@ def test_bitfield_instance(): p.a1 = -1 assert p.a1 == -1 p.a1 = 0 - with pytest.raises(OverflowError): - p.a1 = 2 + with pytest.raises(OverflowError): + p.a1 = 2 assert p.a1 == 0 # p.a1 = -1 p.a2 = 3 p.a3 = -4 - with pytest.raises(OverflowError): - p.a3 = 4 - with pytest.raises(OverflowError) as e: - p.a3 = -5 + with pytest.raises(OverflowError): + p.a3 = 4 + with pytest.raises(OverflowError) as e: + p.a3 = -5 assert str(e.value) == ("value -5 outside the range allowed by the " "bit field width: -4 <= x <= 3") assert p.a1 == -1 and p.a2 == 3 and p.a3 == -4 @@ -1864,8 +1864,8 @@ def test_bitfield_instance(): # allows also setting the value "1" (it still gets read back as -1) p.a1 = 1 assert p.a1 == -1 - with pytest.raises(OverflowError) as e: - p.a1 = -2 + with pytest.raises(OverflowError) as e: + p.a1 = -2 assert str(e.value) == ("value -2 outside the range allowed by the " "bit field width: -1 <= x <= 1") @@ -1925,17 +1925,17 @@ def test_assign_string(): assert string(a[2]) == b"." a[2] = b"12345" assert string(a[2]) == b"12345" - with pytest.raises(IndexError) as e: - a[2] = b"123456" + with pytest.raises(IndexError) as e: + a[2] = b"123456" assert 'char[5]' in str(e.value) assert 'got 6 characters' in str(e.value) def test_add_error(): x = cast(new_primitive_type("int"), 42) - with pytest.raises(TypeError): - x + 1 - with pytest.raises(TypeError): - x - 1 + with pytest.raises(TypeError): + x + 1 + with pytest.raises(TypeError): + x - 1 def test_void_errors(): py.test.raises(ValueError, alignof, new_void_type()) @@ -1969,7 +1969,7 @@ def test_more_overflow_errors(): def test_newp_copying(): """Test that we can do newp(<type>, <cdata of the given type>) for most - types, including same-type arrays. + types, including same-type arrays. """ BInt = new_primitive_type("int") p = newp(new_pointer_type(BInt), cast(BInt, 42)) @@ -1998,9 +1998,9 @@ def test_newp_copying(): a1 = newp(BArray, [1, 2, 3, 4]) py.test.raises(TypeError, newp, BArray, a1) BArray6 = new_array_type(new_pointer_type(BInt), 6) - a1 = newp(BArray6, [10, 20, 30]) - a2 = newp(BArray6, a1) - assert list(a2) == [10, 20, 30, 0, 0, 0] + a1 = newp(BArray6, [10, 20, 30]) + a2 = newp(BArray6, a1) + assert list(a2) == [10, 20, 30, 0, 0, 0] # s1 = newp(BStructPtr, [42]) s2 = newp(BStructPtr, s1[0]) @@ -2053,11 +2053,11 @@ def test_string_byte(): assert string(a, 8).startswith(b'ABC') # may contain additional garbage def test_string_wchar(): - for typename in ["wchar_t", "char16_t", "char32_t"]: - _test_string_wchar_variant(typename) - -def _test_string_wchar_variant(typename): - BWChar = new_primitive_type(typename) + for typename in ["wchar_t", "char16_t", "char32_t"]: + _test_string_wchar_variant(typename) + +def _test_string_wchar_variant(typename): + BWChar = new_primitive_type(typename) assert string(cast(BWChar, 42)) == u+'*' assert string(cast(BWChar, 0x4253)) == u+'\u4253' assert string(cast(BWChar, 0)) == u+'\x00' @@ -2219,45 +2219,45 @@ def test_cast_with_functionptr(): py.test.raises(TypeError, newp, BStructPtr, [cast(BFunc2, 0)]) def test_wchar(): - _test_wchar_variant("wchar_t") - if sys.platform.startswith("linux"): - BWChar = new_primitive_type("wchar_t") - assert sizeof(BWChar) == 4 - # wchar_t is often signed on Linux, but not always (e.g. on ARM) - assert int(cast(BWChar, -1)) in (-1, 4294967295) - -def test_char16(): - BChar16 = new_primitive_type("char16_t") - assert sizeof(BChar16) == 2 - _test_wchar_variant("char16_t") - assert int(cast(BChar16, -1)) == 0xffff # always unsigned - -def test_char32(): - BChar32 = new_primitive_type("char32_t") - assert sizeof(BChar32) == 4 - _test_wchar_variant("char32_t") - assert int(cast(BChar32, -1)) == 0xffffffff # always unsigned - -def _test_wchar_variant(typename): - BWChar = new_primitive_type(typename) + _test_wchar_variant("wchar_t") + if sys.platform.startswith("linux"): + BWChar = new_primitive_type("wchar_t") + assert sizeof(BWChar) == 4 + # wchar_t is often signed on Linux, but not always (e.g. on ARM) + assert int(cast(BWChar, -1)) in (-1, 4294967295) + +def test_char16(): + BChar16 = new_primitive_type("char16_t") + assert sizeof(BChar16) == 2 + _test_wchar_variant("char16_t") + assert int(cast(BChar16, -1)) == 0xffff # always unsigned + +def test_char32(): + BChar32 = new_primitive_type("char32_t") + assert sizeof(BChar32) == 4 + _test_wchar_variant("char32_t") + assert int(cast(BChar32, -1)) == 0xffffffff # always unsigned + +def _test_wchar_variant(typename): + BWChar = new_primitive_type(typename) BInt = new_primitive_type("int") pyuni4 = {1: True, 2: False}[len(u+'\U00012345')] wchar4 = {2: False, 4: True}[sizeof(BWChar)] - assert str(cast(BWChar, 0x45)) == "<cdata '%s' %s'E'>" % ( - typename, mandatory_u_prefix) - assert str(cast(BWChar, 0x1234)) == "<cdata '%s' %s'\u1234'>" % ( - typename, mandatory_u_prefix) - if not _hacked_pypy_uni4(): - if wchar4: + assert str(cast(BWChar, 0x45)) == "<cdata '%s' %s'E'>" % ( + typename, mandatory_u_prefix) + assert str(cast(BWChar, 0x1234)) == "<cdata '%s' %s'\u1234'>" % ( + typename, mandatory_u_prefix) + if not _hacked_pypy_uni4(): + if wchar4: x = cast(BWChar, 0x12345) - assert str(x) == "<cdata '%s' %s'\U00012345'>" % ( - typename, mandatory_u_prefix) + assert str(x) == "<cdata '%s' %s'\U00012345'>" % ( + typename, mandatory_u_prefix) assert int(x) == 0x12345 - else: - x = cast(BWChar, 0x18345) - assert str(x) == "<cdata '%s' %s'\u8345'>" % ( - typename, mandatory_u_prefix) - assert int(x) == 0x8345 + else: + x = cast(BWChar, 0x18345) + assert str(x) == "<cdata '%s' %s'\u8345'>" % ( + typename, mandatory_u_prefix) + assert int(x) == 0x8345 # BWCharP = new_pointer_type(BWChar) BStruct = new_struct_type("struct foo_s") @@ -2267,16 +2267,16 @@ def _test_wchar_variant(typename): s = newp(BStructPtr) s.a1 = u+'\x00' assert s.a1 == u+'\x00' - with pytest.raises(TypeError): - s.a1 = b'a' - with pytest.raises(TypeError): - s.a1 = bytechr(0xFF) + with pytest.raises(TypeError): + s.a1 = b'a' + with pytest.raises(TypeError): + s.a1 = bytechr(0xFF) s.a1 = u+'\u1234' assert s.a1 == u+'\u1234' if pyuni4: - if wchar4: - s.a1 = u+'\U00012345' - assert s.a1 == u+'\U00012345' + if wchar4: + s.a1 = u+'\U00012345' + assert s.a1 == u+'\U00012345' elif wchar4: if not _hacked_pypy_uni4(): s.a1 = cast(BWChar, 0x12345) @@ -2284,8 +2284,8 @@ def _test_wchar_variant(typename): s.a1 = u+'\ud807\udf44' assert s.a1 == u+'\U00011f44' else: - with pytest.raises(TypeError): - s.a1 = u+'\U00012345' + with pytest.raises(TypeError): + s.a1 = u+'\U00012345' # BWCharArray = new_array_type(BWCharP, None) a = newp(BWCharArray, u+'hello \u1234 world') @@ -2309,21 +2309,21 @@ def _test_wchar_variant(typename): assert list(a) == expected got = [a[i] for i in range(4)] assert got == expected - with pytest.raises(IndexError): - a[4] + with pytest.raises(IndexError): + a[4] # w = cast(BWChar, 'a') - assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix) + assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix) assert str(w) == repr(w) assert string(w) == u+'a' assert int(w) == ord('a') w = cast(BWChar, 0x1234) - assert repr(w) == "<cdata '%s' %s'\u1234'>" % (typename, mandatory_u_prefix) + assert repr(w) == "<cdata '%s' %s'\u1234'>" % (typename, mandatory_u_prefix) assert str(w) == repr(w) assert string(w) == u+'\u1234' assert int(w) == 0x1234 w = cast(BWChar, u+'\u8234') - assert repr(w) == "<cdata '%s' %s'\u8234'>" % (typename, mandatory_u_prefix) + assert repr(w) == "<cdata '%s' %s'\u8234'>" % (typename, mandatory_u_prefix) assert str(w) == repr(w) assert string(w) == u+'\u8234' assert int(w) == 0x8234 @@ -2331,8 +2331,8 @@ def _test_wchar_variant(typename): assert repr(w) == "<cdata 'int' 4660>" if wchar4 and not _hacked_pypy_uni4(): w = cast(BWChar, u+'\U00012345') - assert repr(w) == "<cdata '%s' %s'\U00012345'>" % ( - typename, mandatory_u_prefix) + assert repr(w) == "<cdata '%s' %s'\U00012345'>" % ( + typename, mandatory_u_prefix) assert str(w) == repr(w) assert string(w) == u+'\U00012345' assert int(w) == 0x12345 @@ -2359,7 +2359,7 @@ def _test_wchar_variant(typename): py.test.raises(RuntimeError, string, q) # def cb(p): - assert repr(p).startswith("<cdata '%s *' 0x" % typename) + assert repr(p).startswith("<cdata '%s *' 0x" % typename) return len(string(p)) BFunc = new_function_type((BWCharP,), BInt, False) f = callback(BFunc, cb, -42) @@ -2372,27 +2372,27 @@ def _test_wchar_variant(typename): x = cast(BWChar, -1) py.test.raises(ValueError, string, x) -def test_wchar_variants_mix(): - BWChar = new_primitive_type("wchar_t") - BChar16 = new_primitive_type("char16_t") - BChar32 = new_primitive_type("char32_t") - assert int(cast(BChar32, cast(BChar16, -2))) == 0xfffe - assert int(cast(BWChar, cast(BChar16, -2))) == 0xfffe - assert int(cast(BChar16, cast(BChar32, 0x0001f345))) == 0xf345 - assert int(cast(BChar16, cast(BWChar, 0x0001f345))) == 0xf345 - # - BChar16A = new_array_type(new_pointer_type(BChar16), None) - BChar32A = new_array_type(new_pointer_type(BChar32), None) - x = cast(BChar32, 'A') - py.test.raises(TypeError, newp, BChar16A, [x]) - x = cast(BChar16, 'A') - py.test.raises(TypeError, newp, BChar32A, [x]) - # - a = newp(BChar16A, u+'\U00012345') - assert len(a) == 3 - a = newp(BChar32A, u+'\U00012345') - assert len(a) == 2 # even if the Python unicode string above is 2 chars - +def test_wchar_variants_mix(): + BWChar = new_primitive_type("wchar_t") + BChar16 = new_primitive_type("char16_t") + BChar32 = new_primitive_type("char32_t") + assert int(cast(BChar32, cast(BChar16, -2))) == 0xfffe + assert int(cast(BWChar, cast(BChar16, -2))) == 0xfffe + assert int(cast(BChar16, cast(BChar32, 0x0001f345))) == 0xf345 + assert int(cast(BChar16, cast(BWChar, 0x0001f345))) == 0xf345 + # + BChar16A = new_array_type(new_pointer_type(BChar16), None) + BChar32A = new_array_type(new_pointer_type(BChar32), None) + x = cast(BChar32, 'A') + py.test.raises(TypeError, newp, BChar16A, [x]) + x = cast(BChar16, 'A') + py.test.raises(TypeError, newp, BChar32A, [x]) + # + a = newp(BChar16A, u+'\U00012345') + assert len(a) == 3 + a = newp(BChar32A, u+'\U00012345') + assert len(a) == 2 # even if the Python unicode string above is 2 chars + def test_keepalive_struct(): # exception to the no-keepalive rule: p=newp(BStructPtr) returns a # pointer owning the memory, and p[0] returns a pointer to the @@ -2442,11 +2442,11 @@ def test_owning_repr(): def test_cannot_dereference_void(): BVoidP = new_pointer_type(new_void_type()) p = cast(BVoidP, 123456) - with pytest.raises(TypeError): - p[0] + with pytest.raises(TypeError): + p[0] p = cast(BVoidP, 0) - with pytest.raises((TypeError, RuntimeError)): - p[0] + with pytest.raises((TypeError, RuntimeError)): + p[0] def test_iter(): BInt = new_primitive_type("int") @@ -2466,15 +2466,15 @@ def test_cmp(): q = cast(BInt, 124) assert (p == q) is False assert (p != q) is True - assert (q == p) is False - assert (q != p) is True - if strict_compare: - with pytest.raises(TypeError): p < q - with pytest.raises(TypeError): p <= q - with pytest.raises(TypeError): q < p - with pytest.raises(TypeError): q <= p - with pytest.raises(TypeError): p > q - with pytest.raises(TypeError): p >= q + assert (q == p) is False + assert (q != p) is True + if strict_compare: + with pytest.raises(TypeError): p < q + with pytest.raises(TypeError): p <= q + with pytest.raises(TypeError): q < p + with pytest.raises(TypeError): q <= p + with pytest.raises(TypeError): p > q + with pytest.raises(TypeError): p >= q r = cast(BVoidP, p) assert (p < r) is False assert (p <= r) is True @@ -2507,7 +2507,7 @@ def test_buffer(): buf = buffer(c) assert repr(buf).startswith('<_cffi_backend.buffer object at 0x') assert bytes(buf) == b"hi there\x00" - assert type(buf) is buffer + assert type(buf) is buffer if sys.version_info < (3,): assert str(buf) == "hi there\x00" assert unicode(buf) == u+"hi there\x00" @@ -2520,8 +2520,8 @@ def test_buffer(): try: expected = b"hi there\x00"[i] except IndexError: - with pytest.raises(IndexError): - buf[i] + with pytest.raises(IndexError): + buf[i] else: assert buf[i] == bitem2bchr(expected) # --mb_slice-- @@ -2548,18 +2548,18 @@ def test_buffer(): try: expected[i] = bytechr(i & 0xff) except IndexError: - with pytest.raises(IndexError): - buf[i] = bytechr(i & 0xff) + with pytest.raises(IndexError): + buf[i] = bytechr(i & 0xff) else: buf[i] = bytechr(i & 0xff) assert list(buf) == expected # --mb_ass_slice-- buf[:] = b"hi there\x00" assert list(buf) == list(c) == list(map(bitem2bchr, b"hi there\x00")) - with pytest.raises(ValueError): - buf[:] = b"shorter" - with pytest.raises(ValueError): - buf[:] = b"this is much too long!" + with pytest.raises(ValueError): + buf[:] = b"shorter" + with pytest.raises(ValueError): + buf[:] = b"this is much too long!" buf[4:2] = b"" # no effect, but should work assert buf[:] == b"hi there\x00" buf[:2] = b"HI" @@ -2595,8 +2595,8 @@ def test_errno(): assert get_errno() == 95 def test_errno_callback(): - if globals().get('PY_DOT_PY'): - py.test.skip("cannot run this test on py.py (e.g. fails on Windows)") + if globals().get('PY_DOT_PY'): + py.test.skip("cannot run this test on py.py (e.g. fails on Windows)") set_errno(95) def cb(): e = get_errno() @@ -2633,16 +2633,16 @@ def test_bug_delitem(): BChar = new_primitive_type("char") BCharP = new_pointer_type(BChar) x = newp(BCharP) - with pytest.raises(TypeError): - del x[0] + with pytest.raises(TypeError): + del x[0] def test_bug_delattr(): BLong = new_primitive_type("long") BStruct = new_struct_type("struct foo") complete_struct_or_union(BStruct, [('a1', BLong, -1)]) x = newp(new_pointer_type(BStruct)) - with pytest.raises(AttributeError): - del x.a1 + with pytest.raises(AttributeError): + del x.a1 def test_variable_length_struct(): py.test.skip("later") @@ -2660,8 +2660,8 @@ def test_variable_length_struct(): assert sizeof(x) == 6 * size_of_long() x[4] = 123 assert x[4] == 123 - with pytest.raises(IndexError): - x[5] + with pytest.raises(IndexError): + x[5] assert len(x.a2) == 5 # py.test.raises(TypeError, newp, BStructP, [123]) @@ -2891,40 +2891,40 @@ def test_bool(): py.test.raises(OverflowError, newp, BBoolP, 2) py.test.raises(OverflowError, newp, BBoolP, -1) BCharP = new_pointer_type(new_primitive_type("char")) - p = newp(BCharP, b'\x01') - q = cast(BBoolP, p) - assert q[0] is True - p = newp(BCharP, b'\x00') + p = newp(BCharP, b'\x01') q = cast(BBoolP, p) - assert q[0] is False + assert q[0] is True + p = newp(BCharP, b'\x00') + q = cast(BBoolP, p) + assert q[0] is False py.test.raises(TypeError, string, cast(BBool, False)) BDouble = new_primitive_type("double") assert int(cast(BBool, cast(BDouble, 0.1))) == 1 assert int(cast(BBool, cast(BDouble, 0.0))) == 0 - BBoolA = new_array_type(BBoolP, None) - p = newp(BBoolA, b'\x01\x00') - assert p[0] is True - assert p[1] is False - -def test_bool_forbidden_cases(): - BBool = new_primitive_type("_Bool") - BBoolP = new_pointer_type(BBool) - BBoolA = new_array_type(BBoolP, None) - BCharP = new_pointer_type(new_primitive_type("char")) - p = newp(BCharP, b'X') - q = cast(BBoolP, p) - with pytest.raises(ValueError): - q[0] - py.test.raises(TypeError, newp, BBoolP, b'\x00') - assert newp(BBoolP, 0)[0] is False - assert newp(BBoolP, 1)[0] is True - py.test.raises(OverflowError, newp, BBoolP, 2) - py.test.raises(OverflowError, newp, BBoolP, -1) - py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02') - py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2]) - py.test.raises(TypeError, string, newp(BBoolP, 1)) - py.test.raises(TypeError, string, newp(BBoolA, [1])) - + BBoolA = new_array_type(BBoolP, None) + p = newp(BBoolA, b'\x01\x00') + assert p[0] is True + assert p[1] is False + +def test_bool_forbidden_cases(): + BBool = new_primitive_type("_Bool") + BBoolP = new_pointer_type(BBool) + BBoolA = new_array_type(BBoolP, None) + BCharP = new_pointer_type(new_primitive_type("char")) + p = newp(BCharP, b'X') + q = cast(BBoolP, p) + with pytest.raises(ValueError): + q[0] + py.test.raises(TypeError, newp, BBoolP, b'\x00') + assert newp(BBoolP, 0)[0] is False + assert newp(BBoolP, 1)[0] is True + py.test.raises(OverflowError, newp, BBoolP, 2) + py.test.raises(OverflowError, newp, BBoolP, -1) + py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02') + py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2]) + py.test.raises(TypeError, string, newp(BBoolP, 1)) + py.test.raises(TypeError, string, newp(BBoolA, [1])) + def test_typeoffsetof(): BChar = new_primitive_type("char") BStruct = new_struct_type("struct foo") @@ -3214,10 +3214,10 @@ def test_slice(): assert c[1] == 123 assert c[3] == 456 assert d[2] == 456 - with pytest.raises(IndexError): - d[3] - with pytest.raises(IndexError): - d[-1] + with pytest.raises(IndexError): + d[3] + with pytest.raises(IndexError): + d[-1] def test_slice_ptr(): BIntP = new_pointer_type(new_primitive_type("int")) @@ -3235,8 +3235,8 @@ def test_slice_array_checkbounds(): c = newp(BIntArray, 5) c[0:5] assert len(c[5:5]) == 0 - with pytest.raises(IndexError): - c[-1:1] + with pytest.raises(IndexError): + c[-1:1] cp = c + 0 cp[-1:1] @@ -3244,23 +3244,23 @@ def test_nonstandard_slice(): BIntP = new_pointer_type(new_primitive_type("int")) BIntArray = new_array_type(BIntP, None) c = newp(BIntArray, 5) - with pytest.raises(IndexError) as e: - c[:5] + with pytest.raises(IndexError) as e: + c[:5] assert str(e.value) == "slice start must be specified" - with pytest.raises(IndexError) as e: - c[4:] + with pytest.raises(IndexError) as e: + c[4:] assert str(e.value) == "slice stop must be specified" - with pytest.raises(IndexError) as e: - c[1:2:3] + with pytest.raises(IndexError) as e: + c[1:2:3] assert str(e.value) == "slice with step not supported" - with pytest.raises(IndexError) as e: - c[1:2:1] + with pytest.raises(IndexError) as e: + c[1:2:1] assert str(e.value) == "slice with step not supported" - with pytest.raises(IndexError) as e: - c[4:2] + with pytest.raises(IndexError) as e: + c[4:2] assert str(e.value) == "slice start > stop" - with pytest.raises(IndexError) as e: - c[6:6] + with pytest.raises(IndexError) as e: + c[6:6] assert str(e.value) == "index too large (expected 6 <= 5)" def test_setslice(): @@ -3274,11 +3274,11 @@ def test_setslice(): assert list(c) == [0, 100, 300, 400, 0] cp[-1:1] = iter([500, 600]) assert list(c) == [0, 100, 500, 600, 0] - with pytest.raises(ValueError): - cp[-1:1] = [1000] + with pytest.raises(ValueError): + cp[-1:1] = [1000] assert list(c) == [0, 100, 1000, 600, 0] - with pytest.raises(ValueError): - cp[-1:1] = (700, 800, 900) + with pytest.raises(ValueError): + cp[-1:1] = (700, 800, 900) assert list(c) == [0, 100, 700, 800, 0] def test_setslice_array(): @@ -3538,14 +3538,14 @@ def test_struct_array_no_length(): assert sizeof(q[0]) == sizeof(BStruct) # # error cases - with pytest.raises(IndexError): - p.y[4] - with pytest.raises(TypeError): - p.y = cast(BIntP, 0) - with pytest.raises(TypeError): - p.y = 15 - with pytest.raises(TypeError): - p.y = None + with pytest.raises(IndexError): + p.y[4] + with pytest.raises(TypeError): + p.y = cast(BIntP, 0) + with pytest.raises(TypeError): + p.y = 15 + with pytest.raises(TypeError): + p.y = None # # accepting this may be specified by the C99 standard, # or a GCC strangeness... @@ -3567,16 +3567,16 @@ def test_struct_array_no_length(): assert p.a[1] == 20 assert p.a[2] == 30 assert p.a[3] == 0 - # - # struct of struct of varsized array - BStruct2 = new_struct_type("bar") - complete_struct_or_union(BStruct2, [('head', BInt), - ('tail', BStruct)]) - for i in range(2): # try to detect heap overwrites - p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]]) - assert p.tail.y[49] == 49 - - + # + # struct of struct of varsized array + BStruct2 = new_struct_type("bar") + complete_struct_or_union(BStruct2, [('head', BInt), + ('tail', BStruct)]) + for i in range(2): # try to detect heap overwrites + p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]]) + assert p.tail.y[49] == 49 + + def test_struct_array_no_length_explicit_position(): BInt = new_primitive_type("int") BIntP = new_pointer_type(BInt) @@ -3650,22 +3650,22 @@ def test_ass_slice(): p[2:5] = [b"*", b"Z", b"T"] p[1:3] = b"XY" assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"] - with pytest.raises(TypeError): - p[1:5] = u+'XYZT' - with pytest.raises(TypeError): - p[1:5] = [1, 2, 3, 4] - # - for typename in ["wchar_t", "char16_t", "char32_t"]: - BUniChar = new_primitive_type(typename) - BArray = new_array_type(new_pointer_type(BUniChar), None) - p = newp(BArray, u+"foobar") - p[2:5] = [u+"*", u+"Z", u+"T"] - p[1:3] = u+"XY" - assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"] - with pytest.raises(TypeError): - p[1:5] = b'XYZT' - with pytest.raises(TypeError): - p[1:5] = [1, 2, 3, 4] + with pytest.raises(TypeError): + p[1:5] = u+'XYZT' + with pytest.raises(TypeError): + p[1:5] = [1, 2, 3, 4] + # + for typename in ["wchar_t", "char16_t", "char32_t"]: + BUniChar = new_primitive_type(typename) + BArray = new_array_type(new_pointer_type(BUniChar), None) + p = newp(BArray, u+"foobar") + p[2:5] = [u+"*", u+"Z", u+"T"] + p[1:3] = u+"XY" + assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"] + with pytest.raises(TypeError): + p[1:5] = b'XYZT' + with pytest.raises(TypeError): + p[1:5] = [1, 2, 3, 4] def test_void_p_arithmetic(): BVoid = new_void_type() @@ -3676,14 +3676,14 @@ def test_void_p_arithmetic(): assert int(cast(BInt, p - (-42))) == 100042 assert (p + 42) - p == 42 q = cast(new_pointer_type(new_primitive_type("char")), 100000) - with pytest.raises(TypeError): - p - q - with pytest.raises(TypeError): - q - p - with pytest.raises(TypeError): - p + cast(new_primitive_type('int'), 42) - with pytest.raises(TypeError): - p - cast(new_primitive_type('int'), 42) + with pytest.raises(TypeError): + p - q + with pytest.raises(TypeError): + q - p + with pytest.raises(TypeError): + p + cast(new_primitive_type('int'), 42) + with pytest.raises(TypeError): + p - cast(new_primitive_type('int'), 42) def test_sizeof_sliced_array(): BInt = new_primitive_type("int") @@ -3695,50 +3695,50 @@ def test_packed(): BLong = new_primitive_type("long") BChar = new_primitive_type("char") BShort = new_primitive_type("short") - for extra_args in [(SF_PACKED,), (0, 1)]: - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BLong, -1), - ('a2', BChar, -1), - ('a3', BShort, -1)], - None, -1, -1, *extra_args) - d = BStruct.fields - assert len(d) == 3 - assert d[0][0] == 'a1' - assert d[0][1].type is BLong - assert d[0][1].offset == 0 - assert d[0][1].bitshift == -1 - assert d[0][1].bitsize == -1 - assert d[1][0] == 'a2' - assert d[1][1].type is BChar - assert d[1][1].offset == sizeof(BLong) - assert d[1][1].bitshift == -1 - assert d[1][1].bitsize == -1 - assert d[2][0] == 'a3' - assert d[2][1].type is BShort - assert d[2][1].offset == sizeof(BLong) + sizeof(BChar) - assert d[2][1].bitshift == -1 - assert d[2][1].bitsize == -1 - assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort) - assert alignof(BStruct) == 1 - # - BStruct2 = new_struct_type("struct foo") - complete_struct_or_union(BStruct2, [('b1', BChar, -1), - ('b2', BLong, -1)], - None, -1, -1, 0, 2) - d = BStruct2.fields - assert len(d) == 2 - assert d[0][0] == 'b1' - assert d[0][1].type is BChar + for extra_args in [(SF_PACKED,), (0, 1)]: + BStruct = new_struct_type("struct foo") + complete_struct_or_union(BStruct, [('a1', BLong, -1), + ('a2', BChar, -1), + ('a3', BShort, -1)], + None, -1, -1, *extra_args) + d = BStruct.fields + assert len(d) == 3 + assert d[0][0] == 'a1' + assert d[0][1].type is BLong + assert d[0][1].offset == 0 + assert d[0][1].bitshift == -1 + assert d[0][1].bitsize == -1 + assert d[1][0] == 'a2' + assert d[1][1].type is BChar + assert d[1][1].offset == sizeof(BLong) + assert d[1][1].bitshift == -1 + assert d[1][1].bitsize == -1 + assert d[2][0] == 'a3' + assert d[2][1].type is BShort + assert d[2][1].offset == sizeof(BLong) + sizeof(BChar) + assert d[2][1].bitshift == -1 + assert d[2][1].bitsize == -1 + assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort) + assert alignof(BStruct) == 1 + # + BStruct2 = new_struct_type("struct foo") + complete_struct_or_union(BStruct2, [('b1', BChar, -1), + ('b2', BLong, -1)], + None, -1, -1, 0, 2) + d = BStruct2.fields + assert len(d) == 2 + assert d[0][0] == 'b1' + assert d[0][1].type is BChar assert d[0][1].offset == 0 assert d[0][1].bitshift == -1 assert d[0][1].bitsize == -1 - assert d[1][0] == 'b2' - assert d[1][1].type is BLong - assert d[1][1].offset == 2 + assert d[1][0] == 'b2' + assert d[1][1].type is BLong + assert d[1][1].offset == 2 assert d[1][1].bitshift == -1 assert d[1][1].bitsize == -1 - assert sizeof(BStruct2) == 2 + sizeof(BLong) - assert alignof(BStruct2) == 2 + assert sizeof(BStruct2) == 2 + sizeof(BLong) + assert alignof(BStruct2) == 2 def test_packed_with_bitfields(): if sys.platform == "win32": @@ -3780,27 +3780,27 @@ def test_from_buffer_not_str_unicode(): except ImportError: pass else: - # Python 2 only - contents = from_buffer(BCharA, buffer(b"foo")) - assert len(contents) == len(p1) - for i in range(len(contents)): - assert contents[i] == p1[i] - p4 = buffer(u+"foo") - contents = from_buffer(BCharA, buffer(u+"foo")) - assert len(contents) == len(p4) - for i in range(len(contents)): - assert contents[i] == p4[i] + # Python 2 only + contents = from_buffer(BCharA, buffer(b"foo")) + assert len(contents) == len(p1) + for i in range(len(contents)): + assert contents[i] == p1[i] + p4 = buffer(u+"foo") + contents = from_buffer(BCharA, buffer(u+"foo")) + assert len(contents) == len(p4) + for i in range(len(contents)): + assert contents[i] == p4[i] try: from __builtin__ import memoryview except ImportError: pass else: - contents = from_buffer(BCharA, memoryview(b"foo")) - assert len(contents) == len(p1) - for i in range(len(contents)): - assert contents[i] == p1[i] - + contents = from_buffer(BCharA, memoryview(b"foo")) + assert len(contents) == len(p1) + for i in range(len(contents)): + assert contents[i] == p1[i] + def test_from_buffer_bytearray(): a = bytearray(b"xyz") BChar = new_primitive_type("char") @@ -3873,163 +3873,163 @@ def test_from_buffer_more_cases(): check(4 | 8, "CHB", "GTB") check(4 | 16, "CHB", "ROB") -def test_from_buffer_require_writable(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p1 = from_buffer(BCharA, b"foo", False) - assert p1 == from_buffer(BCharA, b"foo", False) - py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True) - ba = bytearray(b"foo") - p1 = from_buffer(BCharA, ba, True) - p1[0] = b"g" - assert ba == b"goo" - -def test_from_buffer_types(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BIntA = new_array_type(BIntP, None) - lst = [-12345678, 87654321, 489148] - bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ') - lst2 = lst + [42, -999999999] - bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ') - # - p1 = from_buffer(BIntA, bytestring) # int[] - assert typeof(p1) is BIntA - assert len(p1) == 3 - assert p1[0] == lst[0] - assert p1[1] == lst[1] - assert p1[2] == lst[2] - with pytest.raises(IndexError): - p1[3] - with pytest.raises(IndexError): - p1[-1] - # - py.test.raises(TypeError, from_buffer, BInt, bytestring) - # - p2 = from_buffer(BIntP, bytestring) # int * - assert p2 == p1 or 'PY_DOT_PY' in globals() - # note: on py.py ^^^, bytearray buffers are not emulated well enough - assert typeof(p2) is BIntP - assert p2[0] == lst[0] - assert p2[1] == lst[1] - assert p2[2] == lst[2] - # hopefully does not crash, but doesn't raise an exception: - p2[3] - p2[-1] - # not enough data even for one, but this is not enforced: - from_buffer(BIntP, b"") - # - BIntA2 = new_array_type(BIntP, 2) - p2 = from_buffer(BIntA2, bytestring) # int[2] - assert typeof(p2) is BIntA2 - assert len(p2) == 2 - assert p2[0] == lst[0] - assert p2[1] == lst[1] - with pytest.raises(IndexError): - p2[2] - with pytest.raises(IndexError): - p2[-1] - assert p2 == p1 or 'PY_DOT_PY' in globals() - # - BIntA4 = new_array_type(BIntP, 4) # int[4]: too big - py.test.raises(ValueError, from_buffer, BIntA4, bytestring) - # - BStruct = new_struct_type("foo") - complete_struct_or_union(BStruct, [('a1', BInt, -1), - ('a2', BInt, -1)]) - BStructP = new_pointer_type(BStruct) - BStructA = new_array_type(BStructP, None) - p1 = from_buffer(BStructA, bytestring2) # struct[] - assert len(p1) == 2 - assert typeof(p1) is BStructA - assert p1[0].a1 == lst2[0] - assert p1[0].a2 == lst2[1] - assert p1[1].a1 == lst2[2] - assert p1[1].a2 == lst2[3] - with pytest.raises(IndexError): - p1[2] - with pytest.raises(IndexError): - p1[-1] - assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>" - # - p2 = from_buffer(BStructP, bytestring2) # 'struct *' - assert p2 == p1 or 'PY_DOT_PY' in globals() - assert typeof(p2) is BStructP - assert p2.a1 == lst2[0] - assert p2.a2 == lst2[1] - assert p2[0].a1 == lst2[0] - assert p2[0].a2 == lst2[1] - assert p2[1].a1 == lst2[2] - assert p2[1].a2 == lst2[3] - # does not crash: - p2[2] - p2[-1] - # not enough data even for one, but this is not enforced: - from_buffer(BStructP, b"") - from_buffer(BStructP, b"1234567") - # - release(p1) - assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>" - # - BEmptyStruct = new_struct_type("empty") - complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0) - assert sizeof(BEmptyStruct) == 0 - BEmptyStructP = new_pointer_type(BEmptyStruct) - BEmptyStructA = new_array_type(BEmptyStructP, None) - py.test.raises(ZeroDivisionError, from_buffer, # empty[] - BEmptyStructA, bytestring) - # - BEmptyStructA5 = new_array_type(BEmptyStructP, 5) - p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5] - assert typeof(p1) is BEmptyStructA5 - assert len(p1) == 5 - assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring) - or 'PY_DOT_PY' in globals()) - # - BVarStruct = new_struct_type("varfoo") - BVarStructP = new_pointer_type(BVarStruct) - complete_struct_or_union(BVarStruct, [('a1', BInt, -1), - ('va', BIntA, -1)]) - with pytest.raises(TypeError): - from_buffer(BVarStruct, bytestring) - pv = from_buffer(BVarStructP, bytestring) # varfoo * - assert pv.a1 == lst[0] - assert pv.va[0] == lst[1] - assert pv.va[1] == lst[2] - assert sizeof(pv[0]) == 1 * size_of_int() - with pytest.raises(TypeError): - len(pv.va) - # hopefully does not crash, but doesn't raise an exception: - pv.va[2] - pv.va[-1] - # not enough data even for one, but this is not enforced: - from_buffer(BVarStructP, b"") - assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>" - assert repr(pv[0]).startswith("<cdata 'varfoo &' ") - # - release(pv) - assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>" - assert repr(pv[0]).startswith("<cdata 'varfoo &' ") - # - pv = from_buffer(BVarStructP, bytestring) # make a fresh one - with pytest.raises(ValueError): - release(pv[0]) - -def test_issue483(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BIntA = new_array_type(BIntP, None) - lst = list(range(25)) - bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ') - p1 = from_buffer(BIntA, bytestring) # int[] - assert len(buffer(p1)) == 25 * size_of_int() - assert sizeof(p1) == 25 * size_of_int() - # - p2 = from_buffer(BIntP, bytestring) - assert sizeof(p2) == size_of_ptr() - assert len(buffer(p2)) == size_of_int() # first element only, by default - +def test_from_buffer_require_writable(): + BChar = new_primitive_type("char") + BCharP = new_pointer_type(BChar) + BCharA = new_array_type(BCharP, None) + p1 = from_buffer(BCharA, b"foo", False) + assert p1 == from_buffer(BCharA, b"foo", False) + py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True) + ba = bytearray(b"foo") + p1 = from_buffer(BCharA, ba, True) + p1[0] = b"g" + assert ba == b"goo" + +def test_from_buffer_types(): + BInt = new_primitive_type("int") + BIntP = new_pointer_type(BInt) + BIntA = new_array_type(BIntP, None) + lst = [-12345678, 87654321, 489148] + bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ') + lst2 = lst + [42, -999999999] + bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ') + # + p1 = from_buffer(BIntA, bytestring) # int[] + assert typeof(p1) is BIntA + assert len(p1) == 3 + assert p1[0] == lst[0] + assert p1[1] == lst[1] + assert p1[2] == lst[2] + with pytest.raises(IndexError): + p1[3] + with pytest.raises(IndexError): + p1[-1] + # + py.test.raises(TypeError, from_buffer, BInt, bytestring) + # + p2 = from_buffer(BIntP, bytestring) # int * + assert p2 == p1 or 'PY_DOT_PY' in globals() + # note: on py.py ^^^, bytearray buffers are not emulated well enough + assert typeof(p2) is BIntP + assert p2[0] == lst[0] + assert p2[1] == lst[1] + assert p2[2] == lst[2] + # hopefully does not crash, but doesn't raise an exception: + p2[3] + p2[-1] + # not enough data even for one, but this is not enforced: + from_buffer(BIntP, b"") + # + BIntA2 = new_array_type(BIntP, 2) + p2 = from_buffer(BIntA2, bytestring) # int[2] + assert typeof(p2) is BIntA2 + assert len(p2) == 2 + assert p2[0] == lst[0] + assert p2[1] == lst[1] + with pytest.raises(IndexError): + p2[2] + with pytest.raises(IndexError): + p2[-1] + assert p2 == p1 or 'PY_DOT_PY' in globals() + # + BIntA4 = new_array_type(BIntP, 4) # int[4]: too big + py.test.raises(ValueError, from_buffer, BIntA4, bytestring) + # + BStruct = new_struct_type("foo") + complete_struct_or_union(BStruct, [('a1', BInt, -1), + ('a2', BInt, -1)]) + BStructP = new_pointer_type(BStruct) + BStructA = new_array_type(BStructP, None) + p1 = from_buffer(BStructA, bytestring2) # struct[] + assert len(p1) == 2 + assert typeof(p1) is BStructA + assert p1[0].a1 == lst2[0] + assert p1[0].a2 == lst2[1] + assert p1[1].a1 == lst2[2] + assert p1[1].a2 == lst2[3] + with pytest.raises(IndexError): + p1[2] + with pytest.raises(IndexError): + p1[-1] + assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>" + # + p2 = from_buffer(BStructP, bytestring2) # 'struct *' + assert p2 == p1 or 'PY_DOT_PY' in globals() + assert typeof(p2) is BStructP + assert p2.a1 == lst2[0] + assert p2.a2 == lst2[1] + assert p2[0].a1 == lst2[0] + assert p2[0].a2 == lst2[1] + assert p2[1].a1 == lst2[2] + assert p2[1].a2 == lst2[3] + # does not crash: + p2[2] + p2[-1] + # not enough data even for one, but this is not enforced: + from_buffer(BStructP, b"") + from_buffer(BStructP, b"1234567") + # + release(p1) + assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>" + # + BEmptyStruct = new_struct_type("empty") + complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0) + assert sizeof(BEmptyStruct) == 0 + BEmptyStructP = new_pointer_type(BEmptyStruct) + BEmptyStructA = new_array_type(BEmptyStructP, None) + py.test.raises(ZeroDivisionError, from_buffer, # empty[] + BEmptyStructA, bytestring) + # + BEmptyStructA5 = new_array_type(BEmptyStructP, 5) + p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5] + assert typeof(p1) is BEmptyStructA5 + assert len(p1) == 5 + assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring) + or 'PY_DOT_PY' in globals()) + # + BVarStruct = new_struct_type("varfoo") + BVarStructP = new_pointer_type(BVarStruct) + complete_struct_or_union(BVarStruct, [('a1', BInt, -1), + ('va', BIntA, -1)]) + with pytest.raises(TypeError): + from_buffer(BVarStruct, bytestring) + pv = from_buffer(BVarStructP, bytestring) # varfoo * + assert pv.a1 == lst[0] + assert pv.va[0] == lst[1] + assert pv.va[1] == lst[2] + assert sizeof(pv[0]) == 1 * size_of_int() + with pytest.raises(TypeError): + len(pv.va) + # hopefully does not crash, but doesn't raise an exception: + pv.va[2] + pv.va[-1] + # not enough data even for one, but this is not enforced: + from_buffer(BVarStructP, b"") + assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>" + assert repr(pv[0]).startswith("<cdata 'varfoo &' ") + # + release(pv) + assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>" + assert repr(pv[0]).startswith("<cdata 'varfoo &' ") + # + pv = from_buffer(BVarStructP, bytestring) # make a fresh one + with pytest.raises(ValueError): + release(pv[0]) + +def test_issue483(): + BInt = new_primitive_type("int") + BIntP = new_pointer_type(BInt) + BIntA = new_array_type(BIntP, None) + lst = list(range(25)) + bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ') + p1 = from_buffer(BIntA, bytestring) # int[] + assert len(buffer(p1)) == 25 * size_of_int() + assert sizeof(p1) == 25 * size_of_int() + # + p2 = from_buffer(BIntP, bytestring) + assert sizeof(p2) == size_of_ptr() + assert len(buffer(p2)) == size_of_int() # first element only, by default + def test_memmove(): Short = new_primitive_type("short") ShortA = new_array_type(new_pointer_type(Short), None) @@ -4106,14 +4106,14 @@ def test_dereference_null_ptr(): BInt = new_primitive_type("int") BIntPtr = new_pointer_type(BInt) p = cast(BIntPtr, 0) - with pytest.raises(RuntimeError): - p[0] - with pytest.raises(RuntimeError): - p[0] = 42 - with pytest.raises(RuntimeError): - p[42] - with pytest.raises(RuntimeError): - p[42] = -1 + with pytest.raises(RuntimeError): + p[0] + with pytest.raises(RuntimeError): + p[0] = 42 + with pytest.raises(RuntimeError): + p[42] + with pytest.raises(RuntimeError): + p[42] = -1 def test_mixup(): BStruct1 = new_struct_type("foo") @@ -4129,12 +4129,12 @@ def test_mixup(): pp2 = newp(BStruct2PtrPtr) pp3 = newp(BStruct3PtrPtr) pp1[0] = pp1[0] - with pytest.raises(TypeError) as e: - pp3[0] = pp1[0] + with pytest.raises(TypeError) as e: + pp3[0] = pp1[0] assert str(e.value).startswith("initializer for ctype 'bar *' must be a ") assert str(e.value).endswith(", not cdata 'foo *'") - with pytest.raises(TypeError) as e: - pp2[0] = pp1[0] + with pytest.raises(TypeError) as e: + pp2[0] = pp1[0] assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to " "be 'foo *', but the types are different (check " "that you are not e.g. mixing up different ffi " @@ -4166,12 +4166,12 @@ def test_unpack(): assert unpack(p, 10) == b"abc\x00def\x00\x00\x00" assert unpack(p+1, 5) == b"bc\x00de" - for typename in ["wchar_t", "char16_t", "char32_t"]: - BWChar = new_primitive_type(typename) - BArray = new_array_type(new_pointer_type(BWChar), 10) # wchar_t[10] - p = newp(BArray, u"abc\x00def") - assert unpack(p, 10) == u"abc\x00def\x00\x00\x00" - + for typename in ["wchar_t", "char16_t", "char32_t"]: + BWChar = new_primitive_type(typename) + BArray = new_array_type(new_pointer_type(BWChar), 10) # wchar_t[10] + p = newp(BArray, u"abc\x00def") + assert unpack(p, 10) == u"abc\x00def\x00\x00\x00" + for typename, samples in [ ("uint8_t", [0, 2**8-1]), ("uint16_t", [0, 2**16-1]), @@ -4181,7 +4181,7 @@ def test_unpack(): ("int16_t", [-2**15, 2**15-1]), ("int32_t", [-2**31, 2**31-1]), ("int64_t", [-2**63, 2**63-1]), - ("_Bool", [False, True]), + ("_Bool", [False, True]), ("float", [0.0, 10.5]), ("double", [12.34, 56.78]), ]: @@ -4192,7 +4192,7 @@ def test_unpack(): assert result == samples for i in range(len(samples)): assert result[i] == p[i] and type(result[i]) is type(p[i]) - assert (type(result[i]) is bool) == (type(samples[i]) is bool) + assert (type(result[i]) is bool) == (type(samples[i]) is bool) # BInt = new_primitive_type("int") py.test.raises(TypeError, unpack, p) @@ -4252,18 +4252,18 @@ def test_cdata_dir(): def test_char_pointer_conversion(): import warnings - assert __version__.startswith("1."), ( - "the warning will be an error if we ever release cffi 2.x") + assert __version__.startswith("1."), ( + "the warning will be an error if we ever release cffi 2.x") BCharP = new_pointer_type(new_primitive_type("char")) BIntP = new_pointer_type(new_primitive_type("int")) BVoidP = new_pointer_type(new_void_type()) - BUCharP = new_pointer_type(new_primitive_type("unsigned char")) + BUCharP = new_pointer_type(new_primitive_type("unsigned char")) z1 = cast(BCharP, 0) z2 = cast(BIntP, 0) z3 = cast(BVoidP, 0) - z4 = cast(BUCharP, 0) + z4 = cast(BUCharP, 0) with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") + warnings.simplefilter("always") newp(new_pointer_type(BIntP), z1) # warn assert len(w) == 1 newp(new_pointer_type(BVoidP), z1) # fine @@ -4276,300 +4276,300 @@ def test_char_pointer_conversion(): assert len(w) == 2 newp(new_pointer_type(BIntP), z3) # fine assert len(w) == 2 - newp(new_pointer_type(BCharP), z4) # fine (ignore signedness here) - assert len(w) == 2 - newp(new_pointer_type(BUCharP), z1) # fine (ignore signedness here) - assert len(w) == 2 - newp(new_pointer_type(BUCharP), z3) # fine - assert len(w) == 2 + newp(new_pointer_type(BCharP), z4) # fine (ignore signedness here) + assert len(w) == 2 + newp(new_pointer_type(BUCharP), z1) # fine (ignore signedness here) + assert len(w) == 2 + newp(new_pointer_type(BUCharP), z3) # fine + assert len(w) == 2 # check that the warnings are associated with lines in this file assert w[1].lineno == w[0].lineno + 4 - -def test_primitive_comparison(): - def assert_eq(a, b): - assert (a == b) is True - assert (b == a) is True - assert (a != b) is False - assert (b != a) is False - assert (a < b) is False - assert (a <= b) is True - assert (a > b) is False - assert (a >= b) is True - assert (b < a) is False - assert (b <= a) is True - assert (b > a) is False - assert (b >= a) is True - assert hash(a) == hash(b) - def assert_lt(a, b, check_hash=True): - assert (a == b) is False - assert (b == a) is False - assert (a != b) is True - assert (b != a) is True - assert (a < b) is True - assert (a <= b) is True - assert (a > b) is False - assert (a >= b) is False - assert (b < a) is False - assert (b <= a) is False - assert (b > a) is True - assert (b >= a) is True - if check_hash: - assert hash(a) != hash(b) # (or at least, it is unlikely) - def assert_gt(a, b, check_hash=True): - assert_lt(b, a, check_hash) - def assert_ne(a, b): - assert (a == b) is False - assert (b == a) is False - assert (a != b) is True - assert (b != a) is True - if strict_compare: - with pytest.raises(TypeError): a < b - with pytest.raises(TypeError): a <= b - with pytest.raises(TypeError): a > b - with pytest.raises(TypeError): a >= b - with pytest.raises(TypeError): b < a - with pytest.raises(TypeError): b <= a - with pytest.raises(TypeError): b > a - with pytest.raises(TypeError): b >= a - elif a < b: - assert_lt(a, b) - else: - assert_lt(b, a) - assert_eq(5, 5) - assert_lt(3, 5) - assert_ne('5', 5) - # - t1 = new_primitive_type("char") - t2 = new_primitive_type("int") - t3 = new_primitive_type("unsigned char") - t4 = new_primitive_type("unsigned int") - t5 = new_primitive_type("float") - t6 = new_primitive_type("double") - assert_eq(cast(t1, 65), b'A') - assert_lt(cast(t1, 64), b'\x99') - assert_gt(cast(t1, 200), b'A') - assert_ne(cast(t1, 65), 65) - assert_eq(cast(t2, -25), -25) - assert_lt(cast(t2, -25), -24) - assert_gt(cast(t2, -25), -26) - assert_eq(cast(t3, 65), 65) - assert_ne(cast(t3, 65), b'A') - assert_ne(cast(t3, 65), cast(t1, 65)) - assert_gt(cast(t4, -1), -1, check_hash=False) - assert_gt(cast(t4, -1), cast(t2, -1), check_hash=False) - assert_gt(cast(t4, -1), 99999) - assert_eq(cast(t4, -1), 256 ** size_of_int() - 1) - assert_eq(cast(t5, 3.0), 3) - assert_eq(cast(t5, 3.5), 3.5) - assert_lt(cast(t5, 3.3), 3.3) # imperfect rounding - assert_eq(cast(t6, 3.3), 3.3) - assert_eq(cast(t5, 3.5), cast(t6, 3.5)) - assert_lt(cast(t5, 3.1), cast(t6, 3.1)) # imperfect rounding - assert_eq(cast(t5, 7.0), cast(t3, 7)) - assert_lt(cast(t5, 3.1), 3.101) - assert_gt(cast(t5, 3.1), 3) - -def test_explicit_release_new(): - # release() on a ffi.new() object has no effect on CPython, but - # really releases memory on PyPy. We can't test that effect - # though, because a released cdata is not marked. - BIntP = new_pointer_type(new_primitive_type("int")) - p = newp(BIntP) - p[0] = 42 - with pytest.raises(IndexError): - p[1] - release(p) - # here, reading p[0] might give garbage or segfault... - release(p) # no effect - # - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('p', BIntP, -1)]) - pstruct = newp(BStructP) - assert pstruct.p == cast(BIntP, 0) - release(pstruct) - # here, reading pstruct.p might give garbage or segfault... - release(pstruct) # no effect - -def test_explicit_release_new_contextmgr(): - BIntP = new_pointer_type(new_primitive_type("int")) - with newp(BIntP) as p: - p[0] = 42 - assert p[0] == 42 - # here, reading p[0] might give garbage or segfault... - release(p) # no effect - -def test_explicit_release_badtype(): - BIntP = new_pointer_type(new_primitive_type("int")) - p = cast(BIntP, 12345) - py.test.raises(ValueError, release, p) - py.test.raises(ValueError, release, p) - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('p', BIntP, -1)]) - pstruct = newp(BStructP) - py.test.raises(ValueError, release, pstruct[0]) - -def test_explicit_release_badtype_contextmgr(): - BIntP = new_pointer_type(new_primitive_type("int")) - p = cast(BIntP, 12345) - with pytest.raises(ValueError): - with p: - pass - with pytest.raises(ValueError): - with p: - pass - -def test_explicit_release_gc(): - BIntP = new_pointer_type(new_primitive_type("int")) - seen = [] - intp1 = newp(BIntP, 12345) - p1 = cast(BIntP, intp1) - p = gcp(p1, seen.append) - assert seen == [] - release(p) - assert seen == [p1] - assert p1[0] == 12345 - assert p[0] == 12345 # true so far, but might change to raise RuntimeError - release(p) # no effect - -def test_explicit_release_gc_contextmgr(): - BIntP = new_pointer_type(new_primitive_type("int")) - seen = [] - intp1 = newp(BIntP, 12345) - p1 = cast(BIntP, intp1) - p = gcp(p1, seen.append) - with p: - assert p[0] == 12345 - assert seen == [] - assert seen == [p1] - assert p1[0] == 12345 - assert p[0] == 12345 # true so far, but might change to raise RuntimeError - release(p) # no effect - -def test_explicit_release_from_buffer(): - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p = from_buffer(BCharA, a) - assert p[2] == b"z" - assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>" - release(p) - assert p[2] == b"z" # true so far, but might change to raise RuntimeError - assert repr(p) == "<cdata 'char[]' buffer RELEASED>" - release(p) # no effect - -def test_explicit_release_from_buffer_contextmgr(): - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p = from_buffer(BCharA, a) - with p: - assert p[2] == b"z" - assert p[2] == b"z" # true so far, but might change to raise RuntimeError - assert repr(p) == "<cdata 'char[]' buffer RELEASED>" - release(p) # no effect - -def test_explicit_release_bytearray_on_cpython(): - if '__pypy__' in sys.builtin_module_names: - py.test.skip("pypy's bytearray are never locked") - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - a += b't' * 10 - p = from_buffer(BCharA, a) - with pytest.raises(BufferError): - a += b'u' * 100 - release(p) - a += b'v' * 100 - release(p) # no effect - a += b'w' * 1000 - assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000) - -def test_int_doesnt_give_bool(): - BBool = new_primitive_type("_Bool") - x = int(cast(BBool, 42)) - assert type(x) is int and x == 1 - x = long(cast(BBool, 42)) - assert type(x) is long and x == 1 - with pytest.raises(TypeError): - float(cast(BBool, 42)) - with pytest.raises(TypeError): - complex(cast(BBool, 42)) - -def test_cannot_call_null_function_pointer(): - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt, BInt), BInt, False) - f = cast(BFunc, 0) - with pytest.raises(RuntimeError): - f(40, 2) - -def test_huge_structure(): - BChar = new_primitive_type("char") - BArray = new_array_type(new_pointer_type(BChar), sys.maxsize) - assert sizeof(BArray) == sys.maxsize - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BArray, -1)]) - assert sizeof(BStruct) == sys.maxsize - -def test_get_types(): - import _cffi_backend - CData, CType = _get_types() - assert CData is _cffi_backend._CDataBase - assert CType is _cffi_backend.CType - -def test_type_available_with_correct_names(): - import _cffi_backend - check_names = [ - 'CType', - 'CField', - 'CLibrary', - '_CDataBase', - 'FFI', - 'Lib', - 'buffer', - ] - if '__pypy__' in sys.builtin_module_names: - check_names += [ - '__CData_iterator', - '__FFIGlobSupport', - '__FFIAllocator', - '__FFIFunctionWrapper', - ] - else: - check_names += [ - '__CDataOwn', - '__CDataOwnGC', - '__CDataFromBuf', - '__CDataGCP', - '__CData_iterator', - '__FFIGlobSupport', - ] - for name in check_names: - tp = getattr(_cffi_backend, name) - assert isinstance(tp, type) - assert (tp.__module__, tp.__name__) == ('_cffi_backend', name) - -def test_unaligned_types(): - BByteArray = new_array_type( - new_pointer_type(new_primitive_type("unsigned char")), None) - pbuf = newp(BByteArray, 40) - buf = buffer(pbuf) - # - for name in ['short', 'int', 'long', 'long long', 'float', 'double', - 'float _Complex', 'double _Complex']: - p = new_primitive_type(name) - if name.endswith(' _Complex'): - num = cast(p, 1.23 - 4.56j) - else: - num = cast(p, 0x0123456789abcdef) - size = sizeof(p) - buf[0:40] = b"\x00" * 40 - pbuf1 = cast(new_pointer_type(p), pbuf + 1) - pbuf1[0] = num - assert pbuf1[0] == num - assert buf[0] == b'\x00' - assert buf[1 + size] == b'\x00' + +def test_primitive_comparison(): + def assert_eq(a, b): + assert (a == b) is True + assert (b == a) is True + assert (a != b) is False + assert (b != a) is False + assert (a < b) is False + assert (a <= b) is True + assert (a > b) is False + assert (a >= b) is True + assert (b < a) is False + assert (b <= a) is True + assert (b > a) is False + assert (b >= a) is True + assert hash(a) == hash(b) + def assert_lt(a, b, check_hash=True): + assert (a == b) is False + assert (b == a) is False + assert (a != b) is True + assert (b != a) is True + assert (a < b) is True + assert (a <= b) is True + assert (a > b) is False + assert (a >= b) is False + assert (b < a) is False + assert (b <= a) is False + assert (b > a) is True + assert (b >= a) is True + if check_hash: + assert hash(a) != hash(b) # (or at least, it is unlikely) + def assert_gt(a, b, check_hash=True): + assert_lt(b, a, check_hash) + def assert_ne(a, b): + assert (a == b) is False + assert (b == a) is False + assert (a != b) is True + assert (b != a) is True + if strict_compare: + with pytest.raises(TypeError): a < b + with pytest.raises(TypeError): a <= b + with pytest.raises(TypeError): a > b + with pytest.raises(TypeError): a >= b + with pytest.raises(TypeError): b < a + with pytest.raises(TypeError): b <= a + with pytest.raises(TypeError): b > a + with pytest.raises(TypeError): b >= a + elif a < b: + assert_lt(a, b) + else: + assert_lt(b, a) + assert_eq(5, 5) + assert_lt(3, 5) + assert_ne('5', 5) + # + t1 = new_primitive_type("char") + t2 = new_primitive_type("int") + t3 = new_primitive_type("unsigned char") + t4 = new_primitive_type("unsigned int") + t5 = new_primitive_type("float") + t6 = new_primitive_type("double") + assert_eq(cast(t1, 65), b'A') + assert_lt(cast(t1, 64), b'\x99') + assert_gt(cast(t1, 200), b'A') + assert_ne(cast(t1, 65), 65) + assert_eq(cast(t2, -25), -25) + assert_lt(cast(t2, -25), -24) + assert_gt(cast(t2, -25), -26) + assert_eq(cast(t3, 65), 65) + assert_ne(cast(t3, 65), b'A') + assert_ne(cast(t3, 65), cast(t1, 65)) + assert_gt(cast(t4, -1), -1, check_hash=False) + assert_gt(cast(t4, -1), cast(t2, -1), check_hash=False) + assert_gt(cast(t4, -1), 99999) + assert_eq(cast(t4, -1), 256 ** size_of_int() - 1) + assert_eq(cast(t5, 3.0), 3) + assert_eq(cast(t5, 3.5), 3.5) + assert_lt(cast(t5, 3.3), 3.3) # imperfect rounding + assert_eq(cast(t6, 3.3), 3.3) + assert_eq(cast(t5, 3.5), cast(t6, 3.5)) + assert_lt(cast(t5, 3.1), cast(t6, 3.1)) # imperfect rounding + assert_eq(cast(t5, 7.0), cast(t3, 7)) + assert_lt(cast(t5, 3.1), 3.101) + assert_gt(cast(t5, 3.1), 3) + +def test_explicit_release_new(): + # release() on a ffi.new() object has no effect on CPython, but + # really releases memory on PyPy. We can't test that effect + # though, because a released cdata is not marked. + BIntP = new_pointer_type(new_primitive_type("int")) + p = newp(BIntP) + p[0] = 42 + with pytest.raises(IndexError): + p[1] + release(p) + # here, reading p[0] might give garbage or segfault... + release(p) # no effect + # + BStruct = new_struct_type("struct foo") + BStructP = new_pointer_type(BStruct) + complete_struct_or_union(BStruct, [('p', BIntP, -1)]) + pstruct = newp(BStructP) + assert pstruct.p == cast(BIntP, 0) + release(pstruct) + # here, reading pstruct.p might give garbage or segfault... + release(pstruct) # no effect + +def test_explicit_release_new_contextmgr(): + BIntP = new_pointer_type(new_primitive_type("int")) + with newp(BIntP) as p: + p[0] = 42 + assert p[0] == 42 + # here, reading p[0] might give garbage or segfault... + release(p) # no effect + +def test_explicit_release_badtype(): + BIntP = new_pointer_type(new_primitive_type("int")) + p = cast(BIntP, 12345) + py.test.raises(ValueError, release, p) + py.test.raises(ValueError, release, p) + BStruct = new_struct_type("struct foo") + BStructP = new_pointer_type(BStruct) + complete_struct_or_union(BStruct, [('p', BIntP, -1)]) + pstruct = newp(BStructP) + py.test.raises(ValueError, release, pstruct[0]) + +def test_explicit_release_badtype_contextmgr(): + BIntP = new_pointer_type(new_primitive_type("int")) + p = cast(BIntP, 12345) + with pytest.raises(ValueError): + with p: + pass + with pytest.raises(ValueError): + with p: + pass + +def test_explicit_release_gc(): + BIntP = new_pointer_type(new_primitive_type("int")) + seen = [] + intp1 = newp(BIntP, 12345) + p1 = cast(BIntP, intp1) + p = gcp(p1, seen.append) + assert seen == [] + release(p) + assert seen == [p1] + assert p1[0] == 12345 + assert p[0] == 12345 # true so far, but might change to raise RuntimeError + release(p) # no effect + +def test_explicit_release_gc_contextmgr(): + BIntP = new_pointer_type(new_primitive_type("int")) + seen = [] + intp1 = newp(BIntP, 12345) + p1 = cast(BIntP, intp1) + p = gcp(p1, seen.append) + with p: + assert p[0] == 12345 + assert seen == [] + assert seen == [p1] + assert p1[0] == 12345 + assert p[0] == 12345 # true so far, but might change to raise RuntimeError + release(p) # no effect + +def test_explicit_release_from_buffer(): + a = bytearray(b"xyz") + BChar = new_primitive_type("char") + BCharP = new_pointer_type(BChar) + BCharA = new_array_type(BCharP, None) + p = from_buffer(BCharA, a) + assert p[2] == b"z" + assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>" + release(p) + assert p[2] == b"z" # true so far, but might change to raise RuntimeError + assert repr(p) == "<cdata 'char[]' buffer RELEASED>" + release(p) # no effect + +def test_explicit_release_from_buffer_contextmgr(): + a = bytearray(b"xyz") + BChar = new_primitive_type("char") + BCharP = new_pointer_type(BChar) + BCharA = new_array_type(BCharP, None) + p = from_buffer(BCharA, a) + with p: + assert p[2] == b"z" + assert p[2] == b"z" # true so far, but might change to raise RuntimeError + assert repr(p) == "<cdata 'char[]' buffer RELEASED>" + release(p) # no effect + +def test_explicit_release_bytearray_on_cpython(): + if '__pypy__' in sys.builtin_module_names: + py.test.skip("pypy's bytearray are never locked") + a = bytearray(b"xyz") + BChar = new_primitive_type("char") + BCharP = new_pointer_type(BChar) + BCharA = new_array_type(BCharP, None) + a += b't' * 10 + p = from_buffer(BCharA, a) + with pytest.raises(BufferError): + a += b'u' * 100 + release(p) + a += b'v' * 100 + release(p) # no effect + a += b'w' * 1000 + assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000) + +def test_int_doesnt_give_bool(): + BBool = new_primitive_type("_Bool") + x = int(cast(BBool, 42)) + assert type(x) is int and x == 1 + x = long(cast(BBool, 42)) + assert type(x) is long and x == 1 + with pytest.raises(TypeError): + float(cast(BBool, 42)) + with pytest.raises(TypeError): + complex(cast(BBool, 42)) + +def test_cannot_call_null_function_pointer(): + BInt = new_primitive_type("int") + BFunc = new_function_type((BInt, BInt), BInt, False) + f = cast(BFunc, 0) + with pytest.raises(RuntimeError): + f(40, 2) + +def test_huge_structure(): + BChar = new_primitive_type("char") + BArray = new_array_type(new_pointer_type(BChar), sys.maxsize) + assert sizeof(BArray) == sys.maxsize + BStruct = new_struct_type("struct foo") + complete_struct_or_union(BStruct, [('a1', BArray, -1)]) + assert sizeof(BStruct) == sys.maxsize + +def test_get_types(): + import _cffi_backend + CData, CType = _get_types() + assert CData is _cffi_backend._CDataBase + assert CType is _cffi_backend.CType + +def test_type_available_with_correct_names(): + import _cffi_backend + check_names = [ + 'CType', + 'CField', + 'CLibrary', + '_CDataBase', + 'FFI', + 'Lib', + 'buffer', + ] + if '__pypy__' in sys.builtin_module_names: + check_names += [ + '__CData_iterator', + '__FFIGlobSupport', + '__FFIAllocator', + '__FFIFunctionWrapper', + ] + else: + check_names += [ + '__CDataOwn', + '__CDataOwnGC', + '__CDataFromBuf', + '__CDataGCP', + '__CData_iterator', + '__FFIGlobSupport', + ] + for name in check_names: + tp = getattr(_cffi_backend, name) + assert isinstance(tp, type) + assert (tp.__module__, tp.__name__) == ('_cffi_backend', name) + +def test_unaligned_types(): + BByteArray = new_array_type( + new_pointer_type(new_primitive_type("unsigned char")), None) + pbuf = newp(BByteArray, 40) + buf = buffer(pbuf) + # + for name in ['short', 'int', 'long', 'long long', 'float', 'double', + 'float _Complex', 'double _Complex']: + p = new_primitive_type(name) + if name.endswith(' _Complex'): + num = cast(p, 1.23 - 4.56j) + else: + num = cast(p, 0x0123456789abcdef) + size = sizeof(p) + buf[0:40] = b"\x00" * 40 + pbuf1 = cast(new_pointer_type(p), pbuf + 1) + pbuf1[0] = num + assert pbuf1[0] == num + assert buf[0] == b'\x00' + assert buf[1 + size] == b'\x00' diff --git a/contrib/python/cffi/c/wchar_helper.h b/contrib/python/cffi/c/wchar_helper.h index 399b55130bc..57c1b2a2bff 100644 --- a/contrib/python/cffi/c/wchar_helper.h +++ b/contrib/python/cffi/c/wchar_helper.h @@ -2,27 +2,27 @@ * wchar_t helpers */ -typedef uint16_t cffi_char16_t; -typedef uint32_t cffi_char32_t; +typedef uint16_t cffi_char16_t; +typedef uint32_t cffi_char32_t; -#if Py_UNICODE_SIZE == 2 +#if Py_UNICODE_SIZE == 2 /* Before Python 2.7, PyUnicode_FromWideChar is not able to convert wchar_t values greater than 65535 into two-unicode-characters surrogates. But even the Python 2.7 version doesn't detect wchar_t values that are out of range(1114112), and just returns nonsense. - - From cffi 1.11 we can't use it anyway, because we need a version - with char32_t input types. + + From cffi 1.11 we can't use it anyway, because we need a version + with char32_t input types. */ static PyObject * -_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) +_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) { PyObject *unicode; Py_ssize_t i; Py_ssize_t alloc; - const cffi_char32_t *orig_w; + const cffi_char32_t *orig_w; alloc = size; orig_w = w; @@ -41,11 +41,11 @@ _my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) Py_UNICODE *u; u = PyUnicode_AS_UNICODE(unicode); for (i = size; i > 0; i--) { - if (*w > 0xFFFF) { - cffi_char32_t ordinal; - if (*w > 0x10FFFF) { + if (*w > 0xFFFF) { + cffi_char32_t ordinal; + if (*w > 0x10FFFF) { PyErr_Format(PyExc_ValueError, - "char32_t out of range for " + "char32_t out of range for " "conversion to unicode: 0x%x", (int)*w); Py_DECREF(unicode); return NULL; @@ -62,56 +62,56 @@ _my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) return unicode; } -static PyObject * -_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) -{ - return PyUnicode_FromUnicode((const Py_UNICODE *)w, size); -} - -#else /* Py_UNICODE_SIZE == 4 */ - -static PyObject * -_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) -{ - return PyUnicode_FromUnicode((const Py_UNICODE *)w, size); -} - -static PyObject * -_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) -{ - /* 'size' is the length of the 'w' array */ - PyObject *result = PyUnicode_FromUnicode(NULL, size); - - if (result != NULL) { - Py_UNICODE *u_base = PyUnicode_AS_UNICODE(result); - Py_UNICODE *u = u_base; - - if (size == 1) { /* performance only */ - *u = (cffi_char32_t)*w; - } - else { - while (size > 0) { - cffi_char32_t ch = *w++; - size--; - if (0xD800 <= ch && ch <= 0xDBFF && size > 0) { - cffi_char32_t ch2 = *w; - if (0xDC00 <= ch2 && ch2 <= 0xDFFF) { - ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000; - w++; - size--; - } - } - *u++ = ch; - } - if (PyUnicode_Resize(&result, u - u_base) < 0) { - Py_DECREF(result); - return NULL; - } - } - } - return result; -} - +static PyObject * +_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) +{ + return PyUnicode_FromUnicode((const Py_UNICODE *)w, size); +} + +#else /* Py_UNICODE_SIZE == 4 */ + +static PyObject * +_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) +{ + return PyUnicode_FromUnicode((const Py_UNICODE *)w, size); +} + +static PyObject * +_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) +{ + /* 'size' is the length of the 'w' array */ + PyObject *result = PyUnicode_FromUnicode(NULL, size); + + if (result != NULL) { + Py_UNICODE *u_base = PyUnicode_AS_UNICODE(result); + Py_UNICODE *u = u_base; + + if (size == 1) { /* performance only */ + *u = (cffi_char32_t)*w; + } + else { + while (size > 0) { + cffi_char32_t ch = *w++; + size--; + if (0xD800 <= ch && ch <= 0xDBFF && size > 0) { + cffi_char32_t ch2 = *w; + if (0xDC00 <= ch2 && ch2 <= 0xDFFF) { + ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000; + w++; + size--; + } + } + *u++ = ch; + } + if (PyUnicode_Resize(&result, u - u_base) < 0) { + Py_DECREF(result); + return NULL; + } + } + } + return result; +} + #endif @@ -120,73 +120,73 @@ _my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) #define AS_SURROGATE(u) (0x10000 + (((u)[0] - 0xD800) << 10) + \ ((u)[1] - 0xDC00)) -static int -_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result, - char *err_got) -{ - Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); - if (PyUnicode_GET_SIZE(unicode) != 1) { - sprintf(err_got, "unicode string of length %zd", - PyUnicode_GET_SIZE(unicode)); - return -1; - } -#if Py_UNICODE_SIZE == 4 - if (((unsigned int)u[0]) > 0xFFFF) - { - sprintf(err_got, "larger-than-0xFFFF character"); - return -1; - } -#endif - *result = (cffi_char16_t)u[0]; - return 0; -} - -static int -_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result, - char *err_got) +static int +_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result, + char *err_got) { Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); + if (PyUnicode_GET_SIZE(unicode) != 1) { + sprintf(err_got, "unicode string of length %zd", + PyUnicode_GET_SIZE(unicode)); + return -1; + } +#if Py_UNICODE_SIZE == 4 + if (((unsigned int)u[0]) > 0xFFFF) + { + sprintf(err_got, "larger-than-0xFFFF character"); + return -1; + } +#endif + *result = (cffi_char16_t)u[0]; + return 0; +} + +static int +_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result, + char *err_got) +{ + Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); if (PyUnicode_GET_SIZE(unicode) == 1) { - *result = (cffi_char32_t)u[0]; + *result = (cffi_char32_t)u[0]; return 0; } -#if Py_UNICODE_SIZE == 2 +#if Py_UNICODE_SIZE == 2 if (PyUnicode_GET_SIZE(unicode) == 2 && IS_SURROGATE(u)) { *result = AS_SURROGATE(u); return 0; } #endif - sprintf(err_got, "unicode string of length %zd", - PyUnicode_GET_SIZE(unicode)); + sprintf(err_got, "unicode string of length %zd", + PyUnicode_GET_SIZE(unicode)); return -1; } -static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode) -{ - Py_ssize_t length = PyUnicode_GET_SIZE(unicode); - Py_ssize_t result = length; - -#if Py_UNICODE_SIZE == 4 - Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); - Py_ssize_t i; - - for (i=0; i<length; i++) { - if (u[i] > 0xFFFF) - result++; - } -#endif - return result; -} - -static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode) +static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode) { Py_ssize_t length = PyUnicode_GET_SIZE(unicode); Py_ssize_t result = length; -#if Py_UNICODE_SIZE == 2 +#if Py_UNICODE_SIZE == 4 Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); Py_ssize_t i; + for (i=0; i<length; i++) { + if (u[i] > 0xFFFF) + result++; + } +#endif + return result; +} + +static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode) +{ + Py_ssize_t length = PyUnicode_GET_SIZE(unicode); + Py_ssize_t result = length; + +#if Py_UNICODE_SIZE == 2 + Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); + Py_ssize_t i; + for (i=0; i<length-1; i++) { if (IS_SURROGATE(u+i)) result--; @@ -195,45 +195,45 @@ static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode) return result; } -static int _my_PyUnicode_AsChar16(PyObject *unicode, - cffi_char16_t *result, - Py_ssize_t resultlen) -{ - Py_ssize_t len = PyUnicode_GET_SIZE(unicode); - Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); - Py_ssize_t i; - for (i=0; i<len; i++) { -#if Py_UNICODE_SIZE == 2 - cffi_char16_t ordinal = u[i]; -#else - cffi_char32_t ordinal = u[i]; - if (ordinal > 0xFFFF) { - if (ordinal > 0x10FFFF) { - PyErr_Format(PyExc_ValueError, - "unicode character out of range for " - "conversion to char16_t: 0x%x", (int)ordinal); - return -1; - } - ordinal -= 0x10000; - *result++ = 0xD800 | (ordinal >> 10); - *result++ = 0xDC00 | (ordinal & 0x3FF); - continue; - } -#endif - *result++ = ordinal; - } - return 0; -} - -static int _my_PyUnicode_AsChar32(PyObject *unicode, - cffi_char32_t *result, - Py_ssize_t resultlen) +static int _my_PyUnicode_AsChar16(PyObject *unicode, + cffi_char16_t *result, + Py_ssize_t resultlen) { + Py_ssize_t len = PyUnicode_GET_SIZE(unicode); Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); Py_ssize_t i; + for (i=0; i<len; i++) { +#if Py_UNICODE_SIZE == 2 + cffi_char16_t ordinal = u[i]; +#else + cffi_char32_t ordinal = u[i]; + if (ordinal > 0xFFFF) { + if (ordinal > 0x10FFFF) { + PyErr_Format(PyExc_ValueError, + "unicode character out of range for " + "conversion to char16_t: 0x%x", (int)ordinal); + return -1; + } + ordinal -= 0x10000; + *result++ = 0xD800 | (ordinal >> 10); + *result++ = 0xDC00 | (ordinal & 0x3FF); + continue; + } +#endif + *result++ = ordinal; + } + return 0; +} + +static int _my_PyUnicode_AsChar32(PyObject *unicode, + cffi_char32_t *result, + Py_ssize_t resultlen) +{ + Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode); + Py_ssize_t i; for (i=0; i<resultlen; i++) { - cffi_char32_t ordinal = *u; -#if Py_UNICODE_SIZE == 2 + cffi_char32_t ordinal = *u; +#if Py_UNICODE_SIZE == 2 if (IS_SURROGATE(u)) { ordinal = AS_SURROGATE(u); u++; @@ -242,5 +242,5 @@ static int _my_PyUnicode_AsChar32(PyObject *unicode, result[i] = ordinal; u++; } - return 0; + return 0; } diff --git a/contrib/python/cffi/c/wchar_helper_3.h b/contrib/python/cffi/c/wchar_helper_3.h index f15464ef609..cfcfeede296 100644 --- a/contrib/python/cffi/c/wchar_helper_3.h +++ b/contrib/python/cffi/c/wchar_helper_3.h @@ -1,149 +1,149 @@ -/* - * wchar_t helpers, version CPython >= 3.3. - * - * CPython 3.3 added support for sys.maxunicode == 0x10FFFF on all - * platforms, even ones with wchar_t limited to 2 bytes. As such, - * this code here works from the outside like wchar_helper.h in the - * case Py_UNICODE_SIZE == 4, but the implementation is very different. - */ - -typedef uint16_t cffi_char16_t; -typedef uint32_t cffi_char32_t; - - -static PyObject * -_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) -{ - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, w, size); -} - -static PyObject * -_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) -{ - /* are there any surrogate pairs, and if so, how many? */ - Py_ssize_t i, count_surrogates = 0; - for (i = 0; i < size - 1; i++) { - if (0xD800 <= w[i] && w[i] <= 0xDBFF && - 0xDC00 <= w[i+1] && w[i+1] <= 0xDFFF) - count_surrogates++; - } - if (count_surrogates == 0) { - /* no, fast path */ - return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, w, size); - } - else - { - PyObject *result = PyUnicode_New(size - count_surrogates, 0x10FFFF); - Py_UCS4 *data; - assert(PyUnicode_KIND(result) == PyUnicode_4BYTE_KIND); - data = PyUnicode_4BYTE_DATA(result); - - for (i = 0; i < size; i++) - { - cffi_char32_t ch = w[i]; - if (0xD800 <= ch && ch <= 0xDBFF && i < size - 1) { - cffi_char32_t ch2 = w[i + 1]; - if (0xDC00 <= ch2 && ch2 <= 0xDFFF) { - ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000; - i++; - } - } - *data++ = ch; - } - return result; - } -} - -static int -_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result, - char *err_got) -{ - cffi_char32_t ch; - if (PyUnicode_GET_LENGTH(unicode) != 1) { - sprintf(err_got, "unicode string of length %zd", - PyUnicode_GET_LENGTH(unicode)); - return -1; - } - ch = PyUnicode_READ_CHAR(unicode, 0); - - if (ch > 0xFFFF) - { - sprintf(err_got, "larger-than-0xFFFF character"); - return -1; - } - *result = (cffi_char16_t)ch; - return 0; -} - -static int -_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result, - char *err_got) -{ - if (PyUnicode_GET_LENGTH(unicode) != 1) { - sprintf(err_got, "unicode string of length %zd", - PyUnicode_GET_LENGTH(unicode)); - return -1; - } - *result = PyUnicode_READ_CHAR(unicode, 0); - return 0; -} - -static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode) -{ - Py_ssize_t length = PyUnicode_GET_LENGTH(unicode); - Py_ssize_t result = length; - unsigned int kind = PyUnicode_KIND(unicode); - - if (kind == PyUnicode_4BYTE_KIND) - { - Py_UCS4 *data = PyUnicode_4BYTE_DATA(unicode); - Py_ssize_t i; - for (i = 0; i < length; i++) { - if (data[i] > 0xFFFF) - result++; - } - } - return result; -} - -static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode) -{ - return PyUnicode_GET_LENGTH(unicode); -} - -static int _my_PyUnicode_AsChar16(PyObject *unicode, - cffi_char16_t *result, - Py_ssize_t resultlen) -{ - Py_ssize_t len = PyUnicode_GET_LENGTH(unicode); - unsigned int kind = PyUnicode_KIND(unicode); - void *data = PyUnicode_DATA(unicode); - Py_ssize_t i; - - for (i = 0; i < len; i++) { - cffi_char32_t ordinal = PyUnicode_READ(kind, data, i); - if (ordinal > 0xFFFF) { - if (ordinal > 0x10FFFF) { - PyErr_Format(PyExc_ValueError, - "unicode character out of range for " - "conversion to char16_t: 0x%x", (int)ordinal); - return -1; - } - ordinal -= 0x10000; - *result++ = 0xD800 | (ordinal >> 10); - *result++ = 0xDC00 | (ordinal & 0x3FF); - } - else - *result++ = ordinal; - } - return 0; -} - -static int _my_PyUnicode_AsChar32(PyObject *unicode, - cffi_char32_t *result, - Py_ssize_t resultlen) -{ - if (PyUnicode_AsUCS4(unicode, (Py_UCS4 *)result, resultlen, 0) == NULL) - return -1; - return 0; -} +/* + * wchar_t helpers, version CPython >= 3.3. + * + * CPython 3.3 added support for sys.maxunicode == 0x10FFFF on all + * platforms, even ones with wchar_t limited to 2 bytes. As such, + * this code here works from the outside like wchar_helper.h in the + * case Py_UNICODE_SIZE == 4, but the implementation is very different. + */ + +typedef uint16_t cffi_char16_t; +typedef uint32_t cffi_char32_t; + + +static PyObject * +_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size) +{ + return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, w, size); +} + +static PyObject * +_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size) +{ + /* are there any surrogate pairs, and if so, how many? */ + Py_ssize_t i, count_surrogates = 0; + for (i = 0; i < size - 1; i++) { + if (0xD800 <= w[i] && w[i] <= 0xDBFF && + 0xDC00 <= w[i+1] && w[i+1] <= 0xDFFF) + count_surrogates++; + } + if (count_surrogates == 0) { + /* no, fast path */ + return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, w, size); + } + else + { + PyObject *result = PyUnicode_New(size - count_surrogates, 0x10FFFF); + Py_UCS4 *data; + assert(PyUnicode_KIND(result) == PyUnicode_4BYTE_KIND); + data = PyUnicode_4BYTE_DATA(result); + + for (i = 0; i < size; i++) + { + cffi_char32_t ch = w[i]; + if (0xD800 <= ch && ch <= 0xDBFF && i < size - 1) { + cffi_char32_t ch2 = w[i + 1]; + if (0xDC00 <= ch2 && ch2 <= 0xDFFF) { + ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000; + i++; + } + } + *data++ = ch; + } + return result; + } +} + +static int +_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result, + char *err_got) +{ + cffi_char32_t ch; + if (PyUnicode_GET_LENGTH(unicode) != 1) { + sprintf(err_got, "unicode string of length %zd", + PyUnicode_GET_LENGTH(unicode)); + return -1; + } + ch = PyUnicode_READ_CHAR(unicode, 0); + + if (ch > 0xFFFF) + { + sprintf(err_got, "larger-than-0xFFFF character"); + return -1; + } + *result = (cffi_char16_t)ch; + return 0; +} + +static int +_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result, + char *err_got) +{ + if (PyUnicode_GET_LENGTH(unicode) != 1) { + sprintf(err_got, "unicode string of length %zd", + PyUnicode_GET_LENGTH(unicode)); + return -1; + } + *result = PyUnicode_READ_CHAR(unicode, 0); + return 0; +} + +static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode) +{ + Py_ssize_t length = PyUnicode_GET_LENGTH(unicode); + Py_ssize_t result = length; + unsigned int kind = PyUnicode_KIND(unicode); + + if (kind == PyUnicode_4BYTE_KIND) + { + Py_UCS4 *data = PyUnicode_4BYTE_DATA(unicode); + Py_ssize_t i; + for (i = 0; i < length; i++) { + if (data[i] > 0xFFFF) + result++; + } + } + return result; +} + +static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode) +{ + return PyUnicode_GET_LENGTH(unicode); +} + +static int _my_PyUnicode_AsChar16(PyObject *unicode, + cffi_char16_t *result, + Py_ssize_t resultlen) +{ + Py_ssize_t len = PyUnicode_GET_LENGTH(unicode); + unsigned int kind = PyUnicode_KIND(unicode); + void *data = PyUnicode_DATA(unicode); + Py_ssize_t i; + + for (i = 0; i < len; i++) { + cffi_char32_t ordinal = PyUnicode_READ(kind, data, i); + if (ordinal > 0xFFFF) { + if (ordinal > 0x10FFFF) { + PyErr_Format(PyExc_ValueError, + "unicode character out of range for " + "conversion to char16_t: 0x%x", (int)ordinal); + return -1; + } + ordinal -= 0x10000; + *result++ = 0xD800 | (ordinal >> 10); + *result++ = 0xDC00 | (ordinal & 0x3FF); + } + else + *result++ = ordinal; + } + return 0; +} + +static int _my_PyUnicode_AsChar32(PyObject *unicode, + cffi_char32_t *result, + Py_ssize_t resultlen) +{ + if (PyUnicode_AsUCS4(unicode, (Py_UCS4 *)result, resultlen, 0) == NULL) + return -1; + return 0; +} |