From 287b5d83bd92aeea84b5c1662e11656d61d423c2 Mon Sep 17 00:00:00 2001 From: Dag Sverre Seljebotn Date: Thu, 27 Nov 2008 21:04:17 +0100 Subject: [PATCH] One shouldn't have to maintain manual recursion stacks in this day and age... --- Cython/Includes/numpy.pxd | 100 ++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/Cython/Includes/numpy.pxd b/Cython/Includes/numpy.pxd index ca840dc5..d351a3c0 100644 --- a/Cython/Includes/numpy.pxd +++ b/Cython/Includes/numpy.pxd @@ -132,58 +132,9 @@ cdef extern from "numpy/arrayobject.h": return else: info.format = stdlib.malloc(255) # static size - f = info.format - stack = [iter(descr.fields.iteritems())] - - while True: - iterator = stack[-1] - descr = None - while descr is None: - try: - descr = iterator.next()[1][0] - except StopIteration: - stack.pop() - if len(stack) > 0: - f[0] = 125 #"}" - f += 1 - iterator = stack[-1] - else: - f[0] = 0 # Terminate string! - return - - hasfields = PyDataType_HASFIELDS(descr) - if not hasfields: - t = descr.type_num - if f - info.format > 240: # this should leave room for "T{" and "}" as well - raise RuntimeError("Format string allocated too short.") - - # Until ticket #99 is fixed, use integers to avoid warnings - if t == NPY_BYTE: f[0] = 98 #"b" - elif t == NPY_UBYTE: f[0] = 66 #"B" - elif t == NPY_SHORT: f[0] = 104 #"h" - elif t == NPY_USHORT: f[0] = 72 #"H" - elif t == NPY_INT: f[0] = 105 #"i" - elif t == NPY_UINT: f[0] = 73 #"I" - elif t == NPY_LONG: f[0] = 108 #"l" - elif t == NPY_ULONG: f[0] = 76 #"L" - elif t == NPY_LONGLONG: f[0] = 113 #"q" - elif t == NPY_ULONGLONG: f[0] = 81 #"Q" - elif t == NPY_FLOAT: f[0] = 102 #"f" - elif t == NPY_DOUBLE: f[0] = 100 #"d" - elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" - elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 - elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 - elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 - elif t == NPY_OBJECT: f[0] = 79 #"O" - else: - raise ValueError("unknown dtype code in numpy.pxd (%d)" % t) - f += 1 - else: - f[0] = 84 #"T" - f[1] = 123 #"{" - f += 2 - stack.append(iter(descr.fields.iteritems())) - + f = _util_dtypestring(descr, info.format, info.format + 255) + f[0] = 0 # Terminate format string + def __releasebuffer__(ndarray self, Py_buffer* info): if PyArray_HASFIELDS(self): stdlib.free(info.format) @@ -292,3 +243,48 @@ ctypedef npy_longdouble longdouble_t ctypedef npy_cfloat cfloat_t ctypedef npy_cdouble cdouble_t ctypedef npy_clongdouble clongdouble_t + + +cdef inline char* _util_dtypestring(dtype descr, char* f, char* end) except NULL: + # Recursive utility function used in __getbuffer__ to get format + # string. The new location in the format string is returned. + + cdef dtype child + cdef tuple i + for i in descr.fields.itervalues(): + child = i[0] + if not PyDataType_HASFIELDS(child): + t = child.type_num + if end - f < 15: # this should leave room for "T{" and "}" as well + raise RuntimeError("Format string allocated too short.") + + # Until ticket #99 is fixed, use integers to avoid warnings + if t == NPY_BYTE: f[0] = 98 #"b" + elif t == NPY_UBYTE: f[0] = 66 #"B" + elif t == NPY_SHORT: f[0] = 104 #"h" + elif t == NPY_USHORT: f[0] = 72 #"H" + elif t == NPY_INT: f[0] = 105 #"i" + elif t == NPY_UINT: f[0] = 73 #"I" + elif t == NPY_LONG: f[0] = 108 #"l" + elif t == NPY_ULONG: f[0] = 76 #"L" + elif t == NPY_LONGLONG: f[0] = 113 #"q" + elif t == NPY_ULONGLONG: f[0] = 81 #"Q" + elif t == NPY_FLOAT: f[0] = 102 #"f" + elif t == NPY_DOUBLE: f[0] = 100 #"d" + elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" + elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 + elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 + elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 + elif t == NPY_OBJECT: f[0] = 79 #"O" + else: + raise ValueError("unknown dtype code in numpy.pxd (%d)" % t) + f += 1 + else: + f[0] = 84 #"T" + f[1] = 123 #"{" + f += 2 + f = _util_dtypestring(child, f, end) + f[0] = 125 #"}" + f += 1 + return f + -- 2.26.2