static Py_ssize_t array_getwritebuf(PyArrayObject *self, Py_ssize_t segment, void **ptrptr) { if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) { return -1; } return array_getreadbuf(self, segment, (void **) ptrptr); }
static int array_getbuffer(PyObject *obj, Py_buffer *view, int flags) { PyArrayObject *self; _buffer_info_t *info = NULL; self = (PyArrayObject*)obj; /* Check whether we can provide the wanted properties */ if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous"); goto fail; } if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS && !PyArray_ISONESEGMENT(self)) { PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous"); goto fail; } if ((flags & PyBUF_STRIDES) != PyBUF_STRIDES && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { /* Non-strided N-dim buffers must be C-contiguous */ PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) { if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) { goto fail; } } /* * If a read-only buffer is requested on a read-write array, we return a * read-write buffer, which is dubious behavior. But that's why this call * is guarded by PyArray_ISWRITEABLE rather than (flags & * PyBUF_WRITEABLE). */ if (PyArray_ISWRITEABLE(self)) { if (array_might_be_written(self) < 0) { goto fail; } } if (view == NULL) { PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer"); goto fail; } /* Fill in information */ info = _buffer_get_info(obj); if (info == NULL) { goto fail; } view->buf = PyArray_DATA(self); view->suboffsets = NULL; view->itemsize = PyArray_ITEMSIZE(self); view->readonly = !PyArray_ISWRITEABLE(self); view->internal = NULL; view->len = PyArray_NBYTES(self); if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { view->format = info->format; } else { view->format = NULL; } if ((flags & PyBUF_ND) == PyBUF_ND) { view->ndim = info->ndim; view->shape = info->shape; } else { view->ndim = 0; view->shape = NULL; } if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { view->strides = info->strides; } else { view->strides = NULL; } view->obj = (PyObject*)self; Py_INCREF(self); return 0; fail: return -1; }
/* * Retrieving buffers for ndarray */ static int array_getbuffer(PyObject *obj, Py_buffer *view, int flags) { PyArrayObject *self; _buffer_info_t *info = NULL; self = (PyArrayObject*)obj; /* Check whether we can provide the wanted properties */ if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous"); goto fail; } if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS && !PyArray_ISONESEGMENT(self)) { PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous"); goto fail; } if ((flags & PyBUF_STRIDES) != PyBUF_STRIDES && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { /* Non-strided N-dim buffers must be C-contiguous */ PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) { if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) { goto fail; } } /* * If a read-only buffer is requested on a read-write array, we return a * read-write buffer, which is dubious behavior. But that's why this call * is guarded by PyArray_ISWRITEABLE rather than (flags & * PyBUF_WRITEABLE). */ if (PyArray_ISWRITEABLE(self)) { if (array_might_be_written(self) < 0) { goto fail; } } if (view == NULL) { PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer"); goto fail; } /* Fill in information */ info = _buffer_get_info(obj); if (info == NULL) { goto fail; } view->buf = PyArray_DATA(self); view->suboffsets = NULL; view->itemsize = PyArray_ITEMSIZE(self); view->readonly = !PyArray_ISWRITEABLE(self); view->internal = NULL; view->len = PyArray_NBYTES(self); if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { view->format = info->format; } else { view->format = NULL; } if ((flags & PyBUF_ND) == PyBUF_ND) { view->ndim = info->ndim; view->shape = info->shape; } else { view->ndim = 0; view->shape = NULL; } if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { view->strides = info->strides; #ifdef NPY_RELAXED_STRIDES_CHECKING /* * If NPY_RELAXED_STRIDES_CHECKING is on, the array may be * contiguous, but it won't look that way to Python when it * tries to determine contiguity by looking at the strides * (since one of the elements may be -1). In that case, just * regenerate strides from shape. */ if (PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS) && !((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)) { Py_ssize_t sd = view->itemsize; int i; for (i = view->ndim-1; i >= 0; --i) { view->strides[i] = sd; sd *= view->shape[i]; } } else if (PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { Py_ssize_t sd = view->itemsize; int i; for (i = 0; i < view->ndim; ++i) { view->strides[i] = sd; sd *= view->shape[i]; } } #endif } else { view->strides = NULL; } view->obj = (PyObject*)self; Py_INCREF(self); return 0; fail: return -1; }