Commit a4eb14b7 authored by Martin v. Löwis's avatar Martin v. Löwis

Patch #495401: Count number of required bytes for encoding UTF-8 before

allocating the target buffer.
parent e21095e3
...@@ -1172,98 +1172,87 @@ int utf8_encoding_error(const Py_UNICODE **source, ...@@ -1172,98 +1172,87 @@ int utf8_encoding_error(const Py_UNICODE **source,
} }
#endif #endif
/* Allocation strategy: we default to Latin-1, then do one resize
whenever we hit an order boundary. The assumption is that
characters from higher orders usually occur often enough to warrant
this.
*/
PyObject *PyUnicode_EncodeUTF8(const Py_UNICODE *s, PyObject *PyUnicode_EncodeUTF8(const Py_UNICODE *s,
int size, int size,
const char *errors) const char *errors)
{ {
PyObject *v; PyObject *v;
char *p; char *p;
int i = 0; unsigned int allocated = 0;
int overalloc = 2; int i;
int len;
/* Short-cut for emtpy strings */ /* Short-cut for emtpy strings */
if (size == 0) if (size == 0)
return PyString_FromStringAndSize(NULL, 0); return PyString_FromStringAndSize(NULL, 0);
v = PyString_FromStringAndSize(NULL, overalloc * size); for (i = 0; i < size; ) {
Py_UCS4 ch = s[i++];
if (ch < 0x80)
allocated += 1;
else if (ch < 0x0800)
allocated += 2;
else if (ch < 0x10000) {
/* Check for high surrogate */
if (0xD800 <= ch && ch <= 0xDBFF &&
i != size &&
0xDC00 <= s[i] && s[i] <= 0xDFFF) {
allocated += 1;
i++;
}
allocated += 3;
} else
allocated += 4;
}
v = PyString_FromStringAndSize(NULL, allocated);
if (v == NULL) if (v == NULL)
return NULL; return NULL;
p = PyString_AS_STRING(v); p = PyString_AS_STRING(v);
for (i = 0; i < size; ) {
while (i < size) {
Py_UCS4 ch = s[i++]; Py_UCS4 ch = s[i++];
if (ch < 0x80) if (ch < 0x80) {
/* Encode ASCII */
*p++ = (char) ch; *p++ = (char) ch;
}
else if (ch < 0x0800) { else if (ch < 0x0800) {
/* Encode Latin-1 */
*p++ = (char)(0xc0 | (ch >> 6)); *p++ = (char)(0xc0 | (ch >> 6));
*p++ = (char)(0x80 | (ch & 0x3f)); *p++ = (char)(0x80 | (ch & 0x3f));
} }
else { else {
/* Encode UCS2 Unicode ordinals */
if (ch < 0x10000) {
/* Special case: check for high surrogate */ if (ch < 0x10000) {
/* Check for high surrogate */
if (0xD800 <= ch && ch <= 0xDBFF && i != size) { if (0xD800 <= ch && ch <= 0xDBFF && i != size) {
Py_UCS4 ch2 = s[i]; Py_UCS4 ch2 = s[i];
/* Check for low surrogate and combine the two to /* Check for low surrogate */
form a UCS4 value */
if (0xDC00 <= ch2 && ch2 <= 0xDFFF) { if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
ch = ((ch - 0xD800) << 10 | (ch2 - 0xDC00)) + 0x10000; ch = ((ch - 0xD800)<<10 | (ch2-0xDC00))+0x10000;
*p++ = (char)((ch >> 18) | 0xf0);
*p++ = (char)(0x80 | ((ch >> 12) & 0x3f));
*p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
*p++ = (char)(0x80 | (ch & 0x3f));
i++; i++;
goto encodeUCS4; continue;
} }
/* Fall through: handles isolated high surrogates */ /* Fall through: handles isolated high surrogates */
} }
if (overalloc < 3) {
len = (int)(p - PyString_AS_STRING(v));
overalloc = 3;
if (_PyString_Resize(&v, overalloc * size))
goto onError;
p = PyString_AS_STRING(v) + len;
}
*p++ = (char)(0xe0 | (ch >> 12)); *p++ = (char)(0xe0 | (ch >> 12));
*p++ = (char)(0x80 | ((ch >> 6) & 0x3f)); *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
*p++ = (char)(0x80 | (ch & 0x3f)); *p++ = (char)(0x80 | (ch & 0x3f));
continue;
}
/* Encode UCS4 Unicode ordinals */ } else {
encodeUCS4: *p++ = (char)(0xf0 | (ch>>18));
if (overalloc < 4) { *p++ = (char)(0x80 | ((ch>>12) & 0x3f));
len = (int)(p - PyString_AS_STRING(v)); *p++ = (char)(0x80 | ((ch>>6) & 0x3f));
overalloc = 4;
if (_PyString_Resize(&v, overalloc * size))
goto onError;
p = PyString_AS_STRING(v) + len;
}
*p++ = (char)(0xf0 | (ch >> 18));
*p++ = (char)(0x80 | ((ch >> 12) & 0x3f));
*p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
*p++ = (char)(0x80 | (ch & 0x3f)); *p++ = (char)(0x80 | (ch & 0x3f));
} }
} }
*p = '\0'; }
if (_PyString_Resize(&v, (int)(p - PyString_AS_STRING(v)))) assert(p - PyString_AS_STRING(v) == allocated);
goto onError;
return v; return v;
onError:
Py_DECREF(v);
return NULL;
} }
PyObject *PyUnicode_AsUTF8String(PyObject *unicode) PyObject *PyUnicode_AsUTF8String(PyObject *unicode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment