Skip to content

Commit fc7d789

Browse files
committed
Merge branch 'main' into writer_readonly
2 parents 4cf02fa + a64b7ec commit fc7d789

3 files changed

Lines changed: 31 additions & 22 deletions

File tree

‎Lib/test/test_capi/test_unicode.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,11 @@ def test_singletons(self):
20882088
for size in (0, 123):
20892089
with self.subTest(size=size):
20902090
writer = self.create_writer(size)
2091+
writer.write_utf8(b'utf8', 0)
2092+
writer.write_ascii(b'ascii', 0)
2093+
writer.write_widechar(b'wstr', 0)
2094+
writer.write_ucs4(b'ucs4', 0)
2095+
writer.write_substring('text', 0, 0)
20912096
self.assertIs(writer.finish(), '')
20922097

20932098
for size in (0, 123):
@@ -2104,6 +2109,8 @@ def test_singletons(self):
21042109
# PyUnicodeWriter_Finish() replaces the buffer
21052110
# with the singleton
21062111
writer = self.create_writer(size)
2112+
# Use PyUnicodeWriter_WriteSubstring() to avoid
2113+
# the read-only buffer optimization
21072114
writer.write_substring(ch + 'xxx', 0, 1)
21082115
self.assertIs(writer.finish(), ch)
21092116

‎Objects/bytesobject.c‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3938,19 +3938,18 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
39383938
}
39393939
}
39403940
else {
3941-
if (size != PyBytes_GET_SIZE(writer->obj)) {
3942-
if (_PyBytes_Resize(&writer->obj, size)) {
3943-
goto error;
3944-
}
3945-
}
3946-
39473941
if (size == 1) {
39483942
// Get the single byte singleton
39493943
unsigned char ch = PyBytes_AS_STRING(writer->obj)[0];
39503944
PyObject *op = (PyObject*)CHARACTER(ch);
39513945
assert(_Py_IsImmortal(op));
39523946
Py_SETREF(writer->obj, op);
39533947
}
3948+
else if (size != PyBytes_GET_SIZE(writer->obj)) {
3949+
if (_PyBytes_Resize(&writer->obj, size)) {
3950+
goto error;
3951+
}
3952+
}
39543953
}
39553954

39563955
result = writer->obj;

‎Objects/unicode_writer.c‎

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,6 @@ _PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
586586
PyObject *
587587
_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
588588
{
589-
PyObject *str;
590-
591589
#ifdef Py_DEBUG
592590
// Check for buffer overflow
593591
if (writer->buffer != NULL) {
@@ -602,23 +600,28 @@ _PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
602600
}
603601
#endif
604602

605-
if (writer->pos == 0) {
606-
Py_CLEAR(writer->buffer);
607-
return _PyUnicode_GetEmpty();
608-
}
609-
610-
str = writer->buffer;
603+
PyObject *str = writer->buffer;
611604
writer->buffer = NULL;
612605

613-
if (writer->readonly) {
614-
assert(PyUnicode_GET_LENGTH(str) == writer->pos);
615-
assert(_PyUnicode_CheckConsistency(str, 1));
616-
return str;
606+
Py_ssize_t final_size = writer->pos;
607+
if (final_size == 0) {
608+
PyObject *empty = _PyUnicode_GetEmpty();
609+
Py_XDECREF(str); // writer->buffer can be NULL if the position is 0
610+
return empty;
617611
}
618612

619-
if (PyUnicode_GET_LENGTH(str) != writer->pos) {
620-
PyObject *str2;
621-
str2 = _PyUnicode_ResizeCompact(str, writer->pos);
613+
Py_ssize_t length = PyUnicode_GET_LENGTH(str);
614+
if (final_size == 1 && PyUnicode_KIND(str) == PyUnicode_1BYTE_KIND) {
615+
assert(length >= 1);
616+
const Py_UCS1 *data = PyUnicode_1BYTE_DATA(str);
617+
Py_UCS1 ch = data[0];
618+
PyObject *latin1_char = _Py_LATIN1_CHR(ch);
619+
Py_DECREF(str);
620+
return latin1_char;
621+
}
622+
623+
if (!writer->readonly && length != final_size) {
624+
PyObject *str2 = _PyUnicode_ResizeCompact(str, final_size);
622625
if (str2 == NULL) {
623626
Py_DECREF(str);
624627
return NULL;
@@ -627,7 +630,7 @@ _PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
627630
}
628631

629632
assert(_PyUnicode_CheckConsistency(str, 1));
630-
return _PyUnicode_Result(str);
633+
return str;
631634
}
632635

633636

0 commit comments

Comments
 (0)