diff -r aaa68dce117e Include/unicodeobject.h --- a/Include/unicodeobject.h Thu Aug 09 21:38:23 2012 +0200 +++ b/Include/unicodeobject.h Fri Aug 10 04:21:09 2012 +0200 @@ -896,6 +896,7 @@ typedef struct { void *data; enum PyUnicode_Kind kind; Py_UCS4 maxchar; + /* size is set to 0 if readonly is 1 */ Py_ssize_t size; Py_ssize_t pos; /* minimum length of the buffer when overallocation is enabled, @@ -911,7 +912,10 @@ typedef struct { If min_length is greater than zero, _PyUnicodeWriter_Prepare() overallocates the buffer and min_length is the minimum length in characters - of the buffer. */ + of the buffer. + + This function must not be called twice on the same writer. Call + _PyUnicodeWriter_Truncate(writer, 0) to reinitialize a writer. */ PyAPI_FUNC(void) _PyUnicodeWriter_Init(_PyUnicodeWriter *writer, Py_ssize_t min_length); @@ -933,12 +937,36 @@ PyAPI_FUNC(int) _PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer, Py_ssize_t length, Py_UCS4 maxchar); + +/* Truncate the buffer to length character. Do nothing if length is bigger + than the buffer. + + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_Truncate(_PyUnicodeWriter *writer, Py_ssize_t length); + +/* Write a string. + Return 0 on success, raise an exception and return -1 on error. */ PyAPI_FUNC(int) _PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str); +/* Write a string at the specified position. The string may override + characters in the buffer. pos must be smaller or equal to writer->pos. + + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteStrAt(_PyUnicodeWriter *writer, PyObject *str, Py_ssize_t pos); + +/* Get the content of the buffer. Return a copy of the buffer if the writer + is not a readonly buffer. Return NULL and raise an exception on error. */ +PyAPI_FUNC(PyObject *) +_PyUnicodeWriter_GetValue(_PyUnicodeWriter *writer); + +/* Return the content of the buffer and clear the buffer. */ PyAPI_FUNC(PyObject *) _PyUnicodeWriter_Finish(_PyUnicodeWriter *writer); +/* Clear the buffer. */ PyAPI_FUNC(void) _PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer); #endif diff -r aaa68dce117e Modules/_io/stringio.c --- a/Modules/_io/stringio.c Thu Aug 09 21:38:23 2012 +0200 +++ b/Modules/_io/stringio.c Fri Aug 10 04:21:09 2012 +0200 @@ -1,31 +1,17 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" -#include "accu.h" #include "_iomodule.h" /* Implementation note: the buffer is always at least one character longer than the enclosed string, for proper functioning of _PyIO_find_line_ending. */ -#define STATE_REALIZED 1 -#define STATE_ACCUMULATING 2 - typedef struct { PyObject_HEAD - Py_UCS4 *buf; Py_ssize_t pos; - Py_ssize_t string_size; - size_t buf_size; - /* The stringio object can be in two states: accumulating or realized. - In accumulating state, the internal buffer contains nothing and - the contents are given by the embedded _PyAccu structure. - In realized state, the internal buffer is meaningful and the - _PyAccu is destroyed. - */ - int state; - _PyAccu accu; + _PyUnicodeWriter writer; char ok; /* initialized? */ char closed; @@ -53,11 +39,6 @@ typedef struct { return NULL; \ } -#define ENSURE_REALIZED(self) \ - if (realize(self) < 0) { \ - return NULL; \ - } - PyDoc_STRVAR(stringio_doc, "Text I/O implementation using an in-memory buffer.\n" "\n" @@ -65,109 +46,6 @@ PyDoc_STRVAR(stringio_doc, "argument is like the one of TextIOWrapper's constructor."); -/* Internal routine for changing the size, in terms of characters, of the - buffer of StringIO objects. The caller should ensure that the 'size' - argument is non-negative. Returns 0 on success, -1 otherwise. */ -static int -resize_buffer(stringio *self, size_t size) -{ - /* Here, unsigned types are used to avoid dealing with signed integer - overflow, which is undefined in C. */ - size_t alloc = self->buf_size; - Py_UCS4 *new_buf = NULL; - - assert(self->buf != NULL); - - /* Reserve one more char for line ending detection. */ - size = size + 1; - /* For simplicity, stay in the range of the signed type. Anyway, Python - doesn't allow strings to be longer than this. */ - if (size > PY_SSIZE_T_MAX) - goto overflow; - - if (size < alloc / 2) { - /* Major downsize; resize down to exact size. */ - alloc = size + 1; - } - else if (size < alloc) { - /* Within allocated size; quick exit */ - return 0; - } - else if (size <= alloc * 1.125) { - /* Moderate upsize; overallocate similar to list_resize() */ - alloc = size + (size >> 3) + (size < 9 ? 3 : 6); - } - else { - /* Major upsize; resize up to exact size */ - alloc = size + 1; - } - - if (alloc > PY_SIZE_MAX / sizeof(Py_UCS4)) - goto overflow; - new_buf = (Py_UCS4 *)PyMem_Realloc(self->buf, alloc * sizeof(Py_UCS4)); - if (new_buf == NULL) { - PyErr_NoMemory(); - return -1; - } - self->buf_size = alloc; - self->buf = new_buf; - - return 0; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "new buffer size too large"); - return -1; -} - -static PyObject * -make_intermediate(stringio *self) -{ - PyObject *intermediate = _PyAccu_Finish(&self->accu); - self->state = STATE_REALIZED; - if (intermediate == NULL) - return NULL; - if (_PyAccu_Init(&self->accu) || - _PyAccu_Accumulate(&self->accu, intermediate)) { - Py_DECREF(intermediate); - return NULL; - } - self->state = STATE_ACCUMULATING; - return intermediate; -} - -static int -realize(stringio *self) -{ - Py_ssize_t len; - PyObject *intermediate; - - if (self->state == STATE_REALIZED) - return 0; - assert(self->state == STATE_ACCUMULATING); - self->state = STATE_REALIZED; - - intermediate = _PyAccu_Finish(&self->accu); - if (intermediate == NULL) - return -1; - - /* Append the intermediate string to the internal buffer. - The length should be equal to the current cursor position. - */ - len = PyUnicode_GET_LENGTH(intermediate); - if (resize_buffer(self, len) < 0) { - Py_DECREF(intermediate); - return -1; - } - if (!PyUnicode_AsUCS4(intermediate, self->buf, len, 0)) { - Py_DECREF(intermediate); - return -1; - } - - Py_DECREF(intermediate); - return 0; -} - /* Internal routine for writing a whole PyUnicode object to the buffer of a StringIO object. Returns 0 on success, or -1 on error. */ static Py_ssize_t @@ -175,8 +53,8 @@ write_str(stringio *self, PyObject *obj) { Py_ssize_t len; PyObject *decoded = NULL; + Py_UCS4 maxchar, maxchar2; - assert(self->buf != NULL); assert(self->pos >= 0); if (self->decoder != NULL) { @@ -203,6 +81,7 @@ write_str(stringio *self, PyObject *obj) } len = PyUnicode_GET_LENGTH(decoded); assert(len >= 0); + maxchar = PyUnicode_MAX_CHAR_VALUE(decoded); /* This overflow check is not strictly necessary. However, it avoids us to deal with funky things like comparing an unsigned and a signed @@ -213,49 +92,21 @@ write_str(stringio *self, PyObject *obj) goto fail; } - if (self->state == STATE_ACCUMULATING) { - if (self->string_size == self->pos) { - if (_PyAccu_Accumulate(&self->accu, decoded)) - goto fail; - goto success; - } - if (realize(self)) + if (self->pos > self->writer.pos) { + /* In case of overseek, pad with null bytes the buffer region between + the end of stream and the current position. */ + Py_ssize_t pad = self->pos - self->writer.pos; + if (_PyUnicodeWriter_Prepare(&self->writer, pad, 0) < 0) goto fail; + if (PyUnicode_Fill(self->writer.buffer, self->writer.pos, pad, 0) < 0) + goto fail; + self->writer.pos += pad; } - if (self->pos + len > self->string_size) { - if (resize_buffer(self, self->pos + len) < 0) - goto fail; - } - - if (self->pos > self->string_size) { - /* In case of overseek, pad with null bytes the buffer region between - the end of stream and the current position. - - 0 lo string_size hi - | |<---used--->|<----------available----------->| - | | <--to pad-->|<---to write---> | - 0 buf position - - */ - memset(self->buf + self->string_size, '\0', - (self->pos - self->string_size) * sizeof(Py_UCS4)); - } - - /* Copy the data to the internal buffer, overwriting some of the - existing data if self->pos < self->string_size. */ - if (!PyUnicode_AsUCS4(decoded, - self->buf + self->pos, - self->buf_size - self->pos, - 0)) + if (_PyUnicodeWriter_WriteStrAt(&self->writer, decoded, self->pos) < 0) goto fail; -success: - /* Set the new length of the internal string if it has changed. */ self->pos += len; - if (self->string_size < self->pos) - self->string_size = self->pos; - Py_DECREF(decoded); return 0; @@ -272,10 +123,7 @@ stringio_getvalue(stringio *self) { CHECK_INITIALIZED(self); CHECK_CLOSED(self); - if (self->state == STATE_ACCUMULATING) - return make_intermediate(self); - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, self->buf, - self->string_size); + return _PyUnicodeWriter_GetValue(&self->writer); } PyDoc_STRVAR(stringio_tell_doc, @@ -299,7 +147,7 @@ static PyObject * stringio_read(stringio *self, PyObject *args) { Py_ssize_t size, n; - Py_UCS4 *output; + PyObject *res; PyObject *arg = Py_None; CHECK_INITIALIZED(self); @@ -323,54 +171,55 @@ stringio_read(stringio *self, PyObject * } /* adjust invalid sizes */ - n = self->string_size - self->pos; + n = self->writer.pos - self->pos; if (size < 0 || size > n) { size = n; if (size < 0) size = 0; } - /* Optimization for seek(0); read() */ - if (self->state == STATE_ACCUMULATING && self->pos == 0 && size == n) { - PyObject *result = make_intermediate(self); - self->pos = self->string_size; - return result; + if (size) { + res = PyUnicode_Substring(self->writer.buffer, self->pos, self->pos + size); + if (res == NULL) + return NULL; + self->pos += size; } - - ENSURE_REALIZED(self); - output = self->buf + self->pos; - self->pos += size; - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output, size); + else { + res = PyUnicode_New(0, 0); + } + return res; } /* Internal helper, used by stringio_readline and stringio_iternext */ static PyObject * _stringio_readline(stringio *self, Py_ssize_t limit) { - Py_UCS4 *start, *end, old_char; + char *start, *end, old_char; Py_ssize_t len, consumed; + PyObject *res; /* In case of overseek, return the empty string */ - if (self->pos >= self->string_size) + if (self->pos >= self->writer.pos) return PyUnicode_New(0, 0); - start = self->buf + self->pos; - if (limit < 0 || limit > self->string_size - self->pos) - limit = self->string_size - self->pos; + start = self->writer.data + self->pos * self->writer.kind; + if (limit < 0 || limit > self->writer.pos - self->pos) + limit = self->writer.pos - self->pos; - end = start + limit; + end = start + limit * self->writer.kind; old_char = *end; *end = '\0'; len = _PyIO_find_line_ending( self->readtranslate, self->readuniversal, self->readnl, - PyUnicode_4BYTE_KIND, (char*)start, (char*)end, &consumed); + self->writer.kind, (char*)start, (char*)end, &consumed); *end = old_char; /* If we haven't found any line ending, we just return everything (`consumed` is ignored). */ if (len < 0) len = limit; + res = PyUnicode_Substring(self->writer.buffer, self->pos, self->pos + len); self->pos += len; - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, start, len); + return res; } PyDoc_STRVAR(stringio_readline_doc, @@ -388,7 +237,6 @@ stringio_readline(stringio *self, PyObje if (!PyArg_ParseTuple(args, "|O:readline", &arg)) return NULL; CHECK_CLOSED(self); - ENSURE_REALIZED(self); if (PyNumber_Check(arg)) { limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError); @@ -410,7 +258,6 @@ stringio_iternext(stringio *self) CHECK_INITIALIZED(self); CHECK_CLOSED(self); - ENSURE_REALIZED(self); if (Py_TYPE(self) == &PyStringIO_Type) { /* Skip method call overhead for speed */ @@ -480,12 +327,8 @@ stringio_truncate(stringio *self, PyObje return NULL; } - if (size < self->string_size) { - ENSURE_REALIZED(self); - if (resize_buffer(self, size) < 0) - return NULL; - self->string_size = size; - } + if (_PyUnicodeWriter_Truncate(&self->writer, size) < 0) + return NULL; return PyLong_FromSsize_t(size); } @@ -533,7 +376,7 @@ stringio_seek(stringio *self, PyObject * pos = self->pos; } else if (mode == 2) { - pos = self->string_size; + pos = self->writer.pos; } self->pos = pos; @@ -580,12 +423,11 @@ stringio_close(stringio *self) { self->closed = 1; /* Free up some memory */ - if (resize_buffer(self, 0) < 0) - return NULL; - _PyAccu_Destroy(&self->accu); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); + if (_PyUnicodeWriter_Truncate(&self->writer, 0) < 0) + return NULL; Py_RETURN_NONE; } @@ -608,11 +450,7 @@ stringio_dealloc(stringio *self) { _PyObject_GC_UNTRACK(self); self->ok = 0; - if (self->buf) { - PyMem_Free(self->buf); - self->buf = NULL; - } - _PyAccu_Destroy(&self->accu); + _PyUnicodeWriter_Dealloc(&self->writer); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -635,11 +473,7 @@ stringio_new(PyTypeObject *type, PyObjec /* tp_alloc initializes all the fields to zero. So we don't have to initialize them here. */ - self->buf = (Py_UCS4 *)PyMem_Malloc(0); - if (self->buf == NULL) { - Py_DECREF(self); - return PyErr_NoMemory(); - } + _PyUnicodeWriter_Init(&self->writer, 1); return (PyObject *)self; } @@ -693,7 +527,8 @@ stringio_init(stringio *self, PyObject * self->ok = 0; - _PyAccu_Destroy(&self->accu); + if (_PyUnicodeWriter_Truncate(&self->writer, 0) < 0) + return -1; Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -729,7 +564,6 @@ stringio_init(stringio *self, PyObject * /* Now everything is set up, resize buffer to size of initial value, and copy it */ - self->string_size = 0; if (value && value != Py_None) value_len = PyUnicode_GetLength(value); else @@ -737,21 +571,10 @@ stringio_init(stringio *self, PyObject * if (value_len > 0) { /* This is a heuristic, for newline translation might change the string length. */ - if (resize_buffer(self, 0) < 0) - return -1; - self->state = STATE_REALIZED; self->pos = 0; if (write_str(self, value) < 0) return -1; } - else { - /* Empty stringio object, we can start by accumulating */ - if (resize_buffer(self, 0) < 0) - return -1; - if (_PyAccu_Init(&self->accu)) - return -1; - self->state = STATE_ACCUMULATING; - } self->pos = 0; self->closed = 0; @@ -858,22 +681,13 @@ stringio_setstate(stringio *self, PyObje buffer completely. */ { PyObject *item; - Py_UCS4 *buf; - Py_ssize_t bufsize; item = PyTuple_GET_ITEM(state, 0); - buf = PyUnicode_AsUCS4Copy(item); - if (buf == NULL) + + if (_PyUnicodeWriter_Truncate(&self->writer, 0) < 0) return NULL; - bufsize = PyUnicode_GET_LENGTH(item); - - if (resize_buffer(self, bufsize) < 0) { - PyMem_Free(buf); + if (_PyUnicodeWriter_WriteStr(&self->writer, item) < 0) return NULL; - } - memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4)); - PyMem_Free(buf); - self->string_size = bufsize; } /* Set carefully the position value. Alternatively, we could use the seek diff -r aaa68dce117e Modules/_io/textio.c --- a/Modules/_io/textio.c Thu Aug 09 21:38:23 2012 +0200 +++ b/Modules/_io/textio.c Fri Aug 10 04:21:09 2012 +0200 @@ -1615,6 +1615,7 @@ textiowrapper_read(textio *self, PyObjec static char * find_control_char(int kind, char *s, char *end, Py_UCS4 ch) { + /* FIXME: reuse PyUnicode_FindChar */ if (kind == PyUnicode_1BYTE_KIND) { assert(ch < 256); return (char *) memchr((void *) s, (char) ch, end - s); diff -r aaa68dce117e Objects/unicodeobject.c --- a/Objects/unicodeobject.c Thu Aug 09 21:38:23 2012 +0200 +++ b/Objects/unicodeobject.c Fri Aug 10 04:21:09 2012 +0200 @@ -12799,7 +12799,7 @@ unicode_endswith(PyObject *self, } Py_LOCAL_INLINE(void) -_PyUnicodeWriter_Update(_PyUnicodeWriter *writer) +unicode_writer_update(_PyUnicodeWriter *writer) { writer->size = PyUnicode_GET_LENGTH(writer->buffer); writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer); @@ -12825,7 +12825,7 @@ _PyUnicodeWriter_PrepareInternal(_PyUnic Py_ssize_t newlen; PyObject *newbuffer; - assert(length > 0); + assert(length >= 0); if (length > PY_SSIZE_T_MAX - writer->pos) { PyErr_NoMemory(); @@ -12844,7 +12844,7 @@ _PyUnicodeWriter_PrepareInternal(_PyUnic writer->buffer = PyUnicode_New(newlen, maxchar); if (writer->buffer == NULL) return -1; - _PyUnicodeWriter_Update(writer); + unicode_writer_update(writer); return 0; } @@ -12873,7 +12873,7 @@ _PyUnicodeWriter_PrepareInternal(_PyUnic return -1; } writer->buffer = newbuffer; - _PyUnicodeWriter_Update(writer); + unicode_writer_update(writer); } else if (maxchar > writer->maxchar) { assert(!writer->readonly); @@ -12884,8 +12884,49 @@ _PyUnicodeWriter_PrepareInternal(_PyUnic writer->buffer, 0, writer->pos); Py_DECREF(writer->buffer); writer->buffer = newbuffer; - _PyUnicodeWriter_Update(writer); - } + unicode_writer_update(writer); + } + return 0; +} + +int +_PyUnicodeWriter_Truncate(_PyUnicodeWriter *writer, Py_ssize_t length) +{ + PyObject *buffer; + if (length < 0) + length = 0; + if (writer->pos <= length) + return 0; + if (length == 0) { + _PyUnicodeWriter_Dealloc(writer); + return 0; + } + + if (writer->readonly) { + buffer = PyUnicode_Substring(writer->buffer, 0, length); + if (buffer == NULL) + return -1; + writer->buffer = buffer; + writer->readonly = 0; + unicode_writer_update(writer); + } + else { + Py_UCS4 maxchar; + maxchar = _PyUnicode_FindMaxChar(writer->buffer, 0, length); + if (maxchar < writer->maxchar) { + buffer = PyUnicode_New(length, maxchar); + if (buffer == NULL) + return -1; + _PyUnicode_FastCopyCharacters(buffer, 0, writer->buffer, 0, length); + Py_DECREF(writer->buffer); + writer->buffer = buffer; + } else { + if (PyUnicode_Resize(&writer->buffer, length) < 0) + return -1; + } + unicode_writer_update(writer); + } + writer->pos = length; return 0; } @@ -12905,12 +12946,14 @@ _PyUnicodeWriter_WriteStr(_PyUnicodeWrit if (writer->buffer == NULL && !writer->overallocate) { Py_INCREF(str); writer->buffer = str; - _PyUnicodeWriter_Update(writer); + unicode_writer_update(writer); writer->readonly = 1; writer->size = 0; writer->pos += len; return 0; } + if (maxchar < writer->maxchar) + maxchar = writer->maxchar; if (_PyUnicodeWriter_PrepareInternal(writer, len, maxchar) == -1) return -1; } @@ -12920,35 +12963,119 @@ _PyUnicodeWriter_WriteStr(_PyUnicodeWrit return 0; } -PyObject * -_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer) -{ +int +_PyUnicodeWriter_WriteStrAt(_PyUnicodeWriter *writer, PyObject *str, Py_ssize_t pos) +{ + Py_UCS4 maxchar, buffer_maxchar; + Py_ssize_t len, extend; + + assert(pos <= writer->pos); + + if (writer->pos == pos) + return _PyUnicodeWriter_WriteStr(writer, str); + + /* otherwise, str overrides existing characters */ + assert(writer->buffer != NULL); + + if (PyUnicode_READY(str) == -1) + return -1; + len = PyUnicode_GET_LENGTH(str); + if (len == 0) + return 0; + + buffer_maxchar = _PyUnicode_FindMaxChar(writer->buffer, 0, pos); + maxchar = PyUnicode_MAX_CHAR_VALUE(str); + buffer_maxchar = MAX_MAXCHAR(buffer_maxchar, maxchar); + if (pos + len < writer->pos) { + maxchar = _PyUnicode_FindMaxChar(writer->buffer, + pos + len, writer->pos); + buffer_maxchar = MAX_MAXCHAR(buffer_maxchar, maxchar); + } + + if (len > writer->pos - pos) + extend = (pos + len) - writer->pos; + else + extend = 0; + + if (buffer_maxchar != writer->maxchar) { + writer->maxchar = 0; + if (_PyUnicodeWriter_PrepareInternal(writer, extend, buffer_maxchar) == -1) + return -1; + } + else if (extend || writer->readonly) { + if (_PyUnicodeWriter_PrepareInternal(writer, extend, buffer_maxchar) == -1) + return -1; + } + assert(!writer->readonly); + _PyUnicode_FastCopyCharacters(writer->buffer, pos, + str, 0, len); + writer->pos += extend; + return 0; +} + +PyObject * +unicode_writer_getvalue(_PyUnicodeWriter *writer, int finish) +{ + PyObject *res; + if (writer->pos == 0) { - Py_XDECREF(writer->buffer); + if (finish) + Py_CLEAR(writer->buffer); Py_INCREF(unicode_empty); return unicode_empty; } + if (writer->readonly) { assert(PyUnicode_GET_LENGTH(writer->buffer) == writer->pos); - return writer->buffer; - } - if (PyUnicode_GET_LENGTH(writer->buffer) != writer->pos) { - PyObject *newbuffer; - newbuffer = resize_compact(writer->buffer, writer->pos); - if (newbuffer == NULL) { - Py_DECREF(writer->buffer); - return NULL; - } - writer->buffer = newbuffer; - } - assert(_PyUnicode_CheckConsistency(writer->buffer, 1)); - return writer->buffer; + res = writer->buffer; + if (finish) { + writer->buffer = NULL; + _PyUnicodeWriter_Init(writer, 0); + } + else + Py_INCREF(res); + return res; + } + + if (writer->size != writer->pos) { + assert(writer->pos <= writer->size); + if (finish) + res = resize_compact(writer->buffer, writer->pos); + else + res = PyUnicode_Substring(writer->buffer, 0, writer->pos); + } + else { + if (finish) + res = writer->buffer; + else + res = _PyUnicode_Copy(writer->buffer); + } + if (finish) { + writer->buffer = NULL; + _PyUnicodeWriter_Init(writer, 0); + } + assert(res == NULL || _PyUnicode_CheckConsistency(res, 1)); + return res; +} + + +PyObject * +_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer) +{ + return unicode_writer_getvalue(writer, 1); +} + +PyObject * +_PyUnicodeWriter_GetValue(_PyUnicodeWriter *writer) +{ + return unicode_writer_getvalue(writer, 0); } void _PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer) { Py_CLEAR(writer->buffer); + _PyUnicodeWriter_Init(writer, 0); } #include "stringlib/unicode_format.h"