Split PyBytes_FromObject() into subfunctions

This commit is contained in:
Victor Stinner 2015-10-14 13:44:29 +02:00
parent 2ec8063cc9
commit f2eafa323b
1 changed files with 122 additions and 79 deletions

View File

@ -3384,89 +3384,100 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return PyBytes_FromObject(x);
}
PyObject *
PyBytes_FromObject(PyObject *x)
static PyObject*
_PyBytes_FromBuffer(PyObject *x)
{
PyObject *new;
Py_buffer view;
if (PyObject_GetBuffer(x, &view, PyBUF_FULL_RO) < 0)
return NULL;
new = PyBytes_FromStringAndSize(NULL, view.len);
if (!new)
goto fail;
if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
&view, view.len, 'C') < 0)
goto fail;
PyBuffer_Release(&view);
return new;
fail:
Py_XDECREF(new);
PyBuffer_Release(&view);
return NULL;
}
static PyObject*
_PyBytes_FromList(PyObject *x)
{
PyObject *new;
Py_ssize_t i;
Py_ssize_t value;
char *str;
new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
if (new == NULL)
return NULL;
str = ((PyBytesObject *)new)->ob_sval;
for (i = 0; i < Py_SIZE(x); i++) {
value = PyNumber_AsSsize_t(PyList_GET_ITEM(x, i), PyExc_ValueError);
if (value == -1 && PyErr_Occurred())
goto error;
if (value < 0 || value >= 256) {
PyErr_SetString(PyExc_ValueError,
"bytes must be in range(0, 256)");
goto error;
}
*str++ = (char) value;
}
return new;
error:
Py_DECREF(new);
return NULL;
}
static PyObject*
_PyBytes_FromTuple(PyObject *x)
{
PyObject *new;
Py_ssize_t i;
Py_ssize_t value;
char *str;
new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
if (new == NULL)
return NULL;
str = ((PyBytesObject *)new)->ob_sval;
for (i = 0; i < Py_SIZE(x); i++) {
value = PyNumber_AsSsize_t(PyTuple_GET_ITEM(x, i), PyExc_ValueError);
if (value == -1 && PyErr_Occurred())
goto error;
if (value < 0 || value >= 256) {
PyErr_SetString(PyExc_ValueError,
"bytes must be in range(0, 256)");
goto error;
}
*str++ = (char) value;
}
return new;
error:
Py_DECREF(new);
return NULL;
}
static PyObject *
_PyBytes_FromIterator(PyObject *x)
{
PyObject *new, *it;
Py_ssize_t i, size;
if (x == NULL) {
PyErr_BadInternalCall();
return NULL;
}
if (PyBytes_CheckExact(x)) {
Py_INCREF(x);
return x;
}
/* Use the modern buffer interface */
if (PyObject_CheckBuffer(x)) {
Py_buffer view;
if (PyObject_GetBuffer(x, &view, PyBUF_FULL_RO) < 0)
return NULL;
new = PyBytes_FromStringAndSize(NULL, view.len);
if (!new)
goto fail;
if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
&view, view.len, 'C') < 0)
goto fail;
PyBuffer_Release(&view);
return new;
fail:
Py_XDECREF(new);
PyBuffer_Release(&view);
return NULL;
}
if (PyUnicode_Check(x)) {
PyErr_SetString(PyExc_TypeError,
"cannot convert unicode object to bytes");
return NULL;
}
if (PyList_CheckExact(x)) {
new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
if (new == NULL)
return NULL;
for (i = 0; i < Py_SIZE(x); i++) {
Py_ssize_t value = PyNumber_AsSsize_t(
PyList_GET_ITEM(x, i), PyExc_ValueError);
if (value == -1 && PyErr_Occurred()) {
Py_DECREF(new);
return NULL;
}
if (value < 0 || value >= 256) {
PyErr_SetString(PyExc_ValueError,
"bytes must be in range(0, 256)");
Py_DECREF(new);
return NULL;
}
((PyBytesObject *)new)->ob_sval[i] = (char) value;
}
return new;
}
if (PyTuple_CheckExact(x)) {
new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
if (new == NULL)
return NULL;
for (i = 0; i < Py_SIZE(x); i++) {
Py_ssize_t value = PyNumber_AsSsize_t(
PyTuple_GET_ITEM(x, i), PyExc_ValueError);
if (value == -1 && PyErr_Occurred()) {
Py_DECREF(new);
return NULL;
}
if (value < 0 || value >= 256) {
PyErr_SetString(PyExc_ValueError,
"bytes must be in range(0, 256)");
Py_DECREF(new);
return NULL;
}
((PyBytesObject *)new)->ob_sval[i] = (char) value;
}
return new;
}
/* For iterator version, create a string object and resize as needed */
size = PyObject_LengthHint(x, 64);
if (size == -1 && PyErr_Occurred())
@ -3533,6 +3544,38 @@ PyBytes_FromObject(PyObject *x)
return NULL;
}
PyObject *
PyBytes_FromObject(PyObject *x)
{
if (x == NULL) {
PyErr_BadInternalCall();
return NULL;
}
if (PyBytes_CheckExact(x)) {
Py_INCREF(x);
return x;
}
/* Use the modern buffer interface */
if (PyObject_CheckBuffer(x))
return _PyBytes_FromBuffer(x);
if (PyList_CheckExact(x))
return _PyBytes_FromList(x);
if (PyTuple_CheckExact(x))
return _PyBytes_FromTuple(x);
if (PyUnicode_Check(x)) {
PyErr_SetString(PyExc_TypeError,
"cannot convert unicode object to bytes");
return NULL;
}
return _PyBytes_FromIterator(x);
}
static PyObject *
str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{