mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
650 lines
18 KiB
C
650 lines
18 KiB
C
/*
|
|
|
|
Unicode implementation based on original code by Fredrik Lundh,
|
|
modified by Marc-Andre Lemburg <mal@lemburg.com>.
|
|
|
|
Major speed upgrades to the method implementations at the Reykjavik
|
|
NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.
|
|
|
|
Copyright (c) Corporation for National Research Initiatives.
|
|
|
|
--------------------------------------------------------------------
|
|
The original string type implementation is:
|
|
|
|
Copyright (c) 1999 by Secret Labs AB
|
|
Copyright (c) 1999 by Fredrik Lundh
|
|
|
|
By obtaining, using, and/or copying this software and/or its
|
|
associated documentation, you agree that you have read, understood,
|
|
and will comply with the following terms and conditions:
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
associated documentation for any purpose and without fee is hereby
|
|
granted, provided that the above copyright notice appears in all
|
|
copies, and that both that copyright notice and this permission notice
|
|
appear in supporting documentation, and that the name of Secret Labs
|
|
AB or the author not be used in advertising or publicity pertaining to
|
|
distribution of the software without specific, written prior
|
|
permission.
|
|
|
|
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
|
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
--------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "Python.h"
|
|
#include "pycore_freelist.h" // _Py_FREELIST_FREE()
|
|
#include "pycore_long.h" // _PyLong_FormatWriter()
|
|
#include "pycore_unicodeobject.h" // _PyUnicode_Result()
|
|
|
|
|
|
#ifdef MS_WINDOWS
|
|
/* On Windows, overallocate by 50% is the best factor */
|
|
# define OVERALLOCATE_FACTOR 2
|
|
#else
|
|
/* On Linux, overallocate by 25% is the best factor */
|
|
# define OVERALLOCATE_FACTOR 4
|
|
#endif
|
|
|
|
|
|
/* Compilation of templated routines */
|
|
|
|
#define STRINGLIB_GET_EMPTY() _PyUnicode_GetEmpty()
|
|
|
|
#include "stringlib/ucs1lib.h"
|
|
#include "stringlib/find_max_char.h"
|
|
#include "stringlib/undef.h"
|
|
|
|
|
|
void
|
|
_PyUnicodeWriter_Init(_PyUnicodeWriter *writer)
|
|
{
|
|
memset(writer, 0, sizeof(*writer));
|
|
|
|
/* ASCII is the bare minimum */
|
|
writer->min_char = 127;
|
|
|
|
/* use a kind value smaller than PyUnicode_1BYTE_KIND so
|
|
_PyUnicodeWriter_PrepareKind() will copy the buffer. */
|
|
assert(writer->kind == 0);
|
|
assert(writer->kind < PyUnicode_1BYTE_KIND);
|
|
}
|
|
|
|
|
|
PyUnicodeWriter*
|
|
PyUnicodeWriter_Create(Py_ssize_t length)
|
|
{
|
|
if (length < 0) {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"length must be positive");
|
|
return NULL;
|
|
}
|
|
|
|
const size_t size = sizeof(_PyUnicodeWriter);
|
|
PyUnicodeWriter *pub_writer;
|
|
pub_writer = _Py_FREELIST_POP_MEM(unicode_writers);
|
|
if (pub_writer == NULL) {
|
|
pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
|
|
if (pub_writer == NULL) {
|
|
return (PyUnicodeWriter *)PyErr_NoMemory();
|
|
}
|
|
}
|
|
_PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
|
|
|
|
_PyUnicodeWriter_Init(writer);
|
|
// The buffer is created lazily at the first write, except if
|
|
// the read-only optimization is used.
|
|
writer->min_length = length;
|
|
writer->overallocate = 1;
|
|
|
|
return pub_writer;
|
|
}
|
|
|
|
|
|
void
|
|
PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
|
|
{
|
|
if (writer == NULL) {
|
|
return;
|
|
}
|
|
_PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
|
|
_Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
|
|
}
|
|
|
|
|
|
// Initialize _PyUnicodeWriter with initial buffer
|
|
void
|
|
_PyUnicodeWriter_InitWithBuffer(_PyUnicodeWriter *writer, PyObject *buffer)
|
|
{
|
|
assert(PyUnstable_Object_IsUniquelyReferenced(buffer));
|
|
|
|
memset(writer, 0, sizeof(*writer));
|
|
_PyUnicodeWriter_SetBuffer(writer, buffer);
|
|
writer->min_length = writer->size;
|
|
assert(_PyUnicodeWriter_CanWrite(writer));
|
|
}
|
|
|
|
|
|
int
|
|
_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
|
|
Py_ssize_t length, Py_UCS4 maxchar)
|
|
{
|
|
assert(length >= 0);
|
|
assert(maxchar <= _Py_MAX_UNICODE);
|
|
|
|
// Check that _PyUnicodeWriter_Prepare() or _PyUnicodeWriter_PrepareKind()
|
|
// was used
|
|
assert(maxchar > writer->maxchar
|
|
|| (length > (writer->size - writer->pos) && length >= 1));
|
|
|
|
if (length > PY_SSIZE_T_MAX - writer->pos) {
|
|
PyErr_NoMemory();
|
|
return -1;
|
|
}
|
|
Py_ssize_t alloc = writer->pos + length;
|
|
|
|
maxchar = Py_MAX(maxchar, writer->min_char);
|
|
|
|
PyObject *new_buffer;
|
|
if (writer->buffer == NULL) {
|
|
assert(!writer->readonly);
|
|
|
|
// Do not overallocate at the first allocation, but use min_length
|
|
if (alloc < writer->min_length) {
|
|
alloc = writer->min_length;
|
|
}
|
|
|
|
new_buffer = PyUnicode_New(alloc, maxchar);
|
|
if (new_buffer == NULL) {
|
|
return -1;
|
|
}
|
|
}
|
|
else if (alloc > writer->size) {
|
|
// Do not overallocate at the first allocation, but use min_length
|
|
int overallocate = (writer->overallocate && !writer->readonly);
|
|
if (overallocate
|
|
&& alloc <= (PY_SSIZE_T_MAX - alloc / OVERALLOCATE_FACTOR)) {
|
|
/* overallocate to limit the number of realloc() */
|
|
alloc += alloc / OVERALLOCATE_FACTOR;
|
|
}
|
|
if (alloc < writer->min_length) {
|
|
alloc = writer->min_length;
|
|
}
|
|
|
|
if (maxchar > writer->maxchar || writer->readonly) {
|
|
/* resize + widen */
|
|
maxchar = Py_MAX(maxchar, writer->maxchar);
|
|
new_buffer = PyUnicode_New(alloc, maxchar);
|
|
if (new_buffer == NULL) {
|
|
return -1;
|
|
}
|
|
_PyUnicode_FastCopyCharacters(new_buffer, 0,
|
|
writer->buffer, 0, writer->pos);
|
|
}
|
|
else {
|
|
new_buffer = _PyUnicode_ResizeCompact(writer->buffer, alloc);
|
|
if (new_buffer == NULL) {
|
|
return -1;
|
|
}
|
|
// Do not DECREF the old buffer
|
|
writer->buffer = NULL;
|
|
}
|
|
}
|
|
else {
|
|
assert(maxchar > writer->maxchar);
|
|
assert(!writer->readonly);
|
|
|
|
new_buffer = PyUnicode_New(writer->size, maxchar);
|
|
if (new_buffer == NULL) {
|
|
return -1;
|
|
}
|
|
_PyUnicode_FastCopyCharacters(new_buffer, 0,
|
|
writer->buffer, 0, writer->pos);
|
|
}
|
|
|
|
_PyUnicodeWriter_SetBuffer(writer, new_buffer);
|
|
return 0;
|
|
|
|
#undef OVERALLOCATE_FACTOR
|
|
}
|
|
|
|
int
|
|
_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
|
|
int kind)
|
|
{
|
|
Py_UCS4 maxchar;
|
|
|
|
/* ensure that the _PyUnicodeWriter_PrepareKind macro was used */
|
|
assert(writer->kind < kind);
|
|
|
|
switch (kind)
|
|
{
|
|
case PyUnicode_1BYTE_KIND: maxchar = 0xff; break;
|
|
case PyUnicode_2BYTE_KIND: maxchar = 0xffff; break;
|
|
case PyUnicode_4BYTE_KIND: maxchar = _Py_MAX_UNICODE; break;
|
|
default:
|
|
Py_UNREACHABLE();
|
|
}
|
|
|
|
return _PyUnicodeWriter_PrepareInternal(writer, 0, maxchar);
|
|
}
|
|
|
|
|
|
int
|
|
_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, Py_UCS4 ch)
|
|
{
|
|
return _PyUnicodeWriter_WriteCharInline(writer, ch);
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
|
|
{
|
|
if (ch > _Py_MAX_UNICODE) {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"character must be in range(0x110000)");
|
|
return -1;
|
|
}
|
|
|
|
return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
|
|
}
|
|
|
|
|
|
int
|
|
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str)
|
|
{
|
|
assert(PyUnicode_Check(str));
|
|
|
|
Py_ssize_t len = PyUnicode_GET_LENGTH(str);
|
|
if (len == 0) {
|
|
return 0;
|
|
}
|
|
Py_UCS4 maxchar = PyUnicode_MAX_CHAR_VALUE(str);
|
|
|
|
if (maxchar > writer->maxchar || len > writer->size - writer->pos) {
|
|
if (writer->buffer == NULL && PyUnicode_CheckExact(str)) {
|
|
assert(_PyUnicode_CheckConsistency(str, 1));
|
|
_PyUnicodeWriter_SetReadOnly(writer, Py_NewRef(str), len);
|
|
return 0;
|
|
}
|
|
if (_PyUnicodeWriter_PrepareInternal(writer, len, maxchar) == -1)
|
|
return -1;
|
|
}
|
|
|
|
assert(_PyUnicodeWriter_CanWrite(writer));
|
|
_PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
|
|
str, 0, len);
|
|
writer->pos += len;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_WriteStr(PyUnicodeWriter *pub_writer, PyObject *obj)
|
|
{
|
|
_PyUnicodeWriter *writer = (_PyUnicodeWriter*)pub_writer;
|
|
PyTypeObject *type = Py_TYPE(obj);
|
|
if (type == &PyUnicode_Type) {
|
|
return _PyUnicodeWriter_WriteStr(writer, obj);
|
|
}
|
|
|
|
if (type == &PyLong_Type) {
|
|
return _PyLong_FormatWriter(writer, obj, 10, 0);
|
|
}
|
|
|
|
PyObject *str = PyObject_Str(obj);
|
|
if (str == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
int res = _PyUnicodeWriter_WriteStr(writer, str);
|
|
Py_DECREF(str);
|
|
return res;
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *pub_writer, PyObject *obj)
|
|
{
|
|
_PyUnicodeWriter *writer = (_PyUnicodeWriter*)pub_writer;
|
|
if (obj == NULL) {
|
|
return _PyUnicodeWriter_WriteASCIIString(writer, "<NULL>", 6);
|
|
}
|
|
|
|
if (Py_TYPE(obj) == &PyLong_Type) {
|
|
return _PyLong_FormatWriter(writer, obj, 10, 0);
|
|
}
|
|
// Fast path for None; see gh-159813 for the rationale.
|
|
if (obj == Py_None) {
|
|
return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
|
|
}
|
|
|
|
PyObject *repr = PyObject_Repr(obj);
|
|
if (repr == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
int res = _PyUnicodeWriter_WriteStr(writer, repr);
|
|
Py_DECREF(repr);
|
|
return res;
|
|
}
|
|
|
|
|
|
int
|
|
_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str,
|
|
Py_ssize_t start, Py_ssize_t end)
|
|
{
|
|
assert(0 <= start);
|
|
assert(start <= end);
|
|
assert(end <= PyUnicode_GET_LENGTH(str));
|
|
|
|
if (start == 0 && end == PyUnicode_GET_LENGTH(str)) {
|
|
return _PyUnicodeWriter_WriteStr(writer, str);
|
|
}
|
|
|
|
Py_ssize_t len = end - start;
|
|
if (len == 0) {
|
|
return 0;
|
|
}
|
|
|
|
Py_UCS4 maxchar;
|
|
if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) {
|
|
maxchar = _PyUnicode_FindMaxChar(str, start, end);
|
|
}
|
|
else {
|
|
maxchar = writer->maxchar;
|
|
}
|
|
if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) {
|
|
return -1;
|
|
}
|
|
assert(_PyUnicodeWriter_CanWrite(writer));
|
|
|
|
_PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
|
|
str, start, len);
|
|
writer->pos += len;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
|
|
Py_ssize_t start, Py_ssize_t end)
|
|
{
|
|
if (!PyUnicode_Check(str)) {
|
|
PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
|
|
return -1;
|
|
}
|
|
if (start < 0 || start > end) {
|
|
PyErr_Format(PyExc_ValueError, "invalid start argument");
|
|
return -1;
|
|
}
|
|
if (end > PyUnicode_GET_LENGTH(str)) {
|
|
PyErr_Format(PyExc_ValueError, "invalid end argument");
|
|
return -1;
|
|
}
|
|
|
|
return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
|
|
start, end);
|
|
}
|
|
|
|
|
|
int
|
|
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
|
|
const char *ascii, Py_ssize_t len)
|
|
{
|
|
if (len == -1)
|
|
len = strlen(ascii);
|
|
|
|
if (len == 0) {
|
|
return 0;
|
|
}
|
|
|
|
assert(ucs1lib_find_max_char((const Py_UCS1*)ascii, (const Py_UCS1*)ascii + len) <= 127);
|
|
|
|
if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1) {
|
|
return -1;
|
|
}
|
|
assert(_PyUnicodeWriter_CanWrite(writer));
|
|
|
|
switch (writer->kind)
|
|
{
|
|
case PyUnicode_1BYTE_KIND:
|
|
{
|
|
const Py_UCS1 *str = (const Py_UCS1 *)ascii;
|
|
Py_UCS1 *data = writer->data;
|
|
|
|
memcpy(data + writer->pos, str, len);
|
|
break;
|
|
}
|
|
case PyUnicode_2BYTE_KIND:
|
|
{
|
|
_PyUnicode_CONVERT_BYTES(
|
|
Py_UCS1, Py_UCS2,
|
|
ascii, ascii + len,
|
|
(Py_UCS2 *)writer->data + writer->pos);
|
|
break;
|
|
}
|
|
case PyUnicode_4BYTE_KIND:
|
|
{
|
|
_PyUnicode_CONVERT_BYTES(
|
|
Py_UCS1, Py_UCS4,
|
|
ascii, ascii + len,
|
|
(Py_UCS4 *)writer->data + writer->pos);
|
|
break;
|
|
}
|
|
default:
|
|
Py_UNREACHABLE();
|
|
}
|
|
|
|
writer->pos += len;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer,
|
|
const char *str,
|
|
Py_ssize_t size)
|
|
{
|
|
assert(writer != NULL);
|
|
_Py_AssertHoldsTstate();
|
|
|
|
return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer, str, size);
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
|
|
const char *str,
|
|
Py_ssize_t size)
|
|
{
|
|
if (size < 0) {
|
|
size = strlen(str);
|
|
}
|
|
|
|
return _PyUnicode_DecodeUTF8Writer((_PyUnicodeWriter*)writer, str, size,
|
|
_Py_ERROR_STRICT, NULL, NULL);
|
|
}
|
|
|
|
|
|
int
|
|
PyUnicodeWriter_DecodeUTF8Stateful(PyUnicodeWriter *writer,
|
|
const char *str,
|
|
Py_ssize_t size,
|
|
const char *errors,
|
|
Py_ssize_t *consumed)
|
|
{
|
|
if (size < 0) {
|
|
size = strlen(str);
|
|
}
|
|
|
|
return _PyUnicode_DecodeUTF8Writer((_PyUnicodeWriter*)writer, str, size,
|
|
_Py_ERROR_UNKNOWN, errors,
|
|
consumed);
|
|
}
|
|
|
|
|
|
int
|
|
_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
|
|
const char *str, Py_ssize_t len)
|
|
{
|
|
if (len == 0) {
|
|
return 0;
|
|
}
|
|
|
|
const Py_UCS1 *ucs1 = (const Py_UCS1 *)str;
|
|
Py_UCS4 maxchar = ucs1lib_find_max_char(ucs1, ucs1 + len);
|
|
if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) {
|
|
return -1;
|
|
}
|
|
assert(_PyUnicodeWriter_CanWrite(writer));
|
|
|
|
Py_ssize_t index = writer->pos;
|
|
switch (writer->kind) {
|
|
case PyUnicode_1BYTE_KIND: {
|
|
memcpy((Py_UCS1 *)writer->data + index, ucs1, len);
|
|
break;
|
|
}
|
|
case PyUnicode_2BYTE_KIND: {
|
|
Py_UCS2 *ucs2 = (Py_UCS2 *)writer->data + index;
|
|
const Py_UCS1 *end = ucs1 + len;
|
|
for (; ucs1 < end; ++ucs2, ++ucs1) {
|
|
*ucs2 = (Py_UCS2)*ucs1;
|
|
}
|
|
break;
|
|
}
|
|
case PyUnicode_4BYTE_KIND: {
|
|
Py_UCS4 *ucs4 = (Py_UCS4 *)writer->data + index;
|
|
const Py_UCS1 *end = ucs1 + len;
|
|
for (; ucs1 < end; ++ucs4, ++ucs1) {
|
|
*ucs4 = (Py_UCS4)*ucs1;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
Py_UNREACHABLE();
|
|
}
|
|
|
|
writer->pos += len;
|
|
return 0;
|
|
}
|
|
|
|
|
|
PyObject *
|
|
_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
|
|
{
|
|
#ifdef Py_DEBUG
|
|
// Check for buffer overflow
|
|
if (writer->buffer != NULL) {
|
|
Py_ssize_t pos = PyUnicode_GET_LENGTH(writer->buffer);
|
|
Py_UCS4 ch = PyUnicode_READ_CHAR(writer->buffer, pos);
|
|
if (ch != 0) {
|
|
_Py_FatalErrorFormat(__func__,
|
|
"Buffer overflow detected in "
|
|
"PyUnicodeWriter %p at position %zd",
|
|
writer, pos);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
PyObject *str = writer->buffer;
|
|
writer->buffer = NULL;
|
|
|
|
Py_ssize_t final_size = writer->pos;
|
|
if (final_size == 0) {
|
|
// Get the empty string singleton
|
|
PyObject *empty = _PyUnicode_GetEmpty();
|
|
Py_XDECREF(str); // writer->buffer can be NULL if the position is 0
|
|
return empty;
|
|
}
|
|
|
|
if (writer->readonly) {
|
|
assert(final_size == PyUnicode_GET_LENGTH(str));
|
|
goto done;
|
|
}
|
|
assert(final_size <= PyUnicode_GET_LENGTH(str));
|
|
|
|
if (final_size == 1 && PyUnicode_KIND(str) == PyUnicode_1BYTE_KIND) {
|
|
// Get the single character singleton
|
|
assert(PyUnicode_GET_LENGTH(str) >= 1);
|
|
const Py_UCS1 *data = PyUnicode_1BYTE_DATA(str);
|
|
Py_UCS1 ch = data[0];
|
|
Py_DECREF(str);
|
|
str = _Py_LATIN1_CHR(ch);
|
|
goto done;
|
|
}
|
|
|
|
if (writer->recheck_maxchar) {
|
|
Py_UCS4 maxchar = _PyUnicode_FindMaxChar(str, 0, final_size);
|
|
if (maxchar != writer->maxchar) {
|
|
// Adjust the string kind
|
|
PyObject *str2 = PyUnicode_New(final_size, maxchar);
|
|
if (str2 == NULL) {
|
|
Py_DECREF(str);
|
|
return NULL;
|
|
}
|
|
_PyUnicode_FastCopyCharacters(str2, 0, str, 0, final_size);
|
|
Py_SETREF(str, str2);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (PyUnicode_GET_LENGTH(str) != final_size) {
|
|
// Truncate the string
|
|
PyObject *str2 = _PyUnicode_ResizeCompact(str, final_size);
|
|
if (str2 == NULL) {
|
|
Py_DECREF(str);
|
|
return NULL;
|
|
}
|
|
str = str2;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
assert(_PyUnicode_CheckConsistency(str, 1));
|
|
return str;
|
|
}
|
|
|
|
|
|
PyObject *
|
|
_PyUnicodeWriter_FinishWithSize(_PyUnicodeWriter *writer, Py_ssize_t size)
|
|
{
|
|
assert(0 <= size);
|
|
if (writer->buffer != NULL) {
|
|
assert(size <= writer->pos);
|
|
assert(size <= PyUnicode_GET_LENGTH(writer->buffer));
|
|
if (size < writer->pos) {
|
|
// Truncate the string: we may need to adjust the string kind
|
|
writer->recheck_maxchar = 1;
|
|
}
|
|
}
|
|
else {
|
|
assert(size == 0);
|
|
}
|
|
writer->pos = size;
|
|
return _PyUnicodeWriter_Finish(writer);
|
|
}
|
|
|
|
|
|
PyObject*
|
|
PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
|
|
{
|
|
PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
|
|
assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
|
|
_Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
|
|
return str;
|
|
}
|
|
|
|
|
|
void
|
|
_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer)
|
|
{
|
|
Py_CLEAR(writer->buffer);
|
|
}
|