[Python-checkins] r68531 - in sandbox/trunk/io-c: _iomodule.h _textio.c io.c

antoine.pitrou python-checkins at python.org
Sun Jan 11 14:53:36 CET 2009


Author: antoine.pitrou
Date: Sun Jan 11 14:53:36 2009
New Revision: 68531

Log:
Use joining instead of appending in TextIOWrapper.read(), and a few
micro-optimizations.



Modified:
   sandbox/trunk/io-c/_iomodule.h
   sandbox/trunk/io-c/_textio.c
   sandbox/trunk/io-c/io.c

Modified: sandbox/trunk/io-c/_iomodule.h
==============================================================================
--- sandbox/trunk/io-c/_iomodule.h	(original)
+++ sandbox/trunk/io-c/_iomodule.h	Sun Jan 11 14:53:36 2009
@@ -64,6 +64,7 @@
 extern PyObject *_PyIO_str_isatty;
 extern PyObject *_PyIO_str_newlines;
 extern PyObject *_PyIO_str_read;
+extern PyObject *_PyIO_str_read1;
 extern PyObject *_PyIO_str_readable;
 extern PyObject *_PyIO_str_readinto;
 extern PyObject *_PyIO_str_readline;

Modified: sandbox/trunk/io-c/_textio.c
==============================================================================
--- sandbox/trunk/io-c/_textio.c	(original)
+++ sandbox/trunk/io-c/_textio.c	Sun Jan 11 14:53:36 2009
@@ -106,18 +106,12 @@
 #define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF)
 
 static PyObject *
-IncrementalNewlineDecoder_decode(PyNewLineDecoderObject *self, 
-                                 PyObject *args, PyObject *kwds)
+_IncrementalNewlineDecoder_decode(PyNewLineDecoderObject *self, 
+                                  PyObject *input, int final)
 {
-    char *kwlist[] = {"input", "final", NULL};
-    PyObject *input, *output;
-    int final = 0;
+    PyObject *output;
     Py_ssize_t output_len;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder",
-                                     kwlist, &input, &final))
-        return NULL;
-
     if (self->decoder == NULL) {
         PyErr_SetString(PyExc_ValueError,
                         "IncrementalNewlineDecoder.__init__ not called");
@@ -296,6 +290,20 @@
 }
 
 static PyObject *
+IncrementalNewlineDecoder_decode(PyNewLineDecoderObject *self, 
+                                 PyObject *args, PyObject *kwds)
+{
+    char *kwlist[] = {"input", "final", NULL};
+    PyObject *input;
+    int final = 0;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder",
+                                     kwlist, &input, &final))
+        return NULL;
+    return _IncrementalNewlineDecoder_decode(self, input, final);
+}
+
+static PyObject *
 IncrementalNewlineDecoder_getstate(PyNewLineDecoderObject *self, PyObject *args)
 {
     PyObject *state = PyObject_CallMethodObjArgs(self->decoder,
@@ -800,11 +808,17 @@
     if (n < 0 || n > avail)
         n = avail;
 
-    chars = PyUnicode_FromUnicode(
-        PyUnicode_AS_UNICODE(self->decoded_chars)
-        + self->decoded_chars_used, n);
-    if (chars == NULL)
-        return NULL;
+    if (self->decoded_chars_used > 0 || n < avail) {
+        chars = PyUnicode_FromUnicode(
+            PyUnicode_AS_UNICODE(self->decoded_chars)
+            + self->decoded_chars_used, n);
+        if (chars == NULL)
+            return NULL;
+    }
+    else {
+        chars = self->decoded_chars;
+        Py_INCREF(chars);
+    }
 
     self->decoded_chars_used += n;
     return chars;
@@ -839,7 +853,8 @@
 {
     PyObject *dec_buffer = NULL;
     PyObject *dec_flags = NULL;
-    PyObject *input_chunk, *decoded_chars;
+    PyObject *input_chunk = NULL;
+    PyObject *decoded_chars, *chunk_size;
     int eof;
 
     /* The return value is True unless EOF was reached.  The decoded string is
@@ -875,16 +890,26 @@
     }
 
     /* Read a chunk, decode it, and put the result in self._decoded_chars. */
-    input_chunk = PyObject_CallMethod(self->buffer, "read1",
-                                      "n", self->chunk_size);
+    chunk_size = PyLong_FromSsize_t(self->chunk_size);
+    if (chunk_size == NULL)
+        goto fail;
+    input_chunk = PyObject_CallMethodObjArgs(self->buffer,
+        _PyIO_str_read1, chunk_size, NULL);
+    Py_DECREF(chunk_size);
     if (input_chunk == NULL)
         goto fail;
     assert(PyBytes_Check(input_chunk));
 
     eof = (PyBytes_Size(input_chunk) == 0);
 
-    decoded_chars = PyObject_CallMethod(self->decoder, "decode",
-                                        "Oi", input_chunk, eof);
+    if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) {
+        decoded_chars = _IncrementalNewlineDecoder_decode(
+            (PyNewLineDecoderObject *) self->decoder, input_chunk, eof);
+    }
+    else {
+        decoded_chars = PyObject_CallMethodObjArgs(self->decoder,
+            _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL);
+    }
 
     /* TODO sanity check: isinstance(decoded_chars, unicode) */
     if (decoded_chars == NULL)
@@ -914,15 +939,13 @@
     Py_XDECREF(dec_flags);
     Py_XDECREF(input_chunk);
     return -1;
-
 }
 
-
 static PyObject *
 TextIOWrapper_read(PyTextIOWrapperObject *self, PyObject *args)
 {
     Py_ssize_t n = -1;
-    PyObject *result;
+    PyObject *result = NULL, *chunks = NULL;
 
     CHECK_INITIALIZED(self);
 
@@ -937,8 +960,8 @@
         PyObject *decoded;
         if (bytes == NULL)
             goto fail;
-        decoded = PyObject_CallMethod(self->decoder, "decode",
-                                      "Oi", bytes, /*final=*/1);
+        decoded = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_decode,
+                                             bytes, Py_True, NULL);
         Py_DECREF(bytes);
         if (decoded == NULL)
             goto fail;
@@ -959,28 +982,48 @@
     }
     else {
         int res = 1;
+        Py_ssize_t remaining = n;
+
         result = TextIOWrapper_get_decoded_chars(self, n);
+        if (result == NULL)
+            goto fail;
+        remaining -= PyUnicode_GET_SIZE(result);
 
         /* Keep reading chunks until we have n characters to return */
-        while (res == 1) {
-            if (result == NULL || Py_SIZE(result) >= n) {
-                break;
-            }
+        while (remaining > 0) {
             res = TextIOWrapper_read_chunk(self);
-            if (res < 0) {
-                Py_DECREF(result);
+            if (res < 0)
                 goto fail;
+            if (res == 0)  /* EOF */
+                break;
+            if (chunks == NULL) {
+                chunks = PyList_New(0);
+                if (chunks == NULL)
+                    goto fail;
             }
-
-            PyUnicode_AppendAndDel(&result,
-                                   TextIOWrapper_get_decoded_chars(
-                                       self, n - Py_SIZE(result)));
+            if (PyList_Append(chunks, result) < 0)
+                goto fail;
+            Py_DECREF(result);
+            result = TextIOWrapper_get_decoded_chars(self, remaining);
+            if (result == NULL)
+                goto fail;
+            remaining -= PyUnicode_GET_SIZE(result);
+        }
+        if (chunks != NULL) {
+            if (result != NULL && PyList_Append(chunks, result) < 0)
+                goto fail;
+            Py_CLEAR(result);
+            result = PyUnicode_Join(PyUnicode_FromStringAndSize(NULL, 0),
+                                    chunks);
             if (result == NULL)
                 goto fail;
+            Py_CLEAR(chunks);
         }
         return result;
     }
   fail:
+    Py_XDECREF(result);
+    Py_XDECREF(chunks);
     return NULL;
 }
 

Modified: sandbox/trunk/io-c/io.c
==============================================================================
--- sandbox/trunk/io-c/io.c	(original)
+++ sandbox/trunk/io-c/io.c	Sun Jan 11 14:53:36 2009
@@ -24,6 +24,7 @@
 PyObject *_PyIO_str_isatty;
 PyObject *_PyIO_str_newlines;
 PyObject *_PyIO_str_read;
+PyObject *_PyIO_str_read1;
 PyObject *_PyIO_str_readable;
 PyObject *_PyIO_str_readinto;
 PyObject *_PyIO_str_readline;
@@ -649,6 +650,8 @@
         goto fail;
     if (!(_PyIO_str_read = PyUnicode_InternFromString("read")))
         goto fail;
+    if (!(_PyIO_str_read1 = PyUnicode_InternFromString("read1")))
+        goto fail;
     if (!(_PyIO_str_readable = PyUnicode_InternFromString("readable")))
         goto fail;
     if (!(_PyIO_str_readinto = PyUnicode_InternFromString("readinto")))


More information about the Python-checkins mailing list