Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: py3k
Changeset: r87005:391d8ffc245f
Date: 2016-09-09 13:59 +0300
http://bitbucket.org/pypy/pypy/changeset/391d8ffc245f/

Log:    move all Py_buffer to memoryobject, create helper function (grafted
        from f8f2080418c8ba11b6bc85e752ba9ad10740d59a)

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,66 +1,19 @@
-from pypy.interpreter.error import oefmt
-from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.lltypesystem import rffi
 from rpython.rlib import buffer
-from rpython.rlib.rarithmetic import widen
 from pypy.module.cpyext.api import (
-    cpython_api, CANNOT_FAIL, Py_buffer)
-from pypy.module.cpyext.pyobject import PyObject, Py_DecRef
+    cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER)
+from pypy.module.cpyext.pyobject import PyObject
 
-def _IsFortranContiguous(view):
-    ndim = widen(view.c_ndim)
-    if ndim == 0:
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def PyObject_CheckBuffer(space, pyobj):
+    """Return 1 if obj supports the buffer interface otherwise 0."""
+    as_buffer = pyobj.c_ob_type.c_tp_as_buffer
+    flags = pyobj.c_ob_type.c_tp_flags
+    if (flags & Py_TPFLAGS_HAVE_NEWBUFFER and as_buffer.c_bf_getbuffer):
         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
 
-    
+
 
 class CBuffer(buffer.Buffer):
 
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,6 +2,7 @@
                          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
 
 from pypy.interpreter.error import oefmt
@@ -10,6 +11,119 @@
 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)
@@ -42,32 +156,7 @@
         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
 
 @cpython_api([lltype.Ptr(Py_buffer)], PyObject)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to