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