Buffer.py 41.4 KB
Newer Older
1 2 3 4 5 6 7
from Visitor import VisitorTransform, CythonTransform
from ModuleNode import ModuleNode
from Nodes import *
from ExprNodes import *
from StringEncoding import EncodedString
from Errors import CompileError
from Code import UtilityCode
8
import Interpreter
9
import PyrexTypes
10

Stefan Behnel's avatar
Stefan Behnel committed
11 12 13 14 15
try:
    set
except NameError:
    from sets import Set as set

16 17 18 19 20 21 22 23
import textwrap

def dedent(text, reindent=0):
    text = textwrap.dedent(text)
    if reindent > 0:
        indent = " " * reindent
        text = '\n'.join([indent + x for x in text.split('\n')])
    return text
24 25 26 27 28 29 30 31 32 33 34

class IntroduceBufferAuxiliaryVars(CythonTransform):

    #
    # Entry point
    #

    buffers_exists = False

    def __call__(self, node):
        assert isinstance(node, ModuleNode)
35
        self.max_ndim = 0
36 37 38
        result = super(IntroduceBufferAuxiliaryVars, self).__call__(node)
        if self.buffers_exists:
            use_py2_buffer_functions(node.scope)
39
            use_empty_bufstruct_code(node.scope, self.max_ndim)
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
        return result


    #
    # Basic operations for transforms
    #
    def handle_scope(self, node, scope):
        # For all buffers, insert extra variables in the scope.
        # The variables are also accessible from the buffer_info
        # on the buffer entry
        bufvars = [entry for name, entry
                   in scope.entries.iteritems()
                   if entry.type.is_buffer]
        if len(bufvars) > 0:
            self.buffers_exists = True


        if isinstance(node, ModuleNode) and len(bufvars) > 0:
            # for now...note that pos is wrong 
            raise CompileError(node.pos, "Buffer vars not allowed in module scope")
        for entry in bufvars:
61 62 63
            if entry.type.dtype.is_ptr:
                raise CompileError(node.pos, "Buffers with pointer types not yet supported.")
            
64 65
            name = entry.name
            buftype = entry.type
66 67
            if buftype.ndim > self.max_ndim:
                self.max_ndim = buftype.ndim
68 69 70 71 72

            # Declare auxiliary vars
            cname = scope.mangle(Naming.bufstruct_prefix, name)
            bufinfo = scope.declare_var(name="$%s" % cname, cname=cname,
                                        type=PyrexTypes.c_py_buffer_type, pos=node.pos)
73 74
            if entry.is_arg:
                bufinfo.used = True # otherwise, NameNode will mark whether it is used
75

76
            def var(prefix, idx, initval):
77 78 79 80
                cname = scope.mangle(prefix, "%d_%s" % (idx, name))
                result = scope.declare_var("$%s" % cname, PyrexTypes.c_py_ssize_t_type,
                                         node.pos, cname=cname, is_cdef=True)

81
                result.init = initval
82 83 84 85
                if entry.is_arg:
                    result.used = True
                return result
            
86

87 88
            stridevars = [var(Naming.bufstride_prefix, i, "0") for i in range(entry.type.ndim)]
            shapevars = [var(Naming.bufshape_prefix, i, "0") for i in range(entry.type.ndim)]            
89 90 91
            mode = entry.type.mode
            if mode == 'full':
                suboffsetvars = [var(Naming.bufsuboffset_prefix, i, "-1") for i in range(entry.type.ndim)]
92
            else:
93 94
                suboffsetvars = None

95
            entry.buffer_aux = Symtab.BufferAux(bufinfo, stridevars, shapevars, suboffsetvars)
96 97 98 99 100 101 102 103 104 105 106 107 108 109
            
        scope.buffer_entries = bufvars
        self.scope = scope

    def visit_ModuleNode(self, node):
        self.handle_scope(node, node.scope)
        self.visitchildren(node)
        return node

    def visit_FuncDefNode(self, node):
        self.handle_scope(node, node.local_scope)
        self.visitchildren(node)
        return node

110 111 112
#
# Analysis
#
113 114
buffer_options = ("dtype", "ndim", "mode", "negative_indices", "cast") # ordered!
buffer_defaults = {"ndim": 1, "mode": "full", "negative_indices": True, "cast": False}
115
buffer_positional_options_count = 1 # anything beyond this needs keyword argument
116 117 118 119 120

ERR_BUF_OPTION_UNKNOWN = '"%s" is not a buffer option'
ERR_BUF_TOO_MANY = 'Too many buffer options'
ERR_BUF_DUP = '"%s" buffer option already supplied'
ERR_BUF_MISSING = '"%s" missing'
121
ERR_BUF_MODE = 'Only allowed buffer modes are: "c", "fortran", "full", "strided" (as a compile-time string)'
122
ERR_BUF_NDIM = 'ndim must be a non-negative integer'
123
ERR_BUF_DTYPE = 'dtype must be "object", numeric type or a struct'
124
ERR_BUF_BOOL = '"%s" must be a boolean'
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, need_complete=True):
    """
    Must be called during type analysis, as analyse is called
    on the dtype argument.

    posargs and dictargs should consist of a list and a dict
    of tuples (value, pos). Defaults should be a dict of values.

    Returns a dict containing all the options a buffer can have and
    its value (with the positions stripped).
    """
    if defaults is None:
        defaults = buffer_defaults
    
140
    posargs, dictargs = Interpreter.interpret_compiletime_options(posargs, dictargs, type_env=env, type_args = (0,'dtype'))
141
    
142
    if len(posargs) > buffer_positional_options_count:
143 144 145
        raise CompileError(posargs[-1][1], ERR_BUF_TOO_MANY)

    options = {}
Stefan Behnel's avatar
Stefan Behnel committed
146
    for name, (value, pos) in dictargs.iteritems():
147 148
        if not name in buffer_options:
            raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name)
Stefan Behnel's avatar
Stefan Behnel committed
149 150
        options[name] = value

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    for name, (value, pos) in zip(buffer_options, posargs):
        if not name in buffer_options:
            raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name)
        if name in options:
            raise CompileError(pos, ERR_BUF_DUP % name)
        options[name] = value

    # Check that they are all there and copy defaults
    for name in buffer_options:
        if not name in options:
            try:
                options[name] = defaults[name]
            except KeyError:
                if need_complete:
                    raise CompileError(globalpos, ERR_BUF_MISSING % name)

167 168 169 170 171 172
    dtype = options.get("dtype")
    if dtype and dtype.is_extension_type:
        raise CompileError(globalpos, ERR_BUF_DTYPE)

    ndim = options.get("ndim")
    if ndim and (not isinstance(ndim, int) or ndim < 0):
173 174
        raise CompileError(globalpos, ERR_BUF_NDIM)

175
    mode = options.get("mode")
176
    if mode and not (mode in ('full', 'strided', 'c', 'fortran')):
177 178
        raise CompileError(globalpos, ERR_BUF_MODE)

179 180 181 182 183 184 185
    def assert_bool(name):
        x = options.get(name)
        if not isinstance(x, bool):
            raise CompileError(globalpos, ERR_BUF_BOOL % name)

    assert_bool('negative_indices')
    assert_bool('cast')
186

187 188 189 190 191 192
    return options
    

#
# Code generation
#
193 194


195
def get_flags(buffer_aux, buffer_type):
196
    flags = 'PyBUF_FORMAT'
197 198
    mode = buffer_type.mode
    if mode == 'full':
199
        flags += '| PyBUF_INDIRECT'
200
    elif mode == 'strided':
201
        flags += '| PyBUF_STRIDES'
202 203 204 205
    elif mode == 'c':
        flags += '| PyBUF_C_CONTIGUOUS'
    elif mode == 'fortran':
        flags += '| PyBUF_F_CONTIGUOUS'
206 207
    else:
        assert False
208 209 210
    if buffer_aux.writable_needed: flags += "| PyBUF_WRITABLE"
    return flags
        
211 212 213 214 215
def used_buffer_aux_vars(entry):
    buffer_aux = entry.buffer_aux
    buffer_aux.buffer_info_var.used = True
    for s in buffer_aux.shapevars: s.used = True
    for s in buffer_aux.stridevars: s.used = True
216 217
    if buffer_aux.suboffsetvars:
        for s in buffer_aux.suboffsetvars: s.used = True
218

219 220 221
def put_unpack_buffer_aux_into_scope(buffer_aux, mode, code):
    # Generate code to copy the needed struct info into local
    # variables.
222 223
    bufstruct = buffer_aux.buffer_info_var.cname

224 225 226 227
    varspec = [("strides", buffer_aux.stridevars),
               ("shape", buffer_aux.shapevars)]
    if mode == 'full':
        varspec.append(("suboffsets", buffer_aux.suboffsetvars))
228

229
    for field, vars in varspec:
230 231 232
        code.putln(" ".join(["%s = %s.%s[%d];" %
                             (s.cname, bufstruct, field, idx)
                             for idx, s in enumerate(vars)]))
233 234

def put_acquire_arg_buffer(entry, code, pos):
235
    code.globalstate.use_utility_code(acquire_utility_code)
236
    buffer_aux = entry.buffer_aux
237
    getbuffer = get_getbuffer_call(code, entry.cname, buffer_aux, entry.type)
238

239
    # Acquire any new buffer
240
    code.putln("{")
241
    code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % entry.type.dtype.struct_nesting_depth())
242 243
    code.putln(code.error_goto_if("%s == -1" % getbuffer, pos))
    code.putln("}")
244
    # An exception raised in arg parsing cannot be catched, so no
245
    # need to care about the buffer then.
246
    put_unpack_buffer_aux_into_scope(buffer_aux, entry.type.mode, code)
247

248 249 250
def put_release_buffer_code(code, entry):
    code.globalstate.use_utility_code(acquire_utility_code)
    code.putln("__Pyx_SafeReleaseBuffer(&%s);" % entry.buffer_aux.buffer_info_var.cname)
251

252 253 254 255 256 257 258 259 260 261 262 263
def get_getbuffer_call(code, obj_cname, buffer_aux, buffer_type):
    ndim = buffer_type.ndim
    cast = int(buffer_type.cast)
    flags = get_flags(buffer_aux, buffer_type)
    bufstruct = buffer_aux.buffer_info_var.cname

    dtype_typeinfo = get_type_information_cname(code, buffer_type.dtype)
    
    return ("__Pyx_GetBufferAndValidate(&%(bufstruct)s, "
            "(PyObject*)%(obj_cname)s, &%(dtype_typeinfo)s, %(flags)s, %(ndim)d, "
            "%(cast)d, __pyx_stack)" % locals())    

264
def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
265
                         is_initialized, pos, code):
266 267 268 269 270 271 272 273 274 275 276 277 278
    """
    Generate code for reassigning a buffer variables. This only deals with getting
    the buffer auxiliary structure and variables set up correctly, the assignment
    itself and refcounting is the responsibility of the caller.

    However, the assignment operation may throw an exception so that the reassignment
    never happens.
    
    Depending on the circumstances there are two possible outcomes:
    - Old buffer released, new acquired, rhs assigned to lhs
    - Old buffer released, new acquired which fails, reaqcuire old lhs buffer
      (which may or may not succeed).
    """
279

280
    code.globalstate.use_utility_code(acquire_utility_code)
281
    bufstruct = buffer_aux.buffer_info_var.cname
282
    flags = get_flags(buffer_aux, buffer_type)
283

284
    code.putln("{")  # Set up necesarry stack for getbuffer
285
    code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % buffer_type.dtype.struct_nesting_depth())
286 287
    
    getbuffer = get_getbuffer_call(code, "%s", buffer_aux, buffer_type) # fill in object below
288

289 290
    if is_initialized:
        # Release any existing buffer
291
        code.putln('__Pyx_SafeReleaseBuffer(&%s);' % bufstruct)
292
        # Acquire
293
        retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
294
        code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname))
Stefan Behnel's avatar
Stefan Behnel committed
295
        code.putln('if (%s) {' % (code.unlikely("%s < 0" % retcode_cname)))
296 297 298 299
        # If acquisition failed, attempt to reacquire the old buffer
        # before raising the exception. A failure of reacquisition
        # will cause the reacquisition exception to be reported, one
        # can consider working around this later.
300
        type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=False)
301 302
                           for i in range(3)]
        code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb))
Stefan Behnel's avatar
Stefan Behnel committed
303
        code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
304
        code.putln('Py_XDECREF(%s); Py_XDECREF(%s); Py_XDECREF(%s);' % (type, value, tb)) # Do not refnanny these!
305
        code.globalstate.use_utility_code(raise_buffer_fallback_code)
306
        code.putln('__Pyx_RaiseBufferFallbackError();')
307
        code.putln('} else {')
308 309
        code.putln('PyErr_Restore(%s, %s, %s);' % (type, value, tb))
        for t in (type, value, tb):
310
            code.funcstate.release_temp(t)
Stefan Behnel's avatar
Stefan Behnel committed
311 312
        code.putln('}')
        code.putln('}')
313
        # Unpack indices
314
        put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code)
315
        code.putln(code.error_goto_if_neg(retcode_cname, pos))
316
        code.funcstate.release_temp(retcode_cname)
317
    else:
318 319 320 321
        # Our entry had no previous value, so set to None when acquisition fails.
        # In this case, auxiliary vars should be set up right in initialization to a zero-buffer,
        # so it suffices to set the buf field to NULL.
        code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % rhs_cname)))
322
        code.putln('%s = %s; __Pyx_INCREF(Py_None); %s.buf = NULL;' %
323 324 325
                   (lhs_cname,
                    PyrexTypes.typecast(buffer_type, PyrexTypes.py_object_type, "Py_None"),
                    bufstruct))
326 327 328
        code.putln(code.error_goto(pos))
        code.put('} else {')
        # Unpack indices
329
        put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code)
330
        code.putln('}')
331

332
    code.putln("}") # Release stack
333

334
def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos, code):
335 336 337 338 339
    """
    Generates code to process indices and calculate an offset into
    a buffer. Returns a C string which gives a pointer which can be
    read from or written to at will (it is an expression so caller should
    store it in a temporary if it is used more than once).
340 341 342 343 344

    As the bounds checking can have any number of combinations of unsigned
    arguments, smart optimizations etc. we insert it directly in the function
    body. The lookup however is delegated to a inline function that is instantiated
    once per ndim (lookup with suboffsets tend to get quite complicated).
345

346
    """
347 348
    bufaux = entry.buffer_aux
    bufstruct = bufaux.buffer_info_var.cname
349
    negative_indices = directives['wraparound'] and entry.type.negative_indices
350

351
    if directives['boundscheck']:
352 353 354 355
        # Check bounds and fix negative indices.
        # We allocate a temporary which is initialized to -1, meaning OK (!).
        # If an error occurs, the temp is set to the dimension index the
        # error is occuring at.
356
        tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
357
        code.putln("%s = -1;" % tmp_cname)
358 359 360 361 362
        for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames,
                                                         bufaux.shapevars)):
            if signed != 0:
                # not unsigned, deal with negative index
                code.putln("if (%s < 0) {" % cname)
363 364 365 366 367 368
                if negative_indices:
                    code.putln("%s += %s;" % (cname, shape.cname))
                    code.putln("if (%s) %s = %d;" % (
                        code.unlikely("%s < 0" % cname), tmp_cname, dim))
                else:
                    code.putln("%s = %d;" % (tmp_cname, dim))
369
                code.put("} else ")
370 371 372
            # check bounds in positive direction
            code.putln("if (%s) %s = %d;" % (
                code.unlikely("%s >= %s" % (cname, shape.cname)),
373 374
                tmp_cname, dim))
        code.globalstate.use_utility_code(raise_indexerror_code)
Stefan Behnel's avatar
Stefan Behnel committed
375
        code.putln("if (%s) {" % code.unlikely("%s != -1" % tmp_cname))
376
        code.putln('__Pyx_RaiseBufferIndexError(%s);' % tmp_cname)
377
        code.putln(code.error_goto(pos))
Stefan Behnel's avatar
Stefan Behnel committed
378
        code.putln('}')
379
        code.funcstate.release_temp(tmp_cname)
380
    elif negative_indices:
381 382 383 384 385 386
        # Only fix negative indices.
        for signed, cname, shape in zip(index_signeds, index_cnames,
                                        bufaux.shapevars):
            if signed != 0:
                code.putln("if (%s < 0) %s += %s;" % (cname, cname, shape.cname))
        
387
    # Create buffer lookup and return it
388 389
    # This is done via utility macros/inline functions, which vary
    # according to the access mode used.
390
    params = []
391
    nd = entry.type.ndim
392 393
    mode = entry.type.mode
    if mode == 'full':
394 395 396 397
        for i, s, o in zip(index_cnames, bufaux.stridevars, bufaux.suboffsetvars):
            params.append(i)
            params.append(s.cname)
            params.append(o.cname)
398 399
        funcname = "__Pyx_BufPtrFull%dd" % nd
        funcgen = buf_lookup_full_code
400
    else:
401 402 403 404 405 406 407 408 409 410 411
        if mode == 'strided':
            funcname = "__Pyx_BufPtrStrided%dd" % nd
            funcgen = buf_lookup_strided_code
        elif mode == 'c':
            funcname = "__Pyx_BufPtrCContig%dd" % nd
            funcgen = buf_lookup_c_code
        elif mode == 'fortran':
            funcname = "__Pyx_BufPtrFortranContig%dd" % nd
            funcgen = buf_lookup_fortran_code
        else:
            assert False
412 413 414
        for i, s in zip(index_cnames, bufaux.stridevars):
            params.append(i)
            params.append(s.cname)
415
        
416
    # Make sure the utility code is available
417 418 419 420 421
    if funcname not in code.globalstate.utility_codes:
        code.globalstate.utility_codes.add(funcname)
        protocode = code.globalstate['utility_code_proto']
        defcode = code.globalstate['utility_code_def']
        funcgen(protocode, defcode, name=funcname, nd=nd)
422

423 424 425 426 427 428
    ptr_type = entry.type.buffer_ptr_type
    ptrcode = "%s(%s, %s.buf, %s)" % (funcname,
                                      ptr_type.declaration_code(""),
                                      bufstruct,
                                      ", ".join(params))
    return ptrcode
429

430 431 432 433 434 435

def use_empty_bufstruct_code(env, max_ndim):
    code = dedent("""
        Py_ssize_t __Pyx_zeros[] = {%s};
        Py_ssize_t __Pyx_minusones[] = {%s};
    """) % (", ".join(["0"] * max_ndim), ", ".join(["-1"] * max_ndim))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
436
    env.use_utility_code(UtilityCode(proto=code))
437

438

439
def buf_lookup_full_code(proto, defin, name, nd):
440
    """
441
    Generates a buffer lookup function for the right number
442 443
    of dimensions. The function gives back a void* at the right location.
    """
444
    # _i_ndex, _s_tride, sub_o_ffset
445 446 447 448
    macroargs = ", ".join(["i%d, s%d, o%d" % (i, i, i) for i in range(nd)])
    proto.putln("#define %s(type, buf, %s) (type)(%s_imp(buf, %s))" % (name, macroargs, name, macroargs))

    funcargs = ", ".join(["Py_ssize_t i%d, Py_ssize_t s%d, Py_ssize_t o%d" % (i, i, i) for i in range(nd)])
449
    proto.putln("static CYTHON_INLINE void* %s_imp(void* buf, %s);" % (name, funcargs))
450
    defin.putln(dedent("""
451
        static CYTHON_INLINE void* %s_imp(void* buf, %s) {
452
          char* ptr = (char*)buf;
453
        """) % (name, funcargs) + "".join([dedent("""\
454 455 456
          ptr += s%d * i%d;
          if (o%d >= 0) ptr = *((char**)ptr) + o%d; 
        """) % (i, i, i, i) for i in range(nd)]
457
        ) + "\nreturn ptr;\n}")
458

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
def buf_lookup_strided_code(proto, defin, name, nd):
    """
    Generates a buffer lookup function for the right number
    of dimensions. The function gives back a void* at the right location.
    """
    # _i_ndex, _s_tride
    args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
    offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd)])
    proto.putln("#define %s(type, buf, %s) (type)((char*)buf + %s)" % (name, args, offset))

def buf_lookup_c_code(proto, defin, name, nd):
    """
    Similar to strided lookup, but can assume that the last dimension
    doesn't need a multiplication as long as.
    Still we keep the same signature for now.
    """
    if nd == 1:
        proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name)
    else:
        args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
        offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd - 1)])
        proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, nd - 1))

def buf_lookup_fortran_code(proto, defin, name, nd):
    """
    Like C lookup, but the first index is optimized instead.
    """
    if nd == 1:
        proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name)
    else:
        args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
        offset = " + ".join(["i%d * s%d" % (i, i) for i in range(1, nd)])
        proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, 0))
492

493 494

def use_py2_buffer_functions(env):
495 496 497
    # Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2.
    # For >= 2.6 we do double mode -- use the new buffer interface on objects
    # which has the right tp_flags set, but emulation otherwise.
498 499 500

    # Search all types for __getbuffer__ overloads
    types = []
501
    visited_scopes = set()
502
    def find_buffer_types(scope):
503 504 505
        if scope in visited_scopes:
            return
        visited_scopes.add(scope)
506 507 508 509 510 511 512 513 514 515 516 517 518 519
        for m in scope.cimported_modules:
            find_buffer_types(m)
        for e in scope.type_entries:
            t = e.type
            if t.is_extension_type:
                release = get = None
                for x in t.scope.pyfunc_entries:
                    if x.name == u"__getbuffer__": get = x.func_cname
                    elif x.name == u"__releasebuffer__": release = x.func_cname
                if get:
                    types.append((t.typeptr_cname, get, release))

    find_buffer_types(env)

520
    code = dedent("""
521
        #if PY_MAJOR_VERSION < 3
522
        static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
523 524 525 526
          #if PY_VERSION_HEX >= 0x02060000
          if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER)
              return PyObject_GetBuffer(obj, view, flags);
          #endif
527
    """)
528 529 530 531 532 533
    if len(types) > 0:
        clause = "if"
        for t, get, release in types:
            code += "  %s (PyObject_TypeCheck(obj, %s)) return %s(obj, view, flags);\n" % (clause, t, get)
            clause = "else if"
        code += "  else {\n"
534 535 536 537
    code += dedent("""\
        PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
        return -1;
    """, 2)
538
    if len(types) > 0: code += "  }"
539 540
    code += dedent("""
        }
541

542 543 544
        static void __Pyx_ReleaseBuffer(Py_buffer *view) {
          PyObject* obj = view->obj;
          if (obj) {
545
    """)
546 547 548 549 550 551
    if len(types) > 0:
        clause = "if"
        for t, get, release in types:
            if release:
                code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release)
                clause = "else if"
552
    code += dedent("""
553 554 555
            Py_DECREF(obj);
            view->obj = NULL;
          }
556 557 558 559 560
        }

        #endif
    """)
                   
561 562
    env.use_utility_code(UtilityCode(
            proto = dedent("""\
563
        #if PY_MAJOR_VERSION < 3
564
        static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
565
        static void __Pyx_ReleaseBuffer(Py_buffer *view);
566 567
        #else
        #define __Pyx_GetBuffer PyObject_GetBuffer
568
        #define __Pyx_ReleaseBuffer PyBuffer_Release
569
        #endif
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
570
    """), impl = code))
571 572


573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
def mangle_dtype_name(dtype):
    # Use prefixes to seperate user defined types from builtins
    # (consider "typedef float unsigned_int")
    if dtype.is_pyobject:
        return "object"
    elif dtype.is_ptr:
        return "ptr"
    else:
        if dtype.is_typedef or dtype.is_struct_or_union:
            prefix = "nn_"
        else:
            prefix = ""
        return prefix + dtype.declaration_code("").replace(" ", "_")

def get_type_information_cname(code, dtype, maxdepth=None):
588
    # Output the run-time type information (__Pyx_TypeInfo) for given dtype,
589 590
    # and return the name of the type info struct.
    #
591 592
    # Structs with two floats of the same size are encoded as complex numbers.
    # One can seperate between complex numbers declared as struct or with native
593 594
    # encoding by inspecting to see if the fields field of the type is
    # filled in.
595 596 597
    namesuffix = mangle_dtype_name(dtype)
    name = "__Pyx_TypeInfo_%s" % namesuffix
    structinfo_name = "__Pyx_StructFields_%s" % namesuffix
598

599
    if dtype.is_error: return "<error>"
600

601 602 603
    # It's critical that walking the type info doesn't use more stack
    # depth than dtype.struct_nesting_depth() returns, so use an assertion for this
    if maxdepth is None: maxdepth = dtype.struct_nesting_depth()
604 605 606
    if maxdepth <= 0:
        assert False

607 608 609 610 611 612 613 614 615 616 617 618 619 620
    if name not in code.globalstate.utility_codes:
        code.globalstate.utility_codes.add(name)
        typecode = code.globalstate['typeinfo']
        
        complex_possible = dtype.is_struct_or_union and dtype.can_be_complex()
        
        declcode = dtype.declaration_code("")
        if dtype.is_simple_buffer_dtype():
            structinfo_name = "NULL"
        elif dtype.is_struct:
            fields = dtype.scope.var_entries
            # Must pre-call all used types in order not to recurse utility code
            # writing.
            assert len(fields) > 0
621
            types = [get_type_information_cname(code, f.type, maxdepth - 1)
622 623 624 625 626 627 628 629 630
                     for f in fields]
            typecode.putln("static __Pyx_StructField %s[] = {" % structinfo_name, safe=True)
            for f, typeinfo in zip(fields, types):
                typecode.putln('  {&%s, "%s", offsetof(%s, %s)},' %
                           (typeinfo, f.name, dtype.declaration_code(""), f.cname), safe=True)
            typecode.putln('  {NULL, NULL, 0}', safe=True)
            typecode.putln("};", safe=True)
        else:
            assert False
631
            
632 633 634 635 636 637
        rep = str(dtype)
        if dtype.is_int:
            if dtype.signed == 0:
                typegroup = 'U'
            else:
                typegroup = 'I'
638
        elif complex_possible or dtype.is_complex:
639 640 641 642 643 644 645
            typegroup = 'C'
        elif dtype.is_float:
            typegroup = 'R'
        elif dtype.is_struct:
            typegroup = 'S'
        elif dtype.is_pyobject:
            typegroup = 'O'
646
        else:
647 648
            print dtype
            assert False
649

650 651 652 653 654 655 656 657
        typecode.putln(('static __Pyx_TypeInfo %s = { "%s", %s, sizeof(%s), \'%s\' };'
                        ) % (name,
                             rep,
                             structinfo_name,
                             declcode,
                             typegroup,
                        ), safe=True)
    return name
658 659


660 661
# Utility function to set the right exception
# The caller should immediately goto_error
662 663
raise_indexerror_code = UtilityCode(
proto = """\
664
static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/
665 666
""",
impl = """\
667
static void __Pyx_RaiseBufferIndexError(int axis) {
668 669
  PyErr_Format(PyExc_IndexError,
     "Out of bounds on buffer access (axis %d)", axis);
670
}
671

672
""")
673

674 675 676 677 678
parse_typestring_repeat_code = UtilityCode(
proto = """
""",
impl = """
""")
679

680 681
raise_buffer_fallback_code = UtilityCode(
proto = """
682
static void __Pyx_RaiseBufferFallbackError(void); /*proto*/
683 684
""",
impl = """
685 686 687 688 689
static void __Pyx_RaiseBufferFallbackError(void) {
  PyErr_Format(PyExc_ValueError,
     "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!");
}

690
""")
691 692 693 694 695 696 697 698 699 700 701 702



#
# Buffer format string checking
#
# Buffer type checking. Utility code for checking that acquired
# buffers match our assumptions. We only need to check ndim and
# the format string; the access mode/flags is checked by the
# exporter.
#
# The alignment code is copied from _struct.c in Python.
703
acquire_utility_code = UtilityCode(proto="""
704 705 706 707 708 709 710 711 712 713 714 715 716
/* Run-time type information about structs used with buffers */
struct __Pyx_StructField_;

typedef struct {
  const char* name; /* for error messages only */
  struct __Pyx_StructField_* fields;
  size_t size;     /* sizeof(type) */
  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
} __Pyx_TypeInfo;

typedef struct __Pyx_StructField_ {
  __Pyx_TypeInfo* type;
  const char* name;
717
  size_t offset;
718 719
} __Pyx_StructField;

720 721 722 723
typedef struct {
  __Pyx_StructField* field;
  size_t parent_offset;
} __Pyx_BufFmt_StackElem;
724

725

726
static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
727
static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
728
""", impl="""
729
static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
730 731 732 733 734 735
  unsigned int n = 1;
  return *(unsigned char*)(&n) != 0;
}

typedef struct {
  __Pyx_StructField root;
736 737
  __Pyx_BufFmt_StackElem* head;
  size_t fmt_offset;
738 739 740 741 742 743 744
  int new_count, enc_count;
  int is_complex;
  char enc_type;
  char packmode;
} __Pyx_BufFmt_Context;

static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
745
                              __Pyx_BufFmt_StackElem* stack,
746
                              __Pyx_TypeInfo* type) {
747 748
  stack[0].field = &ctx->root;
  stack[0].parent_offset = 0;
749 750 751 752
  ctx->root.type = type;
  ctx->root.name = "buffer dtype";
  ctx->root.offset = 0;
  ctx->head = stack;
753
  ctx->head->field = &ctx->root;
754 755
  ctx->fmt_offset = 0;
  ctx->head->parent_offset = 0;
756 757 758 759 760 761 762
  ctx->packmode = '@';
  ctx->new_count = 1;
  ctx->enc_count = 0;
  ctx->enc_type = 0;
  ctx->is_complex = 0;
  while (type->typegroup == 'S') {
    ++ctx->head;
763
    ctx->head->field = type->fields;
764
    ctx->head->parent_offset = 0;
765 766 767 768 769 770 771 772
    type = type->fields->type;
  }
}

static int __Pyx_BufFmt_ParseNumber(const char** ts) {
    int count;
    const char* t = *ts;
    if (*t < '0' || *t > '9') {
773
      return -1;
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
    } else {
        count = *t++ - '0';
        while (*t >= '0' && *t < '9') {
            count *= 10;
            count += *t++ - '0';
        }
    }
    *ts = t;
    return count;
}

static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
  char msg[] = {ch, 0};
  PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%s'", msg);
}

static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
  switch (ch) {
    case 'b': return "'char'";
    case 'B': return "'unsigned char'";
    case 'h': return "'short'";
    case 'H': return "'unsigned short'";
    case 'i': return "'int'";
    case 'I': return "'unsigned int'";
    case 'l': return "'long'";
    case 'L': return "'unsigned long'";
    case 'q': return "'long long'";
    case 'Q': return "'unsigned long long'";
    case 'f': return (is_complex ? "'complex float'" : "'float'");
    case 'd': return (is_complex ? "'complex double'" : "'double'");
    case 'g': return (is_complex ? "'complex long double'" : "'long double'");
    case 'T': return "a struct";
    case 'O': return "Python object";
    case 'P': return "a pointer";
    case 0: return "end";
    default: return "unparseable format string";
  }
}

static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
  switch (ch) {
    case '?': case 'c': case 'b': case 'B': return 1;
    case 'h': case 'H': return 2;
    case 'i': case 'I': case 'l': case 'L': return 4;
    case 'q': case 'Q': return 8;
    case 'f': return (is_complex ? 8 : 4);
    case 'd': return (is_complex ? 16 : 8);
    case 'g': {
      PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g')..");
      return 0;
    }
    case 'O': case 'P': return sizeof(void*);
    default:
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
}

static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
  switch (ch) {
    case 'c': case 'b': case 'B': return 1;
    case 'h': case 'H': return sizeof(short);
    case 'i': case 'I': return sizeof(int);
    case 'l': case 'L': return sizeof(long);
    #ifdef HAVE_LONG_LONG
    case 'q': case 'Q': return sizeof(PY_LONG_LONG);
    #endif
    case 'f': return sizeof(float) * (is_complex ? 2 : 1);
    case 'd': return sizeof(double) * (is_complex ? 2 : 1);
    case 'g': return sizeof(long double) * (is_complex ? 2 : 1);
    case 'O': case 'P': return sizeof(void*);
    default: {
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }    
  }
}

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
typedef struct { char c; short x; } __Pyx_st_short;
typedef struct { char c; int x; } __Pyx_st_int;
typedef struct { char c; long x; } __Pyx_st_long;
typedef struct { char c; float x; } __Pyx_st_float;
typedef struct { char c; double x; } __Pyx_st_double;
typedef struct { char c; long double x; } __Pyx_st_longdouble;
typedef struct { char c; void *x; } __Pyx_st_void_p;
#ifdef HAVE_LONG_LONG
typedef struct { char c; PY_LONG_LONG x; } __Pyx_s_long_long;
#endif

static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
  switch (ch) {
    case '?': case 'c': case 'b': case 'B': return 1;
    case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
    case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
    case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
#ifdef HAVE_LONG_LONG
    case 'q': case 'Q': return sizeof(__Pyx_s_long_long) - sizeof(PY_LONG_LONG);
#endif
    case 'f': return sizeof(__Pyx_st_float) - sizeof(float);
    case 'd': return sizeof(__Pyx_st_double) - sizeof(double);
    case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double);
    case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*);
    default:
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
}

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
static size_t __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
  switch (ch) {
    case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
    case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
    case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
    case 'O': return 'O';
    case 'P': return 'P';
    default: {
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }    
  }
}

static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
897
  if (ctx->head == NULL || ctx->head->field == &ctx->root) {
898 899 900 901 902 903
    const char* expected;
    const char* quote;
    if (ctx->head == NULL) {
      expected = "end";
      quote = "";
    } else {
904
      expected = ctx->head->field->type->name;
905 906 907 908 909 910 911
      quote = "'";
    }
    PyErr_Format(PyExc_ValueError,
                 "Buffer dtype mismatch, expected %s%s%s but got %s",
                 quote, expected, quote,
                 __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex));
  } else {
912 913
    __Pyx_StructField* field = ctx->head->field;
    __Pyx_StructField* parent = (ctx->head - 1)->field;
914 915 916 917 918 919 920 921
    PyErr_Format(PyExc_ValueError,
                 "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'",
                 field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex),
                 parent->type->name, field->name);
  }
}

static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
922
  char group;
923
  size_t size, offset;
924 925
  if (ctx->enc_type == 0) return 0;
  group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
926
  do {
927
    __Pyx_StructField* field = ctx->head->field;
928 929 930 931 932 933 934
    __Pyx_TypeInfo* type = field->type;
  
    if (ctx->packmode == '@' || ctx->packmode == '^') {
      size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
    } else {
      size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex);
    }
935 936 937 938 939 940 941 942
    if (ctx->packmode == '@') {
      int align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex);
      int align_mod_offset;
      if (align_at == 0) return -1;
      align_mod_offset = ctx->fmt_offset % align_at;
      if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
    }

943 944 945
    if (type->size != size || type->typegroup != group) {
      if (type->typegroup == 'C' && type->fields != NULL) {
        /* special case -- treat as struct rather than complex number */
946
        size_t parent_offset = ctx->head->parent_offset + field->offset;
947
        ++ctx->head;
948
        ctx->head->field = type->fields;
949
        ctx->head->parent_offset = parent_offset;
950 951 952 953
        continue;
      }
    
      __Pyx_BufFmt_RaiseExpected(ctx);
954
      return -1;
955 956
    }

957
    offset = ctx->head->parent_offset + field->offset;
958
    if (ctx->fmt_offset != offset) {
959 960 961 962
      PyErr_Format(PyExc_ValueError,
                   "Buffer dtype mismatch; next field is at offset %"PY_FORMAT_SIZE_T"d "
                   "but %"PY_FORMAT_SIZE_T"d expected", ctx->fmt_offset, offset);
      return -1;
963
    }
964 965 966

    ctx->fmt_offset += size;
  
967 968 969 970 971 972 973 974
    --ctx->enc_count; /* Consume from buffer string */

    /* Done checking, move to next field, pushing or popping struct stack if needed */
    while (1) {
      if (field == &ctx->root) {
        ctx->head = NULL;
        if (ctx->enc_count != 0) {
          __Pyx_BufFmt_RaiseExpected(ctx);
975
          return -1;
976 977 978
        }
        break; /* breaks both loops as ctx->enc_count == 0 */
      }
979
      ctx->head->field = ++field;
980 981
      if (field->type == NULL) {
        --ctx->head;
982
        field = ctx->head->field;
983 984
        continue;
      } else if (field->type->typegroup == 'S') {
985
        size_t parent_offset = ctx->head->parent_offset + field->offset;
986 987 988
        if (field->type->fields->type == NULL) continue; /* empty struct */
        field = field->type->fields;
        ++ctx->head;
989 990
        ctx->head->field = field;
        ctx->head->parent_offset = parent_offset;
991 992 993 994 995 996 997 998
        break;
      } else {
        break;
      }
    }
  } while (ctx->enc_count);
  ctx->enc_type = 0;
  ctx->is_complex = 0;
999
  return 0;    
1000 1001
}

1002 1003 1004 1005 1006 1007 1008 1009
static int __Pyx_BufFmt_FirstPack(__Pyx_BufFmt_Context* ctx) {
  if (ctx->enc_type != 0 || ctx->packmode != '@') {
    PyErr_SetString(PyExc_ValueError, "Buffer packing mode currently only allowed at beginning of format string (this is a defect)");
    return -1;
  }
  return 0;
}

1010 1011 1012 1013 1014
static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
  int got_Z = 0;
  while (1) {
    switch(*ts) {
      case 0:
1015 1016 1017
        if (ctx->enc_type != 0 && ctx->head == NULL) {
          __Pyx_BufFmt_RaiseExpected(ctx);
          return NULL;
1018
        }
1019
        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
        if (ctx->head != NULL) {
          __Pyx_BufFmt_RaiseExpected(ctx);
          return NULL;
        }
        return ts;
      case ' ':
      case 10:
      case 13:
        ++ts;
        break;
      case '<':
        if (!__Pyx_IsLittleEndian()) {
          PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler");
          return NULL;
        }
1035
        if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL;
1036 1037 1038 1039 1040 1041 1042 1043 1044
        ctx->packmode = '=';
        ++ts;
        break;
      case '>':
      case '!':
        if (__Pyx_IsLittleEndian()) {
          PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler");
          return NULL;
        }
1045
        if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL;
1046 1047 1048 1049 1050 1051
        ctx->packmode = '=';
        ++ts;
        break;
      case '=':
      case '@':
      case '^':
1052 1053
        if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL;
        ctx->packmode = *ts++;
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
        break;
      case 'T': /* substruct */
        {
          int i;
          const char* ts_after_sub;
          int struct_count = ctx->new_count;
          ctx->new_count = 1;
          ++ts;
          if (*ts != '{') {
            PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
            return NULL;
          }
          ++ts;
          ts_after_sub = ts;
          for (i = 0; i != struct_count; ++i) {
            ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts);
            if (!ts_after_sub) return NULL;
          }
          ts = ts_after_sub;
        }
        break;
      case '}': /* end of substruct; either repeat or move on */
        ++ts;
        return ts;
1078 1079 1080 1081 1082 1083 1084 1085
      case 'x':
        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
        ctx->fmt_offset += ctx->new_count;
        ctx->new_count = 1;
        ctx->enc_count = 0;
        ctx->enc_type = 0;
        ++ts;
        break;
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
      case 'Z':
        got_Z = 1;
        ++ts;
        if (*ts != 'f' && *ts != 'd' && *ts != 'g') {
          __Pyx_BufFmt_RaiseUnexpectedChar('Z');
          return NULL;
        }        /* fall through */
      case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
      case 'l': case 'L': case 'q': case 'Q':
      case 'f': case 'd': case 'g':
      case 'O':
        if (ctx->enc_type == *ts && got_Z == ctx->is_complex) {
          /* Continue pooling same type */
          ctx->enc_count += ctx->new_count;
        } else {
          /* New type */
1102
          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
          ctx->enc_count = ctx->new_count;
          ctx->enc_type = *ts;
          ctx->is_complex = got_Z;
        }
        ++ts;
        ctx->new_count = 1;
        got_Z = 0;
        break;
      default:
        {
          ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts);
1114
          if (ctx->new_count == -1) { /* First char was not a digit */
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
            char msg[2] = { *ts, 0 };
            PyErr_Format(PyExc_ValueError,
                         "Does not understand character buffer dtype format string ('%s')", msg);
            return NULL;
          }
        }
      
    }
  }
}

1126
static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
1127 1128 1129 1130 1131 1132
  buf->buf = NULL;
  buf->obj = NULL;
  buf->strides = __Pyx_zeros;
  buf->shape = __Pyx_zeros;
  buf->suboffsets = __Pyx_minusones;
}
1133

1134
static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
  if (obj == Py_None) {
    __Pyx_ZeroBuffer(buf);
    return 0;
  }
  buf->buf = NULL;
  if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail;
  if (buf->ndim != nd) {
    PyErr_Format(PyExc_ValueError,
                 "Buffer has wrong number of dimensions (expected %d, got %d)",
                 nd, buf->ndim);
    goto fail;
  }
  if (!cast) {
    __Pyx_BufFmt_Context ctx;
    __Pyx_BufFmt_Init(&ctx, stack, dtype);
    if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
  }
1152
  if ((unsigned)buf->itemsize != dtype->size) {
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
    PyErr_Format(PyExc_ValueError,
      "Item size of buffer (%"PY_FORMAT_SIZE_T"d byte%s) does not match size of '%s' (%"PY_FORMAT_SIZE_T"d byte%s)",
      buf->itemsize, (buf->itemsize > 1) ? "s" : "",
      dtype->name,
      dtype->size, (dtype->size > 1) ? "s" : "");
    goto fail;
  }
  if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones;
  return 0;
fail:;
  __Pyx_ZeroBuffer(buf);
  return -1;
}
1166

1167
static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
1168 1169 1170 1171 1172
  if (info->buf == NULL) return;
  if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
  __Pyx_ReleaseBuffer(info);
}
""")
1173