diff -r da14ffe01f08 Objects/bytesobject.c --- a/Objects/bytesobject.c Fri Jan 06 17:44:43 2017 +0900 +++ b/Objects/bytesobject.c Fri Jan 06 19:38:59 2017 +0900 @@ -2313,6 +2313,52 @@ bytes_splitlines_impl(PyBytesObject *sel /*[clinic input] @classmethod +bytes.frombuffer + + byteslike: Py_buffer + length: Py_ssize_t = -1 + offset: Py_ssize_t = 0 + +Create a bytes object from bytes-like object. + +Examples: + bytes.frombuffer(b'abcd') -> b'abcd' + bytes.frombuffer(b'abcd', 2) -> b'ab' + bytes.frombuffer(b'abcd', 8) -> b'abcd' + bytes.frombuffer(b'abcd', offset=2) -> b'cd' + bytes.frombuffer(b'abcd', 1, 2) -> b'c' +[clinic start generated code]*/ + +static PyObject * +bytes_frombuffer_impl(PyTypeObject *type, Py_buffer *byteslike, + Py_ssize_t length, Py_ssize_t offset) +/*[clinic end generated code: output=b55ccc7ef1822501 input=abf5f3799bb68df8]*/ +{ + assert(PyBuffer_IsContiguous(byteslike, 'C')); + if (offset < 0) { + PyErr_Format(PyExc_ValueError, "offset must >= 0, got %zd", offset); + return NULL; + } + + Py_ssize_t len = byteslike->len - offset; + if (length >= 0 && len > length) { + len = length; + } + if (len < 0) { + len = 0; + } + + PyObject *result = PyBytes_FromStringAndSize( + (char*)byteslike->buf + offset, len); + if (type != &PyBytes_Type && result != NULL) { + Py_SETREF(result, PyObject_CallFunctionObjArgs((PyObject *)type, + result, NULL)); + } + return result; +} + +/*[clinic input] +@classmethod bytes.fromhex string: unicode @@ -2450,6 +2496,7 @@ bytes_methods[] = { _Py_expandtabs__doc__}, {"find", (PyCFunction)bytes_find, METH_VARARGS, _Py_find__doc__}, + BYTES_FROMBUFFER_METHODDEF BYTES_FROMHEX_METHODDEF {"hex", (PyCFunction)bytes_hex, METH_NOARGS, hex__doc__}, {"index", (PyCFunction)bytes_index, METH_VARARGS, _Py_index__doc__}, diff -r da14ffe01f08 Objects/clinic/bytesobject.c.h --- a/Objects/clinic/bytesobject.c.h Fri Jan 06 17:44:43 2017 +0900 +++ b/Objects/clinic/bytesobject.c.h Fri Jan 06 19:38:59 2017 +0900 @@ -470,6 +470,51 @@ exit: return return_value; } +PyDoc_STRVAR(bytes_frombuffer__doc__, +"frombuffer($type, /, byteslike, length=-1, offset=0)\n" +"--\n" +"\n" +"Create a bytes object from bytes-like object.\n" +"\n" +"Examples:\n" +" bytes.frombuffer(b\'abcd\') -> b\'abcd\'\n" +" bytes.frombuffer(b\'abcd\', 2) -> b\'ab\'\n" +" bytes.frombuffer(b\'abcd\', 8) -> b\'abcd\'\n" +" bytes.frombuffer(b\'abcd\', offset=2) -> b\'cd\'\n" +" bytes.frombuffer(b\'abcd\', 1, 2) -> b\'c\'"); + +#define BYTES_FROMBUFFER_METHODDEF \ + {"frombuffer", (PyCFunction)bytes_frombuffer, METH_FASTCALL|METH_CLASS, bytes_frombuffer__doc__}, + +static PyObject * +bytes_frombuffer_impl(PyTypeObject *type, Py_buffer *byteslike, + Py_ssize_t length, Py_ssize_t offset); + +static PyObject * +bytes_frombuffer(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"byteslike", "length", "offset", NULL}; + static _PyArg_Parser _parser = {"y*|nn:frombuffer", _keywords, 0}; + Py_buffer byteslike = {NULL, NULL}; + Py_ssize_t length = -1; + Py_ssize_t offset = 0; + + if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser, + &byteslike, &length, &offset)) { + goto exit; + } + return_value = bytes_frombuffer_impl(type, &byteslike, length, offset); + +exit: + /* Cleanup for byteslike */ + if (byteslike.obj) { + PyBuffer_Release(&byteslike); + } + + return return_value; +} + PyDoc_STRVAR(bytes_fromhex__doc__, "fromhex($type, string, /)\n" "--\n" @@ -499,4 +544,4 @@ bytes_fromhex(PyTypeObject *type, PyObje exit: return return_value; } -/*[clinic end generated code: output=2dc3c93cfd2dc440 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e52fcfe6b79a9845 input=a9049054013a1b77]*/