Skip to content

Commit 3424a51

Browse files
committed
gh-158585: Use PyBytesWriter in _io._Buffered.readline()
Replace a list of bytes object with PyBytesWriter.
1 parent 00a1c3a commit 3424a51

1 file changed

Lines changed: 67 additions & 59 deletions

File tree

‎Modules/_io/bufferedio.c‎

Lines changed: 67 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,109 +1205,117 @@ _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
12051205
static PyObject *
12061206
_buffered_readline(buffered *self, Py_ssize_t limit)
12071207
{
1208-
PyObject *res = NULL;
1209-
PyObject *chunks = NULL;
1210-
Py_ssize_t n;
1211-
const char *start, *s, *end;
1208+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
12121209

12131210
CHECK_CLOSED(self, "readline of closed file")
12141211

12151212
/* First, try to find a line in the buffer. This can run unlocked because
12161213
the calls to the C API are simple enough that they can't trigger
12171214
any thread switch. */
1218-
n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1219-
if (limit >= 0 && n > limit)
1215+
Py_ssize_t n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1216+
if (limit >= 0 && n > limit) {
12201217
n = limit;
1221-
start = self->buffer + self->pos;
1222-
s = memchr(start, '\n', n);
1218+
}
1219+
const char *start = self->buffer + self->pos;
1220+
const char *s = memchr(start, '\n', n);
12231221
if (s != NULL) {
1224-
res = PyBytes_FromStringAndSize(start, s - start + 1);
1225-
if (res != NULL)
1226-
self->pos += s - start + 1;
1227-
goto end_unlocked;
1222+
n = s - start + 1;
1223+
PyObject *res = PyBytes_FromStringAndSize(start, n);
1224+
if (res == NULL) {
1225+
return NULL;
1226+
}
1227+
self->pos += n;
1228+
return res;
12281229
}
1230+
12291231
if (n == limit) {
1230-
res = PyBytes_FromStringAndSize(start, n);
1231-
if (res != NULL)
1232-
self->pos += n;
1233-
goto end_unlocked;
1232+
PyObject *res = PyBytes_FromStringAndSize(start, n);
1233+
if (res == NULL) {
1234+
return NULL;
1235+
}
1236+
self->pos += n;
1237+
return res;
12341238
}
12351239

1236-
if (!ENTER_BUFFERED(self))
1237-
goto end_unlocked;
1240+
PyBytesWriter *writer = NULL;
1241+
int locked = 0;
1242+
if (!ENTER_BUFFERED(self)) {
1243+
goto error;
1244+
}
1245+
locked = 1;
12381246

12391247
/* Now we try to get some more from the raw stream */
1240-
chunks = PyList_New(0);
1241-
if (chunks == NULL)
1242-
goto end;
1248+
writer = PyBytesWriter_Create(0);
1249+
if (writer == NULL) {
1250+
goto error;
1251+
}
1252+
12431253
if (n > 0) {
1244-
res = PyBytes_FromStringAndSize(start, n);
1245-
if (res == NULL)
1246-
goto end;
1247-
if (PyList_Append(chunks, res) < 0) {
1248-
Py_CLEAR(res);
1249-
goto end;
1254+
if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
1255+
goto error;
12501256
}
1251-
Py_CLEAR(res);
12521257
self->pos += n;
1253-
if (limit >= 0)
1258+
if (limit >= 0) {
12541259
limit -= n;
1260+
}
12551261
}
12561262
if (self->writable) {
1257-
PyObject *r = buffered_flush_and_rewind_unlocked(self);
1258-
if (r == NULL)
1259-
goto end;
1260-
Py_DECREF(r);
1263+
PyObject *res = buffered_flush_and_rewind_unlocked(self);
1264+
if (res == NULL) {
1265+
goto error;
1266+
}
1267+
Py_DECREF(res);
12611268
}
12621269

12631270
for (;;) {
12641271
_bufferedreader_reset_buf(self);
12651272
n = _bufferedreader_fill_buffer(self);
1266-
if (n == -1)
1267-
goto end;
1268-
if (n <= 0)
1273+
if (n == -1) {
1274+
goto error;
1275+
}
1276+
if (n <= 0) {
12691277
break;
1270-
if (limit >= 0 && n > limit)
1278+
}
1279+
if (limit >= 0 && n > limit) {
12711280
n = limit;
1281+
}
12721282
start = self->buffer;
1273-
end = start + n;
1283+
const char *end = start + n;
12741284
s = start;
12751285
while (s < end) {
12761286
if (*s++ == '\n') {
1277-
res = PyBytes_FromStringAndSize(start, s - start);
1278-
if (res == NULL)
1279-
goto end;
1287+
if (PyBytesWriter_WriteBytes(writer, start, s - start) < 0) {
1288+
goto error;
1289+
}
12801290
self->pos = s - start;
12811291
goto found;
12821292
}
12831293
}
1284-
res = PyBytes_FromStringAndSize(start, n);
1285-
if (res == NULL)
1286-
goto end;
1294+
1295+
if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
1296+
goto error;
1297+
}
12871298
if (n == limit) {
12881299
self->pos = n;
12891300
break;
12901301
}
1291-
if (PyList_Append(chunks, res) < 0) {
1292-
Py_CLEAR(res);
1293-
goto end;
1294-
}
1295-
Py_CLEAR(res);
1296-
if (limit >= 0)
1302+
if (limit >= 0) {
12971303
limit -= n;
1304+
}
12981305
}
1306+
12991307
found:
1300-
if (res != NULL && PyList_Append(chunks, res) < 0) {
1301-
Py_CLEAR(res);
1302-
goto end;
1308+
if (locked) {
1309+
LEAVE_BUFFERED(self)
13031310
}
1304-
Py_XSETREF(res, PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks));
1311+
return PyBytesWriter_Finish(writer);
13051312

1306-
end:
1307-
LEAVE_BUFFERED(self)
1308-
end_unlocked:
1309-
Py_XDECREF(chunks);
1310-
return res;
1313+
error:
1314+
PyBytesWriter_Discard(writer);
1315+
if (locked) {
1316+
LEAVE_BUFFERED(self)
1317+
}
1318+
return NULL;
13111319
}
13121320

13131321
/*[clinic input]

0 commit comments

Comments
 (0)