diff options
Diffstat (limited to 'Objects/bytesobject.c')
| -rw-r--r-- | Objects/bytesobject.c | 1095 | 
1 files changed, 833 insertions, 262 deletions
| diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index b93b9ef10d..f0c26c33e5 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -7,6 +7,11 @@  #include "bytes_methods.h"  #include <stddef.h> +/*[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)  { @@ -71,15 +76,12 @@ static PyBytesObject *nullstring;     PyBytes_FromStringAndSize()) or the length of the string in the `str'     parameter (for PyBytes_FromString()).  */ -PyObject * -PyBytes_FromStringAndSize(const char *str, Py_ssize_t size) +static PyObject * +_PyBytes_FromSize(Py_ssize_t size, int use_calloc)  {      PyBytesObject *op; -    if (size < 0) { -        PyErr_SetString(PyExc_SystemError, -            "Negative size passed to PyBytes_FromStringAndSize"); -        return NULL; -    } +    assert(size >= 0); +      if (size == 0 && (op = nullstring) != NULL) {  #ifdef COUNT_ALLOCS          null_strings++; @@ -87,36 +89,60 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)          Py_INCREF(op);          return (PyObject *)op;      } -    if (size == 1 && str != NULL && -        (op = characters[*str & UCHAR_MAX]) != NULL) -    { -#ifdef COUNT_ALLOCS -        one_strings++; -#endif -        Py_INCREF(op); -        return (PyObject *)op; -    } -    if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) { +    if ((size_t)size > (size_t)PY_SSIZE_T_MAX - PyBytesObject_SIZE) {          PyErr_SetString(PyExc_OverflowError,                          "byte string is too large");          return NULL;      }      /* Inline PyObject_NewVar */ -    op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size); +    if (use_calloc) +        op = (PyBytesObject *)PyObject_Calloc(1, PyBytesObject_SIZE + size); +    else +        op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + size);      if (op == NULL)          return PyErr_NoMemory();      (void)PyObject_INIT_VAR(op, &PyBytes_Type, size);      op->ob_shash = -1; -    if (str != NULL) -        Py_MEMCPY(op->ob_sval, str, size); -    op->ob_sval[size] = '\0'; -    /* share short strings */ +    if (!use_calloc) +        op->ob_sval[size] = '\0'; +    /* empty byte string singleton */      if (size == 0) {          nullstring = op;          Py_INCREF(op); -    } else if (size == 1 && str != NULL) { +    } +    return (PyObject *) op; +} + +PyObject * +PyBytes_FromStringAndSize(const char *str, Py_ssize_t size) +{ +    PyBytesObject *op; +    if (size < 0) { +        PyErr_SetString(PyExc_SystemError, +            "Negative size passed to PyBytes_FromStringAndSize"); +        return NULL; +    } +    if (size == 1 && str != NULL && +        (op = characters[*str & UCHAR_MAX]) != NULL) +    { +#ifdef COUNT_ALLOCS +        one_strings++; +#endif +        Py_INCREF(op); +        return (PyObject *)op; +    } + +    op = (PyBytesObject *)_PyBytes_FromSize(size, 0); +    if (op == NULL) +        return NULL; +    if (str == NULL) +        return (PyObject *) op; + +    Py_MEMCPY(op->ob_sval, str, size); +    /* share short strings */ +    if (size == 1) {          characters[*str & UCHAR_MAX] = op;          Py_INCREF(op);      } @@ -974,7 +1000,7 @@ bytes_subscript(PyBytesObject* self, PyObject* item)      }      else {          PyErr_Format(PyExc_TypeError, -                     "byte indices must be integers, not %.200s", +                     "byte indices must be integers or slices, not %.200s",                       Py_TYPE(item)->tp_name);          return NULL;      } @@ -1014,37 +1040,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(subobj, &vsub) < 0) +    if (_getbuffer(sep, &vsub) < 0)          return NULL;      sub = vsub.buf;      n = vsub.len; @@ -1054,89 +1115,176 @@ bytes_split(PyBytesObject *self, PyObject *args, PyObject *kwds)      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 +    / + +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__},  static PyObject * -bytes_partition(PyBytesObject *self, PyObject *sep_obj) +bytes_partition(PyBytesObject *self, PyObject *sep) +/*[clinic end generated code: output=b41e119c873c08bc input=6c5b9dcc5a9fd62e]*/  { -    const char *sep; +    const char *sep_chars;      Py_ssize_t sep_len; -    if (PyBytes_Check(sep_obj)) { -        sep = PyBytes_AS_STRING(sep_obj); -        sep_len = PyBytes_GET_SIZE(sep_obj); +    if (PyBytes_Check(sep)) { +        sep_chars = PyBytes_AS_STRING(sep); +        sep_len = PyBytes_GET_SIZE(sep);      } -    else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len)) +    else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len))          return NULL;      return stringlib_partition(          (PyObject*) self,          PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), -        sep_obj, sep, sep_len +        sep, sep_chars, sep_len          );  } -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 +    / + +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__},  static PyObject * -bytes_rpartition(PyBytesObject *self, PyObject *sep_obj) +bytes_rpartition(PyBytesObject *self, PyObject *sep) +/*[clinic end generated code: output=3a620803657196ee input=79bc2932e78e5ce0]*/  { -    const char *sep; +    const char *sep_chars;      Py_ssize_t sep_len; -    if (PyBytes_Check(sep_obj)) { -        sep = PyBytes_AS_STRING(sep_obj); -        sep_len = PyBytes_GET_SIZE(sep_obj); +    if (PyBytes_Check(sep)) { +        sep_chars = PyBytes_AS_STRING(sep); +        sep_len = PyBytes_GET_SIZE(sep);      } -    else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len)) +    else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len))          return NULL;      return stringlib_rpartition(          (PyObject*) self,          PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), -        sep_obj, sep, sep_len +        sep, sep_chars, sep_len          );  } -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(PyBytesObject *self, PyObject *args, PyObject *kwds) +bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit); + +static PyObject * +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(subobj, &vsub) < 0) +    if (_getbuffer(sep, &vsub) < 0)          return NULL;      sub = vsub.buf;      n = vsub.len; @@ -1147,16 +1295,41 @@ bytes_rsplit(PyBytesObject *self, PyObject *args, PyObject *kwds)  } -PyDoc_STRVAR(join__doc__, -"B.join(iterable_of_bytes) -> bytes\n\ -\n\ -Concatenate any number of bytes objects, with B in between each pair.\n\ -Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'."); +/*[clinic input] +bytes.join + +    iterable_of_bytes: object +    / + +Concatenate any number of bytes objects. + +The bytes whose method is called is inserted in between each pair. + +The result is returned as a new bytes object. + +Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_join__doc__, +"join($self, iterable_of_bytes, /)\n" +"--\n" +"\n" +"Concatenate any number of bytes objects.\n" +"\n" +"The bytes whose method is called is inserted in between each pair.\n" +"\n" +"The result is returned as a new bytes object.\n" +"\n" +"Example: b\'.\'.join([b\'ab\', b\'pq\', b\'rs\']) -> b\'ab.pq.rs\'."); + +#define BYTES_JOIN_METHODDEF    \ +    {"join", (PyCFunction)bytes_join, METH_O, bytes_join__doc__},  static PyObject * -bytes_join(PyObject *self, PyObject *iterable) +bytes_join(PyBytesObject*self, PyObject *iterable_of_bytes) +/*[clinic end generated code: output=e541a14a8da97908 input=7fe377b95bd549d2]*/  { -    return stringlib_bytes_join(self, iterable); +    return stringlib_bytes_join((PyObject*)self, iterable_of_bytes);  }  PyObject * @@ -1164,7 +1337,7 @@ _PyBytes_Join(PyObject *sep, PyObject *x)  {      assert(sep != NULL && PyBytes_Check(sep));      assert(x != NULL); -    return bytes_join(sep, x); +    return bytes_join((PyBytesObject*)sep, x);  }  /* helper macro to fixup start/end slice values */ @@ -1375,62 +1548,159 @@ do_strip(PyBytesObject *self, int striptype)  Py_LOCAL_INLINE(PyObject *) -do_argstrip(PyBytesObject *self, int striptype, PyObject *args) +do_argstrip(PyBytesObject *self, int striptype, PyObject *bytes)  { -    PyObject *sep = NULL; - -    if (!PyArg_ParseTuple(args, stripformat[striptype], &sep)) -        return NULL; - -    if (sep != NULL && sep != Py_None) { -        return do_xstrip(self, striptype, sep); +    if (bytes != NULL && bytes != Py_None) { +        return do_xstrip(self, striptype, bytes);      }      return do_strip(self, striptype);  } +/*[clinic input] +bytes.strip + +    self: self(type="PyBytesObject *") +    bytes: object = None +    / + +Strip leading and trailing bytes contained in the argument. + +If the argument is omitted or None, strip leading and trailing ASCII whitespace. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_strip__doc__, +"strip($self, bytes=None, /)\n" +"--\n" +"\n" +"Strip leading and trailing bytes contained in the argument.\n" +"\n" +"If the argument is omitted or None, strip leading and trailing ASCII whitespace."); + +#define BYTES_STRIP_METHODDEF    \ +    {"strip", (PyCFunction)bytes_strip, METH_VARARGS, bytes_strip__doc__}, + +static PyObject * +bytes_strip_impl(PyBytesObject *self, PyObject *bytes); -PyDoc_STRVAR(strip__doc__, -"B.strip([bytes]) -> bytes\n\ -\n\ -Strip leading and trailing bytes contained in the argument.\n\ -If the argument is omitted, strip leading and trailing ASCII whitespace.");  static PyObject *  bytes_strip(PyBytesObject *self, PyObject *args)  { -    if (PyTuple_GET_SIZE(args) == 0) -        return do_strip(self, BOTHSTRIP); /* Common case */ -    else -        return do_argstrip(self, BOTHSTRIP, args); +    PyObject *return_value = NULL; +    PyObject *bytes = Py_None; + +    if (!PyArg_UnpackTuple(args, "strip", +        0, 1, +        &bytes)) +        goto exit; +    return_value = bytes_strip_impl(self, bytes); + +exit: +    return return_value; +} + +static PyObject * +bytes_strip_impl(PyBytesObject *self, PyObject *bytes) +/*[clinic end generated code: output=c8234a599ba5ec35 input=37daa5fad1395d95]*/ +{ +    return do_argstrip(self, BOTHSTRIP, bytes);  } +/*[clinic input] +bytes.lstrip + +    self: self(type="PyBytesObject *") +    bytes: object = None +    / + +Strip leading bytes contained in the argument. + +If the argument is omitted or None, strip leading  ASCII whitespace. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_lstrip__doc__, +"lstrip($self, bytes=None, /)\n" +"--\n" +"\n" +"Strip leading bytes contained in the argument.\n" +"\n" +"If the argument is omitted or None, strip leading  ASCII whitespace."); + +#define BYTES_LSTRIP_METHODDEF    \ +    {"lstrip", (PyCFunction)bytes_lstrip, METH_VARARGS, bytes_lstrip__doc__}, + +static PyObject * +bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes); -PyDoc_STRVAR(lstrip__doc__, -"B.lstrip([bytes]) -> bytes\n\ -\n\ -Strip leading bytes contained in the argument.\n\ -If the argument is omitted, strip leading ASCII whitespace.");  static PyObject *  bytes_lstrip(PyBytesObject *self, PyObject *args)  { -    if (PyTuple_GET_SIZE(args) == 0) -        return do_strip(self, LEFTSTRIP); /* Common case */ -    else -        return do_argstrip(self, LEFTSTRIP, args); +    PyObject *return_value = NULL; +    PyObject *bytes = Py_None; + +    if (!PyArg_UnpackTuple(args, "lstrip", +        0, 1, +        &bytes)) +        goto exit; +    return_value = bytes_lstrip_impl(self, bytes); + +exit: +    return return_value; +} + +static PyObject * +bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes) +/*[clinic end generated code: output=529e8511ab6f1115 input=88811b09dfbc2988]*/ +{ +    return do_argstrip(self, LEFTSTRIP, bytes);  } +/*[clinic input] +bytes.rstrip + +    self: self(type="PyBytesObject *") +    bytes: object = None +    / + +Strip trailing bytes contained in the argument. + +If the argument is omitted or None, strip trailing ASCII whitespace. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_rstrip__doc__, +"rstrip($self, bytes=None, /)\n" +"--\n" +"\n" +"Strip trailing bytes contained in the argument.\n" +"\n" +"If the argument is omitted or None, strip trailing ASCII whitespace."); + +#define BYTES_RSTRIP_METHODDEF    \ +    {"rstrip", (PyCFunction)bytes_rstrip, METH_VARARGS, bytes_rstrip__doc__}, + +static PyObject * +bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes); -PyDoc_STRVAR(rstrip__doc__, -"B.rstrip([bytes]) -> bytes\n\ -\n\ -Strip trailing bytes contained in the argument.\n\ -If the argument is omitted, strip trailing ASCII whitespace.");  static PyObject *  bytes_rstrip(PyBytesObject *self, PyObject *args)  { -    if (PyTuple_GET_SIZE(args) == 0) -        return do_strip(self, RIGHTSTRIP); /* Common case */ -    else -        return do_argstrip(self, RIGHTSTRIP, args); +    PyObject *return_value = NULL; +    PyObject *bytes = Py_None; + +    if (!PyArg_UnpackTuple(args, "rstrip", +        0, 1, +        &bytes)) +        goto exit; +    return_value = bytes_rstrip_impl(self, bytes); + +exit: +    return return_value; +} + +static PyObject * +bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) +/*[clinic end generated code: output=e98730bd133e6593 input=8f93c9cd361f0140]*/ +{ +    return do_argstrip(self, RIGHTSTRIP, bytes);  } @@ -1482,40 +1752,89 @@ bytes_count(PyBytesObject *self, PyObject *args)  } -PyDoc_STRVAR(translate__doc__, -"B.translate(table[, deletechars]) -> bytes\n\ -\n\ -Return a copy of B, where all characters occurring in the\n\ -optional argument deletechars are removed, and the remaining\n\ -characters have been mapped through the given translation\n\ -table, which must be a bytes object of length 256."); +/*[clinic input] +bytes.translate + +    self: self(type="PyBytesObject *") +    table: object +        Translation table, which must be a bytes object of length 256. +    [ +    deletechars: object +    ] +    / + +Return a copy with each character mapped by the given translation table. + +All characters occurring in the optional argument deletechars are removed. +The remaining characters are mapped through the given translation table. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_translate__doc__, +"translate(table, [deletechars])\n" +"Return a copy with each character mapped by the given translation table.\n" +"\n" +"  table\n" +"    Translation table, which must be a bytes object of length 256.\n" +"\n" +"All characters occurring in the optional argument deletechars are removed.\n" +"The remaining characters are mapped through the given translation table."); + +#define BYTES_TRANSLATE_METHODDEF    \ +    {"translate", (PyCFunction)bytes_translate, METH_VARARGS, bytes_translate__doc__}, + +static PyObject * +bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars);  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=a90fad893c3c88d7]*/ +{      char *input, *output; -    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(tableobj, &table, &tablen)) +    else if (PyObject_AsCharBuffer(table, &table_chars, &tablen))          return NULL;      if (tablen != 256) { @@ -1524,16 +1843,16 @@ bytes_translate(PyBytesObject *self, PyObject *args)          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(delobj, &del_table, &dellen)) +        else if (PyObject_AsCharBuffer(deletechars, &del_table_chars, &dellen))              return NULL;      }      else { -        del_table = NULL; +        del_table_chars = NULL;          dellen = 0;      } @@ -1544,11 +1863,11 @@ bytes_translate(PyBytesObject *self, PyObject *args)      output_start = output = PyBytes_AsString(result);      input = PyBytes_AS_STRING(input_obj); -    if (dellen == 0 && table != NULL) { +    if (dellen == 0 && table_chars != NULL) {          /* 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)) @@ -1558,16 +1877,16 @@ bytes_translate(PyBytesObject *self, PyObject *args)          return input_obj;      } -    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]);      }      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;      for (i = inlen; --i >= 0; ) {          c = Py_CHARMASK(*input++); @@ -1588,10 +1907,62 @@ bytes_translate(PyBytesObject *self, PyObject *args)  } +/*[clinic input] + +@staticmethod +bytes.maketrans + +    frm: object +    to: object +    / + +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); +  static PyObject * -bytes_maketrans(PyObject *null, PyObject *args) +bytes_maketrans(void *null, PyObject *args)  { -    return _Py_bytes_maketrans(args); +    PyObject *return_value = NULL; +    PyObject *frm; +    PyObject *to; + +    if (!PyArg_UnpackTuple(args, "maketrans", +        2, 2, +        &frm, &to)) +        goto exit; +    return_value = bytes_maketrans_impl(frm, to); + +exit: +    return return_value; +} + +static PyObject * +bytes_maketrans_impl(PyObject *frm, PyObject *to) +/*[clinic end generated code: output=89a3c3556975e466 input=d204f680f85da382]*/ +{ +    return _Py_bytes_maketrans(frm, to);  }  /* find and count characters and substrings */ @@ -2086,41 +2457,84 @@ 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 +    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);  static PyObject * -bytes_replace(PyBytesObject *self, PyObject *args) +bytes_replace(PyBytesObject*self, PyObject *args)  { +    PyObject *return_value = NULL; +    PyObject *old; +    PyObject *new;      Py_ssize_t count = -1; -    PyObject *from, *to; -    const char *from_s, *to_s; -    Py_ssize_t from_len, to_len; -    if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count)) -        return NULL; +    if (!PyArg_ParseTuple(args, +        "OO|n:replace", +        &old, &new, &count)) +        goto exit; +    return_value = bytes_replace_impl(self, old, new, count); -    if (PyBytes_Check(from)) { -        from_s = PyBytes_AS_STRING(from); -        from_len = PyBytes_GET_SIZE(from); +exit: +    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]*/ +{ +    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(from, &from_s, &from_len)) +    else if (PyObject_AsCharBuffer(old, &old_s, &old_len))          return NULL; -    if (PyBytes_Check(to)) { -        to_s = PyBytes_AS_STRING(to); -        to_len = PyBytes_GET_SIZE(to); +    if (PyBytes_Check(new)) { +        new_s = PyBytes_AS_STRING(new); +        new_len = PyBytes_GET_SIZE(new);      } -    else if (PyObject_AsCharBuffer(to, &to_s, &to_len)) +    else if (PyObject_AsCharBuffer(new, &new_s, &new_len))          return NULL;      return (PyObject *)replace((PyBytesObject *) self, -                               from_s, from_len, -                               to_s, to_len, count); +                               old_s, old_len, +                               new_s, new_len, count);  }  /** End DALKE **/ @@ -2254,60 +2668,121 @@ bytes_endswith(PyBytesObject *self, PyObject *args)  } -PyDoc_STRVAR(decode__doc__, -"B.decode(encoding='utf-8', errors='strict') -> str\n\ -\n\ -Decode B using the codec registered for encoding. Default encoding\n\ -is 'utf-8'. errors may be given to set a different error\n\ -handling scheme.  Default is 'strict' meaning that encoding errors raise\n\ -a UnicodeDecodeError.  Other possible values are 'ignore' and 'replace'\n\ -as well as any other name registerd with codecs.register_error that is\n\ -able to handle UnicodeDecodeErrors."); +/*[clinic input] +bytes.decode + +    encoding: str(c_default="NULL") = 'utf-8' +        The encoding with which to decode the bytes. +    errors: str(c_default="NULL") = 'strict' +        The error handling scheme to use for the handling of decoding errors. +        The default is 'strict' meaning that decoding errors raise a +        UnicodeDecodeError. Other possible values are 'ignore' and 'replace' +        as well as any other name registered with codecs.register_error that +        can handle UnicodeDecodeErrors. + +Decode the bytes using the codec registered for encoding. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_decode__doc__, +"decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" +"--\n" +"\n" +"Decode the bytes using the codec registered for encoding.\n" +"\n" +"  encoding\n" +"    The encoding with which to decode the bytes.\n" +"  errors\n" +"    The error handling scheme to use for the handling of decoding errors.\n" +"    The default is \'strict\' meaning that decoding errors raise a\n" +"    UnicodeDecodeError. Other possible values are \'ignore\' and \'replace\'\n" +"    as well as any other name registered with codecs.register_error that\n" +"    can handle UnicodeDecodeErrors."); + +#define BYTES_DECODE_METHODDEF    \ +    {"decode", (PyCFunction)bytes_decode, METH_VARARGS|METH_KEYWORDS, bytes_decode__doc__}, + +static PyObject * +bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors);  static PyObject * -bytes_decode(PyObject *self, PyObject *args, PyObject *kwargs) +bytes_decode(PyBytesObject*self, PyObject *args, PyObject *kwargs)  { +    PyObject *return_value = NULL; +    static char *_keywords[] = {"encoding", "errors", NULL};      const char *encoding = NULL;      const char *errors = NULL; -    static char *kwlist[] = {"encoding", "errors", 0}; -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", kwlist, &encoding, &errors)) -        return NULL; -    return PyUnicode_FromEncodedObject(self, encoding, errors); +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, +        "|ss:decode", _keywords, +        &encoding, &errors)) +        goto exit; +    return_value = bytes_decode_impl(self, encoding, errors); + +exit: +    return return_value;  } +static PyObject * +bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors) +/*[clinic end generated code: output=61a80290bbfce696 input=958174769d2a40ca]*/ +{ +    return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors); +} -PyDoc_STRVAR(splitlines__doc__, -"B.splitlines([keepends]) -> list of lines\n\ -\n\ -Return a list of the lines in B, breaking at line boundaries.\n\ -Line breaks are not included in the resulting list unless keepends\n\ -is given and true."); -static PyObject* -bytes_splitlines(PyObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +bytes.splitlines + +    keepends: int(py_default="False") = 0 + +Return a list of the lines in the bytes, breaking at line boundaries. + +Line breaks are not included in the resulting list unless keepends is given and +true. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_splitlines__doc__, +"splitlines($self, /, keepends=False)\n" +"--\n" +"\n" +"Return a list of the lines in the bytes, breaking at line boundaries.\n" +"\n" +"Line breaks are not included in the resulting list unless keepends is given and\n" +"true."); + +#define BYTES_SPLITLINES_METHODDEF    \ +    {"splitlines", (PyCFunction)bytes_splitlines, METH_VARARGS|METH_KEYWORDS, bytes_splitlines__doc__}, + +static PyObject * +bytes_splitlines_impl(PyBytesObject*self, int keepends); + +static PyObject * +bytes_splitlines(PyBytesObject*self, PyObject *args, PyObject *kwargs)  { -    static char *kwlist[] = {"keepends", 0}; +    PyObject *return_value = NULL; +    static char *_keywords[] = {"keepends", NULL};      int keepends = 0; -    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:splitlines", -                                     kwlist, &keepends)) -        return NULL; +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, +        "|i:splitlines", _keywords, +        &keepends)) +        goto exit; +    return_value = bytes_splitlines_impl(self, keepends); +exit: +    return return_value; +} + +static PyObject * +bytes_splitlines_impl(PyBytesObject*self, int keepends) +/*[clinic end generated code: output=79da057d05d126de input=ddb93e3351080c8c]*/ +{      return stringlib_splitlines(          (PyObject*) self, PyBytes_AS_STRING(self),          PyBytes_GET_SIZE(self), keepends          );  } - -PyDoc_STRVAR(fromhex_doc, -"bytes.fromhex(string) -> bytes\n\ -\n\ -Create a bytes object from a string of hexadecimal numbers.\n\ -Spaces between two numbers are accepted.\n\ -Example: bytes.fromhex('B9 01EF') -> b'\\xb9\\x01\\xef'."); -  static int  hex_digit_to_int(Py_UCS4 c)  { @@ -2324,24 +2799,67 @@ hex_digit_to_int(Py_UCS4 c)      return -1;  } +/*[clinic input] +@classmethod +bytes.fromhex + +    string: unicode +    / + +Create a bytes object from a string of hexadecimal numbers. + +Spaces between two numbers are accepted. +Example: bytes.fromhex('B9 01EF') -> b'\\xb9\\x01\\xef'. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_fromhex__doc__, +"fromhex($type, string, /)\n" +"--\n" +"\n" +"Create a bytes object from a string of hexadecimal numbers.\n" +"\n" +"Spaces between two numbers are accepted.\n" +"Example: bytes.fromhex(\'B9 01EF\') -> b\'\\\\xb9\\\\x01\\\\xef\'."); + +#define BYTES_FROMHEX_METHODDEF    \ +    {"fromhex", (PyCFunction)bytes_fromhex, METH_VARARGS|METH_CLASS, bytes_fromhex__doc__}, + +static PyObject * +bytes_fromhex_impl(PyTypeObject *type, PyObject *string); + +static PyObject * +bytes_fromhex(PyTypeObject *type, PyObject *args) +{ +    PyObject *return_value = NULL; +    PyObject *string; + +    if (!PyArg_ParseTuple(args, +        "U:fromhex", +        &string)) +        goto exit; +    return_value = bytes_fromhex_impl(type, string); + +exit: +    return return_value; +} +  static PyObject * -bytes_fromhex(PyObject *cls, PyObject *args) +bytes_fromhex_impl(PyTypeObject *type, PyObject *string) +/*[clinic end generated code: output=09e6cbef56cbbb65 input=bf4d1c361670acd3]*/  { -    PyObject *newstring, *hexobj; +    PyObject *newstring;      char *buf;      Py_ssize_t hexlen, byteslen, i, j;      int top, bot;      void *data;      unsigned int kind; -    if (!PyArg_ParseTuple(args, "U:fromhex", &hexobj)) +    assert(PyUnicode_Check(string)); +    if (PyUnicode_READY(string))          return NULL; -    assert(PyUnicode_Check(hexobj)); -    if (PyUnicode_READY(hexobj)) -        return NULL; -    kind = PyUnicode_KIND(hexobj); -    data = PyUnicode_DATA(hexobj); -    hexlen = PyUnicode_GET_LENGTH(hexobj); +    kind = PyUnicode_KIND(string); +    data = PyUnicode_DATA(string); +    hexlen = PyUnicode_GET_LENGTH(string);      byteslen = hexlen/2; /* This overestimates if there are spaces */      newstring = PyBytes_FromStringAndSize(NULL, byteslen); @@ -2373,14 +2891,38 @@ bytes_fromhex(PyObject *cls, PyObject *args)      return NULL;  } -PyDoc_STRVAR(sizeof__doc__, -"B.__sizeof__() -> size of B in memory, in bytes"); +/*[clinic input] +bytes.__sizeof__ as bytes_sizeof + +    self: self(type="PyBytesObject *") + +Returns the size of the bytes object in memory, in bytes. +[clinic start generated code]*/ + +PyDoc_STRVAR(bytes_sizeof__doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Returns the size of the bytes object in memory, in bytes."); + +#define BYTES_SIZEOF_METHODDEF    \ +    {"__sizeof__", (PyCFunction)bytes_sizeof, METH_NOARGS, bytes_sizeof__doc__}, + +static PyObject * +bytes_sizeof_impl(PyBytesObject *self); + +static PyObject * +bytes_sizeof(PyBytesObject *self, PyObject *Py_UNUSED(ignored)) +{ +    return bytes_sizeof_impl(self); +}  static PyObject * -bytes_sizeof(PyBytesObject *v) +bytes_sizeof_impl(PyBytesObject *self) +/*[clinic end generated code: output=44933279343f24ae input=bee4c64bb42078ed]*/  {      Py_ssize_t res; -    res = PyBytesObject_SIZE + Py_SIZE(v) * Py_TYPE(v)->tp_itemsize; +    res = PyBytesObject_SIZE + Py_SIZE(self) * Py_TYPE(self)->tp_itemsize;      return PyLong_FromSsize_t(res);  } @@ -2399,14 +2941,13 @@ bytes_methods[] = {       _Py_capitalize__doc__},      {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},      {"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__}, -    {"decode", (PyCFunction)bytes_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__}, +    BYTES_DECODE_METHODDEF      {"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,       endswith__doc__},      {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,       expandtabs__doc__},      {"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__}, -    {"fromhex", (PyCFunction)bytes_fromhex, METH_VARARGS|METH_CLASS, -     fromhex_doc}, +    BYTES_FROMHEX_METHODDEF      {"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__},      {"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,       _Py_isalnum__doc__}, @@ -2422,36 +2963,31 @@ bytes_methods[] = {       _Py_istitle__doc__},      {"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,       _Py_isupper__doc__}, -    {"join", (PyCFunction)bytes_join, METH_O, join__doc__}, +    BYTES_JOIN_METHODDEF      {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},      {"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__}, -    {"lstrip", (PyCFunction)bytes_lstrip, METH_VARARGS, lstrip__doc__}, -    {"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, -     _Py_maketrans__doc__}, -    {"partition", (PyCFunction)bytes_partition, METH_O, partition__doc__}, -    {"replace", (PyCFunction)bytes_replace, METH_VARARGS, replace__doc__}, +    BYTES_LSTRIP_METHODDEF +    BYTES_MAKETRANS_METHODDEF +    BYTES_PARTITION_METHODDEF +    BYTES_REPLACE_METHODDEF      {"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, rfind__doc__},      {"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, rindex__doc__},      {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__}, -    {"rpartition", (PyCFunction)bytes_rpartition, METH_O, -     rpartition__doc__}, -    {"rsplit", (PyCFunction)bytes_rsplit, METH_VARARGS | METH_KEYWORDS, rsplit__doc__}, -    {"rstrip", (PyCFunction)bytes_rstrip, METH_VARARGS, rstrip__doc__}, -    {"split", (PyCFunction)bytes_split, METH_VARARGS | METH_KEYWORDS, split__doc__}, -    {"splitlines", (PyCFunction)bytes_splitlines, METH_VARARGS | METH_KEYWORDS, -     splitlines__doc__}, +    BYTES_RPARTITION_METHODDEF +    BYTES_RSPLIT_METHODDEF +    BYTES_RSTRIP_METHODDEF +    BYTES_SPLIT_METHODDEF +    BYTES_SPLITLINES_METHODDEF      {"startswith", (PyCFunction)bytes_startswith, METH_VARARGS,       startswith__doc__}, -    {"strip", (PyCFunction)bytes_strip, METH_VARARGS, strip__doc__}, +    BYTES_STRIP_METHODDEF      {"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,       _Py_swapcase__doc__},      {"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__}, -    {"translate", (PyCFunction)bytes_translate, METH_VARARGS, -     translate__doc__}, +    BYTES_TRANSLATE_METHODDEF      {"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},      {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__}, -    {"__sizeof__", (PyCFunction)bytes_sizeof, METH_NOARGS, -     sizeof__doc__}, +    BYTES_SIZEOF_METHODDEF      {NULL,     NULL}                         /* sentinel */  }; @@ -2482,7 +3018,7 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)                              "argument");              return NULL;          } -        return PyBytes_FromString(""); +        return PyBytes_FromStringAndSize(NULL, 0);      }      if (PyUnicode_Check(x)) { @@ -2532,11 +3068,9 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)          return NULL;      }      else { -        new = PyBytes_FromStringAndSize(NULL, size); +        new = _PyBytes_FromSize(size, 1);          if (new == NULL)              return NULL; -        if (size > 0) -            memset(((PyBytesObject*)new)->ob_sval, 0, size);          return new;      } @@ -2641,10 +3175,12 @@ PyBytes_FromObject(PyObject *x)         returning a shared empty bytes string. This required because we         want to call _PyBytes_Resize() the returned object, which we can         only do on bytes objects with refcount == 1. */ -    size += 1; +    if (size == 0) +        size = 1;      new = PyBytes_FromStringAndSize(NULL, size);      if (new == NULL)          return NULL; +    assert(Py_REFCNT(new) == 1);      /* Get the iterator */      it = PyObject_GetIter(x); @@ -2781,7 +3317,6 @@ PyTypeObject PyBytes_Type = {  void  PyBytes_Concat(PyObject **pv, PyObject *w)  { -    PyObject *v;      assert(pv != NULL);      if (*pv == NULL)          return; @@ -2789,9 +3324,45 @@ PyBytes_Concat(PyObject **pv, PyObject *w)          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) { +            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 | 
