Author: Matti Picus <matti.pi...@gmail.com> Branch: Changeset: r86973:f8f2080418c8 Date: 2016-09-09 13:59 +0300 http://bitbucket.org/pypy/pypy/changeset/f8f2080418c8/
Log: move all Py_buffer to memoryobject, create helper function diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py --- a/pypy/module/cpyext/buffer.py +++ b/pypy/module/cpyext/buffer.py @@ -1,9 +1,7 @@ -from pypy.interpreter.error import oefmt -from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib.rarithmetic import widen +from rpython.rtyper.lltypesystem import rffi from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, Py_buffer, Py_TPFLAGS_HAVE_NEWBUFFER, Py_ssize_tP) -from pypy.module.cpyext.pyobject import PyObject, make_ref, incref + cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER) +from pypy.module.cpyext.pyobject import PyObject @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyObject_CheckBuffer(space, pyobj): @@ -14,102 +12,4 @@ return 1 return 0 -@cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real], - rffi.INT_real, error=-1) -def PyObject_GetBuffer(space, w_obj, view, flags): - """Export obj into a Py_buffer, view. These arguments must - never be NULL. The flags argument is a bit field indicating what - kind of buffer the caller is prepared to deal with and therefore what - kind of buffer the exporter is allowed to return. The buffer interface - allows for complicated memory sharing possibilities, but some caller may - not be able to handle all the complexity but may want to see if the - exporter will let them take a simpler view to its memory. - - Some exporters may not be able to share memory in every possible way and - may need to raise errors to signal to some consumers that something is - just not possible. These errors should be a BufferError unless - there is another error that is actually causing the problem. The - exporter can use flags information to simplify how much of the - Py_buffer structure is filled in with non-default values and/or - raise an error if the object can't support a simpler view of its memory. - - 0 is returned on success and -1 on error.""" - flags = widen(flags) - buf = space.buffer_w(w_obj, flags) - try: - view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) - except ValueError: - raise BufferError("could not create buffer from object") - view.c_len = buf.getlength() - view.c_obj = make_ref(space, w_obj) - ndim = buf.getndim() - view.c_itemsize = buf.getitemsize() - rffi.setintfield(view, 'c_readonly', int(buf.readonly)) - rffi.setintfield(view, 'c_ndim', ndim) - view.c_format = rffi.str2charp(buf.getformat()) - view.c_shape = lltype.malloc(Py_ssize_tP.TO, ndim, flavor='raw') - view.c_strides = lltype.malloc(Py_ssize_tP.TO, ndim, flavor='raw') - shape = buf.getshape() - strides = buf.getstrides() - for i in range(ndim): - view.c_shape[i] = shape[i] - view.c_strides[i] = strides[i] - view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) - view.c_internal = lltype.nullptr(rffi.VOIDP.TO) - return 0 - -def _IsFortranContiguous(view): - ndim = widen(view.c_ndim) - if ndim == 0: - return 1 - if not view.c_strides: - return ndim == 1 - sd = view.c_itemsize - if ndim == 1: - return view.c_shape[0] == 1 or sd == view.c_strides[0] - for i in range(view.c_ndim): - dim = view.c_shape[i] - if dim == 0: - return 1 - if view.c_strides[i] != sd: - return 0 - sd *= dim - return 1 - -def _IsCContiguous(view): - ndim = widen(view.c_ndim) - if ndim == 0: - return 1 - if not view.c_strides: - return ndim == 1 - sd = view.c_itemsize - if ndim == 1: - return view.c_shape[0] == 1 or sd == view.c_strides[0] - for i in range(ndim - 1, -1, -1): - dim = view.c_shape[i] - if dim == 0: - return 1 - if view.c_strides[i] != sd: - return 0 - sd *= dim - return 1 - - -@cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real, error=CANNOT_FAIL) -def PyBuffer_IsContiguous(space, view, fort): - """Return 1 if the memory defined by the view is C-style (fortran is - 'C') or Fortran-style (fortran is 'F') contiguous or either one - (fortran is 'A'). Return 0 otherwise.""" - # traverse the strides, checking for consistent stride increases from - # right-to-left (c) or left-to-right (fortran). Copied from cpython - if not view.c_suboffsets: - return 0 - if (fort == 'C'): - return _IsCContiguous(view) - elif (fort == 'F'): - return _IsFortranContiguous(view) - elif (fort == 'A'): - return (_IsCContiguous(view) or _IsFortranContiguous(view)) - return 0 - diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -2,10 +2,124 @@ Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers, Py_ssize_tP) from pypy.module.cpyext.pyobject import PyObject, make_ref, incref from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.rarithmetic import widen from pypy.objspace.std.memoryobject import W_MemoryView PyMemoryView_Check, PyMemoryView_CheckExact = build_type_checkers("MemoryView", "w_memoryview") +@cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real], + rffi.INT_real, error=-1) +def PyObject_GetBuffer(space, w_obj, view, flags): + """Export obj into a Py_buffer, view. These arguments must + never be NULL. The flags argument is a bit field indicating what + kind of buffer the caller is prepared to deal with and therefore what + kind of buffer the exporter is allowed to return. The buffer interface + allows for complicated memory sharing possibilities, but some caller may + not be able to handle all the complexity but may want to see if the + exporter will let them take a simpler view to its memory. + + Some exporters may not be able to share memory in every possible way and + may need to raise errors to signal to some consumers that something is + just not possible. These errors should be a BufferError unless + there is another error that is actually causing the problem. The + exporter can use flags information to simplify how much of the + Py_buffer structure is filled in with non-default values and/or + raise an error if the object can't support a simpler view of its memory. + + 0 is returned on success and -1 on error.""" + flags = widen(flags) + buf = space.buffer_w(w_obj, flags) + try: + view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) + except ValueError: + raise BufferError("could not create buffer from object") + return fill_Py_buffer(space, w_obj, view, flags) + view.c_obj = make_ref(space, w_obj) + +def fill_Py_buffer(space, buf, view): + # c_buf, c_obj have been filled in + ndim = buf.getndim() + view.c_len = buf.getlength() + view.c_itemsize = buf.getitemsize() + rffi.setintfield(view, 'c_ndim', ndim) + view.c_format = rffi.cast(rffi.CCHARP, view.c__format) + view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape) + view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides) + fmt = buf.getformat() + n = Py_MAX_FMT - 1 # NULL terminated buffer + if len(fmt) > n: + ### WARN? + pass + else: + n = len(fmt) + for i in range(n): + if ord(fmt[i]) > 255: + view.c_format[i] = '*' + else: + view.c_format[i] = fmt[i] + view.c_format[n] = '\x00' + shape = buf.getshape() + strides = buf.getstrides() + for i in range(ndim): + view.c_shape[i] = shape[i] + view.c_strides[i] = strides[i] + view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) + view.c_internal = lltype.nullptr(rffi.VOIDP.TO) + return 0 + +def _IsFortranContiguous(view): + ndim = widen(view.c_ndim) + if ndim == 0: + return 1 + if not view.c_strides: + return ndim == 1 + sd = view.c_itemsize + if ndim == 1: + return view.c_shape[0] == 1 or sd == view.c_strides[0] + for i in range(view.c_ndim): + dim = view.c_shape[i] + if dim == 0: + return 1 + if view.c_strides[i] != sd: + return 0 + sd *= dim + return 1 + +def _IsCContiguous(view): + ndim = widen(view.c_ndim) + if ndim == 0: + return 1 + if not view.c_strides: + return ndim == 1 + sd = view.c_itemsize + if ndim == 1: + return view.c_shape[0] == 1 or sd == view.c_strides[0] + for i in range(ndim - 1, -1, -1): + dim = view.c_shape[i] + if dim == 0: + return 1 + if view.c_strides[i] != sd: + return 0 + sd *= dim + return 1 + +@cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real, error=CANNOT_FAIL) +def PyBuffer_IsContiguous(space, view, fort): + """Return 1 if the memory defined by the view is C-style (fortran is + 'C') or Fortran-style (fortran is 'F') contiguous or either one + (fortran is 'A'). Return 0 otherwise.""" + # traverse the strides, checking for consistent stride increases from + # right-to-left (c) or left-to-right (fortran). Copied from cpython + if not view.c_suboffsets: + return 0 + if (fort == 'C'): + return _IsCContiguous(view) + elif (fort == 'F'): + return _IsFortranContiguous(view) + elif (fort == 'A'): + return (_IsCContiguous(view) or _IsFortranContiguous(view)) + return 0 + @cpython_api([PyObject], PyObject) def PyMemoryView_FromObject(space, w_obj): return space.call_method(space.builtin, "memoryview", w_obj) @@ -38,31 +152,6 @@ view.c_obj = make_ref(space, w_s) rffi.setintfield(view, 'c_readonly', 1) isstr = True - view.c_len = w_obj.getlength() - view.c_itemsize = w_obj.buf.getitemsize() - rffi.setintfield(view, 'c_ndim', ndim) - view.c_format = rffi.cast(rffi.CCHARP, view.c__format) - view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape) - view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides) - fmt = w_obj.buf.getformat() - n = Py_MAX_FMT - 1 # NULL terminated buffer - if len(fmt) > n: - ### WARN? - pass - else: - n = len(fmt) - for i in range(n): - if ord(fmt[i]) > 255: - view.c_format[i] = '*' - else: - view.c_format[i] = fmt[i] - view.c_format[n] = '\x00' - shape = w_obj.buf.getshape() - strides = w_obj.buf.getstrides() - for i in range(ndim): - view.c_shape[i] = shape[i] - view.c_strides[i] = strides[i] - view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) - view.c_internal = lltype.nullptr(rffi.VOIDP.TO) + fill_Py_buffer(space, w_obj.buf, view) return view _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit