From: Serhiy Storchaka Date: Mon, 2 Feb 2015 23:25:42 +0000 (+0200) Subject: Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer() X-Git-Tag: v3.5.0a1~44 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3dd3e26680110b3eeadedc9c8457dfe1db2b913c;p=thirdparty%2FPython%2Fcpython.git Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer() and PyObject_AsWriteBuffer(). --- 3dd3e26680110b3eeadedc9c8457dfe1db2b913c diff --cc Include/bytes_methods.h index 290488124a79,1498b8f83c2b..11d5f4275231 --- a/Include/bytes_methods.h +++ b/Include/bytes_methods.h @@@ -21,8 -21,8 +21,8 @@@ extern void _Py_bytes_title(char *resul extern void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len); extern void _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len); -/* This one gets the raw argument list. */ -extern PyObject* _Py_bytes_maketrans(PyObject *args); +/* The maketrans() static method. */ - extern PyObject* _Py_bytes_maketrans(PyObject *frm, PyObject *to); ++extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to); /* Shared __doc__ strings. */ extern const char _Py_isspace__doc__[]; diff --cc Modules/_io/bytesio.c index 56ad788d3f11,57c207341cec..801ddcdc88cd --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@@ -553,14 -437,14 +553,14 @@@ PyDoc_STRVAR(readinto_doc "is set not to block as has no data to read."); static PyObject * - bytesio_readinto(bytesio *self, PyObject *buffer) + bytesio_readinto(bytesio *self, PyObject *arg) { - void *raw_buffer; + Py_buffer buffer; Py_ssize_t len, n; - CHECK_CLOSED(self); + CHECK_CLOSED(self, NULL); - if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1) + if (!PyArg_Parse(arg, "w*", &buffer)) return NULL; /* adjust invalid sizes */ diff --cc Objects/abstract.c index d7dde915197d,7e3121a932c7..483f4da4744b --- a/Objects/abstract.c +++ b/Objects/abstract.c @@@ -352,9 -320,11 +320,11 @@@ int PyObject_AsWriteBuffer(PyObject *ob int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { - if (!PyObject_CheckBuffer(obj)) { + PyBufferProcs *pb = obj->ob_type->tp_as_buffer; + + if (pb == NULL || pb->bf_getbuffer == NULL) { PyErr_Format(PyExc_TypeError, - "'%.100s' does not support the buffer interface", + "a bytes-like object is required, not '%.100s'", Py_TYPE(obj)->tp_name); return -1; } diff --cc Objects/bytearrayobject.c index b9a87d6a3159,f5eb321928a0..ce22f4bb4980 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@@ -1616,12 -1465,17 +1598,12 @@@ bytearray_translate_impl(PyByteArrayObj Py_ssize_t inlen; PyObject *result = NULL; int trans_table[256]; - PyObject *tableobj = NULL, *delobj = NULL; Py_buffer vtable, vdel; - if (!PyArg_UnpackTuple(args, "translate", 1, 2, - &tableobj, &delobj)) - return NULL; - - if (tableobj == Py_None) { + if (table == Py_None) { + table_chars = NULL; table = NULL; - } else if (_getbuffer(table, &vtable) < 0) { - tableobj = NULL; - } else if (PyObject_GetBuffer(tableobj, &vtable, PyBUF_SIMPLE) != 0) { ++ } else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) { return NULL; } else { if (vtable.len != 256) { @@@ -1630,12 -1484,12 +1612,12 @@@ PyBuffer_Release(&vtable); return NULL; } - table = (const char*)vtable.buf; + table_chars = (const char*)vtable.buf; } - if (delobj != NULL) { - if (PyObject_GetBuffer(delobj, &vdel, PyBUF_SIMPLE) != 0) { - if (tableobj != NULL) + if (deletechars != NULL) { - if (_getbuffer(deletechars, &vdel) < 0) { ++ if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) { + if (table != NULL) PyBuffer_Release(&vtable); return NULL; } @@@ -1694,62 -1548,10 +1676,69 @@@ done } +/*[clinic input] + +@staticmethod +bytearray.maketrans + - frm: object - to: object ++ frm: Py_buffer ++ to: Py_buffer + / + +Return a translation table useable for the bytes or bytearray translate method. + +The returned table will be one where each byte in frm is mapped to the byte at +the same position in to. + +The bytes objects frm and to must be of the same length. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytearray_maketrans__doc__, +"maketrans(frm, to, /)\n" +"--\n" +"\n" +"Return a translation table useable for the bytes or bytearray translate method.\n" +"\n" +"The returned table will be one where each byte in frm is mapped to the byte at\n" +"the same position in to.\n" +"\n" +"The bytes objects frm and to must be of the same length."); + +#define BYTEARRAY_MAKETRANS_METHODDEF \ + {"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__}, + +static PyObject * - bytearray_maketrans_impl(PyObject *frm, PyObject *to); ++bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to); + static PyObject * -bytearray_maketrans(PyObject *null, PyObject *args) +bytearray_maketrans(void *null, PyObject *args) { - return _Py_bytes_maketrans(args); + PyObject *return_value = NULL; - PyObject *frm; - PyObject *to; ++ Py_buffer frm = {NULL, NULL}; ++ Py_buffer to = {NULL, NULL}; + - if (!PyArg_UnpackTuple(args, "maketrans", - 2, 2, ++ if (!PyArg_ParseTuple(args, ++ "y*y*:maketrans", + &frm, &to)) + goto exit; - return_value = bytearray_maketrans_impl(frm, to); ++ return_value = bytearray_maketrans_impl(&frm, &to); + +exit: ++ /* Cleanup for frm */ ++ if (frm.obj) ++ PyBuffer_Release(&frm); ++ /* Cleanup for to */ ++ if (to.obj) ++ PyBuffer_Release(&to); ++ + return return_value; +} + +static PyObject * - bytearray_maketrans_impl(PyObject *frm, PyObject *to) - /*[clinic end generated code: output=307752019d9b25b5 input=ea9bdc6b328c15e2]*/ ++bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to) ++/*[clinic end generated code: output=d332622814c26f4b input=5925a81d2fbbf151]*/ +{ + return _Py_bytes_maketrans(frm, to); } @@@ -2240,150 -2042,61 +2229,143 @@@ replace(PyByteArrayObject *self } -PyDoc_STRVAR(replace__doc__, -"B.replace(old, new[, count]) -> bytearray\n\ -\n\ -Return a copy of B with all occurrences of subsection\n\ -old replaced by new. If the optional argument count is\n\ -given, only the first count occurrences are replaced."); +/*[clinic input] +bytearray.replace + - old: object - new: object ++ old: Py_buffer ++ new: Py_buffer + count: Py_ssize_t = -1 + Maximum number of occurrences to replace. + -1 (the default value) means replace all occurrences. + / + +Return a copy with all occurrences of substring old replaced by new. + +If the optional argument count is given, only the first count occurrences are +replaced. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytearray_replace__doc__, +"replace($self, old, new, count=-1, /)\n" +"--\n" +"\n" +"Return a copy with all occurrences of substring old replaced by new.\n" +"\n" +" count\n" +" Maximum number of occurrences to replace.\n" +" -1 (the default value) means replace all occurrences.\n" +"\n" +"If the optional argument count is given, only the first count occurrences are\n" +"replaced."); + +#define BYTEARRAY_REPLACE_METHODDEF \ + {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__}, + +static PyObject * - bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count); ++bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * bytearray_replace(PyByteArrayObject *self, PyObject *args) { - PyObject *res; + PyObject *return_value = NULL; - PyObject *old; - PyObject *new; + Py_buffer old = {NULL, NULL}; + Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count)) - return NULL; + if (!PyArg_ParseTuple(args, - "OO|n:replace", ++ "y*y*|n:replace", + &old, &new, &count)) + goto exit; - return_value = bytearray_replace_impl(self, old, new, count); ++ return_value = bytearray_replace_impl(self, &old, &new, count); - res = (PyObject *)replace((PyByteArrayObject *) self, - (const char *)old.buf, old.len, - (const char *)new.buf, new.len, count); +exit: ++ /* Cleanup for old */ ++ if (old.obj) ++ PyBuffer_Release(&old); ++ /* Cleanup for new */ ++ if (new.obj) ++ PyBuffer_Release(&new); + - PyBuffer_Release(&old); - PyBuffer_Release(&new); - return res; + return return_value; } -PyDoc_STRVAR(split__doc__, -"B.split(sep=None, maxsplit=-1) -> list of bytearrays\n\ -\n\ -Return a list of the sections in B, using sep as the delimiter.\n\ -If sep is not given, B is split on ASCII whitespace characters\n\ -(space, tab, return, newline, formfeed, vertical tab).\n\ -If maxsplit is given, at most maxsplit splits are done."); +static PyObject * - bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count) - /*[clinic end generated code: output=4d2e3c9130da0f96 input=9aaaa123608dfc1f]*/ ++bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) ++/*[clinic end generated code: output=9997fbbd5bac4883 input=aa379d988637c7fb]*/ +{ - PyObject *res; - Py_buffer vold, vnew; - - if (_getbuffer(old, &vold) < 0) - return NULL; - if (_getbuffer(new, &vnew) < 0) { - PyBuffer_Release(&vold); - return NULL; - } - - res = (PyObject *)replace((PyByteArrayObject *) self, - vold.buf, vold.len, - vnew.buf, vnew.len, count); - - PyBuffer_Release(&vold); - PyBuffer_Release(&vnew); - return res; ++ return (PyObject *)replace((PyByteArrayObject *) self, ++ old->buf, old->len, ++ new->buf, new->len, count); +} + +/*[clinic input] +bytearray.split + + sep: object = None + The delimiter according which to split the bytearray. + None (the default value) means split on ASCII whitespace characters + (space, tab, return, newline, formfeed, vertical tab). + maxsplit: Py_ssize_t = -1 + Maximum number of splits to do. + -1 (the default value) means no limit. + +Return a list of the sections in the bytearray, using sep as the delimiter. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytearray_split__doc__, +"split($self, /, sep=None, maxsplit=-1)\n" +"--\n" +"\n" +"Return a list of the sections in the bytearray, using sep as the delimiter.\n" +"\n" +" sep\n" +" The delimiter according which to split the bytearray.\n" +" None (the default value) means split on ASCII whitespace characters\n" +" (space, tab, return, newline, formfeed, vertical tab).\n" +" maxsplit\n" +" Maximum number of splits to do.\n" +" -1 (the default value) means no limit."); + +#define BYTEARRAY_SPLIT_METHODDEF \ + {"split", (PyCFunction)bytearray_split, METH_VARARGS|METH_KEYWORDS, bytearray_split__doc__}, static PyObject * -bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwds) +bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); + +static PyObject * +bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = {"sep", "maxsplit", 0}; - Py_ssize_t len = PyByteArray_GET_SIZE(self), n; + PyObject *return_value = NULL; + static char *_keywords[] = {"sep", "maxsplit", NULL}; + PyObject *sep = Py_None; Py_ssize_t maxsplit = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|On:split", _keywords, + &sep, &maxsplit)) + goto exit; + return_value = bytearray_split_impl(self, sep, maxsplit); + +exit: + return return_value; +} + +static PyObject * +bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) +/*[clinic end generated code: output=062a3d87d6f918fa input=24f82669f41bf523]*/ +{ + Py_ssize_t len = PyByteArray_GET_SIZE(self), n; const char *s = PyByteArray_AS_STRING(self), *sub; - PyObject *list, *subobj = Py_None; + PyObject *list; Py_buffer vsub; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|On:split", - kwlist, &subobj, &maxsplit)) - return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; - if (subobj == Py_None) + if (sep == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) - if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@@ -2563,10 -2185,13 +2545,10 @@@ bytearray_rsplit_impl(PyByteArrayObjec if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; - if (subobj == Py_None) + if (sep == Py_None) return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) - if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@@ -3062,36 -2468,21 +3044,36 @@@ bytearray_strip_impl(PyByteArrayObject static PyObject * bytearray_strip(PyByteArrayObject *self, PyObject *args) { - Py_ssize_t left, right, mysize, argsize; - char *myptr, *argptr; - PyObject *arg = Py_None; - Py_buffer varg; - if (!PyArg_ParseTuple(args, "|O:strip", &arg)) - return NULL; - if (arg == Py_None) { - argptr = "\t\n\r\f\v "; - argsize = 6; + PyObject *return_value = NULL; + PyObject *bytes = Py_None; + + if (!PyArg_UnpackTuple(args, "strip", + 0, 1, + &bytes)) + goto exit; + return_value = bytearray_strip_impl(self, bytes); + +exit: + return return_value; +} + +static PyObject * +bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes) +/*[clinic end generated code: output=2e3d3358acc4c235 input=ef7bb59b09c21d62]*/ +{ + Py_ssize_t left, right, mysize, byteslen; + char *myptr, *bytesptr; + Py_buffer vbytes; + + if (bytes == Py_None) { + bytesptr = "\t\n\r\f\v "; + byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) - if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) return NULL; - argptr = (char *) varg.buf; - argsize = varg.len; + bytesptr = (char *) vbytes.buf; + byteslen = vbytes.len; } myptr = PyByteArray_AS_STRING(self); mysize = Py_SIZE(self); @@@ -3133,36 -2505,21 +3115,36 @@@ bytearray_lstrip_impl(PyByteArrayObjec static PyObject * bytearray_lstrip(PyByteArrayObject *self, PyObject *args) { - Py_ssize_t left, right, mysize, argsize; - char *myptr, *argptr; - PyObject *arg = Py_None; - Py_buffer varg; - if (!PyArg_ParseTuple(args, "|O:lstrip", &arg)) - return NULL; - if (arg == Py_None) { - argptr = "\t\n\r\f\v "; - argsize = 6; + PyObject *return_value = NULL; + PyObject *bytes = Py_None; + + if (!PyArg_UnpackTuple(args, "lstrip", + 0, 1, + &bytes)) + goto exit; + return_value = bytearray_lstrip_impl(self, bytes); + +exit: + return return_value; +} + +static PyObject * +bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes) +/*[clinic end generated code: output=2599309808a9ec02 input=80843f975dd7c480]*/ +{ + Py_ssize_t left, right, mysize, byteslen; + char *myptr, *bytesptr; + Py_buffer vbytes; + + if (bytes == Py_None) { + bytesptr = "\t\n\r\f\v "; + byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) - if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) return NULL; - argptr = (char *) varg.buf; - argsize = varg.len; + bytesptr = (char *) vbytes.buf; + byteslen = vbytes.len; } myptr = PyByteArray_AS_STRING(self); mysize = Py_SIZE(self); @@@ -3201,36 -2539,21 +3183,36 @@@ bytearray_rstrip_impl(PyByteArrayObjec static PyObject * bytearray_rstrip(PyByteArrayObject *self, PyObject *args) { - Py_ssize_t right, mysize, argsize; - char *myptr, *argptr; - PyObject *arg = Py_None; - Py_buffer varg; - if (!PyArg_ParseTuple(args, "|O:rstrip", &arg)) - return NULL; - if (arg == Py_None) { - argptr = "\t\n\r\f\v "; - argsize = 6; + PyObject *return_value = NULL; + PyObject *bytes = Py_None; + + if (!PyArg_UnpackTuple(args, "rstrip", + 0, 1, + &bytes)) + goto exit; + return_value = bytearray_rstrip_impl(self, bytes); + +exit: + return return_value; +} + +static PyObject * +bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes) +/*[clinic end generated code: output=b5ca6259f4f4f2a3 input=e728b994954cfd91]*/ +{ + Py_ssize_t right, mysize, byteslen; + char *myptr, *bytesptr; + Py_buffer vbytes; + + if (bytes == Py_None) { + bytesptr = "\t\n\r\f\v "; + byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) - if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) return NULL; - argptr = (char *) varg.buf; - argsize = varg.len; + bytesptr = (char *) vbytes.buf; + byteslen = vbytes.len; } myptr = PyByteArray_AS_STRING(self); mysize = Py_SIZE(self); diff --cc Objects/bytes_methods.c index 1cf20c97d3fe,9ff7ace0dd1c..a29991584a09 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@@ -363,59 -363,40 +363,27 @@@ for use in the bytes or bytearray trans in frm is mapped to the byte at the same position in to.\n\ The bytes objects frm and to must be of the same length."); - static Py_ssize_t - _getbuffer(PyObject *obj, Py_buffer *view) - { - PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer; - - if (buffer == NULL || buffer->bf_getbuffer == NULL) - { - PyErr_Format(PyExc_TypeError, - "a bytes-like object is required, not '%.100s'", - Py_TYPE(obj)->tp_name); - return -1; - } - - if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0) - return -1; - return view->len; - } - PyObject * - _Py_bytes_maketrans(PyObject *frm, PyObject *to) -_Py_bytes_maketrans(PyObject *args) ++_Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to) { PyObject *res = NULL; - Py_buffer bfrm, bto; - Py_buffer bfrm = {NULL, NULL}; - Py_buffer bto = {NULL, NULL}; Py_ssize_t i; char *p; -- bfrm.len = -1; -- bto.len = -1; -- - if (_getbuffer(frm, &bfrm) < 0) - if (!PyArg_ParseTuple(args, "y*y*:maketrans", &bfrm, &bto)) -- return NULL; - if (_getbuffer(to, &bto) < 0) - goto done; -- if (bfrm.len != bto.len) { ++ if (frm->len != to->len) { PyErr_Format(PyExc_ValueError, "maketrans arguments must have same length"); -- goto done; ++ return NULL; } res = PyBytes_FromStringAndSize(NULL, 256); -- if (!res) { -- goto done; -- } ++ if (!res) ++ return NULL; p = PyBytes_AS_STRING(res); for (i = 0; i < 256; i++) p[i] = (char) i; -- for (i = 0; i < bfrm.len; i++) { -- p[((unsigned char *)bfrm.buf)[i]] = ((char *)bto.buf)[i]; ++ for (i = 0; i < frm->len; i++) { ++ p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i]; } --done: - if (bfrm.len != -1) - if (bfrm.obj != NULL) -- PyBuffer_Release(&bfrm); - if (bto.len != -1) - if (bfrm.obj != NULL) -- PyBuffer_Release(&bto); return res; } diff --cc Objects/bytesobject.c index d4f7d01197b4,e56dbed35514..b2fbc926228d --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@@ -7,38 -7,6 +7,11 @@@ #include "bytes_methods.h" #include +/*[clinic input] +class bytes "PyBytesObject*" "&PyBytes_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/ + - static Py_ssize_t - _getbuffer(PyObject *obj, Py_buffer *view) - { - PyBufferProcs *bufferprocs; - if (PyBytes_CheckExact(obj)) { - /* Fast path, e.g. for .join() of many bytes objects */ - Py_INCREF(obj); - view->obj = obj; - view->buf = PyBytes_AS_STRING(obj); - view->len = PyBytes_GET_SIZE(obj); - return view->len; - } - - bufferprocs = Py_TYPE(obj)->tp_as_buffer; - if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL) - { - PyErr_Format(PyExc_TypeError, - "a bytes-like object is required, not '%.100s'", - Py_TYPE(obj)->tp_name); - return -1; - } - - if (bufferprocs->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0) - return -1; - return view->len; - } - #ifdef COUNT_ALLOCS Py_ssize_t null_strings, one_strings; #endif @@@ -1672,72 -991,37 +1645,72 @@@ static PyBufferProcs bytes_as_buffer = #define RIGHTSTRIP 1 #define BOTHSTRIP 2 -/* Arrays indexed by above */ -static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"}; +/*[clinic input] +bytes.split + + sep: object = None + The delimiter according which to split the bytes. + None (the default value) means split on ASCII whitespace characters + (space, tab, return, newline, formfeed, vertical tab). + maxsplit: Py_ssize_t = -1 + Maximum number of splits to do. + -1 (the default value) means no limit. + +Return a list of the sections in the bytes, using sep as the delimiter. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_split__doc__, +"split($self, /, sep=None, maxsplit=-1)\n" +"--\n" +"\n" +"Return a list of the sections in the bytes, using sep as the delimiter.\n" +"\n" +" sep\n" +" The delimiter according which to split the bytes.\n" +" None (the default value) means split on ASCII whitespace characters\n" +" (space, tab, return, newline, formfeed, vertical tab).\n" +" maxsplit\n" +" Maximum number of splits to do.\n" +" -1 (the default value) means no limit."); + +#define BYTES_SPLIT_METHODDEF \ + {"split", (PyCFunction)bytes_split, METH_VARARGS|METH_KEYWORDS, bytes_split__doc__}, -#define STRIPNAME(i) (stripformat[i]+3) +static PyObject * +bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit); -PyDoc_STRVAR(split__doc__, -"B.split(sep=None, maxsplit=-1) -> list of bytes\n\ -\n\ -Return a list of the sections in B, using sep as the delimiter.\n\ -If sep is not specified or is None, B is split on ASCII whitespace\n\ -characters (space, tab, return, newline, formfeed, vertical tab).\n\ -If maxsplit is given, at most maxsplit splits are done."); +static PyObject * +bytes_split(PyBytesObject*self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"sep", "maxsplit", NULL}; + PyObject *sep = Py_None; + Py_ssize_t maxsplit = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|On:split", _keywords, + &sep, &maxsplit)) + goto exit; + return_value = bytes_split_impl(self, sep, maxsplit); + +exit: + return return_value; +} static PyObject * -bytes_split(PyBytesObject *self, PyObject *args, PyObject *kwds) +bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit) +/*[clinic end generated code: output=c80a47afdd505975 input=8b809b39074abbfa]*/ { - static char *kwlist[] = {"sep", "maxsplit", 0}; Py_ssize_t len = PyBytes_GET_SIZE(self), n; - Py_ssize_t maxsplit = -1; const char *s = PyBytes_AS_STRING(self), *sub; Py_buffer vsub; - PyObject *list, *subobj = Py_None; + PyObject *list; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|On:split", - kwlist, &subobj, &maxsplit)) - return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; - if (subobj == Py_None) + if (sep == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) - if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@@ -1747,176 -1031,85 +1720,202 @@@ return list; } -PyDoc_STRVAR(partition__doc__, -"B.partition(sep) -> (head, sep, tail)\n\ -\n\ -Search for the separator sep in B, and return the part before it,\n\ -the separator itself, and the part after it. If the separator is not\n\ -found, returns B and two empty bytes objects."); +/*[clinic input] +bytes.partition + + self: self(type="PyBytesObject *") - sep: object ++ sep: Py_buffer + / + +Partition the bytes into three parts using the given separator. + +This will search for the separator sep in the bytes. If the separator is found, +returns a 3-tuple containing the part before the separator, the separator +itself, and the part after it. + +If the separator is not found, returns a 3-tuple containing the original bytes +object and two empty bytes objects. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_partition__doc__, +"partition($self, sep, /)\n" +"--\n" +"\n" +"Partition the bytes into three parts using the given separator.\n" +"\n" +"This will search for the separator sep in the bytes. If the separator is found,\n" +"returns a 3-tuple containing the part before the separator, the separator\n" +"itself, and the part after it.\n" +"\n" +"If the separator is not found, returns a 3-tuple containing the original bytes\n" +"object and two empty bytes objects."); + +#define BYTES_PARTITION_METHODDEF \ - {"partition", (PyCFunction)bytes_partition, METH_O, bytes_partition__doc__}, ++ {"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__}, + +static PyObject * - bytes_partition(PyBytesObject *self, PyObject *sep) - /*[clinic end generated code: output=b41e119c873c08bc input=6c5b9dcc5a9fd62e]*/ ++bytes_partition_impl(PyBytesObject *self, Py_buffer *sep); + + static PyObject * -bytes_partition(PyBytesObject *self, PyObject *sep_obj) ++bytes_partition(PyBytesObject *self, PyObject *args) { - const char *sep_chars; - Py_ssize_t sep_len; ++ PyObject *return_value = NULL; + Py_buffer sep = {NULL, NULL}; - PyObject *res; - if (PyBytes_Check(sep)) { - sep_chars = PyBytes_AS_STRING(sep); - sep_len = PyBytes_GET_SIZE(sep); - } - else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len)) - if (PyObject_GetBuffer(sep_obj, &sep, PyBUF_SIMPLE) != 0) -- return NULL; ++ if (!PyArg_ParseTuple(args, ++ "y*:partition", ++ &sep)) ++ goto exit; ++ return_value = bytes_partition_impl(self, &sep); + ++exit: ++ /* Cleanup for sep */ ++ if (sep.obj) ++ PyBuffer_Release(&sep); ++ ++ return return_value; ++} + - res = stringlib_partition( ++static PyObject * ++bytes_partition_impl(PyBytesObject *self, Py_buffer *sep) ++/*[clinic end generated code: output=3006727cfbf83aa4 input=bc855dc63ca949de]*/ ++{ + return stringlib_partition( (PyObject*) self, PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sep, sep_chars, sep_len - sep_obj, sep.buf, sep.len ++ sep->obj, (const char *)sep->buf, sep->len ); - PyBuffer_Release(&sep); - return res; } -PyDoc_STRVAR(rpartition__doc__, -"B.rpartition(sep) -> (head, sep, tail)\n\ -\n\ -Search for the separator sep in B, starting at the end of B,\n\ -and return the part before it, the separator itself, and the\n\ -part after it. If the separator is not found, returns two empty\n\ -bytes objects and B."); +/*[clinic input] +bytes.rpartition + + self: self(type="PyBytesObject *") - sep: object ++ sep: Py_buffer + / + +Partition the bytes into three parts using the given separator. + +This will search for the separator sep in the bytes, starting and the end. If +the separator is found, returns a 3-tuple containing the part before the +separator, the separator itself, and the part after it. + +If the separator is not found, returns a 3-tuple containing two empty bytes +objects and the original bytes object. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_rpartition__doc__, +"rpartition($self, sep, /)\n" +"--\n" +"\n" +"Partition the bytes into three parts using the given separator.\n" +"\n" +"This will search for the separator sep in the bytes, starting and the end. If\n" +"the separator is found, returns a 3-tuple containing the part before the\n" +"separator, the separator itself, and the part after it.\n" +"\n" +"If the separator is not found, returns a 3-tuple containing two empty bytes\n" +"objects and the original bytes object."); + +#define BYTES_RPARTITION_METHODDEF \ - {"rpartition", (PyCFunction)bytes_rpartition, METH_O, bytes_rpartition__doc__}, ++ {"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__}, static PyObject * - bytes_rpartition(PyBytesObject *self, PyObject *sep) - /*[clinic end generated code: output=3a620803657196ee input=79bc2932e78e5ce0]*/ -bytes_rpartition(PyBytesObject *self, PyObject *sep_obj) ++bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep); ++ ++static PyObject * ++bytes_rpartition(PyBytesObject *self, PyObject *args) { - const char *sep_chars; - Py_ssize_t sep_len; ++ PyObject *return_value = NULL; + Py_buffer sep = {NULL, NULL}; - PyObject *res; - if (PyBytes_Check(sep)) { - sep_chars = PyBytes_AS_STRING(sep); - sep_len = PyBytes_GET_SIZE(sep); - } - else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len)) - if (PyObject_GetBuffer(sep_obj, &sep, PyBUF_SIMPLE) != 0) -- return NULL; ++ if (!PyArg_ParseTuple(args, ++ "y*:rpartition", ++ &sep)) ++ goto exit; ++ return_value = bytes_rpartition_impl(self, &sep); ++ ++exit: ++ /* Cleanup for sep */ ++ if (sep.obj) ++ PyBuffer_Release(&sep); + - res = stringlib_rpartition( ++ return return_value; ++} + ++static PyObject * ++bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep) ++/*[clinic end generated code: output=57b169dc47fa90e8 input=6588fff262a9170e]*/ ++{ + return stringlib_rpartition( (PyObject*) self, PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sep, sep_chars, sep_len - sep_obj, sep.buf, sep.len ++ sep->obj, (const char *)sep->buf, sep->len ); - PyBuffer_Release(&sep); - return res; } -PyDoc_STRVAR(rsplit__doc__, -"B.rsplit(sep=None, maxsplit=-1) -> list of bytes\n\ -\n\ -Return a list of the sections in B, using sep as the delimiter,\n\ -starting at the end of B and working to the front.\n\ -If sep is not given, B is split on ASCII whitespace characters\n\ -(space, tab, return, newline, formfeed, vertical tab).\n\ -If maxsplit is given, at most maxsplit splits are done."); +/*[clinic input] +bytes.rsplit = bytes.split + +Return a list of the sections in the bytes, using sep as the delimiter. +Splitting is done starting at the end of the bytes and working to the front. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_rsplit__doc__, +"rsplit($self, /, sep=None, maxsplit=-1)\n" +"--\n" +"\n" +"Return a list of the sections in the bytes, using sep as the delimiter.\n" +"\n" +" sep\n" +" The delimiter according which to split the bytes.\n" +" None (the default value) means split on ASCII whitespace characters\n" +" (space, tab, return, newline, formfeed, vertical tab).\n" +" maxsplit\n" +" Maximum number of splits to do.\n" +" -1 (the default value) means no limit.\n" +"\n" +"Splitting is done starting at the end of the bytes and working to the front."); + +#define BYTES_RSPLIT_METHODDEF \ + {"rsplit", (PyCFunction)bytes_rsplit, METH_VARARGS|METH_KEYWORDS, bytes_rsplit__doc__}, + +static PyObject * +bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -bytes_rsplit(PyBytesObject *self, PyObject *args, PyObject *kwds) +bytes_rsplit(PyBytesObject*self, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = {"sep", "maxsplit", 0}; - Py_ssize_t len = PyBytes_GET_SIZE(self), n; + PyObject *return_value = NULL; + static char *_keywords[] = {"sep", "maxsplit", NULL}; + PyObject *sep = Py_None; Py_ssize_t maxsplit = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|On:rsplit", _keywords, + &sep, &maxsplit)) + goto exit; + return_value = bytes_rsplit_impl(self, sep, maxsplit); + +exit: + return return_value; +} + +static PyObject * +bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit) +/*[clinic end generated code: output=f86feddedbd7b26d input=0f86c9f28f7d7b7b]*/ +{ + Py_ssize_t len = PyBytes_GET_SIZE(self), n; const char *s = PyBytes_AS_STRING(self), *sub; Py_buffer vsub; - PyObject *list, *subobj = Py_None; + PyObject *list; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|On:rsplit", - kwlist, &subobj, &maxsplit)) - return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; - if (subobj == Py_None) + if (sep == Py_None) return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) - if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@@ -2419,55 -1465,37 +2418,61 @@@ bytes_translate_impl(PyBytesObject *sel static PyObject * bytes_translate(PyBytesObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *table; + int group_right_1 = 0; + PyObject *deletechars = NULL; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:translate", &table)) + goto exit; + break; + case 2: + if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) + goto exit; + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "bytes.translate requires 1 to 2 arguments"); + goto exit; + } + return_value = bytes_translate_impl(self, table, group_right_1, deletechars); + +exit: + return return_value; +} + +static PyObject * +bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars) +/*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/ { char *input, *output; + Py_buffer table_view = {NULL, NULL}; + Py_buffer del_table_view = {NULL, NULL}; - const char *table; + const char *table_chars; Py_ssize_t i, c, changed = 0; PyObject *input_obj = (PyObject*)self; - const char *output_start, *del_table=NULL; + const char *output_start, *del_table_chars=NULL; Py_ssize_t inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; - PyObject *tableobj, *delobj = NULL; - - if (!PyArg_UnpackTuple(args, "translate", 1, 2, - &tableobj, &delobj)) - return NULL; - if (PyBytes_Check(tableobj)) { - table = PyBytes_AS_STRING(tableobj); - tablen = PyBytes_GET_SIZE(tableobj); + if (PyBytes_Check(table)) { + table_chars = PyBytes_AS_STRING(table); + tablen = PyBytes_GET_SIZE(table); } - else if (tableobj == Py_None) { - table = NULL; + else if (table == Py_None) { + table_chars = NULL; tablen = 256; } - else if (PyObject_AsCharBuffer(table, &table_chars, &tablen)) - return NULL; + else { - if (PyObject_GetBuffer(tableobj, &table_view, PyBUF_SIMPLE) != 0) ++ if (PyObject_GetBuffer(table, &table_view, PyBUF_SIMPLE) != 0) + return NULL; - table = table_view.buf; ++ table_chars = table_view.buf; + tablen = table_view.len; + } if (tablen != 256) { PyErr_SetString(PyExc_ValueError, @@@ -2475,16 -1504,22 +2481,22 @@@ return NULL; } - if (delobj != NULL) { - if (PyBytes_Check(delobj)) { - del_table = PyBytes_AS_STRING(delobj); - dellen = PyBytes_GET_SIZE(delobj); + if (deletechars != NULL) { + if (PyBytes_Check(deletechars)) { + del_table_chars = PyBytes_AS_STRING(deletechars); + dellen = PyBytes_GET_SIZE(deletechars); } - else if (PyObject_AsCharBuffer(deletechars, &del_table_chars, &dellen)) - return NULL; + else { - if (PyObject_GetBuffer(delobj, &del_table_view, PyBUF_SIMPLE) != 0) { ++ if (PyObject_GetBuffer(deletechars, &del_table_view, PyBUF_SIMPLE) != 0) { + PyBuffer_Release(&table_view); + return NULL; + } - del_table = del_table_view.buf; ++ del_table_chars = del_table_view.buf; + dellen = del_table_view.len; + } } else { - del_table = NULL; + del_table_chars = NULL; dellen = 0; } @@@ -2499,26 -1537,31 +2514,31 @@@ /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); - if (Py_CHARMASK((*output++ = table[c])) != c) + if (Py_CHARMASK((*output++ = table_chars[c])) != c) changed = 1; } - if (changed || !PyBytes_CheckExact(input_obj)) - return result; - Py_DECREF(result); - Py_INCREF(input_obj); - return input_obj; + if (!changed && PyBytes_CheckExact(input_obj)) { + Py_INCREF(input_obj); + Py_DECREF(result); + result = input_obj; + } + PyBuffer_Release(&del_table_view); + PyBuffer_Release(&table_view); + return result; } - if (table == NULL) { + if (table_chars == NULL) { for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(i); } else { for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(table[i]); + trans_table[i] = Py_CHARMASK(table_chars[i]); } + PyBuffer_Release(&table_view); for (i = 0; i < dellen; i++) - trans_table[(int) Py_CHARMASK(del_table[i])] = -1; + trans_table[(int) Py_CHARMASK(del_table_chars[i])] = -1; + PyBuffer_Release(&del_table_view); for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); @@@ -2539,62 -1582,10 +2559,69 @@@ } +/*[clinic input] + +@staticmethod +bytes.maketrans + - frm: object - to: object ++ frm: Py_buffer ++ to: Py_buffer + / + +Return a translation table useable for the bytes or bytearray translate method. + +The returned table will be one where each byte in frm is mapped to the byte at +the same position in to. + +The bytes objects frm and to must be of the same length. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_maketrans__doc__, +"maketrans(frm, to, /)\n" +"--\n" +"\n" +"Return a translation table useable for the bytes or bytearray translate method.\n" +"\n" +"The returned table will be one where each byte in frm is mapped to the byte at\n" +"the same position in to.\n" +"\n" +"The bytes objects frm and to must be of the same length."); + +#define BYTES_MAKETRANS_METHODDEF \ + {"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__}, + static PyObject * - bytes_maketrans_impl(PyObject *frm, PyObject *to); -bytes_maketrans(PyObject *null, PyObject *args) ++bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to); + +static PyObject * +bytes_maketrans(void *null, PyObject *args) +{ + PyObject *return_value = NULL; - PyObject *frm; - PyObject *to; ++ Py_buffer frm = {NULL, NULL}; ++ Py_buffer to = {NULL, NULL}; + - if (!PyArg_UnpackTuple(args, "maketrans", - 2, 2, ++ if (!PyArg_ParseTuple(args, ++ "y*y*:maketrans", + &frm, &to)) + goto exit; - return_value = bytes_maketrans_impl(frm, to); ++ return_value = bytes_maketrans_impl(&frm, &to); + +exit: ++ /* Cleanup for frm */ ++ if (frm.obj) ++ PyBuffer_Release(&frm); ++ /* Cleanup for to */ ++ if (to.obj) ++ PyBuffer_Release(&to); ++ + return return_value; +} + +static PyObject * - bytes_maketrans_impl(PyObject *frm, PyObject *to) - /*[clinic end generated code: output=89a3c3556975e466 input=d204f680f85da382]*/ ++bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) ++/*[clinic end generated code: output=7df47390c476ac60 input=de7a8fc5632bb8f1]*/ { - return _Py_bytes_maketrans(args); + return _Py_bytes_maketrans(frm, to); } /* find and count characters and substrings */ @@@ -3089,84 -2080,31 +3116,74 @@@ replace(PyBytesObject *self } } -PyDoc_STRVAR(replace__doc__, -"B.replace(old, new[, count]) -> bytes\n\ -\n\ -Return a copy of B with all occurrences of subsection\n\ -old replaced by new. If the optional argument count is\n\ -given, only first count occurances are replaced."); + +/*[clinic input] +bytes.replace + - old: object - new: object ++ old: Py_buffer ++ new: Py_buffer + count: Py_ssize_t = -1 + Maximum number of occurrences to replace. + -1 (the default value) means replace all occurrences. + / + +Return a copy with all occurrences of substring old replaced by new. + +If the optional argument count is given, only the first count occurrences are +replaced. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_replace__doc__, +"replace($self, old, new, count=-1, /)\n" +"--\n" +"\n" +"Return a copy with all occurrences of substring old replaced by new.\n" +"\n" +" count\n" +" Maximum number of occurrences to replace.\n" +" -1 (the default value) means replace all occurrences.\n" +"\n" +"If the optional argument count is given, only the first count occurrences are\n" +"replaced."); + +#define BYTES_REPLACE_METHODDEF \ + {"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__}, + +static PyObject * - bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count); ++bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytes_replace(PyBytesObject *self, PyObject *args) +bytes_replace(PyBytesObject*self, PyObject *args) { - PyObject *res; + PyObject *return_value = NULL; - PyObject *old; - PyObject *new; + Py_buffer old = {NULL, NULL}; + Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count)) - return NULL; + if (!PyArg_ParseTuple(args, - "OO|n:replace", ++ "y*y*|n:replace", + &old, &new, &count)) + goto exit; - return_value = bytes_replace_impl(self, old, new, count); ++ return_value = bytes_replace_impl(self, &old, &new, count); - res = (PyObject *)replace((PyBytesObject *) self, - (const char *)old.buf, old.len, - (const char *)new.buf, new.len, count); +exit: ++ /* Cleanup for old */ ++ if (old.obj) ++ PyBuffer_Release(&old); ++ /* Cleanup for new */ ++ if (new.obj) ++ PyBuffer_Release(&new); + - PyBuffer_Release(&old); - PyBuffer_Release(&new); - return res; + return return_value; +} + +static PyObject * - bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count) - /*[clinic end generated code: output=14ce72f4f9cb91cf input=d3ac254ea50f4ac1]*/ ++bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) ++/*[clinic end generated code: output=f07bd9ecf29ee8d8 input=b2fbbf0bf04de8e5]*/ +{ - const char *old_s, *new_s; - Py_ssize_t old_len, new_len; - - if (PyBytes_Check(old)) { - old_s = PyBytes_AS_STRING(old); - old_len = PyBytes_GET_SIZE(old); - } - else if (PyObject_AsCharBuffer(old, &old_s, &old_len)) - return NULL; - - if (PyBytes_Check(new)) { - new_s = PyBytes_AS_STRING(new); - new_len = PyBytes_GET_SIZE(new); - } - else if (PyObject_AsCharBuffer(new, &new_s, &new_len)) - return NULL; - + return (PyObject *)replace((PyBytesObject *) self, - old_s, old_len, - new_s, new_len, count); ++ (const char *)old->buf, old->len, ++ (const char *)new->buf, new->len, count); } /** End DALKE **/ @@@ -3971,45 -2786,9 +4001,45 @@@ PyBytes_Concat(PyObject **pv, PyObject Py_CLEAR(*pv); return; } - v = bytes_concat(*pv, w); - Py_DECREF(*pv); - *pv = v; + + if (Py_REFCNT(*pv) == 1 && PyBytes_CheckExact(*pv)) { + /* Only one reference, so we can resize in place */ + Py_ssize_t oldsize; + Py_buffer wb; + + wb.len = -1; - if (_getbuffer(w, &wb) < 0) { ++ if (PyObject_GetBuffer(w, &wb, PyBUF_SIMPLE) != 0) { + PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", + Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name); + Py_CLEAR(*pv); + return; + } + + oldsize = PyBytes_GET_SIZE(*pv); + if (oldsize > PY_SSIZE_T_MAX - wb.len) { + PyErr_NoMemory(); + goto error; + } + if (_PyBytes_Resize(pv, oldsize + wb.len) < 0) + goto error; + + memcpy(PyBytes_AS_STRING(*pv) + oldsize, wb.buf, wb.len); + PyBuffer_Release(&wb); + return; + + error: + PyBuffer_Release(&wb); + Py_CLEAR(*pv); + return; + } + + else { + /* Multiple references, need to create new object */ + PyObject *v; + v = bytes_concat(*pv, w); + Py_DECREF(*pv); + *pv = v; + } } void diff --cc Python/bltinmodule.c index 068398fb9b8a,4b4f979169bf..f9bb388b5a25 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@@ -678,55 -536,33 +678,55 @@@ builtin_format_impl(PyModuleDef *module return PyObject_Format(value, format_spec); } -PyDoc_STRVAR(format_doc, -"format(value[, format_spec]) -> string\n\ -\n\ -Returns value.__format__(format_spec)\n\ -format_spec defaults to \"\""); +/*[clinic input] +chr as builtin_chr + + i: 'i' + / + +Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff. +[clinic start generated code]*/ + +PyDoc_STRVAR(builtin_chr__doc__, +"chr($module, i, /)\n" +"--\n" +"\n" +"Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff."); + +#define BUILTIN_CHR_METHODDEF \ + {"chr", (PyCFunction)builtin_chr, METH_VARARGS, builtin_chr__doc__}, + +static PyObject * +builtin_chr_impl(PyModuleDef *module, int i); static PyObject * -builtin_chr(PyObject *self, PyObject *args) +builtin_chr(PyModuleDef *module, PyObject *args) { - int x; + PyObject *return_value = NULL; + int i; - if (!PyArg_ParseTuple(args, "i:chr", &x)) - return NULL; + if (!PyArg_ParseTuple(args, + "i:chr", + &i)) + goto exit; + return_value = builtin_chr_impl(module, i); - return PyUnicode_FromOrdinal(x); +exit: + return return_value; } -PyDoc_STRVAR(chr_doc, -"chr(i) -> Unicode character\n\ -\n\ -Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff."); +static PyObject * +builtin_chr_impl(PyModuleDef *module, int i) +/*[clinic end generated code: output=4d6bbe948f56e2ae input=9b1ced29615adf66]*/ +{ + return PyUnicode_FromOrdinal(i); +} - static char * - source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) + static const char * + source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, Py_buffer *view) { - char *str; + const char *str; Py_ssize_t size; if (PyUnicode_Check(cmd)) { @@@ -741,96 -581,32 +745,95 @@@ funcname, what); return NULL; } - else if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) { - return NULL; - } - if (strlen(str) != (size_t)size) { - if (strlen(str) != size) { - PyErr_SetString(PyExc_TypeError, ++ if (strlen(str) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, "source code string cannot contain null bytes"); + PyBuffer_Release(view); return NULL; } return str; } +/*[clinic input] +compile as builtin_compile + + source: 'O' + filename: object(converter="PyUnicode_FSDecoder") + mode: 's' + flags: 'i' = 0 + dont_inherit: 'i' = 0 + optimize: 'i' = -1 + +Compile source into a code object that can be executed by exec() or eval(). + +The source code may represent a Python module, statement or expression. +The filename will be used for run-time error messages. +The mode must be 'exec' to compile a module, 'single' to compile a +single (interactive) statement, or 'eval' to compile an expression. +The flags argument, if present, controls which future statements influence +the compilation of the code. +The dont_inherit argument, if non-zero, stops the compilation inheriting +the effects of any future statements in effect in the code calling +compile; if absent or zero these statements do influence the compilation, +in addition to any features explicitly specified. +[clinic start generated code]*/ + +PyDoc_STRVAR(builtin_compile__doc__, +"compile($module, /, source, filename, mode, flags=0, dont_inherit=0,\n" +" optimize=-1)\n" +"--\n" +"\n" +"Compile source into a code object that can be executed by exec() or eval().\n" +"\n" +"The source code may represent a Python module, statement or expression.\n" +"The filename will be used for run-time error messages.\n" +"The mode must be \'exec\' to compile a module, \'single\' to compile a\n" +"single (interactive) statement, or \'eval\' to compile an expression.\n" +"The flags argument, if present, controls which future statements influence\n" +"the compilation of the code.\n" +"The dont_inherit argument, if non-zero, stops the compilation inheriting\n" +"the effects of any future statements in effect in the code calling\n" +"compile; if absent or zero these statements do influence the compilation,\n" +"in addition to any features explicitly specified."); + +#define BUILTIN_COMPILE_METHODDEF \ + {"compile", (PyCFunction)builtin_compile, METH_VARARGS|METH_KEYWORDS, builtin_compile__doc__}, + +static PyObject * +builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize); + static PyObject * -builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) +builtin_compile(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - Py_buffer view = {NULL, NULL}; - const char *str; + PyObject *return_value = NULL; + static char *_keywords[] = {"source", "filename", "mode", "flags", "dont_inherit", "optimize", NULL}; + PyObject *source; PyObject *filename; - char *startstr; - int mode = -1; + const char *mode; + int flags = 0; int dont_inherit = 0; - int supplied_flags = 0; int optimize = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "OO&s|iii:compile", _keywords, + &source, PyUnicode_FSDecoder, &filename, &mode, &flags, &dont_inherit, &optimize)) + goto exit; + return_value = builtin_compile_impl(module, source, filename, mode, flags, dont_inherit, optimize); + +exit: + return return_value; +} + +static PyObject * +builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) +/*[clinic end generated code: output=c72d197809d178fc input=c6212a9d21472f7e]*/ +{ - char *str; ++ Py_buffer view = {NULL, NULL}; ++ const char *str; + int compile_mode = -1; int is_ast; PyCompilerFlags cf; - PyObject *cmd; - static char *kwlist[] = {"source", "filename", "mode", "flags", - "dont_inherit", "optimize", NULL}; int start[] = {Py_file_input, Py_eval_input, Py_single_input}; PyObject *result; @@@ -898,11 -681,12 +901,12 @@@ goto finally; } - str = source_as_string(source, "compile", "string, bytes or AST", &cf); - str = source_as_string(cmd, "compile", "string, bytes or AST", &cf, &view); ++ str = source_as_string(source, "compile", "string, bytes or AST", &cf, &view); if (str == NULL) goto error; - result = Py_CompileStringObject(str, filename, start[mode], &cf, optimize); + result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize); + PyBuffer_Release(&view); goto finally; error: @@@ -937,114 -735,33 +941,115 @@@ PyDoc_STRVAR(dir_doc " for any other object: its attributes, its class's attributes, and\n" " recursively the attributes of its class's base classes."); +/*[clinic input] +divmod as builtin_divmod + + x: 'O' + y: 'O' + / + +Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x. +[clinic start generated code]*/ + +PyDoc_STRVAR(builtin_divmod__doc__, +"divmod($module, x, y, /)\n" +"--\n" +"\n" +"Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x."); + +#define BUILTIN_DIVMOD_METHODDEF \ + {"divmod", (PyCFunction)builtin_divmod, METH_VARARGS, builtin_divmod__doc__}, + +static PyObject * +builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y); + static PyObject * -builtin_divmod(PyObject *self, PyObject *args) +builtin_divmod(PyModuleDef *module, PyObject *args) { - PyObject *v, *w; + PyObject *return_value = NULL; + PyObject *x; + PyObject *y; + + if (!PyArg_UnpackTuple(args, "divmod", + 2, 2, + &x, &y)) + goto exit; + return_value = builtin_divmod_impl(module, x, y); + +exit: + return return_value; +} - if (!PyArg_UnpackTuple(args, "divmod", 2, 2, &v, &w)) - return NULL; - return PyNumber_Divmod(v, w); +static PyObject * +builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y) +/*[clinic end generated code: output=77e8d408b1338886 input=c9c617b7bb74c615]*/ +{ + return PyNumber_Divmod(x, y); } -PyDoc_STRVAR(divmod_doc, -"divmod(x, y) -> (div, mod)\n\ -\n\ -Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x."); +/*[clinic input] +eval as builtin_eval + + source: 'O' + globals: 'O' = None + locals: 'O' = None + / + +Evaluate the given source in the context of globals and locals. + +The source may be a string representing a Python expression +or a code object as returned by compile(). +The globals must be a dictionary and locals can be any mapping, +defaulting to the current globals and locals. +If only globals is given, locals defaults to it. +[clinic start generated code]*/ + +PyDoc_STRVAR(builtin_eval__doc__, +"eval($module, source, globals=None, locals=None, /)\n" +"--\n" +"\n" +"Evaluate the given source in the context of globals and locals.\n" +"\n" +"The source may be a string representing a Python expression\n" +"or a code object as returned by compile().\n" +"The globals must be a dictionary and locals can be any mapping,\n" +"defaulting to the current globals and locals.\n" +"If only globals is given, locals defaults to it."); + +#define BUILTIN_EVAL_METHODDEF \ + {"eval", (PyCFunction)builtin_eval, METH_VARARGS, builtin_eval__doc__}, + +static PyObject * +builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals); static PyObject * -builtin_eval(PyObject *self, PyObject *args) +builtin_eval(PyModuleDef *module, PyObject *args) { - PyObject *cmd, *result, *tmp = NULL; - PyObject *globals = Py_None, *locals = Py_None; + PyObject *return_value = NULL; + PyObject *source; + PyObject *globals = Py_None; + PyObject *locals = Py_None; + + if (!PyArg_UnpackTuple(args, "eval", + 1, 3, + &source, &globals, &locals)) + goto exit; + return_value = builtin_eval_impl(module, source, globals, locals); + +exit: + return return_value; +} + +static PyObject * +builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) +/*[clinic end generated code: output=644fd59012538ce6 input=31e42c1d2125b50b]*/ +{ + PyObject *result, *tmp = NULL; - char *str; + Py_buffer view = {NULL, NULL}; + const char *str; PyCompilerFlags cf; - if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals)) - return NULL; if (locals != Py_None && !PyMapping_Check(locals)) { PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); return NULL; @@@ -1089,7 -806,7 +1094,7 @@@ } cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(source, "eval", "string, bytes or code", &cf); - str = source_as_string(cmd, "eval", "string, bytes or code", &cf, &view); ++ str = source_as_string(source, "eval", "string, bytes or code", &cf, &view); if (str == NULL) return NULL; @@@ -1201,14 -879,15 +1207,15 @@@ builtin_exec_impl(PyModuleDef *module, "contain free variables"); return NULL; } - v = PyEval_EvalCode(prog, globals, locals); + v = PyEval_EvalCode(source, globals, locals); } else { - char *str; + Py_buffer view = {NULL, NULL}; + const char *str; PyCompilerFlags cf; cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(prog, "exec", - "string, bytes or code", &cf, &view); + str = source_as_string(source, "exec", - "string, bytes or code", &cf); ++ "string, bytes or code", &cf, &view); if (str == NULL) return NULL; if (PyEval_MergeCompilerFlags(&cf))