[Python-checkins] r68742 - python/branches/io-c/Modules/_bufferedio.c

antoine.pitrou python-checkins at python.org
Sun Jan 18 22:28:48 CET 2009


Author: antoine.pitrou
Date: Sun Jan 18 22:28:48 2009
New Revision: 68742
Log:
Make binary buffered readline and iteration much faster
(8x as fast as the IOBase generic implementation)
Modified:
 python/branches/io-c/Modules/_bufferedio.c
Modified: python/branches/io-c/Modules/_bufferedio.c
==============================================================================
--- python/branches/io-c/Modules/_bufferedio.c	(original)
+++ python/branches/io-c/Modules/_bufferedio.c	Sun Jan 18 22:28:48 2009
@@ -721,6 +721,132 @@
 }
 
 static PyObject *
+_Buffered_readline(BufferedObject *self, Py_ssize_t limit)
+{
+ PyObject *res = NULL;
+ PyObject *chunks = NULL;
+ Py_ssize_t n, written = 0;
+ const char *start, *s, *end;
+
+ if (BufferedIOMixin_closed(self)) {
+ PyErr_SetString(PyExc_ValueError, "readline of closed file");
+ return NULL;
+ }
+
+ ENTER_BUFFERED(self)
+
+ /* First, try to find a line in the buffer */
+ n = READAHEAD(self);
+ if (limit >= 0 && n > limit)
+ n = limit;
+ start = self->buffer + self->pos;
+ end = start + n;
+ s = start;
+ while (s < end) {
+ if (*s++ == '\n') {
+ res = PyBytes_FromStringAndSize(start, s - start);
+ if (res != NULL)
+ self->pos += s - start;
+ goto end;
+ }
+ }
+ if (n == limit) {
+ res = PyBytes_FromStringAndSize(start, n);
+ if (res != NULL)
+ self->pos += n;
+ goto end;
+ }
+
+ /* Now we try to get some more from the raw stream */
+ if (self->writable) {
+ res = _BufferedWriter_flush_unlocked(self, 1);
+ if (res == NULL)
+ goto end;
+ Py_CLEAR(res);
+ }
+ chunks = PyList_New(0);
+ if (chunks == NULL)
+ goto end;
+ if (n > 0) {
+ res = PyBytes_FromStringAndSize(start, n);
+ if (res == NULL)
+ goto end;
+ if (PyList_Append(chunks, res) < 0) {
+ Py_CLEAR(res);
+ goto end;
+ }
+ Py_CLEAR(res);
+ written += n;
+ if (limit >= 0)
+ limit -= n;
+ }
+
+ for (;;) {
+ _BufferedReader_reset_buf(self);
+ n = _BufferedReader_fill_buffer(self);
+ if (n == -1)
+ goto end;
+ if (n <= 0)
+ break;
+ if (limit >= 0 && n > limit)
+ n = limit;
+ start = self->buffer;
+ end = start + n;
+ s = start;
+ while (s < end) {
+ if (*s++ == '\n') {
+ res = PyBytes_FromStringAndSize(start, s - start);
+ if (res == NULL)
+ goto end;
+ self->pos = s - start;
+ goto found;
+ }
+ }
+ res = PyBytes_FromStringAndSize(start, n);
+ if (res == NULL)
+ goto end;
+ if (n == limit) {
+ self->pos = n;
+ break;
+ }
+ if (PyList_Append(chunks, res) < 0) {
+ Py_CLEAR(res);
+ goto end;
+ }
+ Py_CLEAR(res);
+ written += n;
+ if (limit >= 0)
+ limit -= n;
+ }
+found:
+ if (res != NULL && PyList_Append(chunks, res) < 0) {
+ Py_CLEAR(res);
+ goto end;
+ }
+ Py_CLEAR(res);
+ res = _PyBytes_Join(PyBytes_FromStringAndSize(NULL, 0), chunks);
+
+end:
+ LEAVE_BUFFERED(self)
+ Py_XDECREF(chunks);
+ return res;
+}
+
+static PyObject *
+Buffered_readline(BufferedObject *self, PyObject *args)
+{
+ Py_ssize_t limit = -1;
+
+ CHECK_INITIALIZED(self)
+
+ if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
+ return NULL;
+ }
+ return _Buffered_readline(self, limit);
+}
+
+
+static PyObject *
 Buffered_tell(BufferedObject *self, PyObject *args)
 {
 Py_off_t pos;
@@ -846,6 +972,43 @@
 return res;
 }
 
+static PyObject *
+Buffered_iternext(BufferedObject *self)
+{
+ PyObject *line;
+ PyTypeObject *tp;
+
+ CHECK_INITIALIZED(self);
+
+ tp = Py_TYPE(self);
+ if (tp == &PyBufferedReader_Type ||
+ tp == &PyBufferedRandom_Type) {
+ /* Skip method call overhead for speed */
+ line = _Buffered_readline(self, -1);
+ }
+ else {
+ line = PyObject_CallMethodObjArgs((PyObject *)self,
+ _PyIO_str_readline, NULL);
+ if (line && !PyBytes_Check(line)) {
+ PyErr_Format(PyExc_IOError,
+ "readline() should have returned a bytes object, "
+ "not '%.200s'", Py_TYPE(line)->tp_name);
+ Py_DECREF(line);
+ return NULL;
+ }
+ }
+
+ if (line == NULL)
+ return NULL;
+
+ if (PyBytes_GET_SIZE(line) == 0) {
+ /* Reached EOF or would have blocked */
+ Py_DECREF(line);
+ return NULL;
+ }
+
+ return line;
+}
 
 /*
 * class BufferedReader
@@ -1157,6 +1320,7 @@
 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
+ {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
 {NULL, NULL}
@@ -1202,7 +1366,7 @@
 0, /* tp_richcompare */
 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
 0, /* tp_iter */
- 0, /* tp_iternext */
+ (iternextfunc)Buffered_iternext, /* tp_iternext */
 BufferedReader_methods, /* tp_methods */
 BufferedReader_members, /* tp_members */
 BufferedReader_getset, /* tp_getset */
@@ -1844,6 +2008,7 @@
 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
+ {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
 {NULL, NULL}
@@ -1889,7 +2054,7 @@
 0, /* tp_richcompare */
 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
 0, /* tp_iter */
- 0, /* tp_iternext */
+ (iternextfunc)Buffered_iternext, /* tp_iternext */
 BufferedRandom_methods, /* tp_methods */
 BufferedRandom_members, /* tp_members */
 BufferedRandom_getset, /* tp_getset */


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /