mirror of https://github.com/python/cpython
Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple,
by denying s# to parse objects that have a releasebuffer procedure, and introducing s*. More module might need to get converted to use s*.
This commit is contained in:
parent
aa8efbf084
commit
f91d46a17d
|
@ -40,6 +40,14 @@ variable(s) whose address should be passed.
|
||||||
other read-buffer compatible objects pass back a reference to the raw internal
|
other read-buffer compatible objects pass back a reference to the raw internal
|
||||||
data representation.
|
data representation.
|
||||||
|
|
||||||
|
``s*`` (string, Unicode, or any buffer compatible object) [Py_buffer \*]
|
||||||
|
Similar to ``s#``, this code fills a Py_buffer structure provided by the caller.
|
||||||
|
The buffer gets locked, so that the caller can subsequently use the buffer even
|
||||||
|
inside a ``Py_BEGIN_ALLOW_THREADS`` block; the caller is responsible for calling
|
||||||
|
``PyBuffer_Release`` with the structure after it has processed the data.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
``z`` (string or ``None``) [const char \*]
|
``z`` (string or ``None``) [const char \*]
|
||||||
Like ``s``, but the Python object may also be ``None``, in which case the C
|
Like ``s``, but the Python object may also be ``None``, in which case the C
|
||||||
pointer is set to *NULL*.
|
pointer is set to *NULL*.
|
||||||
|
@ -47,6 +55,10 @@ variable(s) whose address should be passed.
|
||||||
``z#`` (string or ``None`` or any read buffer compatible object) [const char \*, int]
|
``z#`` (string or ``None`` or any read buffer compatible object) [const char \*, int]
|
||||||
This is to ``s#`` as ``z`` is to ``s``.
|
This is to ``s#`` as ``z`` is to ``s``.
|
||||||
|
|
||||||
|
``z*`` (string or ``None`` or any buffer compatible object) [Py_buffer*]
|
||||||
|
This is to ``s*`` as ``z`` is to ``s``.
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
``u`` (Unicode object) [Py_UNICODE \*]
|
``u`` (Unicode object) [Py_UNICODE \*]
|
||||||
Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of
|
Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of
|
||||||
16-bit Unicode (UTF-16) data. As with ``s``, there is no need to provide
|
16-bit Unicode (UTF-16) data. As with ``s``, there is no need to provide
|
||||||
|
@ -240,6 +252,10 @@ variable(s) whose address should be passed.
|
||||||
single-segment buffer objects are accepted; :exc:`TypeError` is raised for all
|
single-segment buffer objects are accepted; :exc:`TypeError` is raised for all
|
||||||
others.
|
others.
|
||||||
|
|
||||||
|
``w*`` (read-write byte-oriented buffer) [Py_buffer \*]
|
||||||
|
This is to ``w`` what ``s*`` is to ``s``.
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
``(items)`` (tuple) [*matching-items*]
|
``(items)`` (tuple) [*matching-items*]
|
||||||
The object must be a Python sequence whose length is the number of format units
|
The object must be a Python sequence whose length is the number of format units
|
||||||
in *items*. The C arguments must correspond to the individual format units in
|
in *items*. The C arguments must correspond to the individual format units in
|
||||||
|
|
|
@ -1064,7 +1064,7 @@ about the object's memory representation. Objects
|
||||||
can use this operation to lock memory in place
|
can use this operation to lock memory in place
|
||||||
while an external caller could be modifying the contents,
|
while an external caller could be modifying the contents,
|
||||||
so there's a corresponding
|
so there's a corresponding
|
||||||
``PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)`` to
|
``PyBuffer_Release(Py_buffer *view)`` to
|
||||||
indicate that the external caller is done.
|
indicate that the external caller is done.
|
||||||
|
|
||||||
The **flags** argument to :cfunc:`PyObject_GetBuffer` specifies
|
The **flags** argument to :cfunc:`PyObject_GetBuffer` specifies
|
||||||
|
@ -2841,7 +2841,7 @@ Changes to Python's build process and to the C API include:
|
||||||
|
|
||||||
* The new buffer interface, previously described in
|
* The new buffer interface, previously described in
|
||||||
`the PEP 3118 section <#pep-3118-revised-buffer-protocol>`__,
|
`the PEP 3118 section <#pep-3118-revised-buffer-protocol>`__,
|
||||||
adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyObject_ReleaseBuffer`,
|
adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyBuffer_Release`,
|
||||||
as well as a few other functions.
|
as well as a few other functions.
|
||||||
|
|
||||||
* Python's use of the C stdio library is now thread-safe, or at least
|
* Python's use of the C stdio library is now thread-safe, or at least
|
||||||
|
|
|
@ -549,24 +549,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
PyAPI_FUNC(void) PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view);
|
|
||||||
|
|
||||||
|
|
||||||
/* C-API version of the releasebuffer function call. It
|
|
||||||
checks to make sure the object has the required function
|
|
||||||
pointer and issues the call. The obj must have the buffer
|
|
||||||
interface or this function will cause a segfault (i.e. it
|
|
||||||
is assumed to be called only after a corresponding
|
|
||||||
getbuffer which already verified the existence of the
|
|
||||||
tp_as_buffer pointer).
|
|
||||||
|
|
||||||
Returns 0 on success and -1 (with an error raised) on
|
|
||||||
failure. This function always succeeds (as a NO-OP) if
|
|
||||||
there is no releasebuffer function for the object so that
|
|
||||||
it can always be called when the consumer is done with the
|
|
||||||
buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices);
|
PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices);
|
||||||
|
|
||||||
/* Get the memory area pointed to by the indices for the buffer given.
|
/* Get the memory area pointed to by the indices for the buffer given.
|
||||||
|
@ -623,7 +605,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
per element.
|
per element.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, void *buf,
|
PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf,
|
||||||
Py_ssize_t len, int readonly,
|
Py_ssize_t len, int readonly,
|
||||||
int flags);
|
int flags);
|
||||||
|
|
||||||
|
@ -633,6 +615,11 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
and -1 (with raising an error) on error.
|
and -1 (with raising an error) on error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view);
|
||||||
|
|
||||||
|
/* Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
|
||||||
|
*/
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyObject_Format(PyObject* obj,
|
PyAPI_FUNC(PyObject *) PyObject_Format(PyObject* obj,
|
||||||
PyObject *format_spec);
|
PyObject *format_spec);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -163,6 +163,7 @@ typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **);
|
||||||
|
|
||||||
typedef struct bufferinfo {
|
typedef struct bufferinfo {
|
||||||
void *buf;
|
void *buf;
|
||||||
|
PyObject *obj; /* borrowed reference */
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
Py_ssize_t itemsize; /* This is Py_ssize_t so it can be
|
Py_ssize_t itemsize; /* This is Py_ssize_t so it can be
|
||||||
pointed to by strides in simple case.*/
|
pointed to by strides in simple case.*/
|
||||||
|
|
|
@ -12,6 +12,10 @@ What's New in Python 2.6 beta 3?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple,
|
||||||
|
by denying s# to parse objects that have a releasebuffer procedure,
|
||||||
|
and introducing s*.
|
||||||
|
|
||||||
- Issue #3537: Fix an assertion failure when an empty but presized dict
|
- Issue #3537: Fix an assertion failure when an empty but presized dict
|
||||||
object was stored in the freelist.
|
object was stored in the freelist.
|
||||||
|
|
||||||
|
|
|
@ -232,20 +232,20 @@ static PyObject *
|
||||||
utf_7_decode(PyObject *self,
|
utf_7_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded = NULL;
|
PyObject *decoded = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_7_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_7_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
consumed = size;
|
consumed = pbuf.len;
|
||||||
|
|
||||||
decoded = PyUnicode_DecodeUTF7Stateful(data, size, errors,
|
decoded = PyUnicode_DecodeUTF7Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
final ? NULL : &consumed);
|
final ? NULL : &consumed);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
@ -255,24 +255,20 @@ static PyObject *
|
||||||
utf_8_decode(PyObject *self,
|
utf_8_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded = NULL;
|
PyObject *decoded = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_8_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_8_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
consumed = pbuf.len;
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
consumed = size;
|
|
||||||
|
|
||||||
decoded = PyUnicode_DecodeUTF8Stateful(data, size, errors,
|
decoded = PyUnicode_DecodeUTF8Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
final ? NULL : &consumed);
|
final ? NULL : &consumed);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
@ -282,24 +278,20 @@ static PyObject *
|
||||||
utf_16_decode(PyObject *self,
|
utf_16_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = 0;
|
int byteorder = 0;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded;
|
PyObject *decoded;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_16_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_16_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
return 0;
|
&byteorder, final ? NULL : &consumed);
|
||||||
}
|
PyBuffer_Release(&pbuf);
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder,
|
|
||||||
final ? NULL : &consumed);
|
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
@ -309,53 +301,45 @@ static PyObject *
|
||||||
utf_16_le_decode(PyObject *self,
|
utf_16_le_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = -1;
|
int byteorder = -1;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded = NULL;
|
PyObject *decoded = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_16_le_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_16_le_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (size < 0) {
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors,
|
|
||||||
&byteorder, final ? NULL : &consumed);
|
&byteorder, final ? NULL : &consumed);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
utf_16_be_decode(PyObject *self,
|
utf_16_be_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = 1;
|
int byteorder = 1;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded = NULL;
|
PyObject *decoded = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_16_be_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_16_be_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
return 0;
|
decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
}
|
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors,
|
|
||||||
&byteorder, final ? NULL : &consumed);
|
&byteorder, final ? NULL : &consumed);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
@ -373,24 +357,20 @@ static PyObject *
|
||||||
utf_16_ex_decode(PyObject *self,
|
utf_16_ex_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = 0;
|
int byteorder = 0;
|
||||||
PyObject *unicode, *tuple;
|
PyObject *unicode, *tuple;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zii:utf_16_ex_decode",
|
if (!PyArg_ParseTuple(args, "s*|zii:utf_16_ex_decode",
|
||||||
&data, &size, &errors, &byteorder, &final))
|
&pbuf, &errors, &byteorder, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
unicode = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
return 0;
|
&byteorder, final ? NULL : &consumed);
|
||||||
}
|
PyBuffer_Release(&pbuf);
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
unicode = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder,
|
|
||||||
final ? NULL : &consumed);
|
|
||||||
if (unicode == NULL)
|
if (unicode == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
|
tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
|
||||||
|
@ -402,24 +382,20 @@ static PyObject *
|
||||||
utf_32_decode(PyObject *self,
|
utf_32_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = 0;
|
int byteorder = 0;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded;
|
PyObject *decoded;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_32_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_32_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
return 0;
|
&byteorder, final ? NULL : &consumed);
|
||||||
}
|
PyBuffer_Release(&pbuf);
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder,
|
|
||||||
final ? NULL : &consumed);
|
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
@ -429,53 +405,43 @@ static PyObject *
|
||||||
utf_32_le_decode(PyObject *self,
|
utf_32_le_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = -1;
|
int byteorder = -1;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded = NULL;
|
PyObject *decoded;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_32_le_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_32_le_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
if (size < 0) {
|
decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors,
|
|
||||||
&byteorder, final ? NULL : &consumed);
|
&byteorder, final ? NULL : &consumed);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
utf_32_be_decode(PyObject *self,
|
utf_32_be_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = 1;
|
int byteorder = 1;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
PyObject *decoded = NULL;
|
PyObject *decoded;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:utf_32_be_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:utf_32_be_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors,
|
|
||||||
&byteorder, final ? NULL : &consumed);
|
&byteorder, final ? NULL : &consumed);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (decoded == NULL)
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
|
@ -493,24 +459,20 @@ static PyObject *
|
||||||
utf_32_ex_decode(PyObject *self,
|
utf_32_ex_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int byteorder = 0;
|
int byteorder = 0;
|
||||||
PyObject *unicode, *tuple;
|
PyObject *unicode, *tuple;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
Py_ssize_t consumed;
|
Py_ssize_t consumed;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zii:utf_32_ex_decode",
|
if (!PyArg_ParseTuple(args, "s*|zii:utf_32_ex_decode",
|
||||||
&data, &size, &errors, &byteorder, &final))
|
&pbuf, &errors, &byteorder, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size < 0) {
|
consumed = pbuf.len; /* This is overwritten unless final is true. */
|
||||||
PyErr_SetString(PyExc_ValueError, "negative argument");
|
unicode = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
|
||||||
return 0;
|
&byteorder, final ? NULL : &consumed);
|
||||||
}
|
PyBuffer_Release(&pbuf);
|
||||||
consumed = size; /* This is overwritten unless final is true. */
|
|
||||||
unicode = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder,
|
|
||||||
final ? NULL : &consumed);
|
|
||||||
if (unicode == NULL)
|
if (unicode == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
|
tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
|
||||||
|
@ -522,83 +484,88 @@ static PyObject *
|
||||||
unicode_escape_decode(PyObject *self,
|
unicode_escape_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
|
PyObject *unicode;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|z:unicode_escape_decode",
|
if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode",
|
||||||
&data, &size, &errors))
|
&pbuf, &errors))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return codec_tuple(PyUnicode_DecodeUnicodeEscape(data, size, errors),
|
unicode = PyUnicode_DecodeUnicodeEscape(pbuf.buf, pbuf.len, errors);
|
||||||
size);
|
PyBuffer_Release(&pbuf);
|
||||||
|
return codec_tuple(unicode, pbuf.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
raw_unicode_escape_decode(PyObject *self,
|
raw_unicode_escape_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
|
PyObject *unicode;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|z:raw_unicode_escape_decode",
|
if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode",
|
||||||
&data, &size, &errors))
|
&pbuf, &errors))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return codec_tuple(PyUnicode_DecodeRawUnicodeEscape(data, size, errors),
|
unicode = PyUnicode_DecodeRawUnicodeEscape(pbuf.buf, pbuf.len, errors);
|
||||||
size);
|
PyBuffer_Release(&pbuf);
|
||||||
|
return codec_tuple(unicode, pbuf.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
latin_1_decode(PyObject *self,
|
latin_1_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
PyObject *unicode;
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|z:latin_1_decode",
|
if (!PyArg_ParseTuple(args, "s*|z:latin_1_decode",
|
||||||
&data, &size, &errors))
|
&pbuf, &errors))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return codec_tuple(PyUnicode_DecodeLatin1(data, size, errors),
|
unicode = PyUnicode_DecodeLatin1(pbuf.buf, pbuf.len, errors);
|
||||||
size);
|
PyBuffer_Release(&pbuf);
|
||||||
|
return codec_tuple(unicode, pbuf.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
ascii_decode(PyObject *self,
|
ascii_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
PyObject *unicode;
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|z:ascii_decode",
|
if (!PyArg_ParseTuple(args, "s*|z:ascii_decode",
|
||||||
&data, &size, &errors))
|
&pbuf, &errors))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return codec_tuple(PyUnicode_DecodeASCII(data, size, errors),
|
unicode = PyUnicode_DecodeASCII(pbuf.buf, pbuf.len, errors);
|
||||||
size);
|
PyBuffer_Release(&pbuf);
|
||||||
|
return codec_tuple(unicode, pbuf.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
charmap_decode(PyObject *self,
|
charmap_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size;
|
PyObject *unicode;
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
PyObject *mapping = NULL;
|
PyObject *mapping = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zO:charmap_decode",
|
if (!PyArg_ParseTuple(args, "s*|zO:charmap_decode",
|
||||||
&data, &size, &errors, &mapping))
|
&pbuf, &errors, &mapping))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (mapping == Py_None)
|
if (mapping == Py_None)
|
||||||
mapping = NULL;
|
mapping = NULL;
|
||||||
|
|
||||||
return codec_tuple(PyUnicode_DecodeCharmap(data, size, mapping, errors),
|
unicode = PyUnicode_DecodeCharmap(pbuf.buf, pbuf.len, mapping, errors);
|
||||||
size);
|
PyBuffer_Release(&pbuf);
|
||||||
|
return codec_tuple(unicode, pbuf.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
|
#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
|
||||||
|
@ -607,21 +574,23 @@ static PyObject *
|
||||||
mbcs_decode(PyObject *self,
|
mbcs_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
const char *data;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t size, consumed;
|
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
int final = 0;
|
int final = 0;
|
||||||
PyObject *decoded;
|
Py_ssize_t consumed;
|
||||||
|
PyObject *decoded = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "t#|zi:mbcs_decode",
|
if (!PyArg_ParseTuple(args, "s*|zi:mbcs_decode",
|
||||||
&data, &size, &errors, &final))
|
&pbuf, &errors, &final))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
consumed = pbuf.len;
|
||||||
|
|
||||||
decoded = PyUnicode_DecodeMBCSStateful(
|
decoded = PyUnicode_DecodeMBCSStateful(pbuf.buf, pbuf.len, errors,
|
||||||
data, size, errors, final ? NULL : &consumed);
|
final ? NULL : &consumed);
|
||||||
if (!decoded)
|
PyBuffer_Release(&pbuf);
|
||||||
|
if (decoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(decoded, final ? size : consumed);
|
return codec_tuple(decoded, consumed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
|
|
|
@ -357,7 +357,7 @@ fileio_seekable(PyFileIOObject *self)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
fileio_readinto(PyFileIOObject *self, PyObject *args)
|
fileio_readinto(PyFileIOObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *ptr;
|
Py_buffer pbuf;
|
||||||
Py_ssize_t n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
if (self->fd < 0)
|
if (self->fd < 0)
|
||||||
|
@ -365,13 +365,14 @@ fileio_readinto(PyFileIOObject *self, PyObject *args)
|
||||||
if (!self->readable)
|
if (!self->readable)
|
||||||
return err_mode("reading");
|
return err_mode("reading");
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "w#", &ptr, &n))
|
if (!PyArg_ParseTuple(args, "w*", &pbuf))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
errno = 0;
|
errno = 0;
|
||||||
n = read(self->fd, ptr, n);
|
n = read(self->fd, pbuf.buf, pbuf.len);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
@ -489,22 +490,24 @@ fileio_read(PyFileIOObject *self, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
fileio_write(PyFileIOObject *self, PyObject *args)
|
fileio_write(PyFileIOObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pbuf;
|
||||||
Py_ssize_t n;
|
Py_ssize_t n;
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
if (self->fd < 0)
|
if (self->fd < 0)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
if (!self->writable)
|
if (!self->writable)
|
||||||
return err_mode("writing");
|
return err_mode("writing");
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#", &ptr, &n))
|
if (!PyArg_ParseTuple(args, "s*", &pbuf))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
errno = 0;
|
errno = 0;
|
||||||
n = write(self->fd, ptr, n);
|
n = write(self->fd, pbuf.buf, pbuf.len);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
|
@ -187,21 +187,25 @@ connection_recvbytes_into(ConnectionObject *self, PyObject *args)
|
||||||
char *freeme = NULL, *buffer = NULL;
|
char *freeme = NULL, *buffer = NULL;
|
||||||
Py_ssize_t res, length, offset = 0;
|
Py_ssize_t res, length, offset = 0;
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
|
Py_buffer pbuf;
|
||||||
if (!PyArg_ParseTuple(args, "w#|" F_PY_SSIZE_T,
|
|
||||||
&buffer, &length, &offset))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
CHECK_READABLE(self);
|
CHECK_READABLE(self);
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T,
|
||||||
|
&pbuf, &offset))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buffer = pbuf.buf;
|
||||||
|
length = pbuf.len;
|
||||||
|
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
PyErr_SetString(PyExc_ValueError, "negative offset");
|
PyErr_SetString(PyExc_ValueError, "negative offset");
|
||||||
return NULL;
|
goto _error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset > length) {
|
if (offset > length) {
|
||||||
PyErr_SetString(PyExc_ValueError, "offset too large");
|
PyErr_SetString(PyExc_ValueError, "offset too large");
|
||||||
return NULL;
|
goto _error;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = conn_recv_string(self, buffer+offset, length-offset,
|
res = conn_recv_string(self, buffer+offset, length-offset,
|
||||||
|
@ -231,11 +235,17 @@ connection_recvbytes_into(ConnectionObject *self, PyObject *args)
|
||||||
PyErr_SetObject(BufferTooShort, result);
|
PyErr_SetObject(BufferTooShort, result);
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
}
|
}
|
||||||
return NULL;
|
goto _error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cleanup:
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
_error:
|
||||||
|
result = NULL;
|
||||||
|
goto _cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -792,12 +792,15 @@ static PyObject *
|
||||||
BZ2File_write(BZ2FileObject *self, PyObject *args)
|
BZ2File_write(BZ2FileObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *ret = NULL;
|
PyObject *ret = NULL;
|
||||||
|
Py_buffer pbuf;
|
||||||
char *buf;
|
char *buf;
|
||||||
int len;
|
int len;
|
||||||
int bzerror;
|
int bzerror;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
|
if (!PyArg_ParseTuple(args, "s*:write", &pbuf))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
buf = pbuf.buf;
|
||||||
|
len = pbuf.len;
|
||||||
|
|
||||||
ACQUIRE_LOCK(self);
|
ACQUIRE_LOCK(self);
|
||||||
switch (self->mode) {
|
switch (self->mode) {
|
||||||
|
@ -831,6 +834,7 @@ BZ2File_write(BZ2FileObject *self, PyObject *args)
|
||||||
ret = Py_None;
|
ret = Py_None;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
RELEASE_LOCK(self);
|
RELEASE_LOCK(self);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1549,6 +1553,7 @@ and return what is left in the internal buffers.\n\
|
||||||
static PyObject *
|
static PyObject *
|
||||||
BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
|
BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pdata;
|
||||||
char *data;
|
char *data;
|
||||||
int datasize;
|
int datasize;
|
||||||
int bufsize = SMALLCHUNK;
|
int bufsize = SMALLCHUNK;
|
||||||
|
@ -1557,11 +1562,15 @@ BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
|
||||||
bz_stream *bzs = &self->bzs;
|
bz_stream *bzs = &self->bzs;
|
||||||
int bzerror;
|
int bzerror;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
|
if (!PyArg_ParseTuple(args, "s*:compress", &pdata))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
data = pdata.buf;
|
||||||
|
datasize = pdata.len;
|
||||||
|
|
||||||
if (datasize == 0)
|
if (datasize == 0) {
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return PyString_FromString("");
|
return PyString_FromString("");
|
||||||
|
}
|
||||||
|
|
||||||
ACQUIRE_LOCK(self);
|
ACQUIRE_LOCK(self);
|
||||||
if (!self->running) {
|
if (!self->running) {
|
||||||
|
@ -1606,10 +1615,12 @@ BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
|
||||||
_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
|
_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
|
||||||
|
|
||||||
RELEASE_LOCK(self);
|
RELEASE_LOCK(self);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
RELEASE_LOCK(self);
|
RELEASE_LOCK(self);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_XDECREF(ret);
|
Py_XDECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1833,6 +1844,7 @@ unused_data attribute.\n\
|
||||||
static PyObject *
|
static PyObject *
|
||||||
BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
|
BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pdata;
|
||||||
char *data;
|
char *data;
|
||||||
int datasize;
|
int datasize;
|
||||||
int bufsize = SMALLCHUNK;
|
int bufsize = SMALLCHUNK;
|
||||||
|
@ -1841,8 +1853,10 @@ BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
|
||||||
bz_stream *bzs = &self->bzs;
|
bz_stream *bzs = &self->bzs;
|
||||||
int bzerror;
|
int bzerror;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
|
if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
data = pdata.buf;
|
||||||
|
datasize = pdata.len;
|
||||||
|
|
||||||
ACQUIRE_LOCK(self);
|
ACQUIRE_LOCK(self);
|
||||||
if (!self->running) {
|
if (!self->running) {
|
||||||
|
@ -1899,10 +1913,12 @@ BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
|
||||||
_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
|
_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
|
||||||
|
|
||||||
RELEASE_LOCK(self);
|
RELEASE_LOCK(self);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
RELEASE_LOCK(self);
|
RELEASE_LOCK(self);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_XDECREF(ret);
|
Py_XDECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2041,6 +2057,7 @@ static PyObject *
|
||||||
bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
int compresslevel=9;
|
int compresslevel=9;
|
||||||
|
Py_buffer pdata;
|
||||||
char *data;
|
char *data;
|
||||||
int datasize;
|
int datasize;
|
||||||
int bufsize;
|
int bufsize;
|
||||||
|
@ -2050,14 +2067,17 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
int bzerror;
|
int bzerror;
|
||||||
static char *kwlist[] = {"data", "compresslevel", 0};
|
static char *kwlist[] = {"data", "compresslevel", 0};
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i",
|
||||||
kwlist, &data, &datasize,
|
kwlist, &pdata,
|
||||||
&compresslevel))
|
&compresslevel))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
data = pdata.buf;
|
||||||
|
datasize = pdata.len;
|
||||||
|
|
||||||
if (compresslevel < 1 || compresslevel > 9) {
|
if (compresslevel < 1 || compresslevel > 9) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"compresslevel must be between 1 and 9");
|
"compresslevel must be between 1 and 9");
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2066,8 +2086,10 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
bufsize = datasize + (datasize/100+1) + 600;
|
bufsize = datasize + (datasize/100+1) + 600;
|
||||||
|
|
||||||
ret = PyString_FromStringAndSize(NULL, bufsize);
|
ret = PyString_FromStringAndSize(NULL, bufsize);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memset(bzs, 0, sizeof(bz_stream));
|
memset(bzs, 0, sizeof(bz_stream));
|
||||||
|
|
||||||
|
@ -2079,6 +2101,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
|
bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
|
||||||
if (bzerror != BZ_OK) {
|
if (bzerror != BZ_OK) {
|
||||||
Util_CatchBZ2Error(bzerror);
|
Util_CatchBZ2Error(bzerror);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2092,6 +2115,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
} else if (bzerror != BZ_FINISH_OK) {
|
} else if (bzerror != BZ_FINISH_OK) {
|
||||||
BZ2_bzCompressEnd(bzs);
|
BZ2_bzCompressEnd(bzs);
|
||||||
Util_CatchBZ2Error(bzerror);
|
Util_CatchBZ2Error(bzerror);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2099,6 +2123,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
bufsize = Util_NewBufferSize(bufsize);
|
bufsize = Util_NewBufferSize(bufsize);
|
||||||
if (_PyString_Resize(&ret, bufsize) < 0) {
|
if (_PyString_Resize(&ret, bufsize) < 0) {
|
||||||
BZ2_bzCompressEnd(bzs);
|
BZ2_bzCompressEnd(bzs);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2111,6 +2136,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
|
_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
|
||||||
BZ2_bzCompressEnd(bzs);
|
BZ2_bzCompressEnd(bzs);
|
||||||
|
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2124,6 +2150,7 @@ use an instance of BZ2Decompressor instead.\n\
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bz2_decompress(PyObject *self, PyObject *args)
|
bz2_decompress(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pdata;
|
||||||
char *data;
|
char *data;
|
||||||
int datasize;
|
int datasize;
|
||||||
int bufsize = SMALLCHUNK;
|
int bufsize = SMALLCHUNK;
|
||||||
|
@ -2132,15 +2159,21 @@ bz2_decompress(PyObject *self, PyObject *args)
|
||||||
bz_stream *bzs = &_bzs;
|
bz_stream *bzs = &_bzs;
|
||||||
int bzerror;
|
int bzerror;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
|
if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
data = pdata.buf;
|
||||||
|
datasize = pdata.len;
|
||||||
|
|
||||||
if (datasize == 0)
|
if (datasize == 0) {
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return PyString_FromString("");
|
return PyString_FromString("");
|
||||||
|
}
|
||||||
|
|
||||||
ret = PyString_FromStringAndSize(NULL, bufsize);
|
ret = PyString_FromStringAndSize(NULL, bufsize);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memset(bzs, 0, sizeof(bz_stream));
|
memset(bzs, 0, sizeof(bz_stream));
|
||||||
|
|
||||||
|
@ -2153,6 +2186,7 @@ bz2_decompress(PyObject *self, PyObject *args)
|
||||||
if (bzerror != BZ_OK) {
|
if (bzerror != BZ_OK) {
|
||||||
Util_CatchBZ2Error(bzerror);
|
Util_CatchBZ2Error(bzerror);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2165,6 +2199,7 @@ bz2_decompress(PyObject *self, PyObject *args)
|
||||||
} else if (bzerror != BZ_OK) {
|
} else if (bzerror != BZ_OK) {
|
||||||
BZ2_bzDecompressEnd(bzs);
|
BZ2_bzDecompressEnd(bzs);
|
||||||
Util_CatchBZ2Error(bzerror);
|
Util_CatchBZ2Error(bzerror);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2172,6 +2207,7 @@ bz2_decompress(PyObject *self, PyObject *args)
|
||||||
BZ2_bzDecompressEnd(bzs);
|
BZ2_bzDecompressEnd(bzs);
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"couldn't find end of stream");
|
"couldn't find end of stream");
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2179,6 +2215,7 @@ bz2_decompress(PyObject *self, PyObject *args)
|
||||||
bufsize = Util_NewBufferSize(bufsize);
|
bufsize = Util_NewBufferSize(bufsize);
|
||||||
if (_PyString_Resize(&ret, bufsize) < 0) {
|
if (_PyString_Resize(&ret, bufsize) < 0) {
|
||||||
BZ2_bzDecompressEnd(bzs);
|
BZ2_bzDecompressEnd(bzs);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2190,6 +2227,7 @@ bz2_decompress(PyObject *self, PyObject *args)
|
||||||
if (bzs->avail_out != 0)
|
if (bzs->avail_out != 0)
|
||||||
_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
|
_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
|
||||||
BZ2_bzDecompressEnd(bzs);
|
BZ2_bzDecompressEnd(bzs);
|
||||||
|
PyBuffer_Release(&pdata);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6334,15 +6334,16 @@ Write a string to a file descriptor.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_write(PyObject *self, PyObject *args)
|
posix_write(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pbuf;
|
||||||
int fd;
|
int fd;
|
||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
char *buffer;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "is#:write", &fd, &buffer, &size))
|
if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
|
||||||
return NULL;
|
return NULL;
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
size = write(fd, buffer, (size_t)size);
|
size = write(fd, pbuf.buf, (size_t)pbuf.len);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
return posix_error();
|
return posix_error();
|
||||||
return PyInt_FromSsize_t(size);
|
return PyInt_FromSsize_t(size);
|
||||||
|
|
|
@ -2647,12 +2647,17 @@ sock_send(PySocketSockObject *s, PyObject *args)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int len, n = -1, flags = 0, timeout;
|
int len, n = -1, flags = 0, timeout;
|
||||||
|
Py_buffer pbuf;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
|
if (!PyArg_ParseTuple(args, "s*|i:send", &pbuf, &flags))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!IS_SELECTABLE(s))
|
if (!IS_SELECTABLE(s)) {
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return select_error();
|
return select_error();
|
||||||
|
}
|
||||||
|
buf = pbuf.buf;
|
||||||
|
len = pbuf.len;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
timeout = internal_select(s, 1);
|
timeout = internal_select(s, 1);
|
||||||
|
@ -2664,6 +2669,8 @@ sock_send(PySocketSockObject *s, PyObject *args)
|
||||||
#endif
|
#endif
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
|
|
||||||
if (timeout == 1) {
|
if (timeout == 1) {
|
||||||
PyErr_SetString(socket_timeout, "timed out");
|
PyErr_SetString(socket_timeout, "timed out");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2688,12 +2695,17 @@ sock_sendall(PySocketSockObject *s, PyObject *args)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int len, n = -1, flags = 0, timeout;
|
int len, n = -1, flags = 0, timeout;
|
||||||
|
Py_buffer pbuf;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
|
if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
buf = pbuf.buf;
|
||||||
|
len = pbuf.len;
|
||||||
|
|
||||||
if (!IS_SELECTABLE(s))
|
if (!IS_SELECTABLE(s)) {
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return select_error();
|
return select_error();
|
||||||
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
do {
|
do {
|
||||||
|
@ -2712,6 +2724,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args)
|
||||||
len -= n;
|
len -= n;
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
|
|
||||||
if (timeout == 1) {
|
if (timeout == 1) {
|
||||||
PyErr_SetString(socket_timeout, "timed out");
|
PyErr_SetString(socket_timeout, "timed out");
|
||||||
|
@ -2738,24 +2751,32 @@ to tell how much data has been sent.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sock_sendto(PySocketSockObject *s, PyObject *args)
|
sock_sendto(PySocketSockObject *s, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pbuf;
|
||||||
PyObject *addro;
|
PyObject *addro;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
Py_ssize_t len;
|
||||||
sock_addr_t addrbuf;
|
sock_addr_t addrbuf;
|
||||||
int addrlen, len, n = -1, flags, timeout;
|
int addrlen, n = -1, flags, timeout;
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (!PyArg_ParseTuple(args, "s#O:sendto", &buf, &len, &addro)) {
|
if (!PyArg_ParseTuple(args, "s*O:sendto", &pbuf, &addro)) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
if (!PyArg_ParseTuple(args, "s#iO:sendto",
|
if (!PyArg_ParseTuple(args, "s*iO:sendto",
|
||||||
&buf, &len, &flags, &addro))
|
&pbuf, &flags, &addro))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
buf = pbuf.buf;
|
||||||
|
len = pbuf.len;
|
||||||
|
|
||||||
if (!IS_SELECTABLE(s))
|
if (!IS_SELECTABLE(s)) {
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return select_error();
|
return select_error();
|
||||||
|
}
|
||||||
|
|
||||||
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))
|
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) {
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
timeout = internal_select(s, 1);
|
timeout = internal_select(s, 1);
|
||||||
|
@ -2763,6 +2784,7 @@ sock_sendto(PySocketSockObject *s, PyObject *args)
|
||||||
n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen);
|
n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (timeout == 1) {
|
if (timeout == 1) {
|
||||||
PyErr_SetString(socket_timeout, "timed out");
|
PyErr_SetString(socket_timeout, "timed out");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -362,16 +362,6 @@ PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
|
||||||
return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
|
return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)
|
|
||||||
{
|
|
||||||
if (obj->ob_type->tp_as_buffer != NULL &&
|
|
||||||
obj->ob_type->tp_as_buffer->bf_releasebuffer != NULL) {
|
|
||||||
(*(obj->ob_type->tp_as_buffer->bf_releasebuffer))(obj, view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_IsFortranContiguous(Py_buffer *view)
|
_IsFortranContiguous(Py_buffer *view)
|
||||||
{
|
{
|
||||||
|
@ -603,15 +593,15 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
|
||||||
|
|
||||||
if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;
|
if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;
|
||||||
if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {
|
if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {
|
||||||
PyObject_ReleaseBuffer(dest, &view_dest);
|
PyBuffer_Release(&view_dest);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view_dest.len < view_src.len) {
|
if (view_dest.len < view_src.len) {
|
||||||
PyErr_SetString(PyExc_BufferError,
|
PyErr_SetString(PyExc_BufferError,
|
||||||
"destination is too small to receive data from source");
|
"destination is too small to receive data from source");
|
||||||
PyObject_ReleaseBuffer(dest, &view_dest);
|
PyBuffer_Release(&view_dest);
|
||||||
PyObject_ReleaseBuffer(src, &view_src);
|
PyBuffer_Release(&view_src);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,8 +611,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
|
||||||
PyBuffer_IsContiguous(&view_src, 'F'))) {
|
PyBuffer_IsContiguous(&view_src, 'F'))) {
|
||||||
/* simplest copy is all that is needed */
|
/* simplest copy is all that is needed */
|
||||||
memcpy(view_dest.buf, view_src.buf, view_src.len);
|
memcpy(view_dest.buf, view_src.buf, view_src.len);
|
||||||
PyObject_ReleaseBuffer(dest, &view_dest);
|
PyBuffer_Release(&view_dest);
|
||||||
PyObject_ReleaseBuffer(src, &view_src);
|
PyBuffer_Release(&view_src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,8 +622,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
|
||||||
indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);
|
indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);
|
||||||
if (indices == NULL) {
|
if (indices == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
PyObject_ReleaseBuffer(dest, &view_dest);
|
PyBuffer_Release(&view_dest);
|
||||||
PyObject_ReleaseBuffer(src, &view_src);
|
PyBuffer_Release(&view_src);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (k=0; k<view_src.ndim;k++) {
|
for (k=0; k<view_src.ndim;k++) {
|
||||||
|
@ -651,8 +641,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
|
||||||
memcpy(dptr, sptr, view_src.itemsize);
|
memcpy(dptr, sptr, view_src.itemsize);
|
||||||
}
|
}
|
||||||
PyMem_Free(indices);
|
PyMem_Free(indices);
|
||||||
PyObject_ReleaseBuffer(dest, &view_dest);
|
PyBuffer_Release(&view_dest);
|
||||||
PyObject_ReleaseBuffer(src, &view_src);
|
PyBuffer_Release(&view_src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,7 +671,7 @@ PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
|
PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,
|
||||||
int readonly, int flags)
|
int readonly, int flags)
|
||||||
{
|
{
|
||||||
if (view == NULL) return 0;
|
if (view == NULL) return 0;
|
||||||
|
@ -692,6 +682,7 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view->obj = obj;
|
||||||
view->buf = buf;
|
view->buf = buf;
|
||||||
view->len = len;
|
view->len = len;
|
||||||
view->readonly = readonly;
|
view->readonly = readonly;
|
||||||
|
@ -711,6 +702,17 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PyBuffer_Release(Py_buffer *view)
|
||||||
|
{
|
||||||
|
PyObject *obj = view->obj;
|
||||||
|
if (!obj || !Py_TYPE(obj)->tp_as_buffer || !Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
|
||||||
|
/* Unmanaged buffer */
|
||||||
|
return;
|
||||||
|
Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyObject_Format(PyObject* obj, PyObject *format_spec)
|
PyObject_Format(PyObject* obj, PyObject *format_spec)
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,7 +123,7 @@ bytes_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags)
|
||||||
ptr = "";
|
ptr = "";
|
||||||
else
|
else
|
||||||
ptr = obj->ob_bytes;
|
ptr = obj->ob_bytes;
|
||||||
ret = PyBuffer_FillInfo(view, ptr, Py_SIZE(obj), 0, flags);
|
ret = PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
obj->ob_exports++;
|
obj->ob_exports++;
|
||||||
}
|
}
|
||||||
|
@ -302,9 +302,9 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (va.len != -1)
|
if (va.len != -1)
|
||||||
PyObject_ReleaseBuffer(a, &va);
|
PyBuffer_Release(&va);
|
||||||
if (vb.len != -1)
|
if (vb.len != -1)
|
||||||
PyObject_ReleaseBuffer(b, &vb);
|
PyBuffer_Release(&vb);
|
||||||
return (PyObject *)result;
|
return (PyObject *)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ bytes_iconcat(PyByteArrayObject *self, PyObject *other)
|
||||||
mysize = Py_SIZE(self);
|
mysize = Py_SIZE(self);
|
||||||
size = mysize + vo.len;
|
size = mysize + vo.len;
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
PyObject_ReleaseBuffer(other, &vo);
|
PyBuffer_Release(&vo);
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
}
|
}
|
||||||
if (size < self->ob_alloc) {
|
if (size < self->ob_alloc) {
|
||||||
|
@ -340,11 +340,11 @@ bytes_iconcat(PyByteArrayObject *self, PyObject *other)
|
||||||
self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
|
self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
|
||||||
}
|
}
|
||||||
else if (PyByteArray_Resize((PyObject *)self, size) < 0) {
|
else if (PyByteArray_Resize((PyObject *)self, size) < 0) {
|
||||||
PyObject_ReleaseBuffer(other, &vo);
|
PyBuffer_Release(&vo);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
|
memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
|
||||||
PyObject_ReleaseBuffer(other, &vo);
|
PyBuffer_Release(&vo);
|
||||||
Py_INCREF(self);
|
Py_INCREF(self);
|
||||||
return (PyObject *)self;
|
return (PyObject *)self;
|
||||||
}
|
}
|
||||||
|
@ -555,7 +555,7 @@ bytes_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (vbytes.len != -1)
|
if (vbytes.len != -1)
|
||||||
PyObject_ReleaseBuffer(values, &vbytes);
|
PyBuffer_Release(&vbytes);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,10 +841,10 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
|
||||||
if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
|
if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
|
||||||
if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)
|
if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
PyObject_ReleaseBuffer(arg, &view);
|
PyBuffer_Release(&view);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
PyObject_ReleaseBuffer(arg, &view);
|
PyBuffer_Release(&view);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,7 +1031,7 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
other_size = _getbuffer(other, &other_bytes);
|
other_size = _getbuffer(other, &other_bytes);
|
||||||
if (other_size < 0) {
|
if (other_size < 0) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyObject_ReleaseBuffer(self, &self_bytes);
|
PyBuffer_Release(&self_bytes);
|
||||||
Py_INCREF(Py_NotImplemented);
|
Py_INCREF(Py_NotImplemented);
|
||||||
return Py_NotImplemented;
|
return Py_NotImplemented;
|
||||||
}
|
}
|
||||||
|
@ -1066,8 +1066,8 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
}
|
}
|
||||||
|
|
||||||
res = cmp ? Py_True : Py_False;
|
res = cmp ? Py_True : Py_False;
|
||||||
PyObject_ReleaseBuffer(self, &self_bytes);
|
PyBuffer_Release(&self_bytes);
|
||||||
PyObject_ReleaseBuffer(other, &other_bytes);
|
PyBuffer_Release(&other_bytes);
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1075,6 +1075,11 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
static void
|
static void
|
||||||
bytes_dealloc(PyByteArrayObject *self)
|
bytes_dealloc(PyByteArrayObject *self)
|
||||||
{
|
{
|
||||||
|
if (self->ob_exports > 0) {
|
||||||
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
"deallocated bytearray object has exported buffers");
|
||||||
|
PyErr_Print();
|
||||||
|
}
|
||||||
if (self->ob_bytes != 0) {
|
if (self->ob_bytes != 0) {
|
||||||
PyMem_Free(self->ob_bytes);
|
PyMem_Free(self->ob_bytes);
|
||||||
}
|
}
|
||||||
|
@ -1142,7 +1147,7 @@ bytes_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
|
||||||
res = stringlib_rfind_slice(
|
res = stringlib_rfind_slice(
|
||||||
PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
|
PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
|
||||||
subbuf.buf, subbuf.len, start, end);
|
subbuf.buf, subbuf.len, start, end);
|
||||||
PyObject_ReleaseBuffer(subobj, &subbuf);
|
PyBuffer_Release(&subbuf);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,7 +1197,7 @@ bytes_count(PyByteArrayObject *self, PyObject *args)
|
||||||
count_obj = PyInt_FromSsize_t(
|
count_obj = PyInt_FromSsize_t(
|
||||||
stringlib_count(str + start, end - start, vsub.buf, vsub.len)
|
stringlib_count(str + start, end - start, vsub.buf, vsub.len)
|
||||||
);
|
);
|
||||||
PyObject_ReleaseBuffer(sub_obj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return count_obj;
|
return count_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,7 +1273,7 @@ bytes_contains(PyObject *self, PyObject *arg)
|
||||||
return -1;
|
return -1;
|
||||||
pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
|
pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
|
||||||
varg.buf, varg.len, 0);
|
varg.buf, varg.len, 0);
|
||||||
PyObject_ReleaseBuffer(arg, &varg);
|
PyBuffer_Release(&varg);
|
||||||
return pos >= 0;
|
return pos >= 0;
|
||||||
}
|
}
|
||||||
if (ival < 0 || ival >= 256) {
|
if (ival < 0 || ival >= 256) {
|
||||||
|
@ -1318,7 +1323,7 @@ _bytes_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start,
|
||||||
rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
|
rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
PyObject_ReleaseBuffer(substr, &vsubstr);
|
PyBuffer_Release(&vsubstr);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1498,9 +1503,9 @@ bytes_translate(PyByteArrayObject *self, PyObject *args)
|
||||||
PyByteArray_Resize(result, output - output_start);
|
PyByteArray_Resize(result, output - output_start);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
PyObject_ReleaseBuffer(tableobj, &vtable);
|
PyBuffer_Release(&vtable);
|
||||||
if (delobj != NULL)
|
if (delobj != NULL)
|
||||||
PyObject_ReleaseBuffer(delobj, &vdel);
|
PyBuffer_Release(&vdel);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2122,7 +2127,7 @@ bytes_replace(PyByteArrayObject *self, PyObject *args)
|
||||||
if (_getbuffer(from, &vfrom) < 0)
|
if (_getbuffer(from, &vfrom) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (_getbuffer(to, &vto) < 0) {
|
if (_getbuffer(to, &vto) < 0) {
|
||||||
PyObject_ReleaseBuffer(from, &vfrom);
|
PyBuffer_Release(&vfrom);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2130,8 +2135,8 @@ bytes_replace(PyByteArrayObject *self, PyObject *args)
|
||||||
vfrom.buf, vfrom.len,
|
vfrom.buf, vfrom.len,
|
||||||
vto.buf, vto.len, count);
|
vto.buf, vto.len, count);
|
||||||
|
|
||||||
PyObject_ReleaseBuffer(from, &vfrom);
|
PyBuffer_Release(&vfrom);
|
||||||
PyObject_ReleaseBuffer(to, &vto);
|
PyBuffer_Release(&vto);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2287,7 +2292,7 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
PyErr_SetString(PyExc_ValueError, "empty separator");
|
PyErr_SetString(PyExc_ValueError, "empty separator");
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
|
@ -2295,7 +2300,7 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
|
||||||
|
|
||||||
list = PyList_New(PREALLOC_SIZE(maxsplit));
|
list = PyList_New(PREALLOC_SIZE(maxsplit));
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2323,12 +2328,12 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
|
||||||
#endif
|
#endif
|
||||||
SPLIT_ADD(s, i, len);
|
SPLIT_ADD(s, i, len);
|
||||||
FIX_PREALLOC_SIZE(list);
|
FIX_PREALLOC_SIZE(list);
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
onError:
|
onError:
|
||||||
Py_DECREF(list);
|
Py_DECREF(list);
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2519,7 +2524,7 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
PyErr_SetString(PyExc_ValueError, "empty separator");
|
PyErr_SetString(PyExc_ValueError, "empty separator");
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (n == 1)
|
else if (n == 1)
|
||||||
|
@ -2527,7 +2532,7 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
|
||||||
|
|
||||||
list = PyList_New(PREALLOC_SIZE(maxsplit));
|
list = PyList_New(PREALLOC_SIZE(maxsplit));
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2548,12 +2553,12 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
|
||||||
FIX_PREALLOC_SIZE(list);
|
FIX_PREALLOC_SIZE(list);
|
||||||
if (PyList_Reverse(list) < 0)
|
if (PyList_Reverse(list) < 0)
|
||||||
goto onError;
|
goto onError;
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
onError:
|
onError:
|
||||||
Py_DECREF(list);
|
Py_DECREF(list);
|
||||||
PyObject_ReleaseBuffer(subobj, &vsub);
|
PyBuffer_Release(&vsub);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2828,7 +2833,7 @@ bytes_strip(PyByteArrayObject *self, PyObject *args)
|
||||||
else
|
else
|
||||||
right = rstrip_helper(myptr, mysize, argptr, argsize);
|
right = rstrip_helper(myptr, mysize, argptr, argsize);
|
||||||
if (arg != Py_None)
|
if (arg != Py_None)
|
||||||
PyObject_ReleaseBuffer(arg, &varg);
|
PyBuffer_Release(&varg);
|
||||||
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
|
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2861,7 +2866,7 @@ bytes_lstrip(PyByteArrayObject *self, PyObject *args)
|
||||||
left = lstrip_helper(myptr, mysize, argptr, argsize);
|
left = lstrip_helper(myptr, mysize, argptr, argsize);
|
||||||
right = mysize;
|
right = mysize;
|
||||||
if (arg != Py_None)
|
if (arg != Py_None)
|
||||||
PyObject_ReleaseBuffer(arg, &varg);
|
PyBuffer_Release(&varg);
|
||||||
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
|
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2894,7 +2899,7 @@ bytes_rstrip(PyByteArrayObject *self, PyObject *args)
|
||||||
left = 0;
|
left = 0;
|
||||||
right = rstrip_helper(myptr, mysize, argptr, argsize);
|
right = rstrip_helper(myptr, mysize, argptr, argsize);
|
||||||
if (arg != Py_None)
|
if (arg != Py_None)
|
||||||
PyObject_ReleaseBuffer(arg, &varg);
|
PyBuffer_Release(&varg);
|
||||||
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
|
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1007,6 +1007,7 @@ file_readinto(PyFileObject *f, PyObject *args)
|
||||||
char *ptr;
|
char *ptr;
|
||||||
Py_ssize_t ntodo;
|
Py_ssize_t ntodo;
|
||||||
Py_ssize_t ndone, nnow;
|
Py_ssize_t ndone, nnow;
|
||||||
|
Py_buffer pbuf;
|
||||||
|
|
||||||
if (f->f_fp == NULL)
|
if (f->f_fp == NULL)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
|
@ -1015,8 +1016,10 @@ file_readinto(PyFileObject *f, PyObject *args)
|
||||||
(f->f_bufend - f->f_bufptr) > 0 &&
|
(f->f_bufend - f->f_bufptr) > 0 &&
|
||||||
f->f_buf[0] != '\0')
|
f->f_buf[0] != '\0')
|
||||||
return err_iterbuffered();
|
return err_iterbuffered();
|
||||||
if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo))
|
if (!PyArg_ParseTuple(args, "w*", &pbuf))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
ptr = pbuf.buf;
|
||||||
|
ntodo = pbuf.len;
|
||||||
ndone = 0;
|
ndone = 0;
|
||||||
while (ntodo > 0) {
|
while (ntodo > 0) {
|
||||||
FILE_BEGIN_ALLOW_THREADS(f)
|
FILE_BEGIN_ALLOW_THREADS(f)
|
||||||
|
@ -1029,11 +1032,13 @@ file_readinto(PyFileObject *f, PyObject *args)
|
||||||
break;
|
break;
|
||||||
PyErr_SetFromErrno(PyExc_IOError);
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
clearerr(f->f_fp);
|
clearerr(f->f_fp);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ndone += nnow;
|
ndone += nnow;
|
||||||
ntodo -= nnow;
|
ntodo -= nnow;
|
||||||
}
|
}
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
return PyInt_FromSsize_t(ndone);
|
return PyInt_FromSsize_t(ndone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1611,17 +1616,26 @@ error:
|
||||||
static PyObject *
|
static PyObject *
|
||||||
file_write(PyFileObject *f, PyObject *args)
|
file_write(PyFileObject *f, PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pbuf;
|
||||||
char *s;
|
char *s;
|
||||||
Py_ssize_t n, n2;
|
Py_ssize_t n, n2;
|
||||||
if (f->f_fp == NULL)
|
if (f->f_fp == NULL)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
if (!PyArg_ParseTuple(args, f->f_binary ? "s#" : "t#", &s, &n))
|
if (f->f_binary) {
|
||||||
|
if (!PyArg_ParseTuple(args, "s*", &pbuf))
|
||||||
|
return NULL;
|
||||||
|
s = pbuf.buf;
|
||||||
|
n = pbuf.len;
|
||||||
|
} else
|
||||||
|
if (!PyArg_ParseTuple(args, "t#", &s, &n))
|
||||||
return NULL;
|
return NULL;
|
||||||
f->f_softspace = 0;
|
f->f_softspace = 0;
|
||||||
FILE_BEGIN_ALLOW_THREADS(f)
|
FILE_BEGIN_ALLOW_THREADS(f)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
n2 = fwrite(s, 1, n, f->f_fp);
|
n2 = fwrite(s, 1, n, f->f_fp);
|
||||||
FILE_END_ALLOW_THREADS(f)
|
FILE_END_ALLOW_THREADS(f)
|
||||||
|
if (f->f_binary)
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
if (n2 != n) {
|
if (n2 != n) {
|
||||||
PyErr_SetFromErrno(PyExc_IOError);
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
clearerr(f->f_fp);
|
clearerr(f->f_fp);
|
||||||
|
|
|
@ -1328,7 +1328,8 @@ string_buffer_getcharbuf(PyStringObject *self, Py_ssize_t index, const char **pt
|
||||||
static int
|
static int
|
||||||
string_buffer_getbuffer(PyStringObject *self, Py_buffer *view, int flags)
|
string_buffer_getbuffer(PyStringObject *self, Py_buffer *view, int flags)
|
||||||
{
|
{
|
||||||
return PyBuffer_FillInfo(view, (void *)self->ob_sval, Py_SIZE(self),
|
return PyBuffer_FillInfo(view, (PyObject*)self,
|
||||||
|
(void *)self->ob_sval, Py_SIZE(self),
|
||||||
1, flags);
|
1, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,7 +1360,7 @@ static PyBufferProcs string_as_buffer = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define LEFTSTRIP 0
|
#define LEFTSTRIP 0
|
||||||
#define RIGHTSTRIP 1
|
#define RIGHTSTRIP 1
|
||||||
#define BOTHSTRIP 2
|
#define BOTHSTRIP 2
|
||||||
|
@ -3996,7 +3997,7 @@ PyDoc_STRVAR(p_format__doc__,
|
||||||
\n\
|
\n\
|
||||||
");
|
");
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef
|
static PyMethodDef
|
||||||
string_methods[] = {
|
string_methods[] = {
|
||||||
/* Counterparts of the obsolete stropmodule functions; except
|
/* Counterparts of the obsolete stropmodule functions; except
|
||||||
|
|
122
Python/getargs.c
122
Python/getargs.c
|
@ -44,6 +44,7 @@ static char *converttuple(PyObject *, const char **, va_list *, int,
|
||||||
static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
|
static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
|
||||||
size_t, PyObject **);
|
size_t, PyObject **);
|
||||||
static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
|
static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
|
||||||
|
static int getbuffer(PyObject *, Py_buffer *, char**);
|
||||||
|
|
||||||
static int vgetargskeywords(PyObject *, PyObject *,
|
static int vgetargskeywords(PyObject *, PyObject *,
|
||||||
const char *, char **, va_list *, int);
|
const char *, char **, va_list *, int);
|
||||||
|
@ -773,7 +774,32 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 's': {/* string */
|
case 's': {/* string */
|
||||||
if (*format == '#') {
|
if (*format == '*') {
|
||||||
|
Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
|
||||||
|
|
||||||
|
if (PyString_Check(arg)) {
|
||||||
|
PyBuffer_FillInfo(p, arg,
|
||||||
|
PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
|
||||||
|
1, 0);
|
||||||
|
}
|
||||||
|
#ifdef Py_USING_UNICODE
|
||||||
|
else if (PyUnicode_Check(arg)) {
|
||||||
|
uarg = UNICODE_DEFAULT_ENCODING(arg);
|
||||||
|
if (uarg == NULL)
|
||||||
|
return converterr(CONV_UNICODE,
|
||||||
|
arg, msgbuf, bufsize);
|
||||||
|
PyBuffer_FillInfo(p, arg,
|
||||||
|
PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
|
||||||
|
1, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else { /* any buffer-like object */
|
||||||
|
char *buf;
|
||||||
|
if (getbuffer(arg, p, &buf) < 0)
|
||||||
|
return converterr(buf, arg, msgbuf, bufsize);
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
} else if (*format == '#') {
|
||||||
void **p = (void **)va_arg(*p_va, char **);
|
void **p = (void **)va_arg(*p_va, char **);
|
||||||
FETCH_SIZE;
|
FETCH_SIZE;
|
||||||
|
|
||||||
|
@ -823,7 +849,34 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'z': {/* string, may be NULL (None) */
|
case 'z': {/* string, may be NULL (None) */
|
||||||
if (*format == '#') { /* any buffer-like object */
|
if (*format == '*') {
|
||||||
|
Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
|
||||||
|
|
||||||
|
if (arg == Py_None)
|
||||||
|
PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);
|
||||||
|
else if (PyString_Check(arg)) {
|
||||||
|
PyBuffer_FillInfo(p, arg,
|
||||||
|
PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
|
||||||
|
1, 0);
|
||||||
|
}
|
||||||
|
#ifdef Py_USING_UNICODE
|
||||||
|
else if (PyUnicode_Check(arg)) {
|
||||||
|
uarg = UNICODE_DEFAULT_ENCODING(arg);
|
||||||
|
if (uarg == NULL)
|
||||||
|
return converterr(CONV_UNICODE,
|
||||||
|
arg, msgbuf, bufsize);
|
||||||
|
PyBuffer_FillInfo(p, arg,
|
||||||
|
PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
|
||||||
|
1, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else { /* any buffer-like object */
|
||||||
|
char *buf;
|
||||||
|
if (getbuffer(arg, p, &buf) < 0)
|
||||||
|
return converterr(buf, arg, msgbuf, bufsize);
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
} else if (*format == '#') { /* any buffer-like object */
|
||||||
void **p = (void **)va_arg(*p_va, char **);
|
void **p = (void **)va_arg(*p_va, char **);
|
||||||
FETCH_SIZE;
|
FETCH_SIZE;
|
||||||
|
|
||||||
|
@ -1144,9 +1197,28 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
|
|
||||||
case 'w': { /* memory buffer, read-write access */
|
case 'w': { /* memory buffer, read-write access */
|
||||||
void **p = va_arg(*p_va, void **);
|
void **p = va_arg(*p_va, void **);
|
||||||
|
void *res;
|
||||||
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
|
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
|
||||||
Py_ssize_t count;
|
Py_ssize_t count;
|
||||||
|
|
||||||
|
if (pb && pb->bf_releasebuffer && *format != '*')
|
||||||
|
/* Buffer must be released, yet caller does not use
|
||||||
|
the Py_buffer protocol. */
|
||||||
|
return converterr("pinned buffer", arg, msgbuf, bufsize);
|
||||||
|
|
||||||
|
if (pb && pb->bf_getbuffer && *format == '*') {
|
||||||
|
/* Caller is interested in Py_buffer, and the object
|
||||||
|
supports it directly. */
|
||||||
|
format++;
|
||||||
|
if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return converterr("read-write buffer", arg, msgbuf, bufsize);
|
||||||
|
}
|
||||||
|
if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C'))
|
||||||
|
return converterr("contiguous buffer", arg, msgbuf, bufsize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (pb == NULL ||
|
if (pb == NULL ||
|
||||||
pb->bf_getwritebuffer == NULL ||
|
pb->bf_getwritebuffer == NULL ||
|
||||||
pb->bf_getsegcount == NULL)
|
pb->bf_getsegcount == NULL)
|
||||||
|
@ -1154,13 +1226,20 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
if ((*pb->bf_getsegcount)(arg, NULL) != 1)
|
if ((*pb->bf_getsegcount)(arg, NULL) != 1)
|
||||||
return converterr("single-segment read-write buffer",
|
return converterr("single-segment read-write buffer",
|
||||||
arg, msgbuf, bufsize);
|
arg, msgbuf, bufsize);
|
||||||
if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0)
|
if ((count = pb->bf_getwritebuffer(arg, 0, &res)) < 0)
|
||||||
return converterr("(unspecified)", arg, msgbuf, bufsize);
|
return converterr("(unspecified)", arg, msgbuf, bufsize);
|
||||||
|
if (*format == '*') {
|
||||||
|
PyBuffer_FillInfo((Py_buffer*)p, arg, res, count, 1, 0);
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*p = res;
|
||||||
if (*format == '#') {
|
if (*format == '#') {
|
||||||
FETCH_SIZE;
|
FETCH_SIZE;
|
||||||
STORE_SIZE(count);
|
STORE_SIZE(count);
|
||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,6 +1265,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
"string or single-segment read-only buffer",
|
"string or single-segment read-only buffer",
|
||||||
arg, msgbuf, bufsize);
|
arg, msgbuf, bufsize);
|
||||||
|
|
||||||
|
if (pb->bf_releasebuffer)
|
||||||
|
return converterr(
|
||||||
|
"string or pinned buffer",
|
||||||
|
arg, msgbuf, bufsize);
|
||||||
|
|
||||||
count = pb->bf_getcharbuffer(arg, 0, p);
|
count = pb->bf_getcharbuffer(arg, 0, p);
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
return converterr("(unspecified)", arg, msgbuf, bufsize);
|
return converterr("(unspecified)", arg, msgbuf, bufsize);
|
||||||
|
@ -1212,7 +1296,8 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
|
||||||
Py_ssize_t count;
|
Py_ssize_t count;
|
||||||
if (pb == NULL ||
|
if (pb == NULL ||
|
||||||
pb->bf_getreadbuffer == NULL ||
|
pb->bf_getreadbuffer == NULL ||
|
||||||
pb->bf_getsegcount == NULL) {
|
pb->bf_getsegcount == NULL ||
|
||||||
|
pb->bf_releasebuffer != NULL) {
|
||||||
*errmsg = "string or read-only buffer";
|
*errmsg = "string or read-only buffer";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1226,6 +1311,33 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getbuffer(PyObject *arg, Py_buffer *view, char**errmsg)
|
||||||
|
{
|
||||||
|
void *buf;
|
||||||
|
Py_ssize_t count;
|
||||||
|
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
|
||||||
|
if (pb == NULL) {
|
||||||
|
*errmsg = "string or buffer";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pb->bf_getbuffer) {
|
||||||
|
if (pb->bf_getbuffer(arg, view, 0) < 0)
|
||||||
|
return -1;
|
||||||
|
if (!PyBuffer_IsContiguous(view, 'C')) {
|
||||||
|
*errmsg = "contiguous buffer";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = convertbuffer(arg, &buf, errmsg);
|
||||||
|
if (count < 0)
|
||||||
|
return count;
|
||||||
|
PyBuffer_FillInfo(view, NULL, buf, count, 1, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Support for keyword arguments donated by
|
/* Support for keyword arguments donated by
|
||||||
Geoff Philbrick <philbric@delphi.hks.com> */
|
Geoff Philbrick <philbric@delphi.hks.com> */
|
||||||
|
|
||||||
|
@ -1566,6 +1678,8 @@ skipitem(const char **p_format, va_list *p_va, int flags)
|
||||||
else
|
else
|
||||||
(void) va_arg(*p_va, int *);
|
(void) va_arg(*p_va, int *);
|
||||||
format++;
|
format++;
|
||||||
|
} else if ((c == 's' || c == 'z') && *format == '*') {
|
||||||
|
format++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue