Home | History | Annotate | Download | only in Utility
      1 /////////////// BufferStructDeclare.proto ///////////////
      2 
      3 /* structs for buffer access */
      4 
      5 typedef struct {
      6   Py_ssize_t shape, strides, suboffsets;
      7 } __Pyx_Buf_DimInfo;
      8 
      9 typedef struct {
     10   size_t refcount;
     11   Py_buffer pybuffer;
     12 } __Pyx_Buffer;
     13 
     14 typedef struct {
     15   __Pyx_Buffer *rcbuffer;
     16   char *data;
     17   __Pyx_Buf_DimInfo diminfo[{{max_dims}}];
     18 } __Pyx_LocalBuf_ND;
     19 
     20 /////////////// BufferIndexError.proto ///////////////
     21 static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/
     22 
     23 /////////////// BufferIndexError ///////////////
     24 static void __Pyx_RaiseBufferIndexError(int axis) {
     25   PyErr_Format(PyExc_IndexError,
     26      "Out of bounds on buffer access (axis %d)", axis);
     27 }
     28 
     29 /////////////// BufferIndexErrorNogil.proto ///////////////
     30 //@requires: BufferIndexError
     31 
     32 static void __Pyx_RaiseBufferIndexErrorNogil(int axis); /*proto*/
     33 
     34 /////////////// BufferIndexErrorNogil ///////////////
     35 static void __Pyx_RaiseBufferIndexErrorNogil(int axis) {
     36     #ifdef WITH_THREAD
     37     PyGILState_STATE gilstate = PyGILState_Ensure();
     38     #endif
     39     __Pyx_RaiseBufferIndexError(axis);
     40     #ifdef WITH_THREAD
     41     PyGILState_Release(gilstate);
     42     #endif
     43 }
     44 
     45 /////////////// BufferFallbackError.proto ///////////////
     46 static void __Pyx_RaiseBufferFallbackError(void); /*proto*/
     47 
     48 /////////////// BufferFallbackError ///////////////
     49 static void __Pyx_RaiseBufferFallbackError(void) {
     50   PyErr_SetString(PyExc_ValueError,
     51      "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!");
     52 }
     53 
     54 /////////////// BufferFormatStructs.proto ///////////////
     55 
     56 #define IS_UNSIGNED(type) (((type) -1) > 0)
     57 
     58 /* Run-time type information about structs used with buffers */
     59 struct __Pyx_StructField_;
     60 
     61 #define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
     62 
     63 typedef struct {
     64   const char* name; /* for error messages only */
     65   struct __Pyx_StructField_* fields;
     66   size_t size;     /* sizeof(type) */
     67   size_t arraysize[8]; /* length of array in each dimension */
     68   int ndim;
     69   char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject, c_H_ar */
     70   char is_unsigned;
     71   int flags;
     72 } __Pyx_TypeInfo;
     73 
     74 typedef struct __Pyx_StructField_ {
     75   __Pyx_TypeInfo* type;
     76   const char* name;
     77   size_t offset;
     78 } __Pyx_StructField;
     79 
     80 typedef struct {
     81   __Pyx_StructField* field;
     82   size_t parent_offset;
     83 } __Pyx_BufFmt_StackElem;
     84 
     85 typedef struct {
     86   __Pyx_StructField root;
     87   __Pyx_BufFmt_StackElem* head;
     88   size_t fmt_offset;
     89   size_t new_count, enc_count;
     90   size_t struct_alignment;
     91   int is_complex;
     92   char enc_type;
     93   char new_packmode;
     94   char enc_packmode;
     95   char is_valid_array;
     96 } __Pyx_BufFmt_Context;
     97 
     98 /////////////// GetAndReleaseBuffer.proto ///////////////
     99 #if PY_MAJOR_VERSION < 3
    100     static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
    101     static void __Pyx_ReleaseBuffer(Py_buffer *view);
    102 #else
    103     #define __Pyx_GetBuffer PyObject_GetBuffer
    104     #define __Pyx_ReleaseBuffer PyBuffer_Release
    105 #endif
    106 
    107 /////////////// GetAndReleaseBuffer ///////////////
    108 #if PY_MAJOR_VERSION < 3
    109 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
    110   #if PY_VERSION_HEX >= 0x02060000
    111     if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
    112   #endif
    113 
    114     {{for type_ptr, getbuffer, releasebuffer in types}}
    115       {{if getbuffer}}
    116         if (PyObject_TypeCheck(obj, {{type_ptr}})) return {{getbuffer}}(obj, view, flags);
    117       {{endif}}
    118     {{endfor}}
    119 
    120   #if PY_VERSION_HEX < 0x02060000
    121     if (obj->ob_type->tp_dict) {
    122         PyObject *getbuffer_cobj = PyObject_GetItem(
    123             obj->ob_type->tp_dict, PYIDENT("__pyx_getbuffer"));
    124         if (getbuffer_cobj) {
    125             getbufferproc func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
    126             Py_DECREF(getbuffer_cobj);
    127             if (!func)
    128                 goto fail;
    129 
    130             return func(obj, view, flags);
    131         } else {
    132             PyErr_Clear();
    133         }
    134     }
    135   #endif
    136 
    137     PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
    138 
    139 #if PY_VERSION_HEX < 0x02060000
    140 fail:
    141 #endif
    142 
    143     return -1;
    144 }
    145 
    146 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
    147     PyObject *obj = view->obj;
    148     if (!obj) return;
    149 
    150   #if PY_VERSION_HEX >= 0x02060000
    151     if (PyObject_CheckBuffer(obj)) {
    152         PyBuffer_Release(view);
    153         return;
    154     }
    155   #endif
    156 
    157     {{for type_ptr, getbuffer, releasebuffer in types}}
    158       {{if releasebuffer}}
    159         if (PyObject_TypeCheck(obj, {{type_ptr}})) { {{releasebuffer}}(obj, view); return; }
    160       {{endif}}
    161     {{endfor}}
    162 
    163   #if PY_VERSION_HEX < 0x02060000
    164     if (obj->ob_type->tp_dict) {
    165         PyObject *releasebuffer_cobj = PyObject_GetItem(
    166             obj->ob_type->tp_dict, PYIDENT("__pyx_releasebuffer"));
    167         if (releasebuffer_cobj) {
    168             releasebufferproc func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
    169             Py_DECREF(releasebuffer_cobj);
    170             if (!func)
    171                 goto fail;
    172             func(obj, view);
    173             return;
    174         } else {
    175             PyErr_Clear();
    176         }
    177     }
    178   #endif
    179 
    180     goto nofail;
    181 
    182 #if PY_VERSION_HEX < 0x02060000
    183 fail:
    184 #endif
    185     PyErr_WriteUnraisable(obj);
    186 
    187 nofail:
    188     Py_DECREF(obj);
    189     view->obj = NULL;
    190 }
    191 
    192 #endif /*  PY_MAJOR_VERSION < 3 */
    193 
    194 /////////////// BufferFormatCheck.proto ///////////////
    195 {{#
    196 
    197     Buffer format string checking
    198 
    199     Buffer type checking. Utility code for checking that acquired
    200     buffers match our assumptions. We only need to check ndim and
    201     the format string; the access mode/flags is checked by the
    202     exporter. See:
    203 
    204     http://docs.python.org/3/library/struct.html
    205     http://legacy.python.org/dev/peps/pep-3118/#additions-to-the-struct-string-syntax
    206 
    207     The alignment code is copied from _struct.c in Python.
    208 }}
    209 
    210 static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
    211     __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
    212 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
    213 
    214 /////////////// BufferFormatCheck ///////////////
    215 static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
    216   unsigned int n = 1;
    217   return *(unsigned char*)(&n) != 0;
    218 }
    219 
    220 
    221 static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
    222                               __Pyx_BufFmt_StackElem* stack,
    223                               __Pyx_TypeInfo* type) {
    224   stack[0].field = &ctx->root;
    225   stack[0].parent_offset = 0;
    226   ctx->root.type = type;
    227   ctx->root.name = "buffer dtype";
    228   ctx->root.offset = 0;
    229   ctx->head = stack;
    230   ctx->head->field = &ctx->root;
    231   ctx->fmt_offset = 0;
    232   ctx->head->parent_offset = 0;
    233   ctx->new_packmode = '@';
    234   ctx->enc_packmode = '@';
    235   ctx->new_count = 1;
    236   ctx->enc_count = 0;
    237   ctx->enc_type = 0;
    238   ctx->is_complex = 0;
    239   ctx->is_valid_array = 0;
    240   ctx->struct_alignment = 0;
    241   while (type->typegroup == 'S') {
    242     ++ctx->head;
    243     ctx->head->field = type->fields;
    244     ctx->head->parent_offset = 0;
    245     type = type->fields->type;
    246   }
    247 }
    248 
    249 static int __Pyx_BufFmt_ParseNumber(const char** ts) {
    250     int count;
    251     const char* t = *ts;
    252     if (*t < '0' || *t > '9') {
    253       return -1;
    254     } else {
    255         count = *t++ - '0';
    256         while (*t >= '0' && *t < '9') {
    257             count *= 10;
    258             count += *t++ - '0';
    259         }
    260     }
    261     *ts = t;
    262     return count;
    263 }
    264 
    265 static int __Pyx_BufFmt_ExpectNumber(const char **ts) {
    266     int number = __Pyx_BufFmt_ParseNumber(ts);
    267     if (number == -1) /* First char was not a digit */
    268         PyErr_Format(PyExc_ValueError,\
    269                      "Does not understand character buffer dtype format string ('%c')", **ts);
    270     return number;
    271 }
    272 
    273 
    274 static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
    275   PyErr_Format(PyExc_ValueError,
    276                "Unexpected format string character: '%c'", ch);
    277 }
    278 
    279 static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
    280   switch (ch) {
    281     case 'c': return "'char'";
    282     case 'b': return "'signed char'";
    283     case 'B': return "'unsigned char'";
    284     case 'h': return "'short'";
    285     case 'H': return "'unsigned short'";
    286     case 'i': return "'int'";
    287     case 'I': return "'unsigned int'";
    288     case 'l': return "'long'";
    289     case 'L': return "'unsigned long'";
    290     case 'q': return "'long long'";
    291     case 'Q': return "'unsigned long long'";
    292     case 'f': return (is_complex ? "'complex float'" : "'float'");
    293     case 'd': return (is_complex ? "'complex double'" : "'double'");
    294     case 'g': return (is_complex ? "'complex long double'" : "'long double'");
    295     case 'T': return "a struct";
    296     case 'O': return "Python object";
    297     case 'P': return "a pointer";
    298     case 's': case 'p': return "a string";
    299     case 0: return "end";
    300     default: return "unparseable format string";
    301   }
    302 }
    303 
    304 static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
    305   switch (ch) {
    306     case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    307     case 'h': case 'H': return 2;
    308     case 'i': case 'I': case 'l': case 'L': return 4;
    309     case 'q': case 'Q': return 8;
    310     case 'f': return (is_complex ? 8 : 4);
    311     case 'd': return (is_complex ? 16 : 8);
    312     case 'g': {
    313       PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g')..");
    314       return 0;
    315     }
    316     case 'O': case 'P': return sizeof(void*);
    317     default:
    318       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
    319       return 0;
    320     }
    321 }
    322 
    323 static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
    324   switch (ch) {
    325     case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    326     case 'h': case 'H': return sizeof(short);
    327     case 'i': case 'I': return sizeof(int);
    328     case 'l': case 'L': return sizeof(long);
    329     #ifdef HAVE_LONG_LONG
    330     case 'q': case 'Q': return sizeof(PY_LONG_LONG);
    331     #endif
    332     case 'f': return sizeof(float) * (is_complex ? 2 : 1);
    333     case 'd': return sizeof(double) * (is_complex ? 2 : 1);
    334     case 'g': return sizeof(long double) * (is_complex ? 2 : 1);
    335     case 'O': case 'P': return sizeof(void*);
    336     default: {
    337       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
    338       return 0;
    339     }
    340   }
    341 }
    342 
    343 typedef struct { char c; short x; } __Pyx_st_short;
    344 typedef struct { char c; int x; } __Pyx_st_int;
    345 typedef struct { char c; long x; } __Pyx_st_long;
    346 typedef struct { char c; float x; } __Pyx_st_float;
    347 typedef struct { char c; double x; } __Pyx_st_double;
    348 typedef struct { char c; long double x; } __Pyx_st_longdouble;
    349 typedef struct { char c; void *x; } __Pyx_st_void_p;
    350 #ifdef HAVE_LONG_LONG
    351 typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
    352 #endif
    353 
    354 static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) {
    355   switch (ch) {
    356     case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    357     case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
    358     case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
    359     case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
    360 #ifdef HAVE_LONG_LONG
    361     case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG);
    362 #endif
    363     case 'f': return sizeof(__Pyx_st_float) - sizeof(float);
    364     case 'd': return sizeof(__Pyx_st_double) - sizeof(double);
    365     case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double);
    366     case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*);
    367     default:
    368       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
    369       return 0;
    370     }
    371 }
    372 
    373 /* These are for computing the padding at the end of the struct to align
    374    on the first member of the struct. This will probably the same as above,
    375    but we don't have any guarantees.
    376  */
    377 typedef struct { short x; char c; } __Pyx_pad_short;
    378 typedef struct { int x; char c; } __Pyx_pad_int;
    379 typedef struct { long x; char c; } __Pyx_pad_long;
    380 typedef struct { float x; char c; } __Pyx_pad_float;
    381 typedef struct { double x; char c; } __Pyx_pad_double;
    382 typedef struct { long double x; char c; } __Pyx_pad_longdouble;
    383 typedef struct { void *x; char c; } __Pyx_pad_void_p;
    384 #ifdef HAVE_LONG_LONG
    385 typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
    386 #endif
    387 
    388 static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) {
    389   switch (ch) {
    390     case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    391     case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
    392     case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int);
    393     case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long);
    394 #ifdef HAVE_LONG_LONG
    395     case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG);
    396 #endif
    397     case 'f': return sizeof(__Pyx_pad_float) - sizeof(float);
    398     case 'd': return sizeof(__Pyx_pad_double) - sizeof(double);
    399     case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double);
    400     case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*);
    401     default:
    402       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
    403       return 0;
    404     }
    405 }
    406 
    407 static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
    408   switch (ch) {
    409     case 'c':
    410         return 'H';
    411     case 'b': case 'h': case 'i':
    412     case 'l': case 'q': case 's': case 'p':
    413         return 'I';
    414     case 'B': case 'H': case 'I': case 'L': case 'Q':
    415         return 'U';
    416     case 'f': case 'd': case 'g':
    417         return (is_complex ? 'C' : 'R');
    418     case 'O':
    419         return 'O';
    420     case 'P':
    421         return 'P';
    422     default: {
    423       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
    424       return 0;
    425     }
    426   }
    427 }
    428 
    429 
    430 static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
    431   if (ctx->head == NULL || ctx->head->field == &ctx->root) {
    432     const char* expected;
    433     const char* quote;
    434     if (ctx->head == NULL) {
    435       expected = "end";
    436       quote = "";
    437     } else {
    438       expected = ctx->head->field->type->name;
    439       quote = "'";
    440     }
    441     PyErr_Format(PyExc_ValueError,
    442                  "Buffer dtype mismatch, expected %s%s%s but got %s",
    443                  quote, expected, quote,
    444                  __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex));
    445   } else {
    446     __Pyx_StructField* field = ctx->head->field;
    447     __Pyx_StructField* parent = (ctx->head - 1)->field;
    448     PyErr_Format(PyExc_ValueError,
    449                  "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'",
    450                  field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex),
    451                  parent->type->name, field->name);
    452   }
    453 }
    454 
    455 static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
    456   char group;
    457   size_t size, offset, arraysize = 1;
    458 
    459   /* printf("processing... %s\n", ctx->head->field->type->name); */
    460 
    461   if (ctx->enc_type == 0) return 0;
    462 
    463   /* Validate array size */
    464   if (ctx->head->field->type->arraysize[0]) {
    465     int i, ndim = 0;
    466 
    467     /* handle strings ('s' and 'p') */
    468     if (ctx->enc_type == 's' || ctx->enc_type == 'p') {
    469         ctx->is_valid_array = ctx->head->field->type->ndim == 1;
    470         ndim = 1;
    471         if (ctx->enc_count != ctx->head->field->type->arraysize[0]) {
    472             PyErr_Format(PyExc_ValueError,
    473                          "Expected a dimension of size %zu, got %zu",
    474                          ctx->head->field->type->arraysize[0], ctx->enc_count);
    475             return -1;
    476         }
    477     }
    478 
    479     if (!ctx->is_valid_array) {
    480       PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d",
    481                    ctx->head->field->type->ndim, ndim);
    482       return -1;
    483     }
    484     for (i = 0; i < ctx->head->field->type->ndim; i++) {
    485       arraysize *= ctx->head->field->type->arraysize[i];
    486     }
    487     ctx->is_valid_array = 0;
    488     ctx->enc_count = 1;
    489   }
    490 
    491   group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
    492   do {
    493     __Pyx_StructField* field = ctx->head->field;
    494     __Pyx_TypeInfo* type = field->type;
    495 
    496     if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
    497       size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
    498     } else {
    499       size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex);
    500     }
    501 
    502     if (ctx->enc_packmode == '@') {
    503       size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex);
    504       size_t align_mod_offset;
    505       if (align_at == 0) return -1;
    506       align_mod_offset = ctx->fmt_offset % align_at;
    507       if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
    508 
    509       if (ctx->struct_alignment == 0)
    510           ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type,
    511                                                                  ctx->is_complex);
    512     }
    513 
    514     if (type->size != size || type->typegroup != group) {
    515       if (type->typegroup == 'C' && type->fields != NULL) {
    516         /* special case -- treat as struct rather than complex number */
    517         size_t parent_offset = ctx->head->parent_offset + field->offset;
    518         ++ctx->head;
    519         ctx->head->field = type->fields;
    520         ctx->head->parent_offset = parent_offset;
    521         continue;
    522       }
    523 
    524       if ((type->typegroup == 'H' || group == 'H') && type->size == size) {
    525           /* special case -- chars don't care about sign */
    526       } else {
    527           __Pyx_BufFmt_RaiseExpected(ctx);
    528           return -1;
    529       }
    530     }
    531 
    532     offset = ctx->head->parent_offset + field->offset;
    533     if (ctx->fmt_offset != offset) {
    534       PyErr_Format(PyExc_ValueError,
    535                    "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected",
    536                    (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
    537       return -1;
    538     }
    539 
    540     ctx->fmt_offset += size;
    541     if (arraysize)
    542       ctx->fmt_offset += (arraysize - 1) * size;
    543 
    544     --ctx->enc_count; /* Consume from buffer string */
    545 
    546     /* Done checking, move to next field, pushing or popping struct stack if needed */
    547     while (1) {
    548       if (field == &ctx->root) {
    549         ctx->head = NULL;
    550         if (ctx->enc_count != 0) {
    551           __Pyx_BufFmt_RaiseExpected(ctx);
    552           return -1;
    553         }
    554         break; /* breaks both loops as ctx->enc_count == 0 */
    555       }
    556       ctx->head->field = ++field;
    557       if (field->type == NULL) {
    558         --ctx->head;
    559         field = ctx->head->field;
    560         continue;
    561       } else if (field->type->typegroup == 'S') {
    562         size_t parent_offset = ctx->head->parent_offset + field->offset;
    563         if (field->type->fields->type == NULL) continue; /* empty struct */
    564         field = field->type->fields;
    565         ++ctx->head;
    566         ctx->head->field = field;
    567         ctx->head->parent_offset = parent_offset;
    568         break;
    569       } else {
    570         break;
    571       }
    572     }
    573   } while (ctx->enc_count);
    574   ctx->enc_type = 0;
    575   ctx->is_complex = 0;
    576   return 0;
    577 }
    578 
    579 /* Parse an array in the format string (e.g. (1,2,3)) */
    580 static CYTHON_INLINE PyObject *
    581 __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
    582 {
    583     const char *ts = *tsp;
    584     int i = 0, number;
    585     int ndim = ctx->head->field->type->ndim;
    586 ;
    587     ++ts;
    588     if (ctx->new_count != 1) {
    589         PyErr_SetString(PyExc_ValueError,
    590                         "Cannot handle repeated arrays in format string");
    591         return NULL;
    592     }
    593 
    594     /* Process the previous element */
    595     if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
    596 
    597     /* Parse all numbers in the format string */
    598     while (*ts && *ts != ')') {
    599         // ignore space characters (not using isspace() due to C/C++ problem on MacOS-X)
    600         switch (*ts) {
    601             case ' ': case '\f': case '\r': case '\n': case '\t': case '\v':  continue;
    602             default:  break;  /* not a 'break' in the loop */
    603         }
    604 
    605         number = __Pyx_BufFmt_ExpectNumber(&ts);
    606         if (number == -1) return NULL;
    607 
    608         if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i])
    609             return PyErr_Format(PyExc_ValueError,
    610                         "Expected a dimension of size %zu, got %d",
    611                         ctx->head->field->type->arraysize[i], number);
    612 
    613         if (*ts != ',' && *ts != ')')
    614             return PyErr_Format(PyExc_ValueError,
    615                                 "Expected a comma in format string, got '%c'", *ts);
    616 
    617         if (*ts == ',') ts++;
    618         i++;
    619     }
    620 
    621     if (i != ndim)
    622         return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d",
    623                             ctx->head->field->type->ndim, i);
    624 
    625     if (!*ts) {
    626         PyErr_SetString(PyExc_ValueError,
    627                         "Unexpected end of format string, expected ')'");
    628         return NULL;
    629     }
    630 
    631     ctx->is_valid_array = 1;
    632     ctx->new_count = 1;
    633     *tsp = ++ts;
    634     return Py_None;
    635 }
    636 
    637 static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
    638   int got_Z = 0;
    639 
    640   while (1) {
    641     /* puts(ts); */
    642     switch(*ts) {
    643       case 0:
    644         if (ctx->enc_type != 0 && ctx->head == NULL) {
    645           __Pyx_BufFmt_RaiseExpected(ctx);
    646           return NULL;
    647         }
    648         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
    649         if (ctx->head != NULL) {
    650           __Pyx_BufFmt_RaiseExpected(ctx);
    651           return NULL;
    652         }
    653         return ts;
    654       case ' ':
    655       case '\r':
    656       case '\n':
    657         ++ts;
    658         break;
    659       case '<':
    660         if (!__Pyx_IsLittleEndian()) {
    661           PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler");
    662           return NULL;
    663         }
    664         ctx->new_packmode = '=';
    665         ++ts;
    666         break;
    667       case '>':
    668       case '!':
    669         if (__Pyx_IsLittleEndian()) {
    670           PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler");
    671           return NULL;
    672         }
    673         ctx->new_packmode = '=';
    674         ++ts;
    675         break;
    676       case '=':
    677       case '@':
    678       case '^':
    679         ctx->new_packmode = *ts++;
    680         break;
    681       case 'T': /* substruct */
    682         {
    683           const char* ts_after_sub;
    684           size_t i, struct_count = ctx->new_count;
    685           size_t struct_alignment = ctx->struct_alignment;
    686           ctx->new_count = 1;
    687           ++ts;
    688           if (*ts != '{') {
    689             PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
    690             return NULL;
    691           }
    692           if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
    693           ctx->enc_type = 0; /* Erase processed last struct element */
    694           ctx->enc_count = 0;
    695           ctx->struct_alignment = 0;
    696           ++ts;
    697           ts_after_sub = ts;
    698           for (i = 0; i != struct_count; ++i) {
    699             ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts);
    700             if (!ts_after_sub) return NULL;
    701           }
    702           ts = ts_after_sub;
    703           if (struct_alignment) ctx->struct_alignment = struct_alignment;
    704         }
    705         break;
    706       case '}': /* end of substruct; either repeat or move on */
    707         {
    708           size_t alignment = ctx->struct_alignment;
    709           ++ts;
    710           if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
    711           ctx->enc_type = 0; /* Erase processed last struct element */
    712           if (alignment && ctx->fmt_offset % alignment) {
    713             /* Pad struct on size of the first member */
    714             ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment);
    715           }
    716         }
    717         return ts;
    718       case 'x':
    719         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
    720         ctx->fmt_offset += ctx->new_count;
    721         ctx->new_count = 1;
    722         ctx->enc_count = 0;
    723         ctx->enc_type = 0;
    724         ctx->enc_packmode = ctx->new_packmode;
    725         ++ts;
    726         break;
    727       case 'Z':
    728         got_Z = 1;
    729         ++ts;
    730         if (*ts != 'f' && *ts != 'd' && *ts != 'g') {
    731           __Pyx_BufFmt_RaiseUnexpectedChar('Z');
    732           return NULL;
    733         }
    734         /* fall through */
    735       case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
    736       case 'l': case 'L': case 'q': case 'Q':
    737       case 'f': case 'd': case 'g':
    738       case 'O': case 'p':
    739         if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
    740             ctx->enc_packmode == ctx->new_packmode) {
    741           /* Continue pooling same type */
    742           ctx->enc_count += ctx->new_count;
    743           ctx->new_count = 1;
    744           got_Z = 0;
    745           ++ts;
    746           break;
    747         }
    748         /* fall through */
    749       case 's':
    750         /* 's' or new type (cannot be added to current pool) */
    751         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
    752         ctx->enc_count = ctx->new_count;
    753         ctx->enc_packmode = ctx->new_packmode;
    754         ctx->enc_type = *ts;
    755         ctx->is_complex = got_Z;
    756         ++ts;
    757         ctx->new_count = 1;
    758         got_Z = 0;
    759         break;
    760       case ':':
    761         ++ts;
    762         while(*ts != ':') ++ts;
    763         ++ts;
    764         break;
    765       case '(':
    766         if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL;
    767         break;
    768       default:
    769         {
    770           int number = __Pyx_BufFmt_ExpectNumber(&ts);
    771           if (number == -1) return NULL;
    772           ctx->new_count = (size_t)number;
    773         }
    774     }
    775   }
    776 }
    777 
    778 static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
    779   buf->buf = NULL;
    780   buf->obj = NULL;
    781   buf->strides = __Pyx_zeros;
    782   buf->shape = __Pyx_zeros;
    783   buf->suboffsets = __Pyx_minusones;
    784 }
    785 
    786 static CYTHON_INLINE int __Pyx_GetBufferAndValidate(
    787         Py_buffer* buf, PyObject* obj,  __Pyx_TypeInfo* dtype, int flags,
    788         int nd, int cast, __Pyx_BufFmt_StackElem* stack)
    789 {
    790   if (obj == Py_None || obj == NULL) {
    791     __Pyx_ZeroBuffer(buf);
    792     return 0;
    793   }
    794   buf->buf = NULL;
    795   if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail;
    796   if (buf->ndim != nd) {
    797     PyErr_Format(PyExc_ValueError,
    798                  "Buffer has wrong number of dimensions (expected %d, got %d)",
    799                  nd, buf->ndim);
    800     goto fail;
    801   }
    802   if (!cast) {
    803     __Pyx_BufFmt_Context ctx;
    804     __Pyx_BufFmt_Init(&ctx, stack, dtype);
    805     if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
    806   }
    807   if ((unsigned)buf->itemsize != dtype->size) {
    808     PyErr_Format(PyExc_ValueError,
    809       "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)",
    810       buf->itemsize, (buf->itemsize > 1) ? "s" : "",
    811       dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : "");
    812     goto fail;
    813   }
    814   if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones;
    815   return 0;
    816 fail:;
    817   __Pyx_ZeroBuffer(buf);
    818   return -1;
    819 }
    820 
    821 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
    822   if (info->buf == NULL) return;
    823   if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
    824   __Pyx_ReleaseBuffer(info);
    825 }
    826 
    827 /////////////// TypeInfoCompare.proto ///////////////
    828 static int __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b);
    829 
    830 /////////////// TypeInfoCompare ///////////////
    831 /* See if two dtypes are equal */
    832 static int
    833 __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b)
    834 {
    835     int i;
    836 
    837     if (!a || !b)
    838         return 0;
    839 
    840     if (a == b)
    841         return 1;
    842 
    843     if (a->size != b->size || a->typegroup != b->typegroup ||
    844             a->is_unsigned != b->is_unsigned || a->ndim != b->ndim) {
    845         if (a->typegroup == 'H' || b->typegroup == 'H') {
    846             /* Special case for chars */
    847             return a->size == b->size;
    848         } else {
    849             return 0;
    850         }
    851     }
    852 
    853     if (a->ndim) {
    854         /* Verify multidimensional C arrays */
    855         for (i = 0; i < a->ndim; i++)
    856             if (a->arraysize[i] != b->arraysize[i])
    857                 return 0;
    858     }
    859 
    860     if (a->typegroup == 'S') {
    861         /* Check for packed struct */
    862         if (a->flags != b->flags)
    863             return 0;
    864 
    865         /* compare all struct fields */
    866         if (a->fields || b->fields) {
    867             /* Check if both have fields */
    868             if (!(a->fields && b->fields))
    869                 return 0;
    870 
    871             /* compare */
    872             for (i = 0; a->fields[i].type && b->fields[i].type; i++) {
    873                 __Pyx_StructField *field_a = a->fields + i;
    874                 __Pyx_StructField *field_b = b->fields + i;
    875 
    876                 if (field_a->offset != field_b->offset ||
    877                     !__pyx_typeinfo_cmp(field_a->type, field_b->type))
    878                     return 0;
    879             }
    880 
    881             /* If all fields are processed, we have a match */
    882             return !a->fields[i].type && !b->fields[i].type;
    883         }
    884     }
    885 
    886     return 1;
    887 }
    888 
    889 
    890 
    891 /////////////// TypeInfoToFormat.proto ///////////////
    892 struct __pyx_typeinfo_string {
    893     char string[3];
    894 };
    895 static struct __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *type);
    896 
    897 /////////////// TypeInfoToFormat ///////////////
    898 {{# See also MemoryView.pyx:BufferFormatFromTypeInfo }}
    899 
    900 static struct __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *type) {
    901     struct __pyx_typeinfo_string result = { {0} };
    902     char *buf = (char *) result.string;
    903     size_t size = type->size;
    904 
    905     switch (type->typegroup) {
    906         case 'H':
    907             *buf = 'c';
    908             break;
    909         case 'I':
    910         case 'U':
    911             if (size == 1)
    912                 *buf = 'b';
    913             else if (size == 2)
    914                 *buf = 'h';
    915             else if (size == 4)
    916                 *buf = 'i';
    917             else if (size == 8)
    918                 *buf = 'q';
    919 
    920             if (type->is_unsigned)
    921                 *buf = toupper(*buf);
    922             break;
    923         case 'P':
    924             *buf = 'P';
    925             break;
    926         case 'C':
    927          {
    928             __Pyx_TypeInfo complex_type = *type;
    929             complex_type.typegroup = 'R';
    930             complex_type.size /= 2;
    931 
    932             *buf++ = 'Z';
    933             *buf = __Pyx_TypeInfoToFormat(&complex_type).string[0];
    934             break;
    935          }
    936         case 'R':
    937             if (size == 4)
    938                 *buf = 'f';
    939             else if (size == 8)
    940                 *buf = 'd';
    941             else
    942                 *buf = 'g';
    943             break;
    944     }
    945 
    946     return result;
    947 }
    948