mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
gh-158585: Use PyBytesWriter in io.BufferedReader.readline() (#158615)
Replace a list of bytes object with PyBytesWriter.
This commit is contained in:
1 parent
6e7738bb5e
commit
880696af1a
1 file changed
+68
-62
+68
-62
@@ -1205,109 +1205,115 @@ _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
|
||||
static PyObject *
|
||||
_buffered_readline(buffered *self, Py_ssize_t limit)
|
||||
{
|
||||
PyObject *res = NULL;
|
||||
PyObject *chunks = NULL;
|
||||
Py_ssize_t n;
|
||||
const char *start, *s, *end;
|
||||
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
|
||||
|
||||
CHECK_CLOSED(self, "readline of closed file")
|
||||
|
||||
/* First, try to find a line in the buffer. This can run unlocked because
|
||||
the calls to the C API are simple enough that they can't trigger
|
||||
any thread switch. */
|
||||
n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
|
||||
if (limit >= 0 && n > limit)
|
||||
Py_ssize_t n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
|
||||
if (limit >= 0 && n > limit) {
|
||||
n = limit;
|
||||
start = self->buffer + self->pos;
|
||||
s = memchr(start, '\n', n);
|
||||
if (s != NULL) {
|
||||
res = PyBytes_FromStringAndSize(start, s - start + 1);
|
||||
if (res != NULL)
|
||||
self->pos += s - start + 1;
|
||||
goto end_unlocked;
|
||||
}
|
||||
if (n == limit) {
|
||||
res = PyBytes_FromStringAndSize(start, n);
|
||||
if (res != NULL)
|
||||
self->pos += n;
|
||||
goto end_unlocked;
|
||||
const char *start = self->buffer + self->pos;
|
||||
const char *s = memchr(start, '\n', n);
|
||||
if (s != NULL) {
|
||||
n = s - start + 1;
|
||||
PyObject *res = PyBytes_FromStringAndSize(start, n);
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
self->pos += n;
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!ENTER_BUFFERED(self))
|
||||
goto end_unlocked;
|
||||
if (n == limit) {
|
||||
PyObject *res = PyBytes_FromStringAndSize(start, n);
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
self->pos += n;
|
||||
return res;
|
||||
}
|
||||
|
||||
PyBytesWriter *writer = NULL;
|
||||
int locked = 0;
|
||||
if (!ENTER_BUFFERED(self)) {
|
||||
goto error;
|
||||
}
|
||||
locked = 1;
|
||||
|
||||
/* Now we try to get some more from the raw stream */
|
||||
chunks = PyList_New(0);
|
||||
if (chunks == NULL)
|
||||
goto end;
|
||||
writer = PyBytesWriter_Create(0);
|
||||
if (writer == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
res = PyBytes_FromStringAndSize(start, n);
|
||||
if (res == NULL)
|
||||
goto end;
|
||||
if (PyList_Append(chunks, res) < 0) {
|
||||
Py_CLEAR(res);
|
||||
goto end;
|
||||
if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
|
||||
goto error;
|
||||
}
|
||||
Py_CLEAR(res);
|
||||
self->pos += n;
|
||||
if (limit >= 0)
|
||||
if (limit >= 0) {
|
||||
limit -= n;
|
||||
}
|
||||
}
|
||||
if (self->writable) {
|
||||
PyObject *r = buffered_flush_and_rewind_unlocked(self);
|
||||
if (r == NULL)
|
||||
goto end;
|
||||
Py_DECREF(r);
|
||||
PyObject *res = buffered_flush_and_rewind_unlocked(self);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_bufferedreader_reset_buf(self);
|
||||
n = _bufferedreader_fill_buffer(self);
|
||||
if (n == -1)
|
||||
goto end;
|
||||
if (n <= 0)
|
||||
if (n == -1) {
|
||||
goto error;
|
||||
}
|
||||
if (n <= 0) {
|
||||
break;
|
||||
if (limit >= 0 && n > limit)
|
||||
}
|
||||
if (limit >= 0 && n > limit) {
|
||||
n = limit;
|
||||
}
|
||||
start = self->buffer;
|
||||
end = start + n;
|
||||
const char *end = start + n;
|
||||
s = start;
|
||||
while (s < end) {
|
||||
if (*s++ == '\n') {
|
||||
res = PyBytes_FromStringAndSize(start, s - start);
|
||||
if (res == NULL)
|
||||
goto end;
|
||||
if (PyBytesWriter_WriteBytes(writer, start, s - start) < 0) {
|
||||
goto error;
|
||||
}
|
||||
self->pos = s - start;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
res = PyBytes_FromStringAndSize(start, n);
|
||||
if (res == NULL)
|
||||
goto end;
|
||||
|
||||
if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (n == limit) {
|
||||
self->pos = n;
|
||||
break;
|
||||
}
|
||||
if (PyList_Append(chunks, res) < 0) {
|
||||
Py_CLEAR(res);
|
||||
goto end;
|
||||
}
|
||||
Py_CLEAR(res);
|
||||
if (limit >= 0)
|
||||
if (limit >= 0) {
|
||||
limit -= n;
|
||||
}
|
||||
}
|
||||
found:
|
||||
if (res != NULL && PyList_Append(chunks, res) < 0) {
|
||||
Py_CLEAR(res);
|
||||
goto end;
|
||||
}
|
||||
Py_XSETREF(res, PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks));
|
||||
|
||||
end:
|
||||
found:
|
||||
LEAVE_BUFFERED(self)
|
||||
end_unlocked:
|
||||
Py_XDECREF(chunks);
|
||||
return res;
|
||||
return PyBytesWriter_Finish(writer);
|
||||
|
||||
error:
|
||||
PyBytesWriter_Discard(writer);
|
||||
if (locked) {
|
||||
LEAVE_BUFFERED(self)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
|
||||
Reference in new issue
Block a user