Skip to content

Commit 1877543

Browse files
authored
gh-125196: Use PyUnicodeWriter for repr(structseq) (#125219)
Replace the private _PyUnicodeWriter with the public PyUnicodeWriter. * Avoid temporary PyUnicode_DecodeUTF8(): call PyUnicodeWriter_WriteUTF8() instead. * Avoid temporary PyObject_Repr(): call PyUnicodeWriter_WriteRepr() instead.
1 parent ee3167b commit 1877543

File tree

1 file changed

+24
-41
lines changed

1 file changed

+24
-41
lines changed

Objects/structseq.c

+24-41
Original file line numberDiff line numberDiff line change
@@ -266,83 +266,66 @@ static PyObject *
266266
structseq_repr(PyStructSequence *obj)
267267
{
268268
PyTypeObject *typ = Py_TYPE(obj);
269-
_PyUnicodeWriter writer;
270269

271-
/* Write "typename(" */
272-
PyObject *type_name = PyUnicode_DecodeUTF8(typ->tp_name,
273-
strlen(typ->tp_name),
274-
NULL);
275-
if (type_name == NULL) {
270+
// count 5 characters per item: "x=1, "
271+
Py_ssize_t type_name_len = strlen(typ->tp_name);
272+
Py_ssize_t prealloc = (type_name_len + 1
273+
+ VISIBLE_SIZE(obj) * 5 + 1);
274+
PyUnicodeWriter *writer = PyUnicodeWriter_Create(prealloc);
275+
if (writer == NULL) {
276276
return NULL;
277277
}
278278

279-
_PyUnicodeWriter_Init(&writer);
280-
writer.overallocate = 1;
281-
/* count 5 characters per item: "x=1, " */
282-
writer.min_length = (PyUnicode_GET_LENGTH(type_name) + 1
283-
+ VISIBLE_SIZE(obj) * 5 + 1);
284-
285-
if (_PyUnicodeWriter_WriteStr(&writer, type_name) < 0) {
286-
Py_DECREF(type_name);
279+
// Write "typename("
280+
if (PyUnicodeWriter_WriteUTF8(writer, typ->tp_name, type_name_len) < 0) {
287281
goto error;
288282
}
289-
Py_DECREF(type_name);
290-
291-
if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) {
283+
if (PyUnicodeWriter_WriteChar(writer, '(') < 0) {
292284
goto error;
293285
}
294286

295287
for (Py_ssize_t i=0; i < VISIBLE_SIZE(obj); i++) {
296288
if (i > 0) {
297-
/* Write ", " */
298-
if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
289+
// Write ", "
290+
if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
291+
goto error;
292+
}
293+
if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) {
299294
goto error;
300295
}
301296
}
302297

303-
/* Write "name=repr" */
298+
// Write name
304299
const char *name_utf8 = typ->tp_members[i].name;
305300
if (name_utf8 == NULL) {
306-
PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %zd name is NULL"
301+
PyErr_Format(PyExc_SystemError,
302+
"In structseq_repr(), member %zd name is NULL"
307303
" for type %.500s", i, typ->tp_name);
308304
goto error;
309305
}
310-
311-
PyObject *name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL);
312-
if (name == NULL) {
313-
goto error;
314-
}
315-
if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
316-
Py_DECREF(name);
306+
if (PyUnicodeWriter_WriteUTF8(writer, name_utf8, -1) < 0) {
317307
goto error;
318308
}
319-
Py_DECREF(name);
320309

321-
if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) {
310+
// Write "=" + repr(value)
311+
if (PyUnicodeWriter_WriteChar(writer, '=') < 0) {
322312
goto error;
323313
}
324-
325314
PyObject *value = PyStructSequence_GetItem((PyObject*)obj, i);
326315
assert(value != NULL);
327-
PyObject *repr = PyObject_Repr(value);
328-
if (repr == NULL) {
329-
goto error;
330-
}
331-
if (_PyUnicodeWriter_WriteStr(&writer, repr) < 0) {
332-
Py_DECREF(repr);
316+
if (PyUnicodeWriter_WriteRepr(writer, value) < 0) {
333317
goto error;
334318
}
335-
Py_DECREF(repr);
336319
}
337320

338-
if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) {
321+
if (PyUnicodeWriter_WriteChar(writer, ')') < 0) {
339322
goto error;
340323
}
341324

342-
return _PyUnicodeWriter_Finish(&writer);
325+
return PyUnicodeWriter_Finish(writer);
343326

344327
error:
345-
_PyUnicodeWriter_Dealloc(&writer);
328+
PyUnicodeWriter_Discard(writer);
346329
return NULL;
347330
}
348331

0 commit comments

Comments
 (0)