diff -r b9d4c013b09a Objects/bytesobject.c --- a/Objects/bytesobject.c Tue Feb 03 09:30:51 2015 +0200 +++ b/Objects/bytesobject.c Tue Feb 03 10:40:23 2015 +0200 @@ -404,6 +404,29 @@ getnextarg(PyObject *args, Py_ssize_t ar #define F_ALT (1<<3) #define F_ZERO (1<<4) +/* repr is borrowed reference */ +static PyObject * +format_as_ascii(PyObject *repr, const char **pbuf, Py_ssize_t *plen) +{ + PyObject *temp; + assert(PyUnicode_Check(repr)); + if (PyUnicode_IS_ASCII(repr)) { + /* Fast path */ + *pbuf = (const char *)PyUnicode_1BYTE_DATA(repr); + *plen = PyUnicode_GET_LENGTH(repr); + temp = repr; + } + else { + temp = _PyUnicode_AsASCIIString(repr, "backslashreplace"); + Py_DECREF(repr); + if (temp == NULL) + return NULL; + *pbuf = PyBytes_AS_STRING(temp); + *plen = PyBytes_GET_SIZE(temp); + } + return temp; +} + /* Returns a new reference to a PyBytes object, or NULL on failure. */ static PyObject * @@ -433,105 +456,44 @@ formatfloat(PyObject *v, int flags, int return result; } -/* format_long emulates the format codes d, u, o, x and X, and - * the F_ALT flag, for Python's long (unbounded) ints. It's not used for - * Python's regular ints. - * Return value: a new PyBytes*, or NULL if error. - * . *pbuf is set to point into it, - * *plen set to the # of chars following that. - * Caller must decref it when done using pbuf. - * The string starting at *pbuf is of the form - * "-"? ("0x" | "0X")? digit+ - * "0x"/"0X" are present only for x and X conversions, with F_ALT - * set in flags. The case of hex digits will be correct, - * There will be at least prec digits, zero-filled on the left if - * necessary to get that many. - * val object to be converted - * flags bitmask of format flags; only F_ALT is looked at - * prec minimum number of digits; 0-fill on left if needed - * type a character in [duoxX]; u acts the same as d - * - * CAUTION: o, x and X conversions on regular ints can never - * produce a '-' sign, but can for Python's unbounded ints. - */ - -static PyObject * -format_long(PyObject *val, int flags, int prec, int type, - char **pbuf, int *plen) +Py_LOCAL_INLINE(int) +formatchar(char *buf, PyObject *v) { - PyObject *s; - PyObject *result = NULL; - - s = _PyUnicode_FormatLong(val, flags & F_ALT, prec, type); - if (!s) - return NULL; - result = _PyUnicode_AsASCIIString(s, "strict"); - Py_DECREF(s); - if (!result) - return NULL; - *pbuf = PyBytes_AS_STRING(result); - *plen = PyBytes_GET_SIZE(result); - return result; -} - -Py_LOCAL_INLINE(int) -formatchar(char *buf, size_t buflen, PyObject *v) -{ - PyObject *w = NULL; - /* convert bytearray to bytes */ - if (PyByteArray_Check(v)) { - w = PyBytes_FromObject(v); - if (w == NULL) - goto error; - v = w; - } /* presume that the buffer is at least 2 characters long */ - if (PyBytes_Check(v)) { - if (!PyArg_Parse(v, "c;%c requires an integer in range(256) or a single byte", &buf[0])) - goto error; + buf[1] = '\0'; + if (PyBytes_Check(v) || PyByteArray_Check(v)) { + if (PyArg_Parse(v, "c", &buf[0])) + return 1; } else { long ival = PyLong_AsLong(v); - if (ival == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "%c requires an integer in range(256) or a single byte"); - goto error; + if (0 <= ival && ival <= 255) { + buf[0] = (char)ival; + return 1; } - if (ival < 0 || ival > 255) { - PyErr_SetString(PyExc_TypeError, - "%c requires an integer in range(256) or a single byte"); - goto error; - } - buf[0] = (char)ival; } - Py_XDECREF(w); - buf[1] = '\0'; - return 1; - - error: - Py_XDECREF(w); - return -1; + PyErr_SetString(PyExc_TypeError, + "%c requires an integer in range(256) or a single byte"); + return 0; } static PyObject * -format_obj(PyObject *v) +format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen) { - PyObject *result = NULL, *w = NULL; - PyObject *func; + PyObject *func, *result; _Py_IDENTIFIER(__bytes__); - /* convert bytearray to bytes */ - if (PyByteArray_Check(v)) { - w = PyBytes_FromObject(v); - if (w == NULL) - return NULL; - v = w; - } /* is it a bytes object? */ if (PyBytes_Check(v)) { - result = v; + *pbuf = PyBytes_AS_STRING(v); + *plen = PyBytes_GET_SIZE(v); Py_INCREF(v); - Py_XDECREF(w); - return result; + return v; + } + if (PyByteArray_Check(v)) { + *pbuf = PyByteArray_AS_STRING(v); + *plen = PyByteArray_GET_SIZE(v); + Py_INCREF(v); + return v; } /* does it support __bytes__? */ func = _PyObject_LookupSpecial(v, &PyId___bytes__); @@ -547,6 +509,8 @@ format_obj(PyObject *v) Py_DECREF(result); return NULL; } + *pbuf = PyBytes_AS_STRING(result); + *plen = PyBytes_GET_SIZE(result); return result; } PyErr_Format(PyExc_TypeError, @@ -622,12 +586,10 @@ PyObject * int isnumok; PyObject *v = NULL; PyObject *temp = NULL; - Py_buffer buf = {NULL, NULL}; - char *pbuf; + const char *pbuf = NULL; int sign; - Py_ssize_t len; - char formatbuf[FORMATBUFLEN]; - /* For format{int,char}() */ + Py_ssize_t len = 0; + char formatbuf[2]; /* For formatchar() */ fmt++; if (*fmt == '(') { @@ -781,37 +743,19 @@ PyObject * len = 1; break; case 'a': - temp = PyObject_Repr(v); - if (temp == NULL) + repr = PyObject_Repr(v); + if (repr == NULL) goto error; - repr = PyUnicode_AsEncodedObject(temp, "ascii", "backslashreplace"); - if (repr == NULL) { - Py_DECREF(temp); - goto error; - } - if (PyObject_GetBuffer(repr, &buf, PyBUF_SIMPLE) != 0) { - temp = format_obj(repr); - if (temp == NULL) { - Py_DECREF(repr); - goto error; - } - Py_DECREF(repr); - repr = temp; - } - pbuf = PyBytes_AS_STRING(repr); - len = PyBytes_GET_SIZE(repr); - Py_DECREF(repr); + temp = format_as_ascii(repr, &pbuf, &len); if (prec >= 0 && len > prec) len = prec; break; case 's': // %s is only for 2/3 code; 3 only code should use %b case 'b': - temp = format_obj(v); + temp = format_obj(v, &pbuf, &len); if (temp == NULL) goto error; - pbuf = PyBytes_AS_STRING(temp); - len = PyBytes_GET_SIZE(temp); if (prec >= 0 && len > prec) len = prec; break; @@ -836,15 +780,15 @@ PyObject * } if (iobj!=NULL) { if (PyLong_Check(iobj)) { - int ilen; - isnumok = 1; - temp = format_long(iobj, flags, prec, c, - &pbuf, &ilen); + repr = _PyUnicode_FormatLong(iobj, flags & F_ALT, + prec, c); Py_DECREF(iobj); + if (!repr) + goto error; + temp = format_as_ascii(repr, &pbuf, &len); if (!temp) goto error; - len = ilen; sign = 1; } else { @@ -878,8 +822,8 @@ PyObject * break; case 'c': pbuf = formatbuf; - len = formatchar(pbuf, sizeof(formatbuf), v); - if (len < 0) + len = formatchar(formatbuf, v); + if (!len) goto error; break; default: @@ -911,12 +855,10 @@ PyObject * reslen += rescnt; if (reslen < 0) { Py_DECREF(result); - PyBuffer_Release(&buf); Py_XDECREF(temp); return PyErr_NoMemory(); } if (_PyBytes_Resize(&result, reslen)) { - PyBuffer_Release(&buf); Py_XDECREF(temp); return NULL; } @@ -970,11 +912,9 @@ PyObject * if (dict && (argidx < arglen) && c != '%') { PyErr_SetString(PyExc_TypeError, "not all arguments converted during bytes formatting"); - PyBuffer_Release(&buf); Py_XDECREF(temp); goto error; } - PyBuffer_Release(&buf); Py_XDECREF(temp); } /* '%' */ } /* until end */