diff -r 2f0716009132 Include/bytes_methods.h --- a/Include/bytes_methods.h Tue Jul 12 18:24:25 2016 -0400 +++ b/Include/bytes_methods.h Wed Jul 13 14:36:51 2016 +0800 @@ -33,6 +33,10 @@ /* The maketrans() static method. */ extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to); +extern PyObject *_Py_bytes_repr(const char *str, Py_ssize_t len, const char *name, + const char *quote_prefix, const char *quote_postfix, + int smartquotes); + /* Shared __doc__ strings. */ extern const char _Py_isspace__doc__[]; extern const char _Py_isalpha__doc__[]; diff -r 2f0716009132 Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c Tue Jul 12 18:24:25 2016 -0400 +++ b/Objects/bytearrayobject.c Wed Jul 13 14:36:51 2016 +0800 @@ -882,89 +882,13 @@ return -1; } -/* Mostly copied from string_repr, but without the - "smart quote" functionality. */ static PyObject * bytearray_repr(PyByteArrayObject *self) { - const char *quote_prefix = "bytearray(b"; - const char *quote_postfix = ")"; - Py_ssize_t length = Py_SIZE(self); - /* 15 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */ - size_t newsize; - PyObject *v; - Py_ssize_t i; - char *bytes; - char c; - char *p; - int quote; - char *test, *start; - char *buffer; - - if (length > (PY_SSIZE_T_MAX - 15) / 4) { - PyErr_SetString(PyExc_OverflowError, - "bytearray object is too large to make repr"); - return NULL; - } - - newsize = 15 + length * 4; - buffer = PyObject_Malloc(newsize); - if (buffer == NULL) { - PyErr_NoMemory(); - return NULL; - } - - /* Figure out which quote to use; single is preferred */ - quote = '\''; - start = PyByteArray_AS_STRING(self); - for (test = start; test < start+length; ++test) { - if (*test == '"') { - quote = '\''; /* back to single */ - break; - } - else if (*test == '\'') - quote = '"'; - } - - p = buffer; - while (*quote_prefix) - *p++ = *quote_prefix++; - *p++ = quote; - - bytes = PyByteArray_AS_STRING(self); - for (i = 0; i < length; i++) { - /* There's at least enough room for a hex escape - and a closing quote. */ - assert(newsize - (p - buffer) >= 5); - c = bytes[i]; - if (c == '\'' || c == '\\') - *p++ = '\\', *p++ = c; - else if (c == '\t') - *p++ = '\\', *p++ = 't'; - else if (c == '\n') - *p++ = '\\', *p++ = 'n'; - else if (c == '\r') - *p++ = '\\', *p++ = 'r'; - else if (c == 0) - *p++ = '\\', *p++ = 'x', *p++ = '0', *p++ = '0'; - else if (c < ' ' || c >= 0x7f) { - *p++ = '\\'; - *p++ = 'x'; - *p++ = Py_hexdigits[(c & 0xf0) >> 4]; - *p++ = Py_hexdigits[c & 0xf]; - } - else - *p++ = c; - } - assert(newsize - (p - buffer) >= 1); - *p++ = quote; - while (*quote_postfix) { - *p++ = *quote_postfix++; - } - - v = PyUnicode_DecodeASCII(buffer, p - buffer, NULL); - PyObject_Free(buffer); - return v; + return _Py_bytes_repr(PyByteArray_AS_STRING(self), + PyByteArray_GET_SIZE(self), + Py_TYPE(self)->tp_name, + "bytearray(b", ")", 1); } static PyObject * diff -r 2f0716009132 Objects/bytes_methods.c --- a/Objects/bytes_methods.c Tue Jul 12 18:24:25 2016 -0400 +++ b/Objects/bytes_methods.c Wed Jul 13 14:36:51 2016 +0800 @@ -812,3 +812,81 @@ "Pad a numeric string B with zeros on the left, to fill a field\n" "of the specified width. B is never truncated."); + +PyObject * +_Py_bytes_repr(const char *str, Py_ssize_t len, const char *name, + const char *quote_prefix, const char *quote_postfix, + int smartquotes) +{ + Py_ssize_t i; + Py_ssize_t newsize, squotes, dquotes; + unsigned char *s, *p, quote; + PyObject *v; + + squotes = dquotes = 0; + newsize = strlen(quote_prefix) + 2 + strlen(quote_postfix); /* 2 quotes */ + s = (unsigned char *)str; + for (i = 0; i < len; i++) { + Py_ssize_t incr = 1; + switch(s[i]) { + case '\'': squotes++; break; + case '"': dquotes++; break; + case '\\': case '\t': case '\n': case '\r': + incr = 2; break; + default: + if (s[i] < ' ' || s[i] >= 0x7f) + incr = 4; + } + if (newsize > PY_SSIZE_T_MAX - incr) + goto overflow; + newsize += incr; + } + quote = '\''; + if (smartquotes && squotes && !dquotes) + quote = '"'; + if (squotes && quote == '\'') { + if (newsize > PY_SSIZE_T_MAX - squotes) + goto overflow; + newsize += squotes; + } + + v = PyUnicode_New(newsize, 127); + if (v == NULL) + return NULL; + p = PyUnicode_1BYTE_DATA(v); + + while (*quote_prefix) + *p++ = *quote_prefix++; + *p++ = quote; + for (i = 0; i < len; i++) { + unsigned char c = (unsigned char)str[i]; + if (c == quote || c == '\\') + *p++ = '\\', *p++ = c; + else if (c == '\t') + *p++ = '\\', *p++ = 't'; + else if (c == '\n') + *p++ = '\\', *p++ = 'n'; + else if (c == '\r') + *p++ = '\\', *p++ = 'r'; + else if (c < ' ' || c >= 0x7f) { + *p++ = '\\'; + *p++ = 'x'; + *p++ = Py_hexdigits[(c & 0xf0) >> 4]; + *p++ = Py_hexdigits[c & 0xf]; + } + else + *p++ = c; + } + *p++ = quote; + while (*quote_postfix) + *p++ = *quote_postfix++; + assert(_PyUnicode_CheckConsistency(v, 1)); + return v; + + overflow: + PyErr_Format(PyExc_OverflowError, + "%.100s object is too large to make repr", + name); + return NULL; + +} diff -r 2f0716009132 Objects/bytesobject.c --- a/Objects/bytesobject.c Tue Jul 12 18:24:25 2016 -0400 +++ b/Objects/bytesobject.c Wed Jul 13 14:36:51 2016 +0800 @@ -1291,74 +1291,8 @@ PyObject * PyBytes_Repr(PyObject *obj, int smartquotes) { - PyBytesObject* op = (PyBytesObject*) obj; - Py_ssize_t i, length = Py_SIZE(op); - Py_ssize_t newsize, squotes, dquotes; - PyObject *v; - unsigned char quote, *s, *p; - - /* Compute size of output string */ - squotes = dquotes = 0; - newsize = 3; /* b'' */ - s = (unsigned char*)op->ob_sval; - for (i = 0; i < length; i++) { - Py_ssize_t incr = 1; - switch(s[i]) { - case '\'': squotes++; break; - case '"': dquotes++; break; - case '\\': case '\t': case '\n': case '\r': - incr = 2; break; /* \C */ - default: - if (s[i] < ' ' || s[i] >= 0x7f) - incr = 4; /* \xHH */ - } - if (newsize > PY_SSIZE_T_MAX - incr) - goto overflow; - newsize += incr; - } - quote = '\''; - if (smartquotes && squotes && !dquotes) - quote = '"'; - if (squotes && quote == '\'') { - if (newsize > PY_SSIZE_T_MAX - squotes) - goto overflow; - newsize += squotes; - } - - v = PyUnicode_New(newsize, 127); - if (v == NULL) { - return NULL; - } - p = PyUnicode_1BYTE_DATA(v); - - *p++ = 'b', *p++ = quote; - for (i = 0; i < length; i++) { - unsigned char c = op->ob_sval[i]; - if (c == quote || c == '\\') - *p++ = '\\', *p++ = c; - else if (c == '\t') - *p++ = '\\', *p++ = 't'; - else if (c == '\n') - *p++ = '\\', *p++ = 'n'; - else if (c == '\r') - *p++ = '\\', *p++ = 'r'; - else if (c < ' ' || c >= 0x7f) { - *p++ = '\\'; - *p++ = 'x'; - *p++ = Py_hexdigits[(c & 0xf0) >> 4]; - *p++ = Py_hexdigits[c & 0xf]; - } - else - *p++ = c; - } - *p++ = quote; - assert(_PyUnicode_CheckConsistency(v, 1)); - return v; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "bytes object is too large to make repr"); - return NULL; + return _Py_bytes_repr(PyBytes_AS_STRING(obj), PyBytes_GET_SIZE(obj), + Py_TYPE(obj)->tp_name, "b", "", smartquotes); } static PyObject *